From 7b1eb2ef0975d678fc5d8a42f2af12b42637a25d Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Fri, 11 Nov 2022 15:13:52 -0800 Subject: [PATCH 01/35] Add an isjunction method to ntpath and posixpath, pass it along as well in pathlib --- Lib/ntpath.py | 14 +++++++++++++- Lib/pathlib.py | 6 ++++++ Lib/posixpath.py | 11 ++++++++++- Lib/test/test_ntpath.py | 15 +++++++++++++++ Lib/test/test_posixpath.py | 3 +++ 5 files changed, 47 insertions(+), 2 deletions(-) diff --git a/Lib/ntpath.py b/Lib/ntpath.py index d9582f4087433e..3ef9886f09e0c0 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -30,7 +30,7 @@ "ismount", "expanduser","expandvars","normpath","abspath", "curdir","pardir","sep","pathsep","defpath","altsep", "extsep","devnull","realpath","supports_unicode_filenames","relpath", - "samefile", "sameopenfile", "samestat", "commonpath"] + "samefile", "sameopenfile", "samestat", "commonpath", "isjunction"] def _get_bothseps(path): if isinstance(path, bytes): @@ -267,6 +267,18 @@ def islink(path): return False return stat.S_ISLNK(st.st_mode) + +# Is a path a junction? + +def isjunction(path): + """Test whether a path is a junction""" + try: + st = os.lstat(path) + except (OSError, ValueError, AttributeError): + return False + return bool(st.st_reparse_tag & stat.IO_REPARSE_TAG_MOUNT_POINT) + + # Being true for dangling symbolic links is also useful. def lexists(path): diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 068d1b02f484bf..bc57ae60e725b2 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -1223,6 +1223,12 @@ def is_symlink(self): # Non-encodable path return False + def is_junction(self): + """ + Whether this path is a junction. + """ + return self._flavour.pathmod.isjunction(self) + def is_block_device(self): """ Whether this path is a block device. diff --git a/Lib/posixpath.py b/Lib/posixpath.py index 5e1ebe3293d849..d0a549b5e68129 100644 --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -35,7 +35,7 @@ "samefile","sameopenfile","samestat", "curdir","pardir","sep","pathsep","defpath","altsep","extsep", "devnull","realpath","supports_unicode_filenames","relpath", - "commonpath"] + "commonpath", "isjunction"] def _get_sep(path): @@ -169,6 +169,15 @@ def islink(path): return False return stat.S_ISLNK(st.st_mode) + +# Is a path a junction? + +def isjunction(path): + """Test whether a path is a junction + Junctions are not a part of posix semantics""" + return False + + # Being true for dangling symbolic links is also useful. def lexists(path): diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py index d51946322c8056..698255e43787f9 100644 --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -1,5 +1,6 @@ import ntpath import os +import subprocess import sys import unittest import warnings @@ -856,6 +857,20 @@ def test_nt_helpers(self): self.assertIsInstance(b_final_path, bytes) self.assertGreater(len(b_final_path), 0) + def test_isjunction(self): + with os_helper.temp_dir() as d: + with os_helper.change_cwd(d): + os.mkdir('tmpdir') + + # create a junction via subprocess, since we don't currently + # support making them via python directly + subprocess.check_call('mklink /J testjunc tmpdir', shell=True) + + self.assertTrue(ntpath.isjunction('testjunc')) + self.assertFalse(ntpath.isjunction('tmpdir')) + self.assertPathEqual(ntpath.realpath('testjunc'), ntpath.realpath('tmpdir')) + + class NtCommonTest(test_genericpath.CommonTest, unittest.TestCase): pathmodule = ntpath attributes = ['relpath'] diff --git a/Lib/test/test_posixpath.py b/Lib/test/test_posixpath.py index c644f881e460fe..a14e16a07c046a 100644 --- a/Lib/test/test_posixpath.py +++ b/Lib/test/test_posixpath.py @@ -242,6 +242,9 @@ def fake_lstat(path): finally: os.lstat = save_lstat + def test_isjunction(self): + self.assertFalse(posixpath.isjunction(ABSTFN)) + def test_expanduser(self): self.assertEqual(posixpath.expanduser("foo"), "foo") self.assertEqual(posixpath.expanduser(b"foo"), b"foo") From d2a769a191bf134ecb69e9a72ff1f603fcf33383 Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Fri, 11 Nov 2022 15:29:52 -0800 Subject: [PATCH 02/35] Add is_junction test for pathlib The actual functionality lives in ntpath/posixpath, so just verify the correct function is called and return value is returned --- Lib/test/test_pathlib.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 3b1f302cc964ba..94401e5429cdf2 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -2411,6 +2411,13 @@ def test_is_symlink(self): self.assertIs((P / 'linkA\udfff').is_file(), False) self.assertIs((P / 'linkA\x00').is_file(), False) + def test_is_junction(self): + P = self.cls(BASE) + + with mock.patch.object(P._flavour, 'pathmod'): + self.assertEqual(P.is_junction(), P._flavour.pathmod.isjunction.return_value) + P._flavour.pathmod.isjunction.assert_called_once_with(P) + def test_is_fifo_false(self): P = self.cls(BASE) self.assertFalse((P / 'fileA').is_fifo()) From 5744fc01a7831e7e61b221499301d5334e79f114 Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Fri, 11 Nov 2022 15:35:48 -0800 Subject: [PATCH 03/35] Add a skipIf not win32 for testing ntpath isjunction on non windows platforms We can only create junctions on windows, thus only test this on win32 --- Lib/test/test_ntpath.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py index 698255e43787f9..42c90e9053eb0f 100644 --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -857,6 +857,7 @@ def test_nt_helpers(self): self.assertIsInstance(b_final_path, bytes) self.assertGreater(len(b_final_path), 0) + @unittest.skipIf(sys.platform != 'win32', "Can only test junctions with creation on win32.") def test_isjunction(self): with os_helper.temp_dir() as d: with os_helper.change_cwd(d): From e54add07c73a1d0ec03b8f176502ea164d850045 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Wed, 16 Nov 2022 21:35:31 +0000 Subject: [PATCH 04/35] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2022-11-16-21-35-30.gh-issue-99547.p_c_bp.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-11-16-21-35-30.gh-issue-99547.p_c_bp.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-11-16-21-35-30.gh-issue-99547.p_c_bp.rst b/Misc/NEWS.d/next/Core and Builtins/2022-11-16-21-35-30.gh-issue-99547.p_c_bp.rst new file mode 100644 index 00000000000000..7e3c52924213ec --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-11-16-21-35-30.gh-issue-99547.p_c_bp.rst @@ -0,0 +1 @@ +Add a function to os.path to check if a path is a junction: isjunction. Add similar functionality to pathlib.Path as is_junction. From db3f5b3c1374fc50c7e04691d8e022663e696294 Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Wed, 16 Nov 2022 16:50:59 -0800 Subject: [PATCH 05/35] Update Lib/test/test_ntpath.py Co-authored-by: Eryk Sun --- Lib/test/test_ntpath.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py index 42c90e9053eb0f..e51cceb27a66ef 100644 --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -863,9 +863,11 @@ def test_isjunction(self): with os_helper.change_cwd(d): os.mkdir('tmpdir') - # create a junction via subprocess, since we don't currently - # support making them via python directly - subprocess.check_call('mklink /J testjunc tmpdir', shell=True) + import _winapi + try: + _winapi.CreateJunction(tmpdir, 'testjunc') + except OSError: + raise unittest.SkipTest('creating the test junction failed') self.assertTrue(ntpath.isjunction('testjunc')) self.assertFalse(ntpath.isjunction('tmpdir')) From 07aaab6fb9f5f69c2c5e631fcc070129bdf5ea6b Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Wed, 16 Nov 2022 16:52:49 -0800 Subject: [PATCH 06/35] remove un-needed import --- Lib/test/test_ntpath.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py index e51cceb27a66ef..e7e75fe992e1f6 100644 --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -1,6 +1,5 @@ import ntpath import os -import subprocess import sys import unittest import warnings From bee6b2cd9f8dc0195696ce3d2f9ecfef90caa802 Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Wed, 16 Nov 2022 17:32:19 -0800 Subject: [PATCH 07/35] Update Lib/ntpath.py ntpath can be used on POSIX, even though the stat_result won't have st_reparse_tag. Co-authored-by: Eryk Sun --- Lib/ntpath.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/Lib/ntpath.py b/Lib/ntpath.py index 3ef9886f09e0c0..500f92df137343 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -270,13 +270,18 @@ def islink(path): # Is a path a junction? -def isjunction(path): - """Test whether a path is a junction""" - try: - st = os.lstat(path) - except (OSError, ValueError, AttributeError): +if hasattr(os.stat_result, 'st_reparse_tag'): + def isjunction(path): + """Test whether a path is a junction""" + try: + st = os.lstat(path) + except (OSError, ValueError, AttributeError): + return False + return bool(st.st_reparse_tag & stat.IO_REPARSE_TAG_MOUNT_POINT) +else: + def isjunction(path): + """Test whether a path is a junction""" return False - return bool(st.st_reparse_tag & stat.IO_REPARSE_TAG_MOUNT_POINT) # Being true for dangling symbolic links is also useful. From e3fbf24455f833a15148d1fd152fe1115740c30e Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Wed, 16 Nov 2022 17:36:11 -0800 Subject: [PATCH 08/35] fix test... this was a string not an obj --- Lib/test/test_ntpath.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py index e7e75fe992e1f6..336648273b6cf1 100644 --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -864,7 +864,7 @@ def test_isjunction(self): import _winapi try: - _winapi.CreateJunction(tmpdir, 'testjunc') + _winapi.CreateJunction('tmpdir', 'testjunc') except OSError: raise unittest.SkipTest('creating the test junction failed') From 262843ffd551d4254f1ca6f6c1c2912da129f25b Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Wed, 16 Nov 2022 17:47:03 -0800 Subject: [PATCH 09/35] Update Lib/posixpath.py Co-authored-by: Eryk Sun --- Lib/posixpath.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/posixpath.py b/Lib/posixpath.py index 026cabaded47be..737f8a5c156d81 100644 --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -175,6 +175,7 @@ def islink(path): def isjunction(path): """Test whether a path is a junction Junctions are not a part of posix semantics""" + os.fspath(path) return False From 1a8695f1b9e41b742e0165cfb0aecd5c417ee8b0 Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Wed, 16 Nov 2022 17:48:31 -0800 Subject: [PATCH 10/35] Update Lib/ntpath.py Co-authored-by: Eryk Sun --- Lib/ntpath.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/ntpath.py b/Lib/ntpath.py index 500f92df137343..e0aa8a747770b7 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -281,6 +281,7 @@ def isjunction(path): else: def isjunction(path): """Test whether a path is a junction""" + os.fspath(path) return False From 8b32ce504d79d30b59598b2538e90f69ad2fddd3 Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Wed, 16 Nov 2022 18:31:51 -0800 Subject: [PATCH 11/35] Empty commit to rekick ci From a20ebeabdf3577c99ac1fee3fb0e613da1acf5d7 Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Thu, 17 Nov 2022 10:01:00 -0800 Subject: [PATCH 12/35] update os.path.rst for isjunction --- Doc/library/os.path.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Doc/library/os.path.rst b/Doc/library/os.path.rst index 6d52a03ba95704..676d8b3257c23c 100644 --- a/Doc/library/os.path.rst +++ b/Doc/library/os.path.rst @@ -266,6 +266,14 @@ the :mod:`glob` module.) Accepts a :term:`path-like object`. +.. function:: isjunction(path) + + Return ``True`` if *path* is a junction. This function exists for both POSIX + and Windows, though can only return True on Windows. + + .. versionadded:: 3.12 + + .. function:: islink(path) Return ``True`` if *path* refers to an :func:`existing ` directory From dfdc033ba509fe1607ef26b2152578ab0b7481c1 Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Thu, 17 Nov 2022 10:06:59 -0800 Subject: [PATCH 13/35] update pathlib docs for is_junction --- Doc/library/pathlib.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index 944963e1e1ae79..4272b97ec02d45 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -889,6 +889,14 @@ call fails (for example because the path doesn't exist). ``False`` is also returned if the path doesn't exist or is a broken symlink; other errors (such as permission errors) are propagated. + + +.. method:: Path.is_junction() + + Return ``True`` if the path points to a junction, and ``False`` for any other + type of file (as returned by :func:`os.path.isjunction`). + + .. versionadded:: 3.12 .. method:: Path.is_mount() From 9f8185c754ed5d4d7d20c600395d2bfa05e796e1 Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Thu, 17 Nov 2022 10:31:18 -0800 Subject: [PATCH 14/35] Update 3.12.rst --- Doc/whatsnew/3.12.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index bb08e4455ee178..84f0bf29e45f56 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -233,6 +233,9 @@ pathlib to allow the insertion of ``..`` entries in the result; this behavior is more consistent with :func:`os.path.relpath`. (Contributed by Domenico Ragusa in :issue:`40358`.) + +* Add :meth:`pathlib.Path.is_junction` as a proxy to :func:`os.path.isjunction`. + dis --- @@ -251,6 +254,9 @@ os * Add :data:`os.PIDFD_NONBLOCK` to open a file descriptor for a process with :func:`os.pidfd_open` in non-blocking mode. (Contributed by Kumar Aditya in :gh:`93312`.) + +* Add :func:`os.path.isjunction` to check if a given path is a junction. + shutil ------ From 5cd2393c09ea867e6df59a6d2cda708cd93e3afc Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Thu, 17 Nov 2022 10:36:16 -0800 Subject: [PATCH 15/35] Update Doc/library/os.path.rst Co-authored-by: Steve Dower --- Doc/library/os.path.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/os.path.rst b/Doc/library/os.path.rst index 676d8b3257c23c..c945e4c68a5df6 100644 --- a/Doc/library/os.path.rst +++ b/Doc/library/os.path.rst @@ -269,7 +269,7 @@ the :mod:`glob` module.) .. function:: isjunction(path) Return ``True`` if *path* is a junction. This function exists for both POSIX - and Windows, though can only return True on Windows. + and Windows, though only Windows currently supports junctions. .. versionadded:: 3.12 From c0366c82c4bd2c0dc16760a3cfc9cf73a09f232f Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Thu, 17 Nov 2022 10:46:22 -0800 Subject: [PATCH 16/35] Update pathlib.rst --- Doc/library/pathlib.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index 4272b97ec02d45..fbe2d475184349 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -894,7 +894,7 @@ call fails (for example because the path doesn't exist). .. method:: Path.is_junction() Return ``True`` if the path points to a junction, and ``False`` for any other - type of file (as returned by :func:`os.path.isjunction`). + type of file. Currently only Windows supports junctions. .. versionadded:: 3.12 From 9d699893bd5218880ef7d05b2a4a54f33f2a73a3 Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Thu, 17 Nov 2022 10:48:32 -0800 Subject: [PATCH 17/35] Update pathlib.rst --- Doc/library/pathlib.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index fbe2d475184349..6537637f33c70e 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -889,8 +889,8 @@ call fails (for example because the path doesn't exist). ``False`` is also returned if the path doesn't exist or is a broken symlink; other errors (such as permission errors) are propagated. - - + + .. method:: Path.is_junction() Return ``True`` if the path points to a junction, and ``False`` for any other From 5ee99792e45a276e0291a4f7c865e58387fca7aa Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Thu, 17 Nov 2022 10:49:08 -0800 Subject: [PATCH 18/35] Update os.path.rst --- Doc/library/os.path.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/os.path.rst b/Doc/library/os.path.rst index c945e4c68a5df6..247ef7ae0718c5 100644 --- a/Doc/library/os.path.rst +++ b/Doc/library/os.path.rst @@ -272,7 +272,7 @@ the :mod:`glob` module.) and Windows, though only Windows currently supports junctions. .. versionadded:: 3.12 - + .. function:: islink(path) From ca01686e71c6c02998e9a946c0ce41b448ca29a8 Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Thu, 17 Nov 2022 10:49:49 -0800 Subject: [PATCH 19/35] Update 3.12.rst --- Doc/whatsnew/3.12.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index 84f0bf29e45f56..babb4f22c9d47c 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -233,7 +233,7 @@ pathlib to allow the insertion of ``..`` entries in the result; this behavior is more consistent with :func:`os.path.relpath`. (Contributed by Domenico Ragusa in :issue:`40358`.) - + * Add :meth:`pathlib.Path.is_junction` as a proxy to :func:`os.path.isjunction`. @@ -254,8 +254,8 @@ os * Add :data:`os.PIDFD_NONBLOCK` to open a file descriptor for a process with :func:`os.pidfd_open` in non-blocking mode. (Contributed by Kumar Aditya in :gh:`93312`.) - -* Add :func:`os.path.isjunction` to check if a given path is a junction. + +* Add :func:`os.path.isjunction` to check if a given path is a junction. shutil From d036f73938e09c737625e047295d09940b2e9f03 Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Thu, 17 Nov 2022 11:09:50 -0800 Subject: [PATCH 20/35] Update os.path.rst --- Doc/library/os.path.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/library/os.path.rst b/Doc/library/os.path.rst index 247ef7ae0718c5..50e089653fe71b 100644 --- a/Doc/library/os.path.rst +++ b/Doc/library/os.path.rst @@ -268,8 +268,9 @@ the :mod:`glob` module.) .. function:: isjunction(path) - Return ``True`` if *path* is a junction. This function exists for both POSIX - and Windows, though only Windows currently supports junctions. + Return ``True`` if *path* refers to an :func:`existing ` directory + entry that is a junction. Always return ``False`` if junctions are not + supported on the current platform. .. versionadded:: 3.12 From a8461eaba823a5a5c914ac0b88532d664e4631fe Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Thu, 17 Nov 2022 19:19:31 -0800 Subject: [PATCH 21/35] Update Lib/ntpath.py Co-authored-by: Eryk Sun --- Lib/ntpath.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/ntpath.py b/Lib/ntpath.py index e0aa8a747770b7..873c884c3bd934 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -277,7 +277,7 @@ def isjunction(path): st = os.lstat(path) except (OSError, ValueError, AttributeError): return False - return bool(st.st_reparse_tag & stat.IO_REPARSE_TAG_MOUNT_POINT) + return bool(st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT) else: def isjunction(path): """Test whether a path is a junction""" From 8f92e67e9f99b71cfb5b68fec764351eb3e0fc17 Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Thu, 17 Nov 2022 21:48:56 -0800 Subject: [PATCH 22/35] pr fixes, also add contribution notices --- Doc/whatsnew/3.12.rst | 6 + Modules/clinic/posixmodule.c.h | 23072 +++++++++++----------- Modules/posixmodule.c | 32092 ++++++++++++++++--------------- Programs/test_frozenmain.h | 84 +- 4 files changed, 27656 insertions(+), 27598 deletions(-) diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index babb4f22c9d47c..5fac9a7a7445d0 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -235,6 +235,7 @@ pathlib (Contributed by Domenico Ragusa in :issue:`40358`.) * Add :meth:`pathlib.Path.is_junction` as a proxy to :func:`os.path.isjunction`. + (Contributed by Charles Machalow in :gh:`99547`.) dis @@ -256,6 +257,11 @@ os (Contributed by Kumar Aditya in :gh:`93312`.) * Add :func:`os.path.isjunction` to check if a given path is a junction. + (Contributed by Charles Machalow in :gh:`99547`.) + +* :class:`os.DirEntry` now includes an :meth:`os.DirEntry.is_junction` + method to check if the entry is a junction. + (Contributed by Charles Machalow in :gh:`99547`.) shutil diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index 1ad96ea296ea68..4cc4f5d46521b4 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -1,11520 +1,11552 @@ -/*[clinic input] -preserve -[clinic start generated code]*/ - -#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) -# include "pycore_gc.h" // PyGC_Head -# include "pycore_runtime.h" // _Py_ID() -#endif - - -PyDoc_STRVAR(os_stat__doc__, -"stat($module, /, path, *, dir_fd=None, follow_symlinks=True)\n" -"--\n" -"\n" -"Perform a stat system call on the given path.\n" -"\n" -" path\n" -" Path to be examined; can be string, bytes, a path-like object or\n" -" open-file-descriptor int.\n" -" dir_fd\n" -" If not None, it should be a file descriptor open to a directory,\n" -" and path should be a relative string; path will then be relative to\n" -" that directory.\n" -" follow_symlinks\n" -" If False, and the last element of the path is a symbolic link,\n" -" stat will examine the symbolic link itself instead of the file\n" -" the link points to.\n" -"\n" -"dir_fd and follow_symlinks may not be implemented\n" -" on your platform. If they are unavailable, using them will raise a\n" -" NotImplementedError.\n" -"\n" -"It\'s an error to use dir_fd or follow_symlinks when specifying path as\n" -" an open file descriptor."); - -#define OS_STAT_METHODDEF \ - {"stat", _PyCFunction_CAST(os_stat), METH_FASTCALL|METH_KEYWORDS, os_stat__doc__}, - -static PyObject * -os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks); - -static PyObject * -os_stat(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(dir_fd), &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "dir_fd", "follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "stat", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("stat", "path", 0, 1); - int dir_fd = DEFAULT_DIR_FD; - int follow_symlinks = 1; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (args[1]) { - if (!FSTATAT_DIR_FD_CONVERTER(args[1], &dir_fd)) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - follow_symlinks = PyObject_IsTrue(args[2]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - return_value = os_stat_impl(module, &path, dir_fd, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -PyDoc_STRVAR(os_lstat__doc__, -"lstat($module, /, path, *, dir_fd=None)\n" -"--\n" -"\n" -"Perform a stat system call on the given path, without following symbolic links.\n" -"\n" -"Like stat(), but do not follow symbolic links.\n" -"Equivalent to stat(path, follow_symlinks=False)."); - -#define OS_LSTAT_METHODDEF \ - {"lstat", _PyCFunction_CAST(os_lstat), METH_FASTCALL|METH_KEYWORDS, os_lstat__doc__}, - -static PyObject * -os_lstat_impl(PyObject *module, path_t *path, int dir_fd); - -static PyObject * -os_lstat(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(dir_fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "dir_fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "lstat", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("lstat", "path", 0, 0); - int dir_fd = DEFAULT_DIR_FD; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (!FSTATAT_DIR_FD_CONVERTER(args[1], &dir_fd)) { - goto exit; - } -skip_optional_kwonly: - return_value = os_lstat_impl(module, &path, dir_fd); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -PyDoc_STRVAR(os_access__doc__, -"access($module, /, path, mode, *, dir_fd=None, effective_ids=False,\n" -" follow_symlinks=True)\n" -"--\n" -"\n" -"Use the real uid/gid to test for access to a path.\n" -"\n" -" path\n" -" Path to be tested; can be string, bytes, or a path-like object.\n" -" mode\n" -" Operating-system mode bitfield. Can be F_OK to test existence,\n" -" or the inclusive-OR of R_OK, W_OK, and X_OK.\n" -" dir_fd\n" -" If not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that\n" -" directory.\n" -" effective_ids\n" -" If True, access will use the effective uid/gid instead of\n" -" the real uid/gid.\n" -" follow_symlinks\n" -" If False, and the last element of the path is a symbolic link,\n" -" access will examine the symbolic link itself instead of the file\n" -" the link points to.\n" -"\n" -"dir_fd, effective_ids, and follow_symlinks may not be implemented\n" -" on your platform. If they are unavailable, using them will raise a\n" -" NotImplementedError.\n" -"\n" -"Note that most operations will use the effective uid/gid, therefore this\n" -" routine can be used in a suid/sgid environment to test if the invoking user\n" -" has the specified access to the path."); - -#define OS_ACCESS_METHODDEF \ - {"access", _PyCFunction_CAST(os_access), METH_FASTCALL|METH_KEYWORDS, os_access__doc__}, - -static int -os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd, - int effective_ids, int follow_symlinks); - -static PyObject * -os_access(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 5 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(mode), &_Py_ID(dir_fd), &_Py_ID(effective_ids), &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "mode", "dir_fd", "effective_ids", "follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "access", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[5]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("access", "path", 0, 0); - int mode; - int dir_fd = DEFAULT_DIR_FD; - int effective_ids = 0; - int follow_symlinks = 1; - int _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - mode = _PyLong_AsInt(args[1]); - if (mode == -1 && PyErr_Occurred()) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (args[2]) { - if (!FACCESSAT_DIR_FD_CONVERTER(args[2], &dir_fd)) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[3]) { - effective_ids = PyObject_IsTrue(args[3]); - if (effective_ids < 0) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - follow_symlinks = PyObject_IsTrue(args[4]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - _return_value = os_access_impl(module, &path, mode, dir_fd, effective_ids, follow_symlinks); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#if defined(HAVE_TTYNAME) - -PyDoc_STRVAR(os_ttyname__doc__, -"ttyname($module, fd, /)\n" -"--\n" -"\n" -"Return the name of the terminal device connected to \'fd\'.\n" -"\n" -" fd\n" -" Integer file descriptor handle."); - -#define OS_TTYNAME_METHODDEF \ - {"ttyname", (PyCFunction)os_ttyname, METH_O, os_ttyname__doc__}, - -static PyObject * -os_ttyname_impl(PyObject *module, int fd); - -static PyObject * -os_ttyname(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int fd; - - fd = _PyLong_AsInt(arg); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_ttyname_impl(module, fd); - -exit: - return return_value; -} - -#endif /* defined(HAVE_TTYNAME) */ - -#if defined(HAVE_CTERMID) - -PyDoc_STRVAR(os_ctermid__doc__, -"ctermid($module, /)\n" -"--\n" -"\n" -"Return the name of the controlling terminal for this process."); - -#define OS_CTERMID_METHODDEF \ - {"ctermid", (PyCFunction)os_ctermid, METH_NOARGS, os_ctermid__doc__}, - -static PyObject * -os_ctermid_impl(PyObject *module); - -static PyObject * -os_ctermid(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_ctermid_impl(module); -} - -#endif /* defined(HAVE_CTERMID) */ - -PyDoc_STRVAR(os_chdir__doc__, -"chdir($module, /, path)\n" -"--\n" -"\n" -"Change the current working directory to the specified path.\n" -"\n" -"path may always be specified as a string.\n" -"On some platforms, path may also be specified as an open file descriptor.\n" -" If this functionality is unavailable, using it raises an exception."); - -#define OS_CHDIR_METHODDEF \ - {"chdir", _PyCFunction_CAST(os_chdir), METH_FASTCALL|METH_KEYWORDS, os_chdir__doc__}, - -static PyObject * -os_chdir_impl(PyObject *module, path_t *path); - -static PyObject * -os_chdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "chdir", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("chdir", "path", 0, PATH_HAVE_FCHDIR); - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - return_value = os_chdir_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#if defined(HAVE_FCHDIR) - -PyDoc_STRVAR(os_fchdir__doc__, -"fchdir($module, /, fd)\n" -"--\n" -"\n" -"Change to the directory of the given file descriptor.\n" -"\n" -"fd must be opened on a directory, not a file.\n" -"Equivalent to os.chdir(fd)."); - -#define OS_FCHDIR_METHODDEF \ - {"fchdir", _PyCFunction_CAST(os_fchdir), METH_FASTCALL|METH_KEYWORDS, os_fchdir__doc__}, - -static PyObject * -os_fchdir_impl(PyObject *module, int fd); - -static PyObject * -os_fchdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "fchdir", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int fd; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { - goto exit; - } - return_value = os_fchdir_impl(module, fd); - -exit: - return return_value; -} - -#endif /* defined(HAVE_FCHDIR) */ - -PyDoc_STRVAR(os_chmod__doc__, -"chmod($module, /, path, mode, *, dir_fd=None, follow_symlinks=True)\n" -"--\n" -"\n" -"Change the access permissions of a file.\n" -"\n" -" path\n" -" Path to be modified. May always be specified as a str, bytes, or a path-like object.\n" -" On some platforms, path may also be specified as an open file descriptor.\n" -" If this functionality is unavailable, using it raises an exception.\n" -" mode\n" -" Operating-system mode bitfield.\n" -" dir_fd\n" -" If not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that\n" -" directory.\n" -" follow_symlinks\n" -" If False, and the last element of the path is a symbolic link,\n" -" chmod will modify the symbolic link itself instead of the file\n" -" the link points to.\n" -"\n" -"It is an error to use dir_fd or follow_symlinks when specifying path as\n" -" an open file descriptor.\n" -"dir_fd and follow_symlinks may not be implemented on your platform.\n" -" If they are unavailable, using them will raise a NotImplementedError."); - -#define OS_CHMOD_METHODDEF \ - {"chmod", _PyCFunction_CAST(os_chmod), METH_FASTCALL|METH_KEYWORDS, os_chmod__doc__}, - -static PyObject * -os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, - int follow_symlinks); - -static PyObject * -os_chmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 4 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(mode), &_Py_ID(dir_fd), &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "mode", "dir_fd", "follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "chmod", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[4]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("chmod", "path", 0, PATH_HAVE_FCHMOD); - int mode; - int dir_fd = DEFAULT_DIR_FD; - int follow_symlinks = 1; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - mode = _PyLong_AsInt(args[1]); - if (mode == -1 && PyErr_Occurred()) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (args[2]) { - if (!FCHMODAT_DIR_FD_CONVERTER(args[2], &dir_fd)) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - follow_symlinks = PyObject_IsTrue(args[3]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - return_value = os_chmod_impl(module, &path, mode, dir_fd, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#if defined(HAVE_FCHMOD) - -PyDoc_STRVAR(os_fchmod__doc__, -"fchmod($module, /, fd, mode)\n" -"--\n" -"\n" -"Change the access permissions of the file given by file descriptor fd.\n" -"\n" -"Equivalent to os.chmod(fd, mode)."); - -#define OS_FCHMOD_METHODDEF \ - {"fchmod", _PyCFunction_CAST(os_fchmod), METH_FASTCALL|METH_KEYWORDS, os_fchmod__doc__}, - -static PyObject * -os_fchmod_impl(PyObject *module, int fd, int mode); - -static PyObject * -os_fchmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(fd), &_Py_ID(mode), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"fd", "mode", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "fchmod", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - int fd; - int mode; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - mode = _PyLong_AsInt(args[1]); - if (mode == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_fchmod_impl(module, fd, mode); - -exit: - return return_value; -} - -#endif /* defined(HAVE_FCHMOD) */ - -#if defined(HAVE_LCHMOD) - -PyDoc_STRVAR(os_lchmod__doc__, -"lchmod($module, /, path, mode)\n" -"--\n" -"\n" -"Change the access permissions of a file, without following symbolic links.\n" -"\n" -"If path is a symlink, this affects the link itself rather than the target.\n" -"Equivalent to chmod(path, mode, follow_symlinks=False).\""); - -#define OS_LCHMOD_METHODDEF \ - {"lchmod", _PyCFunction_CAST(os_lchmod), METH_FASTCALL|METH_KEYWORDS, os_lchmod__doc__}, - -static PyObject * -os_lchmod_impl(PyObject *module, path_t *path, int mode); - -static PyObject * -os_lchmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(mode), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "mode", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "lchmod", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - path_t path = PATH_T_INITIALIZE("lchmod", "path", 0, 0); - int mode; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - mode = _PyLong_AsInt(args[1]); - if (mode == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_lchmod_impl(module, &path, mode); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(HAVE_LCHMOD) */ - -#if defined(HAVE_CHFLAGS) - -PyDoc_STRVAR(os_chflags__doc__, -"chflags($module, /, path, flags, follow_symlinks=True)\n" -"--\n" -"\n" -"Set file flags.\n" -"\n" -"If follow_symlinks is False, and the last element of the path is a symbolic\n" -" link, chflags will change flags on the symbolic link itself instead of the\n" -" file the link points to.\n" -"follow_symlinks may not be implemented on your platform. If it is\n" -"unavailable, using it will raise a NotImplementedError."); - -#define OS_CHFLAGS_METHODDEF \ - {"chflags", _PyCFunction_CAST(os_chflags), METH_FASTCALL|METH_KEYWORDS, os_chflags__doc__}, - -static PyObject * -os_chflags_impl(PyObject *module, path_t *path, unsigned long flags, - int follow_symlinks); - -static PyObject * -os_chflags(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(flags), &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "flags", "follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "chflags", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("chflags", "path", 0, 0); - unsigned long flags; - int follow_symlinks = 1; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!PyLong_Check(args[1])) { - _PyArg_BadArgument("chflags", "argument 'flags'", "int", args[1]); - goto exit; - } - flags = PyLong_AsUnsignedLongMask(args[1]); - if (!noptargs) { - goto skip_optional_pos; - } - follow_symlinks = PyObject_IsTrue(args[2]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_pos: - return_value = os_chflags_impl(module, &path, flags, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(HAVE_CHFLAGS) */ - -#if defined(HAVE_LCHFLAGS) - -PyDoc_STRVAR(os_lchflags__doc__, -"lchflags($module, /, path, flags)\n" -"--\n" -"\n" -"Set file flags.\n" -"\n" -"This function will not follow symbolic links.\n" -"Equivalent to chflags(path, flags, follow_symlinks=False)."); - -#define OS_LCHFLAGS_METHODDEF \ - {"lchflags", _PyCFunction_CAST(os_lchflags), METH_FASTCALL|METH_KEYWORDS, os_lchflags__doc__}, - -static PyObject * -os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags); - -static PyObject * -os_lchflags(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(flags), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "flags", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "lchflags", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - path_t path = PATH_T_INITIALIZE("lchflags", "path", 0, 0); - unsigned long flags; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!PyLong_Check(args[1])) { - _PyArg_BadArgument("lchflags", "argument 'flags'", "int", args[1]); - goto exit; - } - flags = PyLong_AsUnsignedLongMask(args[1]); - return_value = os_lchflags_impl(module, &path, flags); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(HAVE_LCHFLAGS) */ - -#if defined(HAVE_CHROOT) - -PyDoc_STRVAR(os_chroot__doc__, -"chroot($module, /, path)\n" -"--\n" -"\n" -"Change root directory to path."); - -#define OS_CHROOT_METHODDEF \ - {"chroot", _PyCFunction_CAST(os_chroot), METH_FASTCALL|METH_KEYWORDS, os_chroot__doc__}, - -static PyObject * -os_chroot_impl(PyObject *module, path_t *path); - -static PyObject * -os_chroot(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "chroot", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("chroot", "path", 0, 0); - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - return_value = os_chroot_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(HAVE_CHROOT) */ - -#if defined(HAVE_FSYNC) - -PyDoc_STRVAR(os_fsync__doc__, -"fsync($module, /, fd)\n" -"--\n" -"\n" -"Force write of fd to disk."); - -#define OS_FSYNC_METHODDEF \ - {"fsync", _PyCFunction_CAST(os_fsync), METH_FASTCALL|METH_KEYWORDS, os_fsync__doc__}, - -static PyObject * -os_fsync_impl(PyObject *module, int fd); - -static PyObject * -os_fsync(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "fsync", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int fd; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { - goto exit; - } - return_value = os_fsync_impl(module, fd); - -exit: - return return_value; -} - -#endif /* defined(HAVE_FSYNC) */ - -#if defined(HAVE_SYNC) - -PyDoc_STRVAR(os_sync__doc__, -"sync($module, /)\n" -"--\n" -"\n" -"Force write of everything to disk."); - -#define OS_SYNC_METHODDEF \ - {"sync", (PyCFunction)os_sync, METH_NOARGS, os_sync__doc__}, - -static PyObject * -os_sync_impl(PyObject *module); - -static PyObject * -os_sync(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_sync_impl(module); -} - -#endif /* defined(HAVE_SYNC) */ - -#if defined(HAVE_FDATASYNC) - -PyDoc_STRVAR(os_fdatasync__doc__, -"fdatasync($module, /, fd)\n" -"--\n" -"\n" -"Force write of fd to disk without forcing update of metadata."); - -#define OS_FDATASYNC_METHODDEF \ - {"fdatasync", _PyCFunction_CAST(os_fdatasync), METH_FASTCALL|METH_KEYWORDS, os_fdatasync__doc__}, - -static PyObject * -os_fdatasync_impl(PyObject *module, int fd); - -static PyObject * -os_fdatasync(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "fdatasync", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int fd; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { - goto exit; - } - return_value = os_fdatasync_impl(module, fd); - -exit: - return return_value; -} - -#endif /* defined(HAVE_FDATASYNC) */ - -#if defined(HAVE_CHOWN) - -PyDoc_STRVAR(os_chown__doc__, -"chown($module, /, path, uid, gid, *, dir_fd=None, follow_symlinks=True)\n" -"--\n" -"\n" -"Change the owner and group id of path to the numeric uid and gid.\\\n" -"\n" -" path\n" -" Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.\n" -" dir_fd\n" -" If not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that\n" -" directory.\n" -" follow_symlinks\n" -" If False, and the last element of the path is a symbolic link,\n" -" stat will examine the symbolic link itself instead of the file\n" -" the link points to.\n" -"\n" -"path may always be specified as a string.\n" -"On some platforms, path may also be specified as an open file descriptor.\n" -" If this functionality is unavailable, using it raises an exception.\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"If follow_symlinks is False, and the last element of the path is a symbolic\n" -" link, chown will modify the symbolic link itself instead of the file the\n" -" link points to.\n" -"It is an error to use dir_fd or follow_symlinks when specifying path as\n" -" an open file descriptor.\n" -"dir_fd and follow_symlinks may not be implemented on your platform.\n" -" If they are unavailable, using them will raise a NotImplementedError."); - -#define OS_CHOWN_METHODDEF \ - {"chown", _PyCFunction_CAST(os_chown), METH_FASTCALL|METH_KEYWORDS, os_chown__doc__}, - -static PyObject * -os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid, - int dir_fd, int follow_symlinks); - -static PyObject * -os_chown(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 5 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(uid), &_Py_ID(gid), &_Py_ID(dir_fd), &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "uid", "gid", "dir_fd", "follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "chown", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[5]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - path_t path = PATH_T_INITIALIZE("chown", "path", 0, PATH_HAVE_FCHOWN); - uid_t uid; - gid_t gid; - int dir_fd = DEFAULT_DIR_FD; - int follow_symlinks = 1; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!_Py_Uid_Converter(args[1], &uid)) { - goto exit; - } - if (!_Py_Gid_Converter(args[2], &gid)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (args[3]) { - if (!FCHOWNAT_DIR_FD_CONVERTER(args[3], &dir_fd)) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - follow_symlinks = PyObject_IsTrue(args[4]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - return_value = os_chown_impl(module, &path, uid, gid, dir_fd, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(HAVE_CHOWN) */ - -#if defined(HAVE_FCHOWN) - -PyDoc_STRVAR(os_fchown__doc__, -"fchown($module, /, fd, uid, gid)\n" -"--\n" -"\n" -"Change the owner and group id of the file specified by file descriptor.\n" -"\n" -"Equivalent to os.chown(fd, uid, gid)."); - -#define OS_FCHOWN_METHODDEF \ - {"fchown", _PyCFunction_CAST(os_fchown), METH_FASTCALL|METH_KEYWORDS, os_fchown__doc__}, - -static PyObject * -os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid); - -static PyObject * -os_fchown(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(fd), &_Py_ID(uid), &_Py_ID(gid), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"fd", "uid", "gid", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "fchown", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - int fd; - uid_t uid; - gid_t gid; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); - if (!args) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - if (!_Py_Uid_Converter(args[1], &uid)) { - goto exit; - } - if (!_Py_Gid_Converter(args[2], &gid)) { - goto exit; - } - return_value = os_fchown_impl(module, fd, uid, gid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_FCHOWN) */ - -#if defined(HAVE_LCHOWN) - -PyDoc_STRVAR(os_lchown__doc__, -"lchown($module, /, path, uid, gid)\n" -"--\n" -"\n" -"Change the owner and group id of path to the numeric uid and gid.\n" -"\n" -"This function will not follow symbolic links.\n" -"Equivalent to os.chown(path, uid, gid, follow_symlinks=False)."); - -#define OS_LCHOWN_METHODDEF \ - {"lchown", _PyCFunction_CAST(os_lchown), METH_FASTCALL|METH_KEYWORDS, os_lchown__doc__}, - -static PyObject * -os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid); - -static PyObject * -os_lchown(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(uid), &_Py_ID(gid), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "uid", "gid", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "lchown", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - path_t path = PATH_T_INITIALIZE("lchown", "path", 0, 0); - uid_t uid; - gid_t gid; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!_Py_Uid_Converter(args[1], &uid)) { - goto exit; - } - if (!_Py_Gid_Converter(args[2], &gid)) { - goto exit; - } - return_value = os_lchown_impl(module, &path, uid, gid); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(HAVE_LCHOWN) */ - -PyDoc_STRVAR(os_getcwd__doc__, -"getcwd($module, /)\n" -"--\n" -"\n" -"Return a unicode string representing the current working directory."); - -#define OS_GETCWD_METHODDEF \ - {"getcwd", (PyCFunction)os_getcwd, METH_NOARGS, os_getcwd__doc__}, - -static PyObject * -os_getcwd_impl(PyObject *module); - -static PyObject * -os_getcwd(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getcwd_impl(module); -} - -PyDoc_STRVAR(os_getcwdb__doc__, -"getcwdb($module, /)\n" -"--\n" -"\n" -"Return a bytes string representing the current working directory."); - -#define OS_GETCWDB_METHODDEF \ - {"getcwdb", (PyCFunction)os_getcwdb, METH_NOARGS, os_getcwdb__doc__}, - -static PyObject * -os_getcwdb_impl(PyObject *module); - -static PyObject * -os_getcwdb(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getcwdb_impl(module); -} - -#if defined(HAVE_LINK) - -PyDoc_STRVAR(os_link__doc__, -"link($module, /, src, dst, *, src_dir_fd=None, dst_dir_fd=None,\n" -" follow_symlinks=True)\n" -"--\n" -"\n" -"Create a hard link to a file.\n" -"\n" -"If either src_dir_fd or dst_dir_fd is not None, it should be a file\n" -" descriptor open to a directory, and the respective path string (src or dst)\n" -" should be relative; the path will then be relative to that directory.\n" -"If follow_symlinks is False, and the last element of src is a symbolic\n" -" link, link will create a link to the symbolic link itself instead of the\n" -" file the link points to.\n" -"src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your\n" -" platform. If they are unavailable, using them will raise a\n" -" NotImplementedError."); - -#define OS_LINK_METHODDEF \ - {"link", _PyCFunction_CAST(os_link), METH_FASTCALL|METH_KEYWORDS, os_link__doc__}, - -static PyObject * -os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, - int dst_dir_fd, int follow_symlinks); - -static PyObject * -os_link(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 5 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(src), &_Py_ID(dst), &_Py_ID(src_dir_fd), &_Py_ID(dst_dir_fd), &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", "follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "link", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[5]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t src = PATH_T_INITIALIZE("link", "src", 0, 0); - path_t dst = PATH_T_INITIALIZE("link", "dst", 0, 0); - int src_dir_fd = DEFAULT_DIR_FD; - int dst_dir_fd = DEFAULT_DIR_FD; - int follow_symlinks = 1; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &src)) { - goto exit; - } - if (!path_converter(args[1], &dst)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (args[2]) { - if (!dir_fd_converter(args[2], &src_dir_fd)) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[3]) { - if (!dir_fd_converter(args[3], &dst_dir_fd)) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - follow_symlinks = PyObject_IsTrue(args[4]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - return_value = os_link_impl(module, &src, &dst, src_dir_fd, dst_dir_fd, follow_symlinks); - -exit: - /* Cleanup for src */ - path_cleanup(&src); - /* Cleanup for dst */ - path_cleanup(&dst); - - return return_value; -} - -#endif /* defined(HAVE_LINK) */ - -PyDoc_STRVAR(os_listdir__doc__, -"listdir($module, /, path=None)\n" -"--\n" -"\n" -"Return a list containing the names of the files in the directory.\n" -"\n" -"path can be specified as either str, bytes, or a path-like object. If path is bytes,\n" -" the filenames returned will also be bytes; in all other circumstances\n" -" the filenames returned will be str.\n" -"If path is None, uses the path=\'.\'.\n" -"On some platforms, path may also be specified as an open file descriptor;\\\n" -" the file descriptor must refer to a directory.\n" -" If this functionality is unavailable, using it raises NotImplementedError.\n" -"\n" -"The list is in arbitrary order. It does not include the special\n" -"entries \'.\' and \'..\' even if they are present in the directory."); - -#define OS_LISTDIR_METHODDEF \ - {"listdir", _PyCFunction_CAST(os_listdir), METH_FASTCALL|METH_KEYWORDS, os_listdir__doc__}, - -static PyObject * -os_listdir_impl(PyObject *module, path_t *path); - -static PyObject * -os_listdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "listdir", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - path_t path = PATH_T_INITIALIZE("listdir", "path", 1, PATH_HAVE_FDOPENDIR); - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (!path_converter(args[0], &path)) { - goto exit; - } -skip_optional_pos: - return_value = os_listdir_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#if defined(MS_WINDOWS) - -PyDoc_STRVAR(os__getfullpathname__doc__, -"_getfullpathname($module, path, /)\n" -"--\n" -"\n"); - -#define OS__GETFULLPATHNAME_METHODDEF \ - {"_getfullpathname", (PyCFunction)os__getfullpathname, METH_O, os__getfullpathname__doc__}, - -static PyObject * -os__getfullpathname_impl(PyObject *module, path_t *path); - -static PyObject * -os__getfullpathname(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - path_t path = PATH_T_INITIALIZE("_getfullpathname", "path", 0, 0); - - if (!path_converter(arg, &path)) { - goto exit; - } - return_value = os__getfullpathname_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(MS_WINDOWS) */ - -#if defined(MS_WINDOWS) - -PyDoc_STRVAR(os__getfinalpathname__doc__, -"_getfinalpathname($module, path, /)\n" -"--\n" -"\n" -"A helper function for samepath on windows."); - -#define OS__GETFINALPATHNAME_METHODDEF \ - {"_getfinalpathname", (PyCFunction)os__getfinalpathname, METH_O, os__getfinalpathname__doc__}, - -static PyObject * -os__getfinalpathname_impl(PyObject *module, path_t *path); - -static PyObject * -os__getfinalpathname(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - path_t path = PATH_T_INITIALIZE("_getfinalpathname", "path", 0, 0); - - if (!path_converter(arg, &path)) { - goto exit; - } - return_value = os__getfinalpathname_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(MS_WINDOWS) */ - -#if defined(MS_WINDOWS) - -PyDoc_STRVAR(os__getvolumepathname__doc__, -"_getvolumepathname($module, /, path)\n" -"--\n" -"\n" -"A helper function for ismount on Win32."); - -#define OS__GETVOLUMEPATHNAME_METHODDEF \ - {"_getvolumepathname", _PyCFunction_CAST(os__getvolumepathname), METH_FASTCALL|METH_KEYWORDS, os__getvolumepathname__doc__}, - -static PyObject * -os__getvolumepathname_impl(PyObject *module, path_t *path); - -static PyObject * -os__getvolumepathname(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "_getvolumepathname", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_getvolumepathname", "path", 0, 0); - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - return_value = os__getvolumepathname_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(MS_WINDOWS) */ - -#if defined(MS_WINDOWS) - -PyDoc_STRVAR(os__path_splitroot__doc__, -"_path_splitroot($module, /, path)\n" -"--\n" -"\n" -"Removes everything after the root on Win32."); - -#define OS__PATH_SPLITROOT_METHODDEF \ - {"_path_splitroot", _PyCFunction_CAST(os__path_splitroot), METH_FASTCALL|METH_KEYWORDS, os__path_splitroot__doc__}, - -static PyObject * -os__path_splitroot_impl(PyObject *module, path_t *path); - -static PyObject * -os__path_splitroot(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "_path_splitroot", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_path_splitroot", "path", 0, 0); - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - return_value = os__path_splitroot_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(MS_WINDOWS) */ - -PyDoc_STRVAR(os__path_normpath__doc__, -"_path_normpath($module, /, path)\n" -"--\n" -"\n" -"Basic path normalization."); - -#define OS__PATH_NORMPATH_METHODDEF \ - {"_path_normpath", _PyCFunction_CAST(os__path_normpath), METH_FASTCALL|METH_KEYWORDS, os__path_normpath__doc__}, - -static PyObject * -os__path_normpath_impl(PyObject *module, PyObject *path); - -static PyObject * -os__path_normpath(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "_path_normpath", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - PyObject *path; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - path = args[0]; - return_value = os__path_normpath_impl(module, path); - -exit: - return return_value; -} - -PyDoc_STRVAR(os_mkdir__doc__, -"mkdir($module, /, path, mode=511, *, dir_fd=None)\n" -"--\n" -"\n" -"Create a directory.\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"dir_fd may not be implemented on your platform.\n" -" If it is unavailable, using it will raise a NotImplementedError.\n" -"\n" -"The mode argument is ignored on Windows. Where it is used, the current umask\n" -"value is first masked out."); - -#define OS_MKDIR_METHODDEF \ - {"mkdir", _PyCFunction_CAST(os_mkdir), METH_FASTCALL|METH_KEYWORDS, os_mkdir__doc__}, - -static PyObject * -os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd); - -static PyObject * -os_mkdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(mode), &_Py_ID(dir_fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "mode", "dir_fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "mkdir", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("mkdir", "path", 0, 0); - int mode = 511; - int dir_fd = DEFAULT_DIR_FD; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[1]) { - mode = _PyLong_AsInt(args[1]); - if (mode == -1 && PyErr_Occurred()) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } -skip_optional_pos: - if (!noptargs) { - goto skip_optional_kwonly; - } - if (!MKDIRAT_DIR_FD_CONVERTER(args[2], &dir_fd)) { - goto exit; - } -skip_optional_kwonly: - return_value = os_mkdir_impl(module, &path, mode, dir_fd); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#if defined(HAVE_NICE) - -PyDoc_STRVAR(os_nice__doc__, -"nice($module, increment, /)\n" -"--\n" -"\n" -"Add increment to the priority of process and return the new priority."); - -#define OS_NICE_METHODDEF \ - {"nice", (PyCFunction)os_nice, METH_O, os_nice__doc__}, - -static PyObject * -os_nice_impl(PyObject *module, int increment); - -static PyObject * -os_nice(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int increment; - - increment = _PyLong_AsInt(arg); - if (increment == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_nice_impl(module, increment); - -exit: - return return_value; -} - -#endif /* defined(HAVE_NICE) */ - -#if defined(HAVE_GETPRIORITY) - -PyDoc_STRVAR(os_getpriority__doc__, -"getpriority($module, /, which, who)\n" -"--\n" -"\n" -"Return program scheduling priority."); - -#define OS_GETPRIORITY_METHODDEF \ - {"getpriority", _PyCFunction_CAST(os_getpriority), METH_FASTCALL|METH_KEYWORDS, os_getpriority__doc__}, - -static PyObject * -os_getpriority_impl(PyObject *module, int which, int who); - -static PyObject * -os_getpriority(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(which), &_Py_ID(who), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"which", "who", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "getpriority", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - int which; - int who; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - which = _PyLong_AsInt(args[0]); - if (which == -1 && PyErr_Occurred()) { - goto exit; - } - who = _PyLong_AsInt(args[1]); - if (who == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_getpriority_impl(module, which, who); - -exit: - return return_value; -} - -#endif /* defined(HAVE_GETPRIORITY) */ - -#if defined(HAVE_SETPRIORITY) - -PyDoc_STRVAR(os_setpriority__doc__, -"setpriority($module, /, which, who, priority)\n" -"--\n" -"\n" -"Set program scheduling priority."); - -#define OS_SETPRIORITY_METHODDEF \ - {"setpriority", _PyCFunction_CAST(os_setpriority), METH_FASTCALL|METH_KEYWORDS, os_setpriority__doc__}, - -static PyObject * -os_setpriority_impl(PyObject *module, int which, int who, int priority); - -static PyObject * -os_setpriority(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(which), &_Py_ID(who), &_Py_ID(priority), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"which", "who", "priority", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "setpriority", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - int which; - int who; - int priority; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); - if (!args) { - goto exit; - } - which = _PyLong_AsInt(args[0]); - if (which == -1 && PyErr_Occurred()) { - goto exit; - } - who = _PyLong_AsInt(args[1]); - if (who == -1 && PyErr_Occurred()) { - goto exit; - } - priority = _PyLong_AsInt(args[2]); - if (priority == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_setpriority_impl(module, which, who, priority); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SETPRIORITY) */ - -PyDoc_STRVAR(os_rename__doc__, -"rename($module, /, src, dst, *, src_dir_fd=None, dst_dir_fd=None)\n" -"--\n" -"\n" -"Rename a file or directory.\n" -"\n" -"If either src_dir_fd or dst_dir_fd is not None, it should be a file\n" -" descriptor open to a directory, and the respective path string (src or dst)\n" -" should be relative; the path will then be relative to that directory.\n" -"src_dir_fd and dst_dir_fd, may not be implemented on your platform.\n" -" If they are unavailable, using them will raise a NotImplementedError."); - -#define OS_RENAME_METHODDEF \ - {"rename", _PyCFunction_CAST(os_rename), METH_FASTCALL|METH_KEYWORDS, os_rename__doc__}, - -static PyObject * -os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, - int dst_dir_fd); - -static PyObject * -os_rename(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 4 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(src), &_Py_ID(dst), &_Py_ID(src_dir_fd), &_Py_ID(dst_dir_fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "rename", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[4]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t src = PATH_T_INITIALIZE("rename", "src", 0, 0); - path_t dst = PATH_T_INITIALIZE("rename", "dst", 0, 0); - int src_dir_fd = DEFAULT_DIR_FD; - int dst_dir_fd = DEFAULT_DIR_FD; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &src)) { - goto exit; - } - if (!path_converter(args[1], &dst)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (args[2]) { - if (!dir_fd_converter(args[2], &src_dir_fd)) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (!dir_fd_converter(args[3], &dst_dir_fd)) { - goto exit; - } -skip_optional_kwonly: - return_value = os_rename_impl(module, &src, &dst, src_dir_fd, dst_dir_fd); - -exit: - /* Cleanup for src */ - path_cleanup(&src); - /* Cleanup for dst */ - path_cleanup(&dst); - - return return_value; -} - -PyDoc_STRVAR(os_replace__doc__, -"replace($module, /, src, dst, *, src_dir_fd=None, dst_dir_fd=None)\n" -"--\n" -"\n" -"Rename a file or directory, overwriting the destination.\n" -"\n" -"If either src_dir_fd or dst_dir_fd is not None, it should be a file\n" -" descriptor open to a directory, and the respective path string (src or dst)\n" -" should be relative; the path will then be relative to that directory.\n" -"src_dir_fd and dst_dir_fd, may not be implemented on your platform.\n" -" If they are unavailable, using them will raise a NotImplementedError."); - -#define OS_REPLACE_METHODDEF \ - {"replace", _PyCFunction_CAST(os_replace), METH_FASTCALL|METH_KEYWORDS, os_replace__doc__}, - -static PyObject * -os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, - int dst_dir_fd); - -static PyObject * -os_replace(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 4 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(src), &_Py_ID(dst), &_Py_ID(src_dir_fd), &_Py_ID(dst_dir_fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "replace", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[4]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t src = PATH_T_INITIALIZE("replace", "src", 0, 0); - path_t dst = PATH_T_INITIALIZE("replace", "dst", 0, 0); - int src_dir_fd = DEFAULT_DIR_FD; - int dst_dir_fd = DEFAULT_DIR_FD; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &src)) { - goto exit; - } - if (!path_converter(args[1], &dst)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (args[2]) { - if (!dir_fd_converter(args[2], &src_dir_fd)) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (!dir_fd_converter(args[3], &dst_dir_fd)) { - goto exit; - } -skip_optional_kwonly: - return_value = os_replace_impl(module, &src, &dst, src_dir_fd, dst_dir_fd); - -exit: - /* Cleanup for src */ - path_cleanup(&src); - /* Cleanup for dst */ - path_cleanup(&dst); - - return return_value; -} - -PyDoc_STRVAR(os_rmdir__doc__, -"rmdir($module, /, path, *, dir_fd=None)\n" -"--\n" -"\n" -"Remove a directory.\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"dir_fd may not be implemented on your platform.\n" -" If it is unavailable, using it will raise a NotImplementedError."); - -#define OS_RMDIR_METHODDEF \ - {"rmdir", _PyCFunction_CAST(os_rmdir), METH_FASTCALL|METH_KEYWORDS, os_rmdir__doc__}, - -static PyObject * -os_rmdir_impl(PyObject *module, path_t *path, int dir_fd); - -static PyObject * -os_rmdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(dir_fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "dir_fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "rmdir", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("rmdir", "path", 0, 0); - int dir_fd = DEFAULT_DIR_FD; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (!UNLINKAT_DIR_FD_CONVERTER(args[1], &dir_fd)) { - goto exit; - } -skip_optional_kwonly: - return_value = os_rmdir_impl(module, &path, dir_fd); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#if defined(HAVE_SYSTEM) && defined(MS_WINDOWS) - -PyDoc_STRVAR(os_system__doc__, -"system($module, /, command)\n" -"--\n" -"\n" -"Execute the command in a subshell."); - -#define OS_SYSTEM_METHODDEF \ - {"system", _PyCFunction_CAST(os_system), METH_FASTCALL|METH_KEYWORDS, os_system__doc__}, - -static long -os_system_impl(PyObject *module, const Py_UNICODE *command); - -static PyObject * -os_system(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(command), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"command", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "system", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - const Py_UNICODE *command = NULL; - long _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("system", "argument 'command'", "str", args[0]); - goto exit; - } - command = PyUnicode_AsWideCharString(args[0], NULL); - if (command == NULL) { - goto exit; - } - _return_value = os_system_impl(module, command); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromLong(_return_value); - -exit: - /* Cleanup for command */ - PyMem_Free((void *)command); - - return return_value; -} - -#endif /* defined(HAVE_SYSTEM) && defined(MS_WINDOWS) */ - -#if defined(HAVE_SYSTEM) && !defined(MS_WINDOWS) - -PyDoc_STRVAR(os_system__doc__, -"system($module, /, command)\n" -"--\n" -"\n" -"Execute the command in a subshell."); - -#define OS_SYSTEM_METHODDEF \ - {"system", _PyCFunction_CAST(os_system), METH_FASTCALL|METH_KEYWORDS, os_system__doc__}, - -static long -os_system_impl(PyObject *module, PyObject *command); - -static PyObject * -os_system(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(command), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"command", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "system", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - PyObject *command = NULL; - long _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!PyUnicode_FSConverter(args[0], &command)) { - goto exit; - } - _return_value = os_system_impl(module, command); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromLong(_return_value); - -exit: - /* Cleanup for command */ - Py_XDECREF(command); - - return return_value; -} - -#endif /* defined(HAVE_SYSTEM) && !defined(MS_WINDOWS) */ - -#if defined(HAVE_UMASK) - -PyDoc_STRVAR(os_umask__doc__, -"umask($module, mask, /)\n" -"--\n" -"\n" -"Set the current numeric umask and return the previous umask."); - -#define OS_UMASK_METHODDEF \ - {"umask", (PyCFunction)os_umask, METH_O, os_umask__doc__}, - -static PyObject * -os_umask_impl(PyObject *module, int mask); - -static PyObject * -os_umask(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int mask; - - mask = _PyLong_AsInt(arg); - if (mask == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_umask_impl(module, mask); - -exit: - return return_value; -} - -#endif /* defined(HAVE_UMASK) */ - -PyDoc_STRVAR(os_unlink__doc__, -"unlink($module, /, path, *, dir_fd=None)\n" -"--\n" -"\n" -"Remove a file (same as remove()).\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"dir_fd may not be implemented on your platform.\n" -" If it is unavailable, using it will raise a NotImplementedError."); - -#define OS_UNLINK_METHODDEF \ - {"unlink", _PyCFunction_CAST(os_unlink), METH_FASTCALL|METH_KEYWORDS, os_unlink__doc__}, - -static PyObject * -os_unlink_impl(PyObject *module, path_t *path, int dir_fd); - -static PyObject * -os_unlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(dir_fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "dir_fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "unlink", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("unlink", "path", 0, 0); - int dir_fd = DEFAULT_DIR_FD; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (!UNLINKAT_DIR_FD_CONVERTER(args[1], &dir_fd)) { - goto exit; - } -skip_optional_kwonly: - return_value = os_unlink_impl(module, &path, dir_fd); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -PyDoc_STRVAR(os_remove__doc__, -"remove($module, /, path, *, dir_fd=None)\n" -"--\n" -"\n" -"Remove a file (same as unlink()).\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"dir_fd may not be implemented on your platform.\n" -" If it is unavailable, using it will raise a NotImplementedError."); - -#define OS_REMOVE_METHODDEF \ - {"remove", _PyCFunction_CAST(os_remove), METH_FASTCALL|METH_KEYWORDS, os_remove__doc__}, - -static PyObject * -os_remove_impl(PyObject *module, path_t *path, int dir_fd); - -static PyObject * -os_remove(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(dir_fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "dir_fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "remove", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("remove", "path", 0, 0); - int dir_fd = DEFAULT_DIR_FD; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (!UNLINKAT_DIR_FD_CONVERTER(args[1], &dir_fd)) { - goto exit; - } -skip_optional_kwonly: - return_value = os_remove_impl(module, &path, dir_fd); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#if defined(HAVE_UNAME) - -PyDoc_STRVAR(os_uname__doc__, -"uname($module, /)\n" -"--\n" -"\n" -"Return an object identifying the current operating system.\n" -"\n" -"The object behaves like a named tuple with the following fields:\n" -" (sysname, nodename, release, version, machine)"); - -#define OS_UNAME_METHODDEF \ - {"uname", (PyCFunction)os_uname, METH_NOARGS, os_uname__doc__}, - -static PyObject * -os_uname_impl(PyObject *module); - -static PyObject * -os_uname(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_uname_impl(module); -} - -#endif /* defined(HAVE_UNAME) */ - -PyDoc_STRVAR(os_utime__doc__, -"utime($module, /, path, times=None, *, ns=,\n" -" dir_fd=None, follow_symlinks=True)\n" -"--\n" -"\n" -"Set the access and modified time of path.\n" -"\n" -"path may always be specified as a string.\n" -"On some platforms, path may also be specified as an open file descriptor.\n" -" If this functionality is unavailable, using it raises an exception.\n" -"\n" -"If times is not None, it must be a tuple (atime, mtime);\n" -" atime and mtime should be expressed as float seconds since the epoch.\n" -"If ns is specified, it must be a tuple (atime_ns, mtime_ns);\n" -" atime_ns and mtime_ns should be expressed as integer nanoseconds\n" -" since the epoch.\n" -"If times is None and ns is unspecified, utime uses the current time.\n" -"Specifying tuples for both times and ns is an error.\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"If follow_symlinks is False, and the last element of the path is a symbolic\n" -" link, utime will modify the symbolic link itself instead of the file the\n" -" link points to.\n" -"It is an error to use dir_fd or follow_symlinks when specifying path\n" -" as an open file descriptor.\n" -"dir_fd and follow_symlinks may not be available on your platform.\n" -" If they are unavailable, using them will raise a NotImplementedError."); - -#define OS_UTIME_METHODDEF \ - {"utime", _PyCFunction_CAST(os_utime), METH_FASTCALL|METH_KEYWORDS, os_utime__doc__}, - -static PyObject * -os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, - int dir_fd, int follow_symlinks); - -static PyObject * -os_utime(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 5 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(times), &_Py_ID(ns), &_Py_ID(dir_fd), &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "times", "ns", "dir_fd", "follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "utime", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[5]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("utime", "path", 0, PATH_UTIME_HAVE_FD); - PyObject *times = Py_None; - PyObject *ns = NULL; - int dir_fd = DEFAULT_DIR_FD; - int follow_symlinks = 1; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[1]) { - times = args[1]; - if (!--noptargs) { - goto skip_optional_pos; - } - } -skip_optional_pos: - if (!noptargs) { - goto skip_optional_kwonly; - } - if (args[2]) { - ns = args[2]; - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[3]) { - if (!FUTIMENSAT_DIR_FD_CONVERTER(args[3], &dir_fd)) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - follow_symlinks = PyObject_IsTrue(args[4]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - return_value = os_utime_impl(module, &path, times, ns, dir_fd, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -PyDoc_STRVAR(os__exit__doc__, -"_exit($module, /, status)\n" -"--\n" -"\n" -"Exit to the system with specified status, without normal exit processing."); - -#define OS__EXIT_METHODDEF \ - {"_exit", _PyCFunction_CAST(os__exit), METH_FASTCALL|METH_KEYWORDS, os__exit__doc__}, - -static PyObject * -os__exit_impl(PyObject *module, int status); - -static PyObject * -os__exit(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(status), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"status", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "_exit", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int status; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - status = _PyLong_AsInt(args[0]); - if (status == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os__exit_impl(module, status); - -exit: - return return_value; -} - -#if defined(HAVE_EXECV) - -PyDoc_STRVAR(os_execv__doc__, -"execv($module, path, argv, /)\n" -"--\n" -"\n" -"Execute an executable path with arguments, replacing current process.\n" -"\n" -" path\n" -" Path of executable file.\n" -" argv\n" -" Tuple or list of strings."); - -#define OS_EXECV_METHODDEF \ - {"execv", _PyCFunction_CAST(os_execv), METH_FASTCALL, os_execv__doc__}, - -static PyObject * -os_execv_impl(PyObject *module, path_t *path, PyObject *argv); - -static PyObject * -os_execv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - path_t path = PATH_T_INITIALIZE("execv", "path", 0, 0); - PyObject *argv; - - if (!_PyArg_CheckPositional("execv", nargs, 2, 2)) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - argv = args[1]; - return_value = os_execv_impl(module, &path, argv); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(HAVE_EXECV) */ - -#if defined(HAVE_EXECV) - -PyDoc_STRVAR(os_execve__doc__, -"execve($module, /, path, argv, env)\n" -"--\n" -"\n" -"Execute an executable path with arguments, replacing current process.\n" -"\n" -" path\n" -" Path of executable file.\n" -" argv\n" -" Tuple or list of strings.\n" -" env\n" -" Dictionary of strings mapping to strings."); - -#define OS_EXECVE_METHODDEF \ - {"execve", _PyCFunction_CAST(os_execve), METH_FASTCALL|METH_KEYWORDS, os_execve__doc__}, - -static PyObject * -os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env); - -static PyObject * -os_execve(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(argv), &_Py_ID(env), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "argv", "env", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "execve", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - path_t path = PATH_T_INITIALIZE("execve", "path", 0, PATH_HAVE_FEXECVE); - PyObject *argv; - PyObject *env; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - argv = args[1]; - env = args[2]; - return_value = os_execve_impl(module, &path, argv, env); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(HAVE_EXECV) */ - -#if defined(HAVE_POSIX_SPAWN) - -PyDoc_STRVAR(os_posix_spawn__doc__, -"posix_spawn($module, path, argv, env, /, *, file_actions=(),\n" -" setpgroup=, resetids=False, setsid=False,\n" -" setsigmask=(), setsigdef=(), scheduler=)\n" -"--\n" -"\n" -"Execute the program specified by path in a new process.\n" -"\n" -" path\n" -" Path of executable file.\n" -" argv\n" -" Tuple or list of strings.\n" -" env\n" -" Dictionary of strings mapping to strings.\n" -" file_actions\n" -" A sequence of file action tuples.\n" -" setpgroup\n" -" The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.\n" -" resetids\n" -" If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.\n" -" setsid\n" -" If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.\n" -" setsigmask\n" -" The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.\n" -" setsigdef\n" -" The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.\n" -" scheduler\n" -" A tuple with the scheduler policy (optional) and parameters."); - -#define OS_POSIX_SPAWN_METHODDEF \ - {"posix_spawn", _PyCFunction_CAST(os_posix_spawn), METH_FASTCALL|METH_KEYWORDS, os_posix_spawn__doc__}, - -static PyObject * -os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, - PyObject *env, PyObject *file_actions, - PyObject *setpgroup, int resetids, int setsid, - PyObject *setsigmask, PyObject *setsigdef, - PyObject *scheduler); - -static PyObject * -os_posix_spawn(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 7 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(file_actions), &_Py_ID(setpgroup), &_Py_ID(resetids), &_Py_ID(setsid), &_Py_ID(setsigmask), &_Py_ID(setsigdef), &_Py_ID(scheduler), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"", "", "", "file_actions", "setpgroup", "resetids", "setsid", "setsigmask", "setsigdef", "scheduler", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "posix_spawn", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[10]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - path_t path = PATH_T_INITIALIZE("posix_spawn", "path", 0, 0); - PyObject *argv; - PyObject *env; - PyObject *file_actions = NULL; - PyObject *setpgroup = NULL; - int resetids = 0; - int setsid = 0; - PyObject *setsigmask = NULL; - PyObject *setsigdef = NULL; - PyObject *scheduler = NULL; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - argv = args[1]; - env = args[2]; - if (!noptargs) { - goto skip_optional_kwonly; - } - if (args[3]) { - file_actions = args[3]; - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[4]) { - setpgroup = args[4]; - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[5]) { - resetids = _PyLong_AsInt(args[5]); - if (resetids == -1 && PyErr_Occurred()) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[6]) { - setsid = _PyLong_AsInt(args[6]); - if (setsid == -1 && PyErr_Occurred()) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[7]) { - setsigmask = args[7]; - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[8]) { - setsigdef = args[8]; - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - scheduler = args[9]; -skip_optional_kwonly: - return_value = os_posix_spawn_impl(module, &path, argv, env, file_actions, setpgroup, resetids, setsid, setsigmask, setsigdef, scheduler); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(HAVE_POSIX_SPAWN) */ - -#if defined(HAVE_POSIX_SPAWNP) - -PyDoc_STRVAR(os_posix_spawnp__doc__, -"posix_spawnp($module, path, argv, env, /, *, file_actions=(),\n" -" setpgroup=, resetids=False, setsid=False,\n" -" setsigmask=(), setsigdef=(), scheduler=)\n" -"--\n" -"\n" -"Execute the program specified by path in a new process.\n" -"\n" -" path\n" -" Path of executable file.\n" -" argv\n" -" Tuple or list of strings.\n" -" env\n" -" Dictionary of strings mapping to strings.\n" -" file_actions\n" -" A sequence of file action tuples.\n" -" setpgroup\n" -" The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.\n" -" resetids\n" -" If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.\n" -" setsid\n" -" If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.\n" -" setsigmask\n" -" The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.\n" -" setsigdef\n" -" The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.\n" -" scheduler\n" -" A tuple with the scheduler policy (optional) and parameters."); - -#define OS_POSIX_SPAWNP_METHODDEF \ - {"posix_spawnp", _PyCFunction_CAST(os_posix_spawnp), METH_FASTCALL|METH_KEYWORDS, os_posix_spawnp__doc__}, - -static PyObject * -os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv, - PyObject *env, PyObject *file_actions, - PyObject *setpgroup, int resetids, int setsid, - PyObject *setsigmask, PyObject *setsigdef, - PyObject *scheduler); - -static PyObject * -os_posix_spawnp(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 7 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(file_actions), &_Py_ID(setpgroup), &_Py_ID(resetids), &_Py_ID(setsid), &_Py_ID(setsigmask), &_Py_ID(setsigdef), &_Py_ID(scheduler), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"", "", "", "file_actions", "setpgroup", "resetids", "setsid", "setsigmask", "setsigdef", "scheduler", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "posix_spawnp", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[10]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - path_t path = PATH_T_INITIALIZE("posix_spawnp", "path", 0, 0); - PyObject *argv; - PyObject *env; - PyObject *file_actions = NULL; - PyObject *setpgroup = NULL; - int resetids = 0; - int setsid = 0; - PyObject *setsigmask = NULL; - PyObject *setsigdef = NULL; - PyObject *scheduler = NULL; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - argv = args[1]; - env = args[2]; - if (!noptargs) { - goto skip_optional_kwonly; - } - if (args[3]) { - file_actions = args[3]; - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[4]) { - setpgroup = args[4]; - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[5]) { - resetids = _PyLong_AsInt(args[5]); - if (resetids == -1 && PyErr_Occurred()) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[6]) { - setsid = _PyLong_AsInt(args[6]); - if (setsid == -1 && PyErr_Occurred()) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[7]) { - setsigmask = args[7]; - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[8]) { - setsigdef = args[8]; - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - scheduler = args[9]; -skip_optional_kwonly: - return_value = os_posix_spawnp_impl(module, &path, argv, env, file_actions, setpgroup, resetids, setsid, setsigmask, setsigdef, scheduler); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(HAVE_POSIX_SPAWNP) */ - -#if (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)) - -PyDoc_STRVAR(os_spawnv__doc__, -"spawnv($module, mode, path, argv, /)\n" -"--\n" -"\n" -"Execute the program specified by path in a new process.\n" -"\n" -" mode\n" -" Mode of process creation.\n" -" path\n" -" Path of executable file.\n" -" argv\n" -" Tuple or list of strings."); - -#define OS_SPAWNV_METHODDEF \ - {"spawnv", _PyCFunction_CAST(os_spawnv), METH_FASTCALL, os_spawnv__doc__}, - -static PyObject * -os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv); - -static PyObject * -os_spawnv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int mode; - path_t path = PATH_T_INITIALIZE("spawnv", "path", 0, 0); - PyObject *argv; - - if (!_PyArg_CheckPositional("spawnv", nargs, 3, 3)) { - goto exit; - } - mode = _PyLong_AsInt(args[0]); - if (mode == -1 && PyErr_Occurred()) { - goto exit; - } - if (!path_converter(args[1], &path)) { - goto exit; - } - argv = args[2]; - return_value = os_spawnv_impl(module, mode, &path, argv); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)) */ - -#if (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)) - -PyDoc_STRVAR(os_spawnve__doc__, -"spawnve($module, mode, path, argv, env, /)\n" -"--\n" -"\n" -"Execute the program specified by path in a new process.\n" -"\n" -" mode\n" -" Mode of process creation.\n" -" path\n" -" Path of executable file.\n" -" argv\n" -" Tuple or list of strings.\n" -" env\n" -" Dictionary of strings mapping to strings."); - -#define OS_SPAWNVE_METHODDEF \ - {"spawnve", _PyCFunction_CAST(os_spawnve), METH_FASTCALL, os_spawnve__doc__}, - -static PyObject * -os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv, - PyObject *env); - -static PyObject * -os_spawnve(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int mode; - path_t path = PATH_T_INITIALIZE("spawnve", "path", 0, 0); - PyObject *argv; - PyObject *env; - - if (!_PyArg_CheckPositional("spawnve", nargs, 4, 4)) { - goto exit; - } - mode = _PyLong_AsInt(args[0]); - if (mode == -1 && PyErr_Occurred()) { - goto exit; - } - if (!path_converter(args[1], &path)) { - goto exit; - } - argv = args[2]; - env = args[3]; - return_value = os_spawnve_impl(module, mode, &path, argv, env); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)) */ - -#if defined(HAVE_FORK) - -PyDoc_STRVAR(os_register_at_fork__doc__, -"register_at_fork($module, /, *, before=,\n" -" after_in_child=,\n" -" after_in_parent=)\n" -"--\n" -"\n" -"Register callables to be called when forking a new process.\n" -"\n" -" before\n" -" A callable to be called in the parent before the fork() syscall.\n" -" after_in_child\n" -" A callable to be called in the child after fork().\n" -" after_in_parent\n" -" A callable to be called in the parent after fork().\n" -"\n" -"\'before\' callbacks are called in reverse order.\n" -"\'after_in_child\' and \'after_in_parent\' callbacks are called in order."); - -#define OS_REGISTER_AT_FORK_METHODDEF \ - {"register_at_fork", _PyCFunction_CAST(os_register_at_fork), METH_FASTCALL|METH_KEYWORDS, os_register_at_fork__doc__}, - -static PyObject * -os_register_at_fork_impl(PyObject *module, PyObject *before, - PyObject *after_in_child, PyObject *after_in_parent); - -static PyObject * -os_register_at_fork(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(before), &_Py_ID(after_in_child), &_Py_ID(after_in_parent), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"before", "after_in_child", "after_in_parent", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "register_at_fork", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - PyObject *before = NULL; - PyObject *after_in_child = NULL; - PyObject *after_in_parent = NULL; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf); - if (!args) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (args[0]) { - before = args[0]; - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[1]) { - after_in_child = args[1]; - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - after_in_parent = args[2]; -skip_optional_kwonly: - return_value = os_register_at_fork_impl(module, before, after_in_child, after_in_parent); - -exit: - return return_value; -} - -#endif /* defined(HAVE_FORK) */ - -#if defined(HAVE_FORK1) - -PyDoc_STRVAR(os_fork1__doc__, -"fork1($module, /)\n" -"--\n" -"\n" -"Fork a child process with a single multiplexed (i.e., not bound) thread.\n" -"\n" -"Return 0 to child process and PID of child to parent process."); - -#define OS_FORK1_METHODDEF \ - {"fork1", (PyCFunction)os_fork1, METH_NOARGS, os_fork1__doc__}, - -static PyObject * -os_fork1_impl(PyObject *module); - -static PyObject * -os_fork1(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_fork1_impl(module); -} - -#endif /* defined(HAVE_FORK1) */ - -#if defined(HAVE_FORK) - -PyDoc_STRVAR(os_fork__doc__, -"fork($module, /)\n" -"--\n" -"\n" -"Fork a child process.\n" -"\n" -"Return 0 to child process and PID of child to parent process."); - -#define OS_FORK_METHODDEF \ - {"fork", (PyCFunction)os_fork, METH_NOARGS, os_fork__doc__}, - -static PyObject * -os_fork_impl(PyObject *module); - -static PyObject * -os_fork(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_fork_impl(module); -} - -#endif /* defined(HAVE_FORK) */ - -#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_GET_PRIORITY_MAX) - -PyDoc_STRVAR(os_sched_get_priority_max__doc__, -"sched_get_priority_max($module, /, policy)\n" -"--\n" -"\n" -"Get the maximum scheduling priority for policy."); - -#define OS_SCHED_GET_PRIORITY_MAX_METHODDEF \ - {"sched_get_priority_max", _PyCFunction_CAST(os_sched_get_priority_max), METH_FASTCALL|METH_KEYWORDS, os_sched_get_priority_max__doc__}, - -static PyObject * -os_sched_get_priority_max_impl(PyObject *module, int policy); - -static PyObject * -os_sched_get_priority_max(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(policy), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"policy", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "sched_get_priority_max", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int policy; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - policy = _PyLong_AsInt(args[0]); - if (policy == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_sched_get_priority_max_impl(module, policy); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_GET_PRIORITY_MAX) */ - -#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_GET_PRIORITY_MAX) - -PyDoc_STRVAR(os_sched_get_priority_min__doc__, -"sched_get_priority_min($module, /, policy)\n" -"--\n" -"\n" -"Get the minimum scheduling priority for policy."); - -#define OS_SCHED_GET_PRIORITY_MIN_METHODDEF \ - {"sched_get_priority_min", _PyCFunction_CAST(os_sched_get_priority_min), METH_FASTCALL|METH_KEYWORDS, os_sched_get_priority_min__doc__}, - -static PyObject * -os_sched_get_priority_min_impl(PyObject *module, int policy); - -static PyObject * -os_sched_get_priority_min(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(policy), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"policy", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "sched_get_priority_min", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int policy; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - policy = _PyLong_AsInt(args[0]); - if (policy == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_sched_get_priority_min_impl(module, policy); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_GET_PRIORITY_MAX) */ - -#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETSCHEDULER) - -PyDoc_STRVAR(os_sched_getscheduler__doc__, -"sched_getscheduler($module, pid, /)\n" -"--\n" -"\n" -"Get the scheduling policy for the process identified by pid.\n" -"\n" -"Passing 0 for pid returns the scheduling policy for the calling process."); - -#define OS_SCHED_GETSCHEDULER_METHODDEF \ - {"sched_getscheduler", (PyCFunction)os_sched_getscheduler, METH_O, os_sched_getscheduler__doc__}, - -static PyObject * -os_sched_getscheduler_impl(PyObject *module, pid_t pid); - -static PyObject * -os_sched_getscheduler(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - pid_t pid; - - if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":sched_getscheduler", &pid)) { - goto exit; - } - return_value = os_sched_getscheduler_impl(module, pid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETSCHEDULER) */ - -#if defined(HAVE_SCHED_H) && (defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)) - -PyDoc_STRVAR(os_sched_param__doc__, -"sched_param(sched_priority)\n" -"--\n" -"\n" -"Currently has only one field: sched_priority\n" -"\n" -" sched_priority\n" -" A scheduling parameter."); - -static PyObject * -os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority); - -static PyObject * -os_sched_param(PyTypeObject *type, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(sched_priority), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"sched_priority", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "sched_param", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - PyObject * const *fastargs; - Py_ssize_t nargs = PyTuple_GET_SIZE(args); - PyObject *sched_priority; - - fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, argsbuf); - if (!fastargs) { - goto exit; - } - sched_priority = fastargs[0]; - return_value = os_sched_param_impl(type, sched_priority); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SCHED_H) && (defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)) */ - -#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETSCHEDULER) - -PyDoc_STRVAR(os_sched_setscheduler__doc__, -"sched_setscheduler($module, pid, policy, param, /)\n" -"--\n" -"\n" -"Set the scheduling policy for the process identified by pid.\n" -"\n" -"If pid is 0, the calling process is changed.\n" -"param is an instance of sched_param."); - -#define OS_SCHED_SETSCHEDULER_METHODDEF \ - {"sched_setscheduler", _PyCFunction_CAST(os_sched_setscheduler), METH_FASTCALL, os_sched_setscheduler__doc__}, - -static PyObject * -os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy, - PyObject *param_obj); - -static PyObject * -os_sched_setscheduler(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - pid_t pid; - int policy; - PyObject *param_obj; - - if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "iO:sched_setscheduler", - &pid, &policy, ¶m_obj)) { - goto exit; - } - return_value = os_sched_setscheduler_impl(module, pid, policy, param_obj); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETSCHEDULER) */ - -#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETPARAM) - -PyDoc_STRVAR(os_sched_getparam__doc__, -"sched_getparam($module, pid, /)\n" -"--\n" -"\n" -"Returns scheduling parameters for the process identified by pid.\n" -"\n" -"If pid is 0, returns parameters for the calling process.\n" -"Return value is an instance of sched_param."); - -#define OS_SCHED_GETPARAM_METHODDEF \ - {"sched_getparam", (PyCFunction)os_sched_getparam, METH_O, os_sched_getparam__doc__}, - -static PyObject * -os_sched_getparam_impl(PyObject *module, pid_t pid); - -static PyObject * -os_sched_getparam(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - pid_t pid; - - if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":sched_getparam", &pid)) { - goto exit; - } - return_value = os_sched_getparam_impl(module, pid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETPARAM) */ - -#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETPARAM) - -PyDoc_STRVAR(os_sched_setparam__doc__, -"sched_setparam($module, pid, param, /)\n" -"--\n" -"\n" -"Set scheduling parameters for the process identified by pid.\n" -"\n" -"If pid is 0, sets parameters for the calling process.\n" -"param should be an instance of sched_param."); - -#define OS_SCHED_SETPARAM_METHODDEF \ - {"sched_setparam", _PyCFunction_CAST(os_sched_setparam), METH_FASTCALL, os_sched_setparam__doc__}, - -static PyObject * -os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj); - -static PyObject * -os_sched_setparam(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - pid_t pid; - PyObject *param_obj; - - if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "O:sched_setparam", - &pid, ¶m_obj)) { - goto exit; - } - return_value = os_sched_setparam_impl(module, pid, param_obj); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETPARAM) */ - -#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_RR_GET_INTERVAL) - -PyDoc_STRVAR(os_sched_rr_get_interval__doc__, -"sched_rr_get_interval($module, pid, /)\n" -"--\n" -"\n" -"Return the round-robin quantum for the process identified by pid, in seconds.\n" -"\n" -"Value returned is a float."); - -#define OS_SCHED_RR_GET_INTERVAL_METHODDEF \ - {"sched_rr_get_interval", (PyCFunction)os_sched_rr_get_interval, METH_O, os_sched_rr_get_interval__doc__}, - -static double -os_sched_rr_get_interval_impl(PyObject *module, pid_t pid); - -static PyObject * -os_sched_rr_get_interval(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - pid_t pid; - double _return_value; - - if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":sched_rr_get_interval", &pid)) { - goto exit; - } - _return_value = os_sched_rr_get_interval_impl(module, pid); - if ((_return_value == -1.0) && PyErr_Occurred()) { - goto exit; - } - return_value = PyFloat_FromDouble(_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_RR_GET_INTERVAL) */ - -#if defined(HAVE_SCHED_H) - -PyDoc_STRVAR(os_sched_yield__doc__, -"sched_yield($module, /)\n" -"--\n" -"\n" -"Voluntarily relinquish the CPU."); - -#define OS_SCHED_YIELD_METHODDEF \ - {"sched_yield", (PyCFunction)os_sched_yield, METH_NOARGS, os_sched_yield__doc__}, - -static PyObject * -os_sched_yield_impl(PyObject *module); - -static PyObject * -os_sched_yield(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_sched_yield_impl(module); -} - -#endif /* defined(HAVE_SCHED_H) */ - -#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETAFFINITY) - -PyDoc_STRVAR(os_sched_setaffinity__doc__, -"sched_setaffinity($module, pid, mask, /)\n" -"--\n" -"\n" -"Set the CPU affinity of the process identified by pid to mask.\n" -"\n" -"mask should be an iterable of integers identifying CPUs."); - -#define OS_SCHED_SETAFFINITY_METHODDEF \ - {"sched_setaffinity", _PyCFunction_CAST(os_sched_setaffinity), METH_FASTCALL, os_sched_setaffinity__doc__}, - -static PyObject * -os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask); - -static PyObject * -os_sched_setaffinity(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - pid_t pid; - PyObject *mask; - - if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "O:sched_setaffinity", - &pid, &mask)) { - goto exit; - } - return_value = os_sched_setaffinity_impl(module, pid, mask); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETAFFINITY) */ - -#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETAFFINITY) - -PyDoc_STRVAR(os_sched_getaffinity__doc__, -"sched_getaffinity($module, pid, /)\n" -"--\n" -"\n" -"Return the affinity of the process identified by pid (or the current process if zero).\n" -"\n" -"The affinity is returned as a set of CPU identifiers."); - -#define OS_SCHED_GETAFFINITY_METHODDEF \ - {"sched_getaffinity", (PyCFunction)os_sched_getaffinity, METH_O, os_sched_getaffinity__doc__}, - -static PyObject * -os_sched_getaffinity_impl(PyObject *module, pid_t pid); - -static PyObject * -os_sched_getaffinity(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - pid_t pid; - - if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":sched_getaffinity", &pid)) { - goto exit; - } - return_value = os_sched_getaffinity_impl(module, pid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETAFFINITY) */ - -#if (defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)) - -PyDoc_STRVAR(os_openpty__doc__, -"openpty($module, /)\n" -"--\n" -"\n" -"Open a pseudo-terminal.\n" -"\n" -"Return a tuple of (master_fd, slave_fd) containing open file descriptors\n" -"for both the master and slave ends."); - -#define OS_OPENPTY_METHODDEF \ - {"openpty", (PyCFunction)os_openpty, METH_NOARGS, os_openpty__doc__}, - -static PyObject * -os_openpty_impl(PyObject *module); - -static PyObject * -os_openpty(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_openpty_impl(module); -} - -#endif /* (defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)) */ - -#if (defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)) - -PyDoc_STRVAR(os_login_tty__doc__, -"login_tty($module, fd, /)\n" -"--\n" -"\n" -"Prepare the tty of which fd is a file descriptor for a new login session.\n" -"\n" -"Make the calling process a session leader; make the tty the\n" -"controlling tty, the stdin, the stdout, and the stderr of the\n" -"calling process; close fd."); - -#define OS_LOGIN_TTY_METHODDEF \ - {"login_tty", (PyCFunction)os_login_tty, METH_O, os_login_tty__doc__}, - -static PyObject * -os_login_tty_impl(PyObject *module, int fd); - -static PyObject * -os_login_tty(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int fd; - - if (!_PyLong_FileDescriptor_Converter(arg, &fd)) { - goto exit; - } - return_value = os_login_tty_impl(module, fd); - -exit: - return return_value; -} - -#endif /* (defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)) */ - -#if defined(HAVE_FORKPTY) - -PyDoc_STRVAR(os_forkpty__doc__, -"forkpty($module, /)\n" -"--\n" -"\n" -"Fork a new process with a new pseudo-terminal as controlling tty.\n" -"\n" -"Returns a tuple of (pid, master_fd).\n" -"Like fork(), return pid of 0 to the child process,\n" -"and pid of child to the parent process.\n" -"To both, return fd of newly opened pseudo-terminal."); - -#define OS_FORKPTY_METHODDEF \ - {"forkpty", (PyCFunction)os_forkpty, METH_NOARGS, os_forkpty__doc__}, - -static PyObject * -os_forkpty_impl(PyObject *module); - -static PyObject * -os_forkpty(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_forkpty_impl(module); -} - -#endif /* defined(HAVE_FORKPTY) */ - -#if defined(HAVE_GETEGID) - -PyDoc_STRVAR(os_getegid__doc__, -"getegid($module, /)\n" -"--\n" -"\n" -"Return the current process\'s effective group id."); - -#define OS_GETEGID_METHODDEF \ - {"getegid", (PyCFunction)os_getegid, METH_NOARGS, os_getegid__doc__}, - -static PyObject * -os_getegid_impl(PyObject *module); - -static PyObject * -os_getegid(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getegid_impl(module); -} - -#endif /* defined(HAVE_GETEGID) */ - -#if defined(HAVE_GETEUID) - -PyDoc_STRVAR(os_geteuid__doc__, -"geteuid($module, /)\n" -"--\n" -"\n" -"Return the current process\'s effective user id."); - -#define OS_GETEUID_METHODDEF \ - {"geteuid", (PyCFunction)os_geteuid, METH_NOARGS, os_geteuid__doc__}, - -static PyObject * -os_geteuid_impl(PyObject *module); - -static PyObject * -os_geteuid(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_geteuid_impl(module); -} - -#endif /* defined(HAVE_GETEUID) */ - -#if defined(HAVE_GETGID) - -PyDoc_STRVAR(os_getgid__doc__, -"getgid($module, /)\n" -"--\n" -"\n" -"Return the current process\'s group id."); - -#define OS_GETGID_METHODDEF \ - {"getgid", (PyCFunction)os_getgid, METH_NOARGS, os_getgid__doc__}, - -static PyObject * -os_getgid_impl(PyObject *module); - -static PyObject * -os_getgid(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getgid_impl(module); -} - -#endif /* defined(HAVE_GETGID) */ - -#if defined(HAVE_GETPID) - -PyDoc_STRVAR(os_getpid__doc__, -"getpid($module, /)\n" -"--\n" -"\n" -"Return the current process id."); - -#define OS_GETPID_METHODDEF \ - {"getpid", (PyCFunction)os_getpid, METH_NOARGS, os_getpid__doc__}, - -static PyObject * -os_getpid_impl(PyObject *module); - -static PyObject * -os_getpid(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getpid_impl(module); -} - -#endif /* defined(HAVE_GETPID) */ - -#if defined(HAVE_GETGROUPLIST) && defined(__APPLE__) - -PyDoc_STRVAR(os_getgrouplist__doc__, -"getgrouplist($module, user, group, /)\n" -"--\n" -"\n" -"Returns a list of groups to which a user belongs.\n" -"\n" -" user\n" -" username to lookup\n" -" group\n" -" base group id of the user"); - -#define OS_GETGROUPLIST_METHODDEF \ - {"getgrouplist", _PyCFunction_CAST(os_getgrouplist), METH_FASTCALL, os_getgrouplist__doc__}, - -static PyObject * -os_getgrouplist_impl(PyObject *module, const char *user, int basegid); - -static PyObject * -os_getgrouplist(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - const char *user; - int basegid; - - if (!_PyArg_CheckPositional("getgrouplist", nargs, 2, 2)) { - goto exit; - } - if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("getgrouplist", "argument 1", "str", args[0]); - goto exit; - } - Py_ssize_t user_length; - user = PyUnicode_AsUTF8AndSize(args[0], &user_length); - if (user == NULL) { - goto exit; - } - if (strlen(user) != (size_t)user_length) { - PyErr_SetString(PyExc_ValueError, "embedded null character"); - goto exit; - } - basegid = _PyLong_AsInt(args[1]); - if (basegid == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_getgrouplist_impl(module, user, basegid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_GETGROUPLIST) && defined(__APPLE__) */ - -#if defined(HAVE_GETGROUPLIST) && !defined(__APPLE__) - -PyDoc_STRVAR(os_getgrouplist__doc__, -"getgrouplist($module, user, group, /)\n" -"--\n" -"\n" -"Returns a list of groups to which a user belongs.\n" -"\n" -" user\n" -" username to lookup\n" -" group\n" -" base group id of the user"); - -#define OS_GETGROUPLIST_METHODDEF \ - {"getgrouplist", _PyCFunction_CAST(os_getgrouplist), METH_FASTCALL, os_getgrouplist__doc__}, - -static PyObject * -os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid); - -static PyObject * -os_getgrouplist(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - const char *user; - gid_t basegid; - - if (!_PyArg_CheckPositional("getgrouplist", nargs, 2, 2)) { - goto exit; - } - if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("getgrouplist", "argument 1", "str", args[0]); - goto exit; - } - Py_ssize_t user_length; - user = PyUnicode_AsUTF8AndSize(args[0], &user_length); - if (user == NULL) { - goto exit; - } - if (strlen(user) != (size_t)user_length) { - PyErr_SetString(PyExc_ValueError, "embedded null character"); - goto exit; - } - if (!_Py_Gid_Converter(args[1], &basegid)) { - goto exit; - } - return_value = os_getgrouplist_impl(module, user, basegid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_GETGROUPLIST) && !defined(__APPLE__) */ - -#if defined(HAVE_GETGROUPS) - -PyDoc_STRVAR(os_getgroups__doc__, -"getgroups($module, /)\n" -"--\n" -"\n" -"Return list of supplemental group IDs for the process."); - -#define OS_GETGROUPS_METHODDEF \ - {"getgroups", (PyCFunction)os_getgroups, METH_NOARGS, os_getgroups__doc__}, - -static PyObject * -os_getgroups_impl(PyObject *module); - -static PyObject * -os_getgroups(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getgroups_impl(module); -} - -#endif /* defined(HAVE_GETGROUPS) */ - -#if defined(HAVE_INITGROUPS) && defined(__APPLE__) - -PyDoc_STRVAR(os_initgroups__doc__, -"initgroups($module, username, gid, /)\n" -"--\n" -"\n" -"Initialize the group access list.\n" -"\n" -"Call the system initgroups() to initialize the group access list with all of\n" -"the groups of which the specified username is a member, plus the specified\n" -"group id."); - -#define OS_INITGROUPS_METHODDEF \ - {"initgroups", _PyCFunction_CAST(os_initgroups), METH_FASTCALL, os_initgroups__doc__}, - -static PyObject * -os_initgroups_impl(PyObject *module, PyObject *oname, int gid); - -static PyObject * -os_initgroups(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - PyObject *oname = NULL; - int gid; - - if (!_PyArg_CheckPositional("initgroups", nargs, 2, 2)) { - goto exit; - } - if (!PyUnicode_FSConverter(args[0], &oname)) { - goto exit; - } - gid = _PyLong_AsInt(args[1]); - if (gid == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_initgroups_impl(module, oname, gid); - -exit: - /* Cleanup for oname */ - Py_XDECREF(oname); - - return return_value; -} - -#endif /* defined(HAVE_INITGROUPS) && defined(__APPLE__) */ - -#if defined(HAVE_INITGROUPS) && !defined(__APPLE__) - -PyDoc_STRVAR(os_initgroups__doc__, -"initgroups($module, username, gid, /)\n" -"--\n" -"\n" -"Initialize the group access list.\n" -"\n" -"Call the system initgroups() to initialize the group access list with all of\n" -"the groups of which the specified username is a member, plus the specified\n" -"group id."); - -#define OS_INITGROUPS_METHODDEF \ - {"initgroups", _PyCFunction_CAST(os_initgroups), METH_FASTCALL, os_initgroups__doc__}, - -static PyObject * -os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid); - -static PyObject * -os_initgroups(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - PyObject *oname = NULL; - gid_t gid; - - if (!_PyArg_CheckPositional("initgroups", nargs, 2, 2)) { - goto exit; - } - if (!PyUnicode_FSConverter(args[0], &oname)) { - goto exit; - } - if (!_Py_Gid_Converter(args[1], &gid)) { - goto exit; - } - return_value = os_initgroups_impl(module, oname, gid); - -exit: - /* Cleanup for oname */ - Py_XDECREF(oname); - - return return_value; -} - -#endif /* defined(HAVE_INITGROUPS) && !defined(__APPLE__) */ - -#if defined(HAVE_GETPGID) - -PyDoc_STRVAR(os_getpgid__doc__, -"getpgid($module, /, pid)\n" -"--\n" -"\n" -"Call the system call getpgid(), and return the result."); - -#define OS_GETPGID_METHODDEF \ - {"getpgid", _PyCFunction_CAST(os_getpgid), METH_FASTCALL|METH_KEYWORDS, os_getpgid__doc__}, - -static PyObject * -os_getpgid_impl(PyObject *module, pid_t pid); - -static PyObject * -os_getpgid(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(pid), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"pid", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .format = "" _Py_PARSE_PID ":getpgid", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - pid_t pid; - - if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &pid)) { - goto exit; - } - return_value = os_getpgid_impl(module, pid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_GETPGID) */ - -#if defined(HAVE_GETPGRP) - -PyDoc_STRVAR(os_getpgrp__doc__, -"getpgrp($module, /)\n" -"--\n" -"\n" -"Return the current process group id."); - -#define OS_GETPGRP_METHODDEF \ - {"getpgrp", (PyCFunction)os_getpgrp, METH_NOARGS, os_getpgrp__doc__}, - -static PyObject * -os_getpgrp_impl(PyObject *module); - -static PyObject * -os_getpgrp(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getpgrp_impl(module); -} - -#endif /* defined(HAVE_GETPGRP) */ - -#if defined(HAVE_SETPGRP) - -PyDoc_STRVAR(os_setpgrp__doc__, -"setpgrp($module, /)\n" -"--\n" -"\n" -"Make the current process the leader of its process group."); - -#define OS_SETPGRP_METHODDEF \ - {"setpgrp", (PyCFunction)os_setpgrp, METH_NOARGS, os_setpgrp__doc__}, - -static PyObject * -os_setpgrp_impl(PyObject *module); - -static PyObject * -os_setpgrp(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_setpgrp_impl(module); -} - -#endif /* defined(HAVE_SETPGRP) */ - -#if defined(HAVE_GETPPID) - -PyDoc_STRVAR(os_getppid__doc__, -"getppid($module, /)\n" -"--\n" -"\n" -"Return the parent\'s process id.\n" -"\n" -"If the parent process has already exited, Windows machines will still\n" -"return its id; others systems will return the id of the \'init\' process (1)."); - -#define OS_GETPPID_METHODDEF \ - {"getppid", (PyCFunction)os_getppid, METH_NOARGS, os_getppid__doc__}, - -static PyObject * -os_getppid_impl(PyObject *module); - -static PyObject * -os_getppid(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getppid_impl(module); -} - -#endif /* defined(HAVE_GETPPID) */ - -#if defined(HAVE_GETLOGIN) - -PyDoc_STRVAR(os_getlogin__doc__, -"getlogin($module, /)\n" -"--\n" -"\n" -"Return the actual login name."); - -#define OS_GETLOGIN_METHODDEF \ - {"getlogin", (PyCFunction)os_getlogin, METH_NOARGS, os_getlogin__doc__}, - -static PyObject * -os_getlogin_impl(PyObject *module); - -static PyObject * -os_getlogin(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getlogin_impl(module); -} - -#endif /* defined(HAVE_GETLOGIN) */ - -#if defined(HAVE_GETUID) - -PyDoc_STRVAR(os_getuid__doc__, -"getuid($module, /)\n" -"--\n" -"\n" -"Return the current process\'s user id."); - -#define OS_GETUID_METHODDEF \ - {"getuid", (PyCFunction)os_getuid, METH_NOARGS, os_getuid__doc__}, - -static PyObject * -os_getuid_impl(PyObject *module); - -static PyObject * -os_getuid(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getuid_impl(module); -} - -#endif /* defined(HAVE_GETUID) */ - -#if defined(HAVE_KILL) - -PyDoc_STRVAR(os_kill__doc__, -"kill($module, pid, signal, /)\n" -"--\n" -"\n" -"Kill a process with a signal."); - -#define OS_KILL_METHODDEF \ - {"kill", _PyCFunction_CAST(os_kill), METH_FASTCALL, os_kill__doc__}, - -static PyObject * -os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal); - -static PyObject * -os_kill(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - pid_t pid; - Py_ssize_t signal; - - if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "n:kill", - &pid, &signal)) { - goto exit; - } - return_value = os_kill_impl(module, pid, signal); - -exit: - return return_value; -} - -#endif /* defined(HAVE_KILL) */ - -#if defined(HAVE_KILLPG) - -PyDoc_STRVAR(os_killpg__doc__, -"killpg($module, pgid, signal, /)\n" -"--\n" -"\n" -"Kill a process group with a signal."); - -#define OS_KILLPG_METHODDEF \ - {"killpg", _PyCFunction_CAST(os_killpg), METH_FASTCALL, os_killpg__doc__}, - -static PyObject * -os_killpg_impl(PyObject *module, pid_t pgid, int signal); - -static PyObject * -os_killpg(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - pid_t pgid; - int signal; - - if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "i:killpg", - &pgid, &signal)) { - goto exit; - } - return_value = os_killpg_impl(module, pgid, signal); - -exit: - return return_value; -} - -#endif /* defined(HAVE_KILLPG) */ - -#if defined(HAVE_PLOCK) - -PyDoc_STRVAR(os_plock__doc__, -"plock($module, op, /)\n" -"--\n" -"\n" -"Lock program segments into memory.\");"); - -#define OS_PLOCK_METHODDEF \ - {"plock", (PyCFunction)os_plock, METH_O, os_plock__doc__}, - -static PyObject * -os_plock_impl(PyObject *module, int op); - -static PyObject * -os_plock(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int op; - - op = _PyLong_AsInt(arg); - if (op == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_plock_impl(module, op); - -exit: - return return_value; -} - -#endif /* defined(HAVE_PLOCK) */ - -#if defined(HAVE_SETUID) - -PyDoc_STRVAR(os_setuid__doc__, -"setuid($module, uid, /)\n" -"--\n" -"\n" -"Set the current process\'s user id."); - -#define OS_SETUID_METHODDEF \ - {"setuid", (PyCFunction)os_setuid, METH_O, os_setuid__doc__}, - -static PyObject * -os_setuid_impl(PyObject *module, uid_t uid); - -static PyObject * -os_setuid(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - uid_t uid; - - if (!_Py_Uid_Converter(arg, &uid)) { - goto exit; - } - return_value = os_setuid_impl(module, uid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SETUID) */ - -#if defined(HAVE_SETEUID) - -PyDoc_STRVAR(os_seteuid__doc__, -"seteuid($module, euid, /)\n" -"--\n" -"\n" -"Set the current process\'s effective user id."); - -#define OS_SETEUID_METHODDEF \ - {"seteuid", (PyCFunction)os_seteuid, METH_O, os_seteuid__doc__}, - -static PyObject * -os_seteuid_impl(PyObject *module, uid_t euid); - -static PyObject * -os_seteuid(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - uid_t euid; - - if (!_Py_Uid_Converter(arg, &euid)) { - goto exit; - } - return_value = os_seteuid_impl(module, euid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SETEUID) */ - -#if defined(HAVE_SETEGID) - -PyDoc_STRVAR(os_setegid__doc__, -"setegid($module, egid, /)\n" -"--\n" -"\n" -"Set the current process\'s effective group id."); - -#define OS_SETEGID_METHODDEF \ - {"setegid", (PyCFunction)os_setegid, METH_O, os_setegid__doc__}, - -static PyObject * -os_setegid_impl(PyObject *module, gid_t egid); - -static PyObject * -os_setegid(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - gid_t egid; - - if (!_Py_Gid_Converter(arg, &egid)) { - goto exit; - } - return_value = os_setegid_impl(module, egid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SETEGID) */ - -#if defined(HAVE_SETREUID) - -PyDoc_STRVAR(os_setreuid__doc__, -"setreuid($module, ruid, euid, /)\n" -"--\n" -"\n" -"Set the current process\'s real and effective user ids."); - -#define OS_SETREUID_METHODDEF \ - {"setreuid", _PyCFunction_CAST(os_setreuid), METH_FASTCALL, os_setreuid__doc__}, - -static PyObject * -os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid); - -static PyObject * -os_setreuid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - uid_t ruid; - uid_t euid; - - if (!_PyArg_CheckPositional("setreuid", nargs, 2, 2)) { - goto exit; - } - if (!_Py_Uid_Converter(args[0], &ruid)) { - goto exit; - } - if (!_Py_Uid_Converter(args[1], &euid)) { - goto exit; - } - return_value = os_setreuid_impl(module, ruid, euid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SETREUID) */ - -#if defined(HAVE_SETREGID) - -PyDoc_STRVAR(os_setregid__doc__, -"setregid($module, rgid, egid, /)\n" -"--\n" -"\n" -"Set the current process\'s real and effective group ids."); - -#define OS_SETREGID_METHODDEF \ - {"setregid", _PyCFunction_CAST(os_setregid), METH_FASTCALL, os_setregid__doc__}, - -static PyObject * -os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid); - -static PyObject * -os_setregid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - gid_t rgid; - gid_t egid; - - if (!_PyArg_CheckPositional("setregid", nargs, 2, 2)) { - goto exit; - } - if (!_Py_Gid_Converter(args[0], &rgid)) { - goto exit; - } - if (!_Py_Gid_Converter(args[1], &egid)) { - goto exit; - } - return_value = os_setregid_impl(module, rgid, egid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SETREGID) */ - -#if defined(HAVE_SETGID) - -PyDoc_STRVAR(os_setgid__doc__, -"setgid($module, gid, /)\n" -"--\n" -"\n" -"Set the current process\'s group id."); - -#define OS_SETGID_METHODDEF \ - {"setgid", (PyCFunction)os_setgid, METH_O, os_setgid__doc__}, - -static PyObject * -os_setgid_impl(PyObject *module, gid_t gid); - -static PyObject * -os_setgid(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - gid_t gid; - - if (!_Py_Gid_Converter(arg, &gid)) { - goto exit; - } - return_value = os_setgid_impl(module, gid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SETGID) */ - -#if defined(HAVE_SETGROUPS) - -PyDoc_STRVAR(os_setgroups__doc__, -"setgroups($module, groups, /)\n" -"--\n" -"\n" -"Set the groups of the current process to list."); - -#define OS_SETGROUPS_METHODDEF \ - {"setgroups", (PyCFunction)os_setgroups, METH_O, os_setgroups__doc__}, - -#endif /* defined(HAVE_SETGROUPS) */ - -#if defined(HAVE_WAIT3) - -PyDoc_STRVAR(os_wait3__doc__, -"wait3($module, /, options)\n" -"--\n" -"\n" -"Wait for completion of a child process.\n" -"\n" -"Returns a tuple of information about the child process:\n" -" (pid, status, rusage)"); - -#define OS_WAIT3_METHODDEF \ - {"wait3", _PyCFunction_CAST(os_wait3), METH_FASTCALL|METH_KEYWORDS, os_wait3__doc__}, - -static PyObject * -os_wait3_impl(PyObject *module, int options); - -static PyObject * -os_wait3(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(options), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"options", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "wait3", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int options; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - options = _PyLong_AsInt(args[0]); - if (options == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_wait3_impl(module, options); - -exit: - return return_value; -} - -#endif /* defined(HAVE_WAIT3) */ - -#if defined(HAVE_WAIT4) - -PyDoc_STRVAR(os_wait4__doc__, -"wait4($module, /, pid, options)\n" -"--\n" -"\n" -"Wait for completion of a specific child process.\n" -"\n" -"Returns a tuple of information about the child process:\n" -" (pid, status, rusage)"); - -#define OS_WAIT4_METHODDEF \ - {"wait4", _PyCFunction_CAST(os_wait4), METH_FASTCALL|METH_KEYWORDS, os_wait4__doc__}, - -static PyObject * -os_wait4_impl(PyObject *module, pid_t pid, int options); - -static PyObject * -os_wait4(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(pid), &_Py_ID(options), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"pid", "options", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .format = "" _Py_PARSE_PID "i:wait4", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - pid_t pid; - int options; - - if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &pid, &options)) { - goto exit; - } - return_value = os_wait4_impl(module, pid, options); - -exit: - return return_value; -} - -#endif /* defined(HAVE_WAIT4) */ - -#if (defined(HAVE_WAITID) && !defined(__APPLE__)) - -PyDoc_STRVAR(os_waitid__doc__, -"waitid($module, idtype, id, options, /)\n" -"--\n" -"\n" -"Returns the result of waiting for a process or processes.\n" -"\n" -" idtype\n" -" Must be one of be P_PID, P_PGID or P_ALL.\n" -" id\n" -" The id to wait on.\n" -" options\n" -" Constructed from the ORing of one or more of WEXITED, WSTOPPED\n" -" or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.\n" -"\n" -"Returns either waitid_result or None if WNOHANG is specified and there are\n" -"no children in a waitable state."); - -#define OS_WAITID_METHODDEF \ - {"waitid", _PyCFunction_CAST(os_waitid), METH_FASTCALL, os_waitid__doc__}, - -static PyObject * -os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options); - -static PyObject * -os_waitid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - idtype_t idtype; - id_t id; - int options; - - if (!_PyArg_ParseStack(args, nargs, "i" _Py_PARSE_PID "i:waitid", - &idtype, &id, &options)) { - goto exit; - } - return_value = os_waitid_impl(module, idtype, id, options); - -exit: - return return_value; -} - -#endif /* (defined(HAVE_WAITID) && !defined(__APPLE__)) */ - -#if defined(HAVE_WAITPID) - -PyDoc_STRVAR(os_waitpid__doc__, -"waitpid($module, pid, options, /)\n" -"--\n" -"\n" -"Wait for completion of a given child process.\n" -"\n" -"Returns a tuple of information regarding the child process:\n" -" (pid, status)\n" -"\n" -"The options argument is ignored on Windows."); - -#define OS_WAITPID_METHODDEF \ - {"waitpid", _PyCFunction_CAST(os_waitpid), METH_FASTCALL, os_waitpid__doc__}, - -static PyObject * -os_waitpid_impl(PyObject *module, pid_t pid, int options); - -static PyObject * -os_waitpid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - pid_t pid; - int options; - - if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "i:waitpid", - &pid, &options)) { - goto exit; - } - return_value = os_waitpid_impl(module, pid, options); - -exit: - return return_value; -} - -#endif /* defined(HAVE_WAITPID) */ - -#if !defined(HAVE_WAITPID) && defined(HAVE_CWAIT) - -PyDoc_STRVAR(os_waitpid__doc__, -"waitpid($module, pid, options, /)\n" -"--\n" -"\n" -"Wait for completion of a given process.\n" -"\n" -"Returns a tuple of information regarding the process:\n" -" (pid, status << 8)\n" -"\n" -"The options argument is ignored on Windows."); - -#define OS_WAITPID_METHODDEF \ - {"waitpid", _PyCFunction_CAST(os_waitpid), METH_FASTCALL, os_waitpid__doc__}, - -static PyObject * -os_waitpid_impl(PyObject *module, intptr_t pid, int options); - -static PyObject * -os_waitpid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - intptr_t pid; - int options; - - if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_INTPTR "i:waitpid", - &pid, &options)) { - goto exit; - } - return_value = os_waitpid_impl(module, pid, options); - -exit: - return return_value; -} - -#endif /* !defined(HAVE_WAITPID) && defined(HAVE_CWAIT) */ - -#if defined(HAVE_WAIT) - -PyDoc_STRVAR(os_wait__doc__, -"wait($module, /)\n" -"--\n" -"\n" -"Wait for completion of a child process.\n" -"\n" -"Returns a tuple of information about the child process:\n" -" (pid, status)"); - -#define OS_WAIT_METHODDEF \ - {"wait", (PyCFunction)os_wait, METH_NOARGS, os_wait__doc__}, - -static PyObject * -os_wait_impl(PyObject *module); - -static PyObject * -os_wait(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_wait_impl(module); -} - -#endif /* defined(HAVE_WAIT) */ - -#if (defined(__linux__) && defined(__NR_pidfd_open)) - -PyDoc_STRVAR(os_pidfd_open__doc__, -"pidfd_open($module, /, pid, flags=0)\n" -"--\n" -"\n" -"Return a file descriptor referring to the process *pid*.\n" -"\n" -"The descriptor can be used to perform process management without races and\n" -"signals."); - -#define OS_PIDFD_OPEN_METHODDEF \ - {"pidfd_open", _PyCFunction_CAST(os_pidfd_open), METH_FASTCALL|METH_KEYWORDS, os_pidfd_open__doc__}, - -static PyObject * -os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags); - -static PyObject * -os_pidfd_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(pid), &_Py_ID(flags), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"pid", "flags", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .format = "" _Py_PARSE_PID "|O&:pidfd_open", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - pid_t pid; - unsigned int flags = 0; - - if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &pid, _PyLong_UnsignedInt_Converter, &flags)) { - goto exit; - } - return_value = os_pidfd_open_impl(module, pid, flags); - -exit: - return return_value; -} - -#endif /* (defined(__linux__) && defined(__NR_pidfd_open)) */ - -#if defined(HAVE_SETNS) - -PyDoc_STRVAR(os_setns__doc__, -"setns($module, /, fd, nstype=0)\n" -"--\n" -"\n" -"Move the calling thread into different namespaces.\n" -"\n" -" fd\n" -" A file descriptor to a namespace.\n" -" nstype\n" -" Type of namespace."); - -#define OS_SETNS_METHODDEF \ - {"setns", _PyCFunction_CAST(os_setns), METH_FASTCALL|METH_KEYWORDS, os_setns__doc__}, - -static PyObject * -os_setns_impl(PyObject *module, int fd, int nstype); - -static PyObject * -os_setns(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(fd), &_Py_ID(nstype), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"fd", "nstype", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "setns", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - int fd; - int nstype = 0; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - nstype = _PyLong_AsInt(args[1]); - if (nstype == -1 && PyErr_Occurred()) { - goto exit; - } -skip_optional_pos: - return_value = os_setns_impl(module, fd, nstype); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SETNS) */ - -#if defined(HAVE_UNSHARE) - -PyDoc_STRVAR(os_unshare__doc__, -"unshare($module, /, flags)\n" -"--\n" -"\n" -"Disassociate parts of a process (or thread) execution context.\n" -"\n" -" flags\n" -" Namespaces to be unshared."); - -#define OS_UNSHARE_METHODDEF \ - {"unshare", _PyCFunction_CAST(os_unshare), METH_FASTCALL|METH_KEYWORDS, os_unshare__doc__}, - -static PyObject * -os_unshare_impl(PyObject *module, int flags); - -static PyObject * -os_unshare(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(flags), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"flags", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "unshare", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int flags; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - flags = _PyLong_AsInt(args[0]); - if (flags == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_unshare_impl(module, flags); - -exit: - return return_value; -} - -#endif /* defined(HAVE_UNSHARE) */ - -#if (defined(HAVE_READLINK) || defined(MS_WINDOWS)) - -PyDoc_STRVAR(os_readlink__doc__, -"readlink($module, /, path, *, dir_fd=None)\n" -"--\n" -"\n" -"Return a string representing the path to which the symbolic link points.\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -"and path should be relative; path will then be relative to that directory.\n" -"\n" -"dir_fd may not be implemented on your platform. If it is unavailable,\n" -"using it will raise a NotImplementedError."); - -#define OS_READLINK_METHODDEF \ - {"readlink", _PyCFunction_CAST(os_readlink), METH_FASTCALL|METH_KEYWORDS, os_readlink__doc__}, - -static PyObject * -os_readlink_impl(PyObject *module, path_t *path, int dir_fd); - -static PyObject * -os_readlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(dir_fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "dir_fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "readlink", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("readlink", "path", 0, 0); - int dir_fd = DEFAULT_DIR_FD; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (!READLINKAT_DIR_FD_CONVERTER(args[1], &dir_fd)) { - goto exit; - } -skip_optional_kwonly: - return_value = os_readlink_impl(module, &path, dir_fd); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* (defined(HAVE_READLINK) || defined(MS_WINDOWS)) */ - -#if defined(HAVE_SYMLINK) - -PyDoc_STRVAR(os_symlink__doc__, -"symlink($module, /, src, dst, target_is_directory=False, *, dir_fd=None)\n" -"--\n" -"\n" -"Create a symbolic link pointing to src named dst.\n" -"\n" -"target_is_directory is required on Windows if the target is to be\n" -" interpreted as a directory. (On Windows, symlink requires\n" -" Windows 6.0 or greater, and raises a NotImplementedError otherwise.)\n" -" target_is_directory is ignored on non-Windows platforms.\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"dir_fd may not be implemented on your platform.\n" -" If it is unavailable, using it will raise a NotImplementedError."); - -#define OS_SYMLINK_METHODDEF \ - {"symlink", _PyCFunction_CAST(os_symlink), METH_FASTCALL|METH_KEYWORDS, os_symlink__doc__}, - -static PyObject * -os_symlink_impl(PyObject *module, path_t *src, path_t *dst, - int target_is_directory, int dir_fd); - -static PyObject * -os_symlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 4 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(src), &_Py_ID(dst), &_Py_ID(target_is_directory), &_Py_ID(dir_fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"src", "dst", "target_is_directory", "dir_fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "symlink", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[4]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t src = PATH_T_INITIALIZE("symlink", "src", 0, 0); - path_t dst = PATH_T_INITIALIZE("symlink", "dst", 0, 0); - int target_is_directory = 0; - int dir_fd = DEFAULT_DIR_FD; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &src)) { - goto exit; - } - if (!path_converter(args[1], &dst)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[2]) { - target_is_directory = PyObject_IsTrue(args[2]); - if (target_is_directory < 0) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } -skip_optional_pos: - if (!noptargs) { - goto skip_optional_kwonly; - } - if (!SYMLINKAT_DIR_FD_CONVERTER(args[3], &dir_fd)) { - goto exit; - } -skip_optional_kwonly: - return_value = os_symlink_impl(module, &src, &dst, target_is_directory, dir_fd); - -exit: - /* Cleanup for src */ - path_cleanup(&src); - /* Cleanup for dst */ - path_cleanup(&dst); - - return return_value; -} - -#endif /* defined(HAVE_SYMLINK) */ - -#if defined(HAVE_TIMES) - -PyDoc_STRVAR(os_times__doc__, -"times($module, /)\n" -"--\n" -"\n" -"Return a collection containing process timing information.\n" -"\n" -"The object returned behaves like a named tuple with these fields:\n" -" (utime, stime, cutime, cstime, elapsed_time)\n" -"All fields are floating point numbers."); - -#define OS_TIMES_METHODDEF \ - {"times", (PyCFunction)os_times, METH_NOARGS, os_times__doc__}, - -static PyObject * -os_times_impl(PyObject *module); - -static PyObject * -os_times(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_times_impl(module); -} - -#endif /* defined(HAVE_TIMES) */ - -#if defined(HAVE_GETSID) - -PyDoc_STRVAR(os_getsid__doc__, -"getsid($module, pid, /)\n" -"--\n" -"\n" -"Call the system call getsid(pid) and return the result."); - -#define OS_GETSID_METHODDEF \ - {"getsid", (PyCFunction)os_getsid, METH_O, os_getsid__doc__}, - -static PyObject * -os_getsid_impl(PyObject *module, pid_t pid); - -static PyObject * -os_getsid(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - pid_t pid; - - if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":getsid", &pid)) { - goto exit; - } - return_value = os_getsid_impl(module, pid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_GETSID) */ - -#if defined(HAVE_SETSID) - -PyDoc_STRVAR(os_setsid__doc__, -"setsid($module, /)\n" -"--\n" -"\n" -"Call the system call setsid()."); - -#define OS_SETSID_METHODDEF \ - {"setsid", (PyCFunction)os_setsid, METH_NOARGS, os_setsid__doc__}, - -static PyObject * -os_setsid_impl(PyObject *module); - -static PyObject * -os_setsid(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_setsid_impl(module); -} - -#endif /* defined(HAVE_SETSID) */ - -#if defined(HAVE_SETPGID) - -PyDoc_STRVAR(os_setpgid__doc__, -"setpgid($module, pid, pgrp, /)\n" -"--\n" -"\n" -"Call the system call setpgid(pid, pgrp)."); - -#define OS_SETPGID_METHODDEF \ - {"setpgid", _PyCFunction_CAST(os_setpgid), METH_FASTCALL, os_setpgid__doc__}, - -static PyObject * -os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp); - -static PyObject * -os_setpgid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - pid_t pid; - pid_t pgrp; - - if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "" _Py_PARSE_PID ":setpgid", - &pid, &pgrp)) { - goto exit; - } - return_value = os_setpgid_impl(module, pid, pgrp); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SETPGID) */ - -#if defined(HAVE_TCGETPGRP) - -PyDoc_STRVAR(os_tcgetpgrp__doc__, -"tcgetpgrp($module, fd, /)\n" -"--\n" -"\n" -"Return the process group associated with the terminal specified by fd."); - -#define OS_TCGETPGRP_METHODDEF \ - {"tcgetpgrp", (PyCFunction)os_tcgetpgrp, METH_O, os_tcgetpgrp__doc__}, - -static PyObject * -os_tcgetpgrp_impl(PyObject *module, int fd); - -static PyObject * -os_tcgetpgrp(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int fd; - - fd = _PyLong_AsInt(arg); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_tcgetpgrp_impl(module, fd); - -exit: - return return_value; -} - -#endif /* defined(HAVE_TCGETPGRP) */ - -#if defined(HAVE_TCSETPGRP) - -PyDoc_STRVAR(os_tcsetpgrp__doc__, -"tcsetpgrp($module, fd, pgid, /)\n" -"--\n" -"\n" -"Set the process group associated with the terminal specified by fd."); - -#define OS_TCSETPGRP_METHODDEF \ - {"tcsetpgrp", _PyCFunction_CAST(os_tcsetpgrp), METH_FASTCALL, os_tcsetpgrp__doc__}, - -static PyObject * -os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid); - -static PyObject * -os_tcsetpgrp(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - pid_t pgid; - - if (!_PyArg_ParseStack(args, nargs, "i" _Py_PARSE_PID ":tcsetpgrp", - &fd, &pgid)) { - goto exit; - } - return_value = os_tcsetpgrp_impl(module, fd, pgid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_TCSETPGRP) */ - -PyDoc_STRVAR(os_open__doc__, -"open($module, /, path, flags, mode=511, *, dir_fd=None)\n" -"--\n" -"\n" -"Open a file for low level IO. Returns a file descriptor (integer).\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"dir_fd may not be implemented on your platform.\n" -" If it is unavailable, using it will raise a NotImplementedError."); - -#define OS_OPEN_METHODDEF \ - {"open", _PyCFunction_CAST(os_open), METH_FASTCALL|METH_KEYWORDS, os_open__doc__}, - -static int -os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd); - -static PyObject * -os_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 4 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(flags), &_Py_ID(mode), &_Py_ID(dir_fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "flags", "mode", "dir_fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "open", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[4]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("open", "path", 0, 0); - int flags; - int mode = 511; - int dir_fd = DEFAULT_DIR_FD; - int _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - flags = _PyLong_AsInt(args[1]); - if (flags == -1 && PyErr_Occurred()) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[2]) { - mode = _PyLong_AsInt(args[2]); - if (mode == -1 && PyErr_Occurred()) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } -skip_optional_pos: - if (!noptargs) { - goto skip_optional_kwonly; - } - if (!OPENAT_DIR_FD_CONVERTER(args[3], &dir_fd)) { - goto exit; - } -skip_optional_kwonly: - _return_value = os_open_impl(module, &path, flags, mode, dir_fd); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromLong((long)_return_value); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -PyDoc_STRVAR(os_close__doc__, -"close($module, /, fd)\n" -"--\n" -"\n" -"Close a file descriptor."); - -#define OS_CLOSE_METHODDEF \ - {"close", _PyCFunction_CAST(os_close), METH_FASTCALL|METH_KEYWORDS, os_close__doc__}, - -static PyObject * -os_close_impl(PyObject *module, int fd); - -static PyObject * -os_close(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "close", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int fd; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_close_impl(module, fd); - -exit: - return return_value; -} - -PyDoc_STRVAR(os_closerange__doc__, -"closerange($module, fd_low, fd_high, /)\n" -"--\n" -"\n" -"Closes all file descriptors in [fd_low, fd_high), ignoring errors."); - -#define OS_CLOSERANGE_METHODDEF \ - {"closerange", _PyCFunction_CAST(os_closerange), METH_FASTCALL, os_closerange__doc__}, - -static PyObject * -os_closerange_impl(PyObject *module, int fd_low, int fd_high); - -static PyObject * -os_closerange(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd_low; - int fd_high; - - if (!_PyArg_CheckPositional("closerange", nargs, 2, 2)) { - goto exit; - } - fd_low = _PyLong_AsInt(args[0]); - if (fd_low == -1 && PyErr_Occurred()) { - goto exit; - } - fd_high = _PyLong_AsInt(args[1]); - if (fd_high == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_closerange_impl(module, fd_low, fd_high); - -exit: - return return_value; -} - -PyDoc_STRVAR(os_dup__doc__, -"dup($module, fd, /)\n" -"--\n" -"\n" -"Return a duplicate of a file descriptor."); - -#define OS_DUP_METHODDEF \ - {"dup", (PyCFunction)os_dup, METH_O, os_dup__doc__}, - -static int -os_dup_impl(PyObject *module, int fd); - -static PyObject * -os_dup(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int fd; - int _return_value; - - fd = _PyLong_AsInt(arg); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_dup_impl(module, fd); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromLong((long)_return_value); - -exit: - return return_value; -} - -#if ((defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))) - -PyDoc_STRVAR(os_dup2__doc__, -"dup2($module, /, fd, fd2, inheritable=True)\n" -"--\n" -"\n" -"Duplicate file descriptor."); - -#define OS_DUP2_METHODDEF \ - {"dup2", _PyCFunction_CAST(os_dup2), METH_FASTCALL|METH_KEYWORDS, os_dup2__doc__}, - -static int -os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable); - -static PyObject * -os_dup2(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(fd), &_Py_ID(fd2), &_Py_ID(inheritable), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"fd", "fd2", "inheritable", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "dup2", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - int fd; - int fd2; - int inheritable = 1; - int _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf); - if (!args) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - fd2 = _PyLong_AsInt(args[1]); - if (fd2 == -1 && PyErr_Occurred()) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - inheritable = PyObject_IsTrue(args[2]); - if (inheritable < 0) { - goto exit; - } -skip_optional_pos: - _return_value = os_dup2_impl(module, fd, fd2, inheritable); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromLong((long)_return_value); - -exit: - return return_value; -} - -#endif /* ((defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))) */ - -#if defined(HAVE_LOCKF) - -PyDoc_STRVAR(os_lockf__doc__, -"lockf($module, fd, command, length, /)\n" -"--\n" -"\n" -"Apply, test or remove a POSIX lock on an open file descriptor.\n" -"\n" -" fd\n" -" An open file descriptor.\n" -" command\n" -" One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.\n" -" length\n" -" The number of bytes to lock, starting at the current position."); - -#define OS_LOCKF_METHODDEF \ - {"lockf", _PyCFunction_CAST(os_lockf), METH_FASTCALL, os_lockf__doc__}, - -static PyObject * -os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length); - -static PyObject * -os_lockf(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - int command; - Py_off_t length; - - if (!_PyArg_CheckPositional("lockf", nargs, 3, 3)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - command = _PyLong_AsInt(args[1]); - if (command == -1 && PyErr_Occurred()) { - goto exit; - } - if (!Py_off_t_converter(args[2], &length)) { - goto exit; - } - return_value = os_lockf_impl(module, fd, command, length); - -exit: - return return_value; -} - -#endif /* defined(HAVE_LOCKF) */ - -PyDoc_STRVAR(os_lseek__doc__, -"lseek($module, fd, position, how, /)\n" -"--\n" -"\n" -"Set the position of a file descriptor. Return the new position.\n" -"\n" -"Return the new cursor position in number of bytes\n" -"relative to the beginning of the file."); - -#define OS_LSEEK_METHODDEF \ - {"lseek", _PyCFunction_CAST(os_lseek), METH_FASTCALL, os_lseek__doc__}, - -static Py_off_t -os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how); - -static PyObject * -os_lseek(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - Py_off_t position; - int how; - Py_off_t _return_value; - - if (!_PyArg_CheckPositional("lseek", nargs, 3, 3)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - if (!Py_off_t_converter(args[1], &position)) { - goto exit; - } - how = _PyLong_AsInt(args[2]); - if (how == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_lseek_impl(module, fd, position, how); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromPy_off_t(_return_value); - -exit: - return return_value; -} - -PyDoc_STRVAR(os_read__doc__, -"read($module, fd, length, /)\n" -"--\n" -"\n" -"Read from a file descriptor. Returns a bytes object."); - -#define OS_READ_METHODDEF \ - {"read", _PyCFunction_CAST(os_read), METH_FASTCALL, os_read__doc__}, - -static PyObject * -os_read_impl(PyObject *module, int fd, Py_ssize_t length); - -static PyObject * -os_read(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - Py_ssize_t length; - - if (!_PyArg_CheckPositional("read", nargs, 2, 2)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[1]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - length = ival; - } - return_value = os_read_impl(module, fd, length); - -exit: - return return_value; -} - -#if defined(HAVE_READV) - -PyDoc_STRVAR(os_readv__doc__, -"readv($module, fd, buffers, /)\n" -"--\n" -"\n" -"Read from a file descriptor fd into an iterable of buffers.\n" -"\n" -"The buffers should be mutable buffers accepting bytes.\n" -"readv will transfer data into each buffer until it is full\n" -"and then move on to the next buffer in the sequence to hold\n" -"the rest of the data.\n" -"\n" -"readv returns the total number of bytes read,\n" -"which may be less than the total capacity of all the buffers."); - -#define OS_READV_METHODDEF \ - {"readv", _PyCFunction_CAST(os_readv), METH_FASTCALL, os_readv__doc__}, - -static Py_ssize_t -os_readv_impl(PyObject *module, int fd, PyObject *buffers); - -static PyObject * -os_readv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - PyObject *buffers; - Py_ssize_t _return_value; - - if (!_PyArg_CheckPositional("readv", nargs, 2, 2)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - buffers = args[1]; - _return_value = os_readv_impl(module, fd, buffers); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromSsize_t(_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_READV) */ - -#if defined(HAVE_PREAD) - -PyDoc_STRVAR(os_pread__doc__, -"pread($module, fd, length, offset, /)\n" -"--\n" -"\n" -"Read a number of bytes from a file descriptor starting at a particular offset.\n" -"\n" -"Read length bytes from file descriptor fd, starting at offset bytes from\n" -"the beginning of the file. The file offset remains unchanged."); - -#define OS_PREAD_METHODDEF \ - {"pread", _PyCFunction_CAST(os_pread), METH_FASTCALL, os_pread__doc__}, - -static PyObject * -os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset); - -static PyObject * -os_pread(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - Py_ssize_t length; - Py_off_t offset; - - if (!_PyArg_CheckPositional("pread", nargs, 3, 3)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[1]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - length = ival; - } - if (!Py_off_t_converter(args[2], &offset)) { - goto exit; - } - return_value = os_pread_impl(module, fd, length, offset); - -exit: - return return_value; -} - -#endif /* defined(HAVE_PREAD) */ - -#if (defined(HAVE_PREADV) || defined (HAVE_PREADV2)) - -PyDoc_STRVAR(os_preadv__doc__, -"preadv($module, fd, buffers, offset, flags=0, /)\n" -"--\n" -"\n" -"Reads from a file descriptor into a number of mutable bytes-like objects.\n" -"\n" -"Combines the functionality of readv() and pread(). As readv(), it will\n" -"transfer data into each buffer until it is full and then move on to the next\n" -"buffer in the sequence to hold the rest of the data. Its fourth argument,\n" -"specifies the file offset at which the input operation is to be performed. It\n" -"will return the total number of bytes read (which can be less than the total\n" -"capacity of all the objects).\n" -"\n" -"The flags argument contains a bitwise OR of zero or more of the following flags:\n" -"\n" -"- RWF_HIPRI\n" -"- RWF_NOWAIT\n" -"\n" -"Using non-zero flags requires Linux 4.6 or newer."); - -#define OS_PREADV_METHODDEF \ - {"preadv", _PyCFunction_CAST(os_preadv), METH_FASTCALL, os_preadv__doc__}, - -static Py_ssize_t -os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, - int flags); - -static PyObject * -os_preadv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - PyObject *buffers; - Py_off_t offset; - int flags = 0; - Py_ssize_t _return_value; - - if (!_PyArg_CheckPositional("preadv", nargs, 3, 4)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - buffers = args[1]; - if (!Py_off_t_converter(args[2], &offset)) { - goto exit; - } - if (nargs < 4) { - goto skip_optional; - } - flags = _PyLong_AsInt(args[3]); - if (flags == -1 && PyErr_Occurred()) { - goto exit; - } -skip_optional: - _return_value = os_preadv_impl(module, fd, buffers, offset, flags); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromSsize_t(_return_value); - -exit: - return return_value; -} - -#endif /* (defined(HAVE_PREADV) || defined (HAVE_PREADV2)) */ - -PyDoc_STRVAR(os_write__doc__, -"write($module, fd, data, /)\n" -"--\n" -"\n" -"Write a bytes object to a file descriptor."); - -#define OS_WRITE_METHODDEF \ - {"write", _PyCFunction_CAST(os_write), METH_FASTCALL, os_write__doc__}, - -static Py_ssize_t -os_write_impl(PyObject *module, int fd, Py_buffer *data); - -static PyObject * -os_write(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - Py_buffer data = {NULL, NULL}; - Py_ssize_t _return_value; - - if (!_PyArg_CheckPositional("write", nargs, 2, 2)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - if (PyObject_GetBuffer(args[1], &data, PyBUF_SIMPLE) != 0) { - goto exit; - } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("write", "argument 2", "contiguous buffer", args[1]); - goto exit; - } - _return_value = os_write_impl(module, fd, &data); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromSsize_t(_return_value); - -exit: - /* Cleanup for data */ - if (data.obj) { - PyBuffer_Release(&data); - } - - return return_value; -} - -#if defined(HAVE_SENDFILE) && defined(__APPLE__) - -PyDoc_STRVAR(os_sendfile__doc__, -"sendfile($module, /, out_fd, in_fd, offset, count, headers=(),\n" -" trailers=(), flags=0)\n" -"--\n" -"\n" -"Copy count bytes from file descriptor in_fd to file descriptor out_fd."); - -#define OS_SENDFILE_METHODDEF \ - {"sendfile", _PyCFunction_CAST(os_sendfile), METH_FASTCALL|METH_KEYWORDS, os_sendfile__doc__}, - -static PyObject * -os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset, - Py_off_t sbytes, PyObject *headers, PyObject *trailers, - int flags); - -static PyObject * -os_sendfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 7 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(out_fd), &_Py_ID(in_fd), &_Py_ID(offset), &_Py_ID(count), &_Py_ID(headers), &_Py_ID(trailers), &_Py_ID(flags), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"out_fd", "in_fd", "offset", "count", "headers", "trailers", "flags", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "sendfile", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[7]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 4; - int out_fd; - int in_fd; - Py_off_t offset; - Py_off_t sbytes; - PyObject *headers = NULL; - PyObject *trailers = NULL; - int flags = 0; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 4, 7, 0, argsbuf); - if (!args) { - goto exit; - } - out_fd = _PyLong_AsInt(args[0]); - if (out_fd == -1 && PyErr_Occurred()) { - goto exit; - } - in_fd = _PyLong_AsInt(args[1]); - if (in_fd == -1 && PyErr_Occurred()) { - goto exit; - } - if (!Py_off_t_converter(args[2], &offset)) { - goto exit; - } - if (!Py_off_t_converter(args[3], &sbytes)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[4]) { - headers = args[4]; - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (args[5]) { - trailers = args[5]; - if (!--noptargs) { - goto skip_optional_pos; - } - } - flags = _PyLong_AsInt(args[6]); - if (flags == -1 && PyErr_Occurred()) { - goto exit; - } -skip_optional_pos: - return_value = os_sendfile_impl(module, out_fd, in_fd, offset, sbytes, headers, trailers, flags); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SENDFILE) && defined(__APPLE__) */ - -#if defined(HAVE_SENDFILE) && !defined(__APPLE__) && (defined(__FreeBSD__) || defined(__DragonFly__)) - -PyDoc_STRVAR(os_sendfile__doc__, -"sendfile($module, /, out_fd, in_fd, offset, count, headers=(),\n" -" trailers=(), flags=0)\n" -"--\n" -"\n" -"Copy count bytes from file descriptor in_fd to file descriptor out_fd."); - -#define OS_SENDFILE_METHODDEF \ - {"sendfile", _PyCFunction_CAST(os_sendfile), METH_FASTCALL|METH_KEYWORDS, os_sendfile__doc__}, - -static PyObject * -os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset, - Py_ssize_t count, PyObject *headers, PyObject *trailers, - int flags); - -static PyObject * -os_sendfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 7 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(out_fd), &_Py_ID(in_fd), &_Py_ID(offset), &_Py_ID(count), &_Py_ID(headers), &_Py_ID(trailers), &_Py_ID(flags), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"out_fd", "in_fd", "offset", "count", "headers", "trailers", "flags", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "sendfile", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[7]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 4; - int out_fd; - int in_fd; - Py_off_t offset; - Py_ssize_t count; - PyObject *headers = NULL; - PyObject *trailers = NULL; - int flags = 0; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 4, 7, 0, argsbuf); - if (!args) { - goto exit; - } - out_fd = _PyLong_AsInt(args[0]); - if (out_fd == -1 && PyErr_Occurred()) { - goto exit; - } - in_fd = _PyLong_AsInt(args[1]); - if (in_fd == -1 && PyErr_Occurred()) { - goto exit; - } - if (!Py_off_t_converter(args[2], &offset)) { - goto exit; - } - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[3]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - count = ival; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[4]) { - headers = args[4]; - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (args[5]) { - trailers = args[5]; - if (!--noptargs) { - goto skip_optional_pos; - } - } - flags = _PyLong_AsInt(args[6]); - if (flags == -1 && PyErr_Occurred()) { - goto exit; - } -skip_optional_pos: - return_value = os_sendfile_impl(module, out_fd, in_fd, offset, count, headers, trailers, flags); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SENDFILE) && !defined(__APPLE__) && (defined(__FreeBSD__) || defined(__DragonFly__)) */ - -#if defined(HAVE_SENDFILE) && !defined(__APPLE__) && !(defined(__FreeBSD__) || defined(__DragonFly__)) - -PyDoc_STRVAR(os_sendfile__doc__, -"sendfile($module, /, out_fd, in_fd, offset, count)\n" -"--\n" -"\n" -"Copy count bytes from file descriptor in_fd to file descriptor out_fd."); - -#define OS_SENDFILE_METHODDEF \ - {"sendfile", _PyCFunction_CAST(os_sendfile), METH_FASTCALL|METH_KEYWORDS, os_sendfile__doc__}, - -static PyObject * -os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj, - Py_ssize_t count); - -static PyObject * -os_sendfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 4 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(out_fd), &_Py_ID(in_fd), &_Py_ID(offset), &_Py_ID(count), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"out_fd", "in_fd", "offset", "count", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "sendfile", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[4]; - int out_fd; - int in_fd; - PyObject *offobj; - Py_ssize_t count; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 4, 4, 0, argsbuf); - if (!args) { - goto exit; - } - out_fd = _PyLong_AsInt(args[0]); - if (out_fd == -1 && PyErr_Occurred()) { - goto exit; - } - in_fd = _PyLong_AsInt(args[1]); - if (in_fd == -1 && PyErr_Occurred()) { - goto exit; - } - offobj = args[2]; - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[3]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - count = ival; - } - return_value = os_sendfile_impl(module, out_fd, in_fd, offobj, count); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SENDFILE) && !defined(__APPLE__) && !(defined(__FreeBSD__) || defined(__DragonFly__)) */ - -#if defined(__APPLE__) - -PyDoc_STRVAR(os__fcopyfile__doc__, -"_fcopyfile($module, in_fd, out_fd, flags, /)\n" -"--\n" -"\n" -"Efficiently copy content or metadata of 2 regular file descriptors (macOS)."); - -#define OS__FCOPYFILE_METHODDEF \ - {"_fcopyfile", _PyCFunction_CAST(os__fcopyfile), METH_FASTCALL, os__fcopyfile__doc__}, - -static PyObject * -os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags); - -static PyObject * -os__fcopyfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int in_fd; - int out_fd; - int flags; - - if (!_PyArg_CheckPositional("_fcopyfile", nargs, 3, 3)) { - goto exit; - } - in_fd = _PyLong_AsInt(args[0]); - if (in_fd == -1 && PyErr_Occurred()) { - goto exit; - } - out_fd = _PyLong_AsInt(args[1]); - if (out_fd == -1 && PyErr_Occurred()) { - goto exit; - } - flags = _PyLong_AsInt(args[2]); - if (flags == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os__fcopyfile_impl(module, in_fd, out_fd, flags); - -exit: - return return_value; -} - -#endif /* defined(__APPLE__) */ - -PyDoc_STRVAR(os_fstat__doc__, -"fstat($module, /, fd)\n" -"--\n" -"\n" -"Perform a stat system call on the given file descriptor.\n" -"\n" -"Like stat(), but for an open file descriptor.\n" -"Equivalent to os.stat(fd)."); - -#define OS_FSTAT_METHODDEF \ - {"fstat", _PyCFunction_CAST(os_fstat), METH_FASTCALL|METH_KEYWORDS, os_fstat__doc__}, - -static PyObject * -os_fstat_impl(PyObject *module, int fd); - -static PyObject * -os_fstat(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "fstat", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int fd; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_fstat_impl(module, fd); - -exit: - return return_value; -} - -PyDoc_STRVAR(os_isatty__doc__, -"isatty($module, fd, /)\n" -"--\n" -"\n" -"Return True if the fd is connected to a terminal.\n" -"\n" -"Return True if the file descriptor is an open file descriptor\n" -"connected to the slave end of a terminal."); - -#define OS_ISATTY_METHODDEF \ - {"isatty", (PyCFunction)os_isatty, METH_O, os_isatty__doc__}, - -static int -os_isatty_impl(PyObject *module, int fd); - -static PyObject * -os_isatty(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int fd; - int _return_value; - - fd = _PyLong_AsInt(arg); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_isatty_impl(module, fd); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - -#if defined(HAVE_PIPE) - -PyDoc_STRVAR(os_pipe__doc__, -"pipe($module, /)\n" -"--\n" -"\n" -"Create a pipe.\n" -"\n" -"Returns a tuple of two file descriptors:\n" -" (read_fd, write_fd)"); - -#define OS_PIPE_METHODDEF \ - {"pipe", (PyCFunction)os_pipe, METH_NOARGS, os_pipe__doc__}, - -static PyObject * -os_pipe_impl(PyObject *module); - -static PyObject * -os_pipe(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_pipe_impl(module); -} - -#endif /* defined(HAVE_PIPE) */ - -#if defined(HAVE_PIPE2) - -PyDoc_STRVAR(os_pipe2__doc__, -"pipe2($module, flags, /)\n" -"--\n" -"\n" -"Create a pipe with flags set atomically.\n" -"\n" -"Returns a tuple of two file descriptors:\n" -" (read_fd, write_fd)\n" -"\n" -"flags can be constructed by ORing together one or more of these values:\n" -"O_NONBLOCK, O_CLOEXEC."); - -#define OS_PIPE2_METHODDEF \ - {"pipe2", (PyCFunction)os_pipe2, METH_O, os_pipe2__doc__}, - -static PyObject * -os_pipe2_impl(PyObject *module, int flags); - -static PyObject * -os_pipe2(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int flags; - - flags = _PyLong_AsInt(arg); - if (flags == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_pipe2_impl(module, flags); - -exit: - return return_value; -} - -#endif /* defined(HAVE_PIPE2) */ - -#if defined(HAVE_WRITEV) - -PyDoc_STRVAR(os_writev__doc__, -"writev($module, fd, buffers, /)\n" -"--\n" -"\n" -"Iterate over buffers, and write the contents of each to a file descriptor.\n" -"\n" -"Returns the total number of bytes written.\n" -"buffers must be a sequence of bytes-like objects."); - -#define OS_WRITEV_METHODDEF \ - {"writev", _PyCFunction_CAST(os_writev), METH_FASTCALL, os_writev__doc__}, - -static Py_ssize_t -os_writev_impl(PyObject *module, int fd, PyObject *buffers); - -static PyObject * -os_writev(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - PyObject *buffers; - Py_ssize_t _return_value; - - if (!_PyArg_CheckPositional("writev", nargs, 2, 2)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - buffers = args[1]; - _return_value = os_writev_impl(module, fd, buffers); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromSsize_t(_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_WRITEV) */ - -#if defined(HAVE_PWRITE) - -PyDoc_STRVAR(os_pwrite__doc__, -"pwrite($module, fd, buffer, offset, /)\n" -"--\n" -"\n" -"Write bytes to a file descriptor starting at a particular offset.\n" -"\n" -"Write buffer to fd, starting at offset bytes from the beginning of\n" -"the file. Returns the number of bytes writte. Does not change the\n" -"current file offset."); - -#define OS_PWRITE_METHODDEF \ - {"pwrite", _PyCFunction_CAST(os_pwrite), METH_FASTCALL, os_pwrite__doc__}, - -static Py_ssize_t -os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset); - -static PyObject * -os_pwrite(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - Py_buffer buffer = {NULL, NULL}; - Py_off_t offset; - Py_ssize_t _return_value; - - if (!_PyArg_CheckPositional("pwrite", nargs, 3, 3)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - if (PyObject_GetBuffer(args[1], &buffer, PyBUF_SIMPLE) != 0) { - goto exit; - } - if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("pwrite", "argument 2", "contiguous buffer", args[1]); - goto exit; - } - if (!Py_off_t_converter(args[2], &offset)) { - goto exit; - } - _return_value = os_pwrite_impl(module, fd, &buffer, offset); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromSsize_t(_return_value); - -exit: - /* Cleanup for buffer */ - if (buffer.obj) { - PyBuffer_Release(&buffer); - } - - return return_value; -} - -#endif /* defined(HAVE_PWRITE) */ - -#if (defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)) - -PyDoc_STRVAR(os_pwritev__doc__, -"pwritev($module, fd, buffers, offset, flags=0, /)\n" -"--\n" -"\n" -"Writes the contents of bytes-like objects to a file descriptor at a given offset.\n" -"\n" -"Combines the functionality of writev() and pwrite(). All buffers must be a sequence\n" -"of bytes-like objects. Buffers are processed in array order. Entire contents of first\n" -"buffer is written before proceeding to second, and so on. The operating system may\n" -"set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.\n" -"This function writes the contents of each object to the file descriptor and returns\n" -"the total number of bytes written.\n" -"\n" -"The flags argument contains a bitwise OR of zero or more of the following flags:\n" -"\n" -"- RWF_DSYNC\n" -"- RWF_SYNC\n" -"- RWF_APPEND\n" -"\n" -"Using non-zero flags requires Linux 4.7 or newer."); - -#define OS_PWRITEV_METHODDEF \ - {"pwritev", _PyCFunction_CAST(os_pwritev), METH_FASTCALL, os_pwritev__doc__}, - -static Py_ssize_t -os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, - int flags); - -static PyObject * -os_pwritev(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - PyObject *buffers; - Py_off_t offset; - int flags = 0; - Py_ssize_t _return_value; - - if (!_PyArg_CheckPositional("pwritev", nargs, 3, 4)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - buffers = args[1]; - if (!Py_off_t_converter(args[2], &offset)) { - goto exit; - } - if (nargs < 4) { - goto skip_optional; - } - flags = _PyLong_AsInt(args[3]); - if (flags == -1 && PyErr_Occurred()) { - goto exit; - } -skip_optional: - _return_value = os_pwritev_impl(module, fd, buffers, offset, flags); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromSsize_t(_return_value); - -exit: - return return_value; -} - -#endif /* (defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)) */ - -#if defined(HAVE_COPY_FILE_RANGE) - -PyDoc_STRVAR(os_copy_file_range__doc__, -"copy_file_range($module, /, src, dst, count, offset_src=None,\n" -" offset_dst=None)\n" -"--\n" -"\n" -"Copy count bytes from one file descriptor to another.\n" -"\n" -" src\n" -" Source file descriptor.\n" -" dst\n" -" Destination file descriptor.\n" -" count\n" -" Number of bytes to copy.\n" -" offset_src\n" -" Starting offset in src.\n" -" offset_dst\n" -" Starting offset in dst.\n" -"\n" -"If offset_src is None, then src is read from the current position;\n" -"respectively for offset_dst."); - -#define OS_COPY_FILE_RANGE_METHODDEF \ - {"copy_file_range", _PyCFunction_CAST(os_copy_file_range), METH_FASTCALL|METH_KEYWORDS, os_copy_file_range__doc__}, - -static PyObject * -os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count, - PyObject *offset_src, PyObject *offset_dst); - -static PyObject * -os_copy_file_range(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 5 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(src), &_Py_ID(dst), &_Py_ID(count), &_Py_ID(offset_src), &_Py_ID(offset_dst), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"src", "dst", "count", "offset_src", "offset_dst", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "copy_file_range", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[5]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - int src; - int dst; - Py_ssize_t count; - PyObject *offset_src = Py_None; - PyObject *offset_dst = Py_None; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 5, 0, argsbuf); - if (!args) { - goto exit; - } - src = _PyLong_AsInt(args[0]); - if (src == -1 && PyErr_Occurred()) { - goto exit; - } - dst = _PyLong_AsInt(args[1]); - if (dst == -1 && PyErr_Occurred()) { - goto exit; - } - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[2]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - count = ival; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[3]) { - offset_src = args[3]; - if (!--noptargs) { - goto skip_optional_pos; - } - } - offset_dst = args[4]; -skip_optional_pos: - return_value = os_copy_file_range_impl(module, src, dst, count, offset_src, offset_dst); - -exit: - return return_value; -} - -#endif /* defined(HAVE_COPY_FILE_RANGE) */ - -#if ((defined(HAVE_SPLICE) && !defined(_AIX))) - -PyDoc_STRVAR(os_splice__doc__, -"splice($module, /, src, dst, count, offset_src=None, offset_dst=None,\n" -" flags=0)\n" -"--\n" -"\n" -"Transfer count bytes from one pipe to a descriptor or vice versa.\n" -"\n" -" src\n" -" Source file descriptor.\n" -" dst\n" -" Destination file descriptor.\n" -" count\n" -" Number of bytes to copy.\n" -" offset_src\n" -" Starting offset in src.\n" -" offset_dst\n" -" Starting offset in dst.\n" -" flags\n" -" Flags to modify the semantics of the call.\n" -"\n" -"If offset_src is None, then src is read from the current position;\n" -"respectively for offset_dst. The offset associated to the file\n" -"descriptor that refers to a pipe must be None."); - -#define OS_SPLICE_METHODDEF \ - {"splice", _PyCFunction_CAST(os_splice), METH_FASTCALL|METH_KEYWORDS, os_splice__doc__}, - -static PyObject * -os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count, - PyObject *offset_src, PyObject *offset_dst, - unsigned int flags); - -static PyObject * -os_splice(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 6 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(src), &_Py_ID(dst), &_Py_ID(count), &_Py_ID(offset_src), &_Py_ID(offset_dst), &_Py_ID(flags), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"src", "dst", "count", "offset_src", "offset_dst", "flags", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "splice", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[6]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - int src; - int dst; - Py_ssize_t count; - PyObject *offset_src = Py_None; - PyObject *offset_dst = Py_None; - unsigned int flags = 0; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 6, 0, argsbuf); - if (!args) { - goto exit; - } - src = _PyLong_AsInt(args[0]); - if (src == -1 && PyErr_Occurred()) { - goto exit; - } - dst = _PyLong_AsInt(args[1]); - if (dst == -1 && PyErr_Occurred()) { - goto exit; - } - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[2]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - count = ival; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[3]) { - offset_src = args[3]; - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (args[4]) { - offset_dst = args[4]; - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (!_PyLong_UnsignedInt_Converter(args[5], &flags)) { - goto exit; - } -skip_optional_pos: - return_value = os_splice_impl(module, src, dst, count, offset_src, offset_dst, flags); - -exit: - return return_value; -} - -#endif /* ((defined(HAVE_SPLICE) && !defined(_AIX))) */ - -#if defined(HAVE_MKFIFO) - -PyDoc_STRVAR(os_mkfifo__doc__, -"mkfifo($module, /, path, mode=438, *, dir_fd=None)\n" -"--\n" -"\n" -"Create a \"fifo\" (a POSIX named pipe).\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"dir_fd may not be implemented on your platform.\n" -" If it is unavailable, using it will raise a NotImplementedError."); - -#define OS_MKFIFO_METHODDEF \ - {"mkfifo", _PyCFunction_CAST(os_mkfifo), METH_FASTCALL|METH_KEYWORDS, os_mkfifo__doc__}, - -static PyObject * -os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd); - -static PyObject * -os_mkfifo(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(mode), &_Py_ID(dir_fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "mode", "dir_fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "mkfifo", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("mkfifo", "path", 0, 0); - int mode = 438; - int dir_fd = DEFAULT_DIR_FD; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[1]) { - mode = _PyLong_AsInt(args[1]); - if (mode == -1 && PyErr_Occurred()) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } -skip_optional_pos: - if (!noptargs) { - goto skip_optional_kwonly; - } - if (!MKFIFOAT_DIR_FD_CONVERTER(args[2], &dir_fd)) { - goto exit; - } -skip_optional_kwonly: - return_value = os_mkfifo_impl(module, &path, mode, dir_fd); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(HAVE_MKFIFO) */ - -#if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) - -PyDoc_STRVAR(os_mknod__doc__, -"mknod($module, /, path, mode=384, device=0, *, dir_fd=None)\n" -"--\n" -"\n" -"Create a node in the file system.\n" -"\n" -"Create a node in the file system (file, device special file or named pipe)\n" -"at path. mode specifies both the permissions to use and the\n" -"type of node to be created, being combined (bitwise OR) with one of\n" -"S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode,\n" -"device defines the newly created device special file (probably using\n" -"os.makedev()). Otherwise device is ignored.\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"dir_fd may not be implemented on your platform.\n" -" If it is unavailable, using it will raise a NotImplementedError."); - -#define OS_MKNOD_METHODDEF \ - {"mknod", _PyCFunction_CAST(os_mknod), METH_FASTCALL|METH_KEYWORDS, os_mknod__doc__}, - -static PyObject * -os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device, - int dir_fd); - -static PyObject * -os_mknod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 4 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(mode), &_Py_ID(device), &_Py_ID(dir_fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "mode", "device", "dir_fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "mknod", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[4]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("mknod", "path", 0, 0); - int mode = 384; - dev_t device = 0; - int dir_fd = DEFAULT_DIR_FD; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[1]) { - mode = _PyLong_AsInt(args[1]); - if (mode == -1 && PyErr_Occurred()) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (args[2]) { - if (!_Py_Dev_Converter(args[2], &device)) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } -skip_optional_pos: - if (!noptargs) { - goto skip_optional_kwonly; - } - if (!MKNODAT_DIR_FD_CONVERTER(args[3], &dir_fd)) { - goto exit; - } -skip_optional_kwonly: - return_value = os_mknod_impl(module, &path, mode, device, dir_fd); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) */ - -#if defined(HAVE_DEVICE_MACROS) - -PyDoc_STRVAR(os_major__doc__, -"major($module, device, /)\n" -"--\n" -"\n" -"Extracts a device major number from a raw device number."); - -#define OS_MAJOR_METHODDEF \ - {"major", (PyCFunction)os_major, METH_O, os_major__doc__}, - -static unsigned int -os_major_impl(PyObject *module, dev_t device); - -static PyObject * -os_major(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - dev_t device; - unsigned int _return_value; - - if (!_Py_Dev_Converter(arg, &device)) { - goto exit; - } - _return_value = os_major_impl(module, device); - if ((_return_value == (unsigned int)-1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromUnsignedLong((unsigned long)_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_DEVICE_MACROS) */ - -#if defined(HAVE_DEVICE_MACROS) - -PyDoc_STRVAR(os_minor__doc__, -"minor($module, device, /)\n" -"--\n" -"\n" -"Extracts a device minor number from a raw device number."); - -#define OS_MINOR_METHODDEF \ - {"minor", (PyCFunction)os_minor, METH_O, os_minor__doc__}, - -static unsigned int -os_minor_impl(PyObject *module, dev_t device); - -static PyObject * -os_minor(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - dev_t device; - unsigned int _return_value; - - if (!_Py_Dev_Converter(arg, &device)) { - goto exit; - } - _return_value = os_minor_impl(module, device); - if ((_return_value == (unsigned int)-1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromUnsignedLong((unsigned long)_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_DEVICE_MACROS) */ - -#if defined(HAVE_DEVICE_MACROS) - -PyDoc_STRVAR(os_makedev__doc__, -"makedev($module, major, minor, /)\n" -"--\n" -"\n" -"Composes a raw device number from the major and minor device numbers."); - -#define OS_MAKEDEV_METHODDEF \ - {"makedev", _PyCFunction_CAST(os_makedev), METH_FASTCALL, os_makedev__doc__}, - -static dev_t -os_makedev_impl(PyObject *module, int major, int minor); - -static PyObject * -os_makedev(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int major; - int minor; - dev_t _return_value; - - if (!_PyArg_CheckPositional("makedev", nargs, 2, 2)) { - goto exit; - } - major = _PyLong_AsInt(args[0]); - if (major == -1 && PyErr_Occurred()) { - goto exit; - } - minor = _PyLong_AsInt(args[1]); - if (minor == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_makedev_impl(module, major, minor); - if ((_return_value == (dev_t)-1) && PyErr_Occurred()) { - goto exit; - } - return_value = _PyLong_FromDev(_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_DEVICE_MACROS) */ - -#if (defined HAVE_FTRUNCATE || defined MS_WINDOWS) - -PyDoc_STRVAR(os_ftruncate__doc__, -"ftruncate($module, fd, length, /)\n" -"--\n" -"\n" -"Truncate a file, specified by file descriptor, to a specific length."); - -#define OS_FTRUNCATE_METHODDEF \ - {"ftruncate", _PyCFunction_CAST(os_ftruncate), METH_FASTCALL, os_ftruncate__doc__}, - -static PyObject * -os_ftruncate_impl(PyObject *module, int fd, Py_off_t length); - -static PyObject * -os_ftruncate(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - Py_off_t length; - - if (!_PyArg_CheckPositional("ftruncate", nargs, 2, 2)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - if (!Py_off_t_converter(args[1], &length)) { - goto exit; - } - return_value = os_ftruncate_impl(module, fd, length); - -exit: - return return_value; -} - -#endif /* (defined HAVE_FTRUNCATE || defined MS_WINDOWS) */ - -#if (defined HAVE_TRUNCATE || defined MS_WINDOWS) - -PyDoc_STRVAR(os_truncate__doc__, -"truncate($module, /, path, length)\n" -"--\n" -"\n" -"Truncate a file, specified by path, to a specific length.\n" -"\n" -"On some platforms, path may also be specified as an open file descriptor.\n" -" If this functionality is unavailable, using it raises an exception."); - -#define OS_TRUNCATE_METHODDEF \ - {"truncate", _PyCFunction_CAST(os_truncate), METH_FASTCALL|METH_KEYWORDS, os_truncate__doc__}, - -static PyObject * -os_truncate_impl(PyObject *module, path_t *path, Py_off_t length); - -static PyObject * -os_truncate(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(length), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "length", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "truncate", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - path_t path = PATH_T_INITIALIZE("truncate", "path", 0, PATH_HAVE_FTRUNCATE); - Py_off_t length; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!Py_off_t_converter(args[1], &length)) { - goto exit; - } - return_value = os_truncate_impl(module, &path, length); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* (defined HAVE_TRUNCATE || defined MS_WINDOWS) */ - -#if (defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)) - -PyDoc_STRVAR(os_posix_fallocate__doc__, -"posix_fallocate($module, fd, offset, length, /)\n" -"--\n" -"\n" -"Ensure a file has allocated at least a particular number of bytes on disk.\n" -"\n" -"Ensure that the file specified by fd encompasses a range of bytes\n" -"starting at offset bytes from the beginning and continuing for length bytes."); - -#define OS_POSIX_FALLOCATE_METHODDEF \ - {"posix_fallocate", _PyCFunction_CAST(os_posix_fallocate), METH_FASTCALL, os_posix_fallocate__doc__}, - -static PyObject * -os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset, - Py_off_t length); - -static PyObject * -os_posix_fallocate(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - Py_off_t offset; - Py_off_t length; - - if (!_PyArg_CheckPositional("posix_fallocate", nargs, 3, 3)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - if (!Py_off_t_converter(args[1], &offset)) { - goto exit; - } - if (!Py_off_t_converter(args[2], &length)) { - goto exit; - } - return_value = os_posix_fallocate_impl(module, fd, offset, length); - -exit: - return return_value; -} - -#endif /* (defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)) */ - -#if (defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)) - -PyDoc_STRVAR(os_posix_fadvise__doc__, -"posix_fadvise($module, fd, offset, length, advice, /)\n" -"--\n" -"\n" -"Announce an intention to access data in a specific pattern.\n" -"\n" -"Announce an intention to access data in a specific pattern, thus allowing\n" -"the kernel to make optimizations.\n" -"The advice applies to the region of the file specified by fd starting at\n" -"offset and continuing for length bytes.\n" -"advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,\n" -"POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or\n" -"POSIX_FADV_DONTNEED."); - -#define OS_POSIX_FADVISE_METHODDEF \ - {"posix_fadvise", _PyCFunction_CAST(os_posix_fadvise), METH_FASTCALL, os_posix_fadvise__doc__}, - -static PyObject * -os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset, - Py_off_t length, int advice); - -static PyObject * -os_posix_fadvise(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - Py_off_t offset; - Py_off_t length; - int advice; - - if (!_PyArg_CheckPositional("posix_fadvise", nargs, 4, 4)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - if (!Py_off_t_converter(args[1], &offset)) { - goto exit; - } - if (!Py_off_t_converter(args[2], &length)) { - goto exit; - } - advice = _PyLong_AsInt(args[3]); - if (advice == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_posix_fadvise_impl(module, fd, offset, length, advice); - -exit: - return return_value; -} - -#endif /* (defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)) */ - -#if defined(MS_WINDOWS) - -PyDoc_STRVAR(os_putenv__doc__, -"putenv($module, name, value, /)\n" -"--\n" -"\n" -"Change or add an environment variable."); - -#define OS_PUTENV_METHODDEF \ - {"putenv", _PyCFunction_CAST(os_putenv), METH_FASTCALL, os_putenv__doc__}, - -static PyObject * -os_putenv_impl(PyObject *module, PyObject *name, PyObject *value); - -static PyObject * -os_putenv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - PyObject *name; - PyObject *value; - - if (!_PyArg_CheckPositional("putenv", nargs, 2, 2)) { - goto exit; - } - if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("putenv", "argument 1", "str", args[0]); - goto exit; - } - if (PyUnicode_READY(args[0]) == -1) { - goto exit; - } - name = args[0]; - if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("putenv", "argument 2", "str", args[1]); - goto exit; - } - if (PyUnicode_READY(args[1]) == -1) { - goto exit; - } - value = args[1]; - return_value = os_putenv_impl(module, name, value); - -exit: - return return_value; -} - -#endif /* defined(MS_WINDOWS) */ - -#if !defined(MS_WINDOWS) - -PyDoc_STRVAR(os_putenv__doc__, -"putenv($module, name, value, /)\n" -"--\n" -"\n" -"Change or add an environment variable."); - -#define OS_PUTENV_METHODDEF \ - {"putenv", _PyCFunction_CAST(os_putenv), METH_FASTCALL, os_putenv__doc__}, - -static PyObject * -os_putenv_impl(PyObject *module, PyObject *name, PyObject *value); - -static PyObject * -os_putenv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - PyObject *name = NULL; - PyObject *value = NULL; - - if (!_PyArg_CheckPositional("putenv", nargs, 2, 2)) { - goto exit; - } - if (!PyUnicode_FSConverter(args[0], &name)) { - goto exit; - } - if (!PyUnicode_FSConverter(args[1], &value)) { - goto exit; - } - return_value = os_putenv_impl(module, name, value); - -exit: - /* Cleanup for name */ - Py_XDECREF(name); - /* Cleanup for value */ - Py_XDECREF(value); - - return return_value; -} - -#endif /* !defined(MS_WINDOWS) */ - -#if defined(MS_WINDOWS) - -PyDoc_STRVAR(os_unsetenv__doc__, -"unsetenv($module, name, /)\n" -"--\n" -"\n" -"Delete an environment variable."); - -#define OS_UNSETENV_METHODDEF \ - {"unsetenv", (PyCFunction)os_unsetenv, METH_O, os_unsetenv__doc__}, - -static PyObject * -os_unsetenv_impl(PyObject *module, PyObject *name); - -static PyObject * -os_unsetenv(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - PyObject *name; - - if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("unsetenv", "argument", "str", arg); - goto exit; - } - if (PyUnicode_READY(arg) == -1) { - goto exit; - } - name = arg; - return_value = os_unsetenv_impl(module, name); - -exit: - return return_value; -} - -#endif /* defined(MS_WINDOWS) */ - -#if !defined(MS_WINDOWS) - -PyDoc_STRVAR(os_unsetenv__doc__, -"unsetenv($module, name, /)\n" -"--\n" -"\n" -"Delete an environment variable."); - -#define OS_UNSETENV_METHODDEF \ - {"unsetenv", (PyCFunction)os_unsetenv, METH_O, os_unsetenv__doc__}, - -static PyObject * -os_unsetenv_impl(PyObject *module, PyObject *name); - -static PyObject * -os_unsetenv(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - PyObject *name = NULL; - - if (!PyUnicode_FSConverter(arg, &name)) { - goto exit; - } - return_value = os_unsetenv_impl(module, name); - -exit: - /* Cleanup for name */ - Py_XDECREF(name); - - return return_value; -} - -#endif /* !defined(MS_WINDOWS) */ - -PyDoc_STRVAR(os_strerror__doc__, -"strerror($module, code, /)\n" -"--\n" -"\n" -"Translate an error code to a message string."); - -#define OS_STRERROR_METHODDEF \ - {"strerror", (PyCFunction)os_strerror, METH_O, os_strerror__doc__}, - -static PyObject * -os_strerror_impl(PyObject *module, int code); - -static PyObject * -os_strerror(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int code; - - code = _PyLong_AsInt(arg); - if (code == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_strerror_impl(module, code); - -exit: - return return_value; -} - -#if defined(HAVE_SYS_WAIT_H) && defined(WCOREDUMP) - -PyDoc_STRVAR(os_WCOREDUMP__doc__, -"WCOREDUMP($module, status, /)\n" -"--\n" -"\n" -"Return True if the process returning status was dumped to a core file."); - -#define OS_WCOREDUMP_METHODDEF \ - {"WCOREDUMP", (PyCFunction)os_WCOREDUMP, METH_O, os_WCOREDUMP__doc__}, - -static int -os_WCOREDUMP_impl(PyObject *module, int status); - -static PyObject * -os_WCOREDUMP(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int status; - int _return_value; - - status = _PyLong_AsInt(arg); - if (status == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_WCOREDUMP_impl(module, status); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SYS_WAIT_H) && defined(WCOREDUMP) */ - -#if defined(HAVE_SYS_WAIT_H) && defined(WIFCONTINUED) - -PyDoc_STRVAR(os_WIFCONTINUED__doc__, -"WIFCONTINUED($module, /, status)\n" -"--\n" -"\n" -"Return True if a particular process was continued from a job control stop.\n" -"\n" -"Return True if the process returning status was continued from a\n" -"job control stop."); - -#define OS_WIFCONTINUED_METHODDEF \ - {"WIFCONTINUED", _PyCFunction_CAST(os_WIFCONTINUED), METH_FASTCALL|METH_KEYWORDS, os_WIFCONTINUED__doc__}, - -static int -os_WIFCONTINUED_impl(PyObject *module, int status); - -static PyObject * -os_WIFCONTINUED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(status), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"status", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "WIFCONTINUED", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int status; - int _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - status = _PyLong_AsInt(args[0]); - if (status == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_WIFCONTINUED_impl(module, status); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SYS_WAIT_H) && defined(WIFCONTINUED) */ - -#if defined(HAVE_SYS_WAIT_H) && defined(WIFSTOPPED) - -PyDoc_STRVAR(os_WIFSTOPPED__doc__, -"WIFSTOPPED($module, /, status)\n" -"--\n" -"\n" -"Return True if the process returning status was stopped."); - -#define OS_WIFSTOPPED_METHODDEF \ - {"WIFSTOPPED", _PyCFunction_CAST(os_WIFSTOPPED), METH_FASTCALL|METH_KEYWORDS, os_WIFSTOPPED__doc__}, - -static int -os_WIFSTOPPED_impl(PyObject *module, int status); - -static PyObject * -os_WIFSTOPPED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(status), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"status", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "WIFSTOPPED", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int status; - int _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - status = _PyLong_AsInt(args[0]); - if (status == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_WIFSTOPPED_impl(module, status); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SYS_WAIT_H) && defined(WIFSTOPPED) */ - -#if defined(HAVE_SYS_WAIT_H) && defined(WIFSIGNALED) - -PyDoc_STRVAR(os_WIFSIGNALED__doc__, -"WIFSIGNALED($module, /, status)\n" -"--\n" -"\n" -"Return True if the process returning status was terminated by a signal."); - -#define OS_WIFSIGNALED_METHODDEF \ - {"WIFSIGNALED", _PyCFunction_CAST(os_WIFSIGNALED), METH_FASTCALL|METH_KEYWORDS, os_WIFSIGNALED__doc__}, - -static int -os_WIFSIGNALED_impl(PyObject *module, int status); - -static PyObject * -os_WIFSIGNALED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(status), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"status", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "WIFSIGNALED", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int status; - int _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - status = _PyLong_AsInt(args[0]); - if (status == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_WIFSIGNALED_impl(module, status); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SYS_WAIT_H) && defined(WIFSIGNALED) */ - -#if defined(HAVE_SYS_WAIT_H) && defined(WIFEXITED) - -PyDoc_STRVAR(os_WIFEXITED__doc__, -"WIFEXITED($module, /, status)\n" -"--\n" -"\n" -"Return True if the process returning status exited via the exit() system call."); - -#define OS_WIFEXITED_METHODDEF \ - {"WIFEXITED", _PyCFunction_CAST(os_WIFEXITED), METH_FASTCALL|METH_KEYWORDS, os_WIFEXITED__doc__}, - -static int -os_WIFEXITED_impl(PyObject *module, int status); - -static PyObject * -os_WIFEXITED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(status), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"status", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "WIFEXITED", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int status; - int _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - status = _PyLong_AsInt(args[0]); - if (status == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_WIFEXITED_impl(module, status); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SYS_WAIT_H) && defined(WIFEXITED) */ - -#if defined(HAVE_SYS_WAIT_H) && defined(WEXITSTATUS) - -PyDoc_STRVAR(os_WEXITSTATUS__doc__, -"WEXITSTATUS($module, /, status)\n" -"--\n" -"\n" -"Return the process return code from status."); - -#define OS_WEXITSTATUS_METHODDEF \ - {"WEXITSTATUS", _PyCFunction_CAST(os_WEXITSTATUS), METH_FASTCALL|METH_KEYWORDS, os_WEXITSTATUS__doc__}, - -static int -os_WEXITSTATUS_impl(PyObject *module, int status); - -static PyObject * -os_WEXITSTATUS(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(status), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"status", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "WEXITSTATUS", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int status; - int _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - status = _PyLong_AsInt(args[0]); - if (status == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_WEXITSTATUS_impl(module, status); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromLong((long)_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SYS_WAIT_H) && defined(WEXITSTATUS) */ - -#if defined(HAVE_SYS_WAIT_H) && defined(WTERMSIG) - -PyDoc_STRVAR(os_WTERMSIG__doc__, -"WTERMSIG($module, /, status)\n" -"--\n" -"\n" -"Return the signal that terminated the process that provided the status value."); - -#define OS_WTERMSIG_METHODDEF \ - {"WTERMSIG", _PyCFunction_CAST(os_WTERMSIG), METH_FASTCALL|METH_KEYWORDS, os_WTERMSIG__doc__}, - -static int -os_WTERMSIG_impl(PyObject *module, int status); - -static PyObject * -os_WTERMSIG(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(status), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"status", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "WTERMSIG", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int status; - int _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - status = _PyLong_AsInt(args[0]); - if (status == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_WTERMSIG_impl(module, status); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromLong((long)_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SYS_WAIT_H) && defined(WTERMSIG) */ - -#if defined(HAVE_SYS_WAIT_H) && defined(WSTOPSIG) - -PyDoc_STRVAR(os_WSTOPSIG__doc__, -"WSTOPSIG($module, /, status)\n" -"--\n" -"\n" -"Return the signal that stopped the process that provided the status value."); - -#define OS_WSTOPSIG_METHODDEF \ - {"WSTOPSIG", _PyCFunction_CAST(os_WSTOPSIG), METH_FASTCALL|METH_KEYWORDS, os_WSTOPSIG__doc__}, - -static int -os_WSTOPSIG_impl(PyObject *module, int status); - -static PyObject * -os_WSTOPSIG(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(status), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"status", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "WSTOPSIG", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int status; - int _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - status = _PyLong_AsInt(args[0]); - if (status == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_WSTOPSIG_impl(module, status); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromLong((long)_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SYS_WAIT_H) && defined(WSTOPSIG) */ - -#if (defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)) - -PyDoc_STRVAR(os_fstatvfs__doc__, -"fstatvfs($module, fd, /)\n" -"--\n" -"\n" -"Perform an fstatvfs system call on the given fd.\n" -"\n" -"Equivalent to statvfs(fd)."); - -#define OS_FSTATVFS_METHODDEF \ - {"fstatvfs", (PyCFunction)os_fstatvfs, METH_O, os_fstatvfs__doc__}, - -static PyObject * -os_fstatvfs_impl(PyObject *module, int fd); - -static PyObject * -os_fstatvfs(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int fd; - - fd = _PyLong_AsInt(arg); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_fstatvfs_impl(module, fd); - -exit: - return return_value; -} - -#endif /* (defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)) */ - -#if (defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)) - -PyDoc_STRVAR(os_statvfs__doc__, -"statvfs($module, /, path)\n" -"--\n" -"\n" -"Perform a statvfs system call on the given path.\n" -"\n" -"path may always be specified as a string.\n" -"On some platforms, path may also be specified as an open file descriptor.\n" -" If this functionality is unavailable, using it raises an exception."); - -#define OS_STATVFS_METHODDEF \ - {"statvfs", _PyCFunction_CAST(os_statvfs), METH_FASTCALL|METH_KEYWORDS, os_statvfs__doc__}, - -static PyObject * -os_statvfs_impl(PyObject *module, path_t *path); - -static PyObject * -os_statvfs(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "statvfs", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("statvfs", "path", 0, PATH_HAVE_FSTATVFS); - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - return_value = os_statvfs_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* (defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)) */ - -#if defined(MS_WINDOWS) - -PyDoc_STRVAR(os__getdiskusage__doc__, -"_getdiskusage($module, /, path)\n" -"--\n" -"\n" -"Return disk usage statistics about the given path as a (total, free) tuple."); - -#define OS__GETDISKUSAGE_METHODDEF \ - {"_getdiskusage", _PyCFunction_CAST(os__getdiskusage), METH_FASTCALL|METH_KEYWORDS, os__getdiskusage__doc__}, - -static PyObject * -os__getdiskusage_impl(PyObject *module, path_t *path); - -static PyObject * -os__getdiskusage(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "_getdiskusage", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_getdiskusage", "path", 0, 0); - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - return_value = os__getdiskusage_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(MS_WINDOWS) */ - -#if defined(HAVE_FPATHCONF) - -PyDoc_STRVAR(os_fpathconf__doc__, -"fpathconf($module, fd, name, /)\n" -"--\n" -"\n" -"Return the configuration limit name for the file descriptor fd.\n" -"\n" -"If there is no limit, return -1."); - -#define OS_FPATHCONF_METHODDEF \ - {"fpathconf", _PyCFunction_CAST(os_fpathconf), METH_FASTCALL, os_fpathconf__doc__}, - -static long -os_fpathconf_impl(PyObject *module, int fd, int name); - -static PyObject * -os_fpathconf(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - int name; - long _return_value; - - if (!_PyArg_CheckPositional("fpathconf", nargs, 2, 2)) { - goto exit; - } - if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { - goto exit; - } - if (!conv_path_confname(args[1], &name)) { - goto exit; - } - _return_value = os_fpathconf_impl(module, fd, name); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromLong(_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_FPATHCONF) */ - -#if defined(HAVE_PATHCONF) - -PyDoc_STRVAR(os_pathconf__doc__, -"pathconf($module, /, path, name)\n" -"--\n" -"\n" -"Return the configuration limit name for the file or directory path.\n" -"\n" -"If there is no limit, return -1.\n" -"On some platforms, path may also be specified as an open file descriptor.\n" -" If this functionality is unavailable, using it raises an exception."); - -#define OS_PATHCONF_METHODDEF \ - {"pathconf", _PyCFunction_CAST(os_pathconf), METH_FASTCALL|METH_KEYWORDS, os_pathconf__doc__}, - -static long -os_pathconf_impl(PyObject *module, path_t *path, int name); - -static PyObject * -os_pathconf(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(name), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "name", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "pathconf", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - path_t path = PATH_T_INITIALIZE("pathconf", "path", 0, PATH_HAVE_FPATHCONF); - int name; - long _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!conv_path_confname(args[1], &name)) { - goto exit; - } - _return_value = os_pathconf_impl(module, &path, name); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromLong(_return_value); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(HAVE_PATHCONF) */ - -#if defined(HAVE_CONFSTR) - -PyDoc_STRVAR(os_confstr__doc__, -"confstr($module, name, /)\n" -"--\n" -"\n" -"Return a string-valued system configuration variable."); - -#define OS_CONFSTR_METHODDEF \ - {"confstr", (PyCFunction)os_confstr, METH_O, os_confstr__doc__}, - -static PyObject * -os_confstr_impl(PyObject *module, int name); - -static PyObject * -os_confstr(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int name; - - if (!conv_confstr_confname(arg, &name)) { - goto exit; - } - return_value = os_confstr_impl(module, name); - -exit: - return return_value; -} - -#endif /* defined(HAVE_CONFSTR) */ - -#if defined(HAVE_SYSCONF) - -PyDoc_STRVAR(os_sysconf__doc__, -"sysconf($module, name, /)\n" -"--\n" -"\n" -"Return an integer-valued system configuration variable."); - -#define OS_SYSCONF_METHODDEF \ - {"sysconf", (PyCFunction)os_sysconf, METH_O, os_sysconf__doc__}, - -static long -os_sysconf_impl(PyObject *module, int name); - -static PyObject * -os_sysconf(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int name; - long _return_value; - - if (!conv_sysconf_confname(arg, &name)) { - goto exit; - } - _return_value = os_sysconf_impl(module, name); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromLong(_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SYSCONF) */ - -PyDoc_STRVAR(os_abort__doc__, -"abort($module, /)\n" -"--\n" -"\n" -"Abort the interpreter immediately.\n" -"\n" -"This function \'dumps core\' or otherwise fails in the hardest way possible\n" -"on the hosting operating system. This function never returns."); - -#define OS_ABORT_METHODDEF \ - {"abort", (PyCFunction)os_abort, METH_NOARGS, os_abort__doc__}, - -static PyObject * -os_abort_impl(PyObject *module); - -static PyObject * -os_abort(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_abort_impl(module); -} - -#if defined(MS_WINDOWS) - -PyDoc_STRVAR(os_startfile__doc__, -"startfile($module, /, filepath, operation=,\n" -" arguments=, cwd=None, show_cmd=1)\n" -"--\n" -"\n" -"Start a file with its associated application.\n" -"\n" -"When \"operation\" is not specified or \"open\", this acts like\n" -"double-clicking the file in Explorer, or giving the file name as an\n" -"argument to the DOS \"start\" command: the file is opened with whatever\n" -"application (if any) its extension is associated.\n" -"When another \"operation\" is given, it specifies what should be done with\n" -"the file. A typical operation is \"print\".\n" -"\n" -"\"arguments\" is passed to the application, but should be omitted if the\n" -"file is a document.\n" -"\n" -"\"cwd\" is the working directory for the operation. If \"filepath\" is\n" -"relative, it will be resolved against this directory. This argument\n" -"should usually be an absolute path.\n" -"\n" -"\"show_cmd\" can be used to override the recommended visibility option.\n" -"See the Windows ShellExecute documentation for values.\n" -"\n" -"startfile returns as soon as the associated application is launched.\n" -"There is no option to wait for the application to close, and no way\n" -"to retrieve the application\'s exit status.\n" -"\n" -"The filepath is relative to the current directory. If you want to use\n" -"an absolute path, make sure the first character is not a slash (\"/\");\n" -"the underlying Win32 ShellExecute function doesn\'t work if it is."); - -#define OS_STARTFILE_METHODDEF \ - {"startfile", _PyCFunction_CAST(os_startfile), METH_FASTCALL|METH_KEYWORDS, os_startfile__doc__}, - -static PyObject * -os_startfile_impl(PyObject *module, path_t *filepath, - const Py_UNICODE *operation, const Py_UNICODE *arguments, - path_t *cwd, int show_cmd); - -static PyObject * -os_startfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 5 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(filepath), &_Py_ID(operation), &_Py_ID(arguments), &_Py_ID(cwd), &_Py_ID(show_cmd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"filepath", "operation", "arguments", "cwd", "show_cmd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "startfile", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[5]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t filepath = PATH_T_INITIALIZE("startfile", "filepath", 0, 0); - const Py_UNICODE *operation = NULL; - const Py_UNICODE *arguments = NULL; - path_t cwd = PATH_T_INITIALIZE("startfile", "cwd", 1, 0); - int show_cmd = 1; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 5, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &filepath)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[1]) { - if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("startfile", "argument 'operation'", "str", args[1]); - goto exit; - } - operation = PyUnicode_AsWideCharString(args[1], NULL); - if (operation == NULL) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (args[2]) { - if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("startfile", "argument 'arguments'", "str", args[2]); - goto exit; - } - arguments = PyUnicode_AsWideCharString(args[2], NULL); - if (arguments == NULL) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (args[3]) { - if (!path_converter(args[3], &cwd)) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - show_cmd = _PyLong_AsInt(args[4]); - if (show_cmd == -1 && PyErr_Occurred()) { - goto exit; - } -skip_optional_pos: - return_value = os_startfile_impl(module, &filepath, operation, arguments, &cwd, show_cmd); - -exit: - /* Cleanup for filepath */ - path_cleanup(&filepath); - /* Cleanup for operation */ - PyMem_Free((void *)operation); - /* Cleanup for arguments */ - PyMem_Free((void *)arguments); - /* Cleanup for cwd */ - path_cleanup(&cwd); - - return return_value; -} - -#endif /* defined(MS_WINDOWS) */ - -#if defined(HAVE_GETLOADAVG) - -PyDoc_STRVAR(os_getloadavg__doc__, -"getloadavg($module, /)\n" -"--\n" -"\n" -"Return average recent system load information.\n" -"\n" -"Return the number of processes in the system run queue averaged over\n" -"the last 1, 5, and 15 minutes as a tuple of three floats.\n" -"Raises OSError if the load average was unobtainable."); - -#define OS_GETLOADAVG_METHODDEF \ - {"getloadavg", (PyCFunction)os_getloadavg, METH_NOARGS, os_getloadavg__doc__}, - -static PyObject * -os_getloadavg_impl(PyObject *module); - -static PyObject * -os_getloadavg(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getloadavg_impl(module); -} - -#endif /* defined(HAVE_GETLOADAVG) */ - -PyDoc_STRVAR(os_device_encoding__doc__, -"device_encoding($module, /, fd)\n" -"--\n" -"\n" -"Return a string describing the encoding of a terminal\'s file descriptor.\n" -"\n" -"The file descriptor must be attached to a terminal.\n" -"If the device is not a terminal, return None."); - -#define OS_DEVICE_ENCODING_METHODDEF \ - {"device_encoding", _PyCFunction_CAST(os_device_encoding), METH_FASTCALL|METH_KEYWORDS, os_device_encoding__doc__}, - -static PyObject * -os_device_encoding_impl(PyObject *module, int fd); - -static PyObject * -os_device_encoding(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "device_encoding", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int fd; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_device_encoding_impl(module, fd); - -exit: - return return_value; -} - -#if defined(HAVE_SETRESUID) - -PyDoc_STRVAR(os_setresuid__doc__, -"setresuid($module, ruid, euid, suid, /)\n" -"--\n" -"\n" -"Set the current process\'s real, effective, and saved user ids."); - -#define OS_SETRESUID_METHODDEF \ - {"setresuid", _PyCFunction_CAST(os_setresuid), METH_FASTCALL, os_setresuid__doc__}, - -static PyObject * -os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid); - -static PyObject * -os_setresuid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - uid_t ruid; - uid_t euid; - uid_t suid; - - if (!_PyArg_CheckPositional("setresuid", nargs, 3, 3)) { - goto exit; - } - if (!_Py_Uid_Converter(args[0], &ruid)) { - goto exit; - } - if (!_Py_Uid_Converter(args[1], &euid)) { - goto exit; - } - if (!_Py_Uid_Converter(args[2], &suid)) { - goto exit; - } - return_value = os_setresuid_impl(module, ruid, euid, suid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SETRESUID) */ - -#if defined(HAVE_SETRESGID) - -PyDoc_STRVAR(os_setresgid__doc__, -"setresgid($module, rgid, egid, sgid, /)\n" -"--\n" -"\n" -"Set the current process\'s real, effective, and saved group ids."); - -#define OS_SETRESGID_METHODDEF \ - {"setresgid", _PyCFunction_CAST(os_setresgid), METH_FASTCALL, os_setresgid__doc__}, - -static PyObject * -os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid); - -static PyObject * -os_setresgid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - gid_t rgid; - gid_t egid; - gid_t sgid; - - if (!_PyArg_CheckPositional("setresgid", nargs, 3, 3)) { - goto exit; - } - if (!_Py_Gid_Converter(args[0], &rgid)) { - goto exit; - } - if (!_Py_Gid_Converter(args[1], &egid)) { - goto exit; - } - if (!_Py_Gid_Converter(args[2], &sgid)) { - goto exit; - } - return_value = os_setresgid_impl(module, rgid, egid, sgid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SETRESGID) */ - -#if defined(HAVE_GETRESUID) - -PyDoc_STRVAR(os_getresuid__doc__, -"getresuid($module, /)\n" -"--\n" -"\n" -"Return a tuple of the current process\'s real, effective, and saved user ids."); - -#define OS_GETRESUID_METHODDEF \ - {"getresuid", (PyCFunction)os_getresuid, METH_NOARGS, os_getresuid__doc__}, - -static PyObject * -os_getresuid_impl(PyObject *module); - -static PyObject * -os_getresuid(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getresuid_impl(module); -} - -#endif /* defined(HAVE_GETRESUID) */ - -#if defined(HAVE_GETRESGID) - -PyDoc_STRVAR(os_getresgid__doc__, -"getresgid($module, /)\n" -"--\n" -"\n" -"Return a tuple of the current process\'s real, effective, and saved group ids."); - -#define OS_GETRESGID_METHODDEF \ - {"getresgid", (PyCFunction)os_getresgid, METH_NOARGS, os_getresgid__doc__}, - -static PyObject * -os_getresgid_impl(PyObject *module); - -static PyObject * -os_getresgid(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getresgid_impl(module); -} - -#endif /* defined(HAVE_GETRESGID) */ - -#if defined(USE_XATTRS) - -PyDoc_STRVAR(os_getxattr__doc__, -"getxattr($module, /, path, attribute, *, follow_symlinks=True)\n" -"--\n" -"\n" -"Return the value of extended attribute attribute on path.\n" -"\n" -"path may be either a string, a path-like object, or an open file descriptor.\n" -"If follow_symlinks is False, and the last element of the path is a symbolic\n" -" link, getxattr will examine the symbolic link itself instead of the file\n" -" the link points to."); - -#define OS_GETXATTR_METHODDEF \ - {"getxattr", _PyCFunction_CAST(os_getxattr), METH_FASTCALL|METH_KEYWORDS, os_getxattr__doc__}, - -static PyObject * -os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute, - int follow_symlinks); - -static PyObject * -os_getxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(attribute), &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "attribute", "follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "getxattr", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("getxattr", "path", 0, 1); - path_t attribute = PATH_T_INITIALIZE("getxattr", "attribute", 0, 0); - int follow_symlinks = 1; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!path_converter(args[1], &attribute)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - follow_symlinks = PyObject_IsTrue(args[2]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - return_value = os_getxattr_impl(module, &path, &attribute, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - /* Cleanup for attribute */ - path_cleanup(&attribute); - - return return_value; -} - -#endif /* defined(USE_XATTRS) */ - -#if defined(USE_XATTRS) - -PyDoc_STRVAR(os_setxattr__doc__, -"setxattr($module, /, path, attribute, value, flags=0, *,\n" -" follow_symlinks=True)\n" -"--\n" -"\n" -"Set extended attribute attribute on path to value.\n" -"\n" -"path may be either a string, a path-like object, or an open file descriptor.\n" -"If follow_symlinks is False, and the last element of the path is a symbolic\n" -" link, setxattr will modify the symbolic link itself instead of the file\n" -" the link points to."); - -#define OS_SETXATTR_METHODDEF \ - {"setxattr", _PyCFunction_CAST(os_setxattr), METH_FASTCALL|METH_KEYWORDS, os_setxattr__doc__}, - -static PyObject * -os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute, - Py_buffer *value, int flags, int follow_symlinks); - -static PyObject * -os_setxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 5 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(attribute), &_Py_ID(value), &_Py_ID(flags), &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "attribute", "value", "flags", "follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "setxattr", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[5]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - path_t path = PATH_T_INITIALIZE("setxattr", "path", 0, 1); - path_t attribute = PATH_T_INITIALIZE("setxattr", "attribute", 0, 0); - Py_buffer value = {NULL, NULL}; - int flags = 0; - int follow_symlinks = 1; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 4, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!path_converter(args[1], &attribute)) { - goto exit; - } - if (PyObject_GetBuffer(args[2], &value, PyBUF_SIMPLE) != 0) { - goto exit; - } - if (!PyBuffer_IsContiguous(&value, 'C')) { - _PyArg_BadArgument("setxattr", "argument 'value'", "contiguous buffer", args[2]); - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[3]) { - flags = _PyLong_AsInt(args[3]); - if (flags == -1 && PyErr_Occurred()) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } -skip_optional_pos: - if (!noptargs) { - goto skip_optional_kwonly; - } - follow_symlinks = PyObject_IsTrue(args[4]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - return_value = os_setxattr_impl(module, &path, &attribute, &value, flags, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - /* Cleanup for attribute */ - path_cleanup(&attribute); - /* Cleanup for value */ - if (value.obj) { - PyBuffer_Release(&value); - } - - return return_value; -} - -#endif /* defined(USE_XATTRS) */ - -#if defined(USE_XATTRS) - -PyDoc_STRVAR(os_removexattr__doc__, -"removexattr($module, /, path, attribute, *, follow_symlinks=True)\n" -"--\n" -"\n" -"Remove extended attribute attribute on path.\n" -"\n" -"path may be either a string, a path-like object, or an open file descriptor.\n" -"If follow_symlinks is False, and the last element of the path is a symbolic\n" -" link, removexattr will modify the symbolic link itself instead of the file\n" -" the link points to."); - -#define OS_REMOVEXATTR_METHODDEF \ - {"removexattr", _PyCFunction_CAST(os_removexattr), METH_FASTCALL|METH_KEYWORDS, os_removexattr__doc__}, - -static PyObject * -os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute, - int follow_symlinks); - -static PyObject * -os_removexattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(attribute), &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "attribute", "follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "removexattr", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("removexattr", "path", 0, 1); - path_t attribute = PATH_T_INITIALIZE("removexattr", "attribute", 0, 0); - int follow_symlinks = 1; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!path_converter(args[1], &attribute)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - follow_symlinks = PyObject_IsTrue(args[2]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - return_value = os_removexattr_impl(module, &path, &attribute, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - /* Cleanup for attribute */ - path_cleanup(&attribute); - - return return_value; -} - -#endif /* defined(USE_XATTRS) */ - -#if defined(USE_XATTRS) - -PyDoc_STRVAR(os_listxattr__doc__, -"listxattr($module, /, path=None, *, follow_symlinks=True)\n" -"--\n" -"\n" -"Return a list of extended attributes on path.\n" -"\n" -"path may be either None, a string, a path-like object, or an open file descriptor.\n" -"if path is None, listxattr will examine the current directory.\n" -"If follow_symlinks is False, and the last element of the path is a symbolic\n" -" link, listxattr will examine the symbolic link itself instead of the file\n" -" the link points to."); - -#define OS_LISTXATTR_METHODDEF \ - {"listxattr", _PyCFunction_CAST(os_listxattr), METH_FASTCALL|METH_KEYWORDS, os_listxattr__doc__}, - -static PyObject * -os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks); - -static PyObject * -os_listxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "listxattr", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - path_t path = PATH_T_INITIALIZE("listxattr", "path", 1, 1); - int follow_symlinks = 1; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[0]) { - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } -skip_optional_pos: - if (!noptargs) { - goto skip_optional_kwonly; - } - follow_symlinks = PyObject_IsTrue(args[1]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - return_value = os_listxattr_impl(module, &path, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(USE_XATTRS) */ - -PyDoc_STRVAR(os_urandom__doc__, -"urandom($module, size, /)\n" -"--\n" -"\n" -"Return a bytes object containing random bytes suitable for cryptographic use."); - -#define OS_URANDOM_METHODDEF \ - {"urandom", (PyCFunction)os_urandom, METH_O, os_urandom__doc__}, - -static PyObject * -os_urandom_impl(PyObject *module, Py_ssize_t size); - -static PyObject * -os_urandom(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - Py_ssize_t size; - - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(arg); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - size = ival; - } - return_value = os_urandom_impl(module, size); - -exit: - return return_value; -} - -#if defined(HAVE_MEMFD_CREATE) - -PyDoc_STRVAR(os_memfd_create__doc__, -"memfd_create($module, /, name, flags=MFD_CLOEXEC)\n" -"--\n" -"\n"); - -#define OS_MEMFD_CREATE_METHODDEF \ - {"memfd_create", _PyCFunction_CAST(os_memfd_create), METH_FASTCALL|METH_KEYWORDS, os_memfd_create__doc__}, - -static PyObject * -os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags); - -static PyObject * -os_memfd_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(name), &_Py_ID(flags), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"name", "flags", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "memfd_create", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - PyObject *name = NULL; - unsigned int flags = MFD_CLOEXEC; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!PyUnicode_FSConverter(args[0], &name)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - flags = (unsigned int)PyLong_AsUnsignedLongMask(args[1]); - if (flags == (unsigned int)-1 && PyErr_Occurred()) { - goto exit; - } -skip_optional_pos: - return_value = os_memfd_create_impl(module, name, flags); - -exit: - /* Cleanup for name */ - Py_XDECREF(name); - - return return_value; -} - -#endif /* defined(HAVE_MEMFD_CREATE) */ - -#if (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) - -PyDoc_STRVAR(os_eventfd__doc__, -"eventfd($module, /, initval, flags=EFD_CLOEXEC)\n" -"--\n" -"\n" -"Creates and returns an event notification file descriptor."); - -#define OS_EVENTFD_METHODDEF \ - {"eventfd", _PyCFunction_CAST(os_eventfd), METH_FASTCALL|METH_KEYWORDS, os_eventfd__doc__}, - -static PyObject * -os_eventfd_impl(PyObject *module, unsigned int initval, int flags); - -static PyObject * -os_eventfd(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(initval), &_Py_ID(flags), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"initval", "flags", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "eventfd", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - unsigned int initval; - int flags = EFD_CLOEXEC; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!_PyLong_UnsignedInt_Converter(args[0], &initval)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - flags = _PyLong_AsInt(args[1]); - if (flags == -1 && PyErr_Occurred()) { - goto exit; - } -skip_optional_pos: - return_value = os_eventfd_impl(module, initval, flags); - -exit: - return return_value; -} - -#endif /* (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) */ - -#if (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) - -PyDoc_STRVAR(os_eventfd_read__doc__, -"eventfd_read($module, /, fd)\n" -"--\n" -"\n" -"Read eventfd value"); - -#define OS_EVENTFD_READ_METHODDEF \ - {"eventfd_read", _PyCFunction_CAST(os_eventfd_read), METH_FASTCALL|METH_KEYWORDS, os_eventfd_read__doc__}, - -static PyObject * -os_eventfd_read_impl(PyObject *module, int fd); - -static PyObject * -os_eventfd_read(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "eventfd_read", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int fd; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { - goto exit; - } - return_value = os_eventfd_read_impl(module, fd); - -exit: - return return_value; -} - -#endif /* (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) */ - -#if (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) - -PyDoc_STRVAR(os_eventfd_write__doc__, -"eventfd_write($module, /, fd, value)\n" -"--\n" -"\n" -"Write eventfd value."); - -#define OS_EVENTFD_WRITE_METHODDEF \ - {"eventfd_write", _PyCFunction_CAST(os_eventfd_write), METH_FASTCALL|METH_KEYWORDS, os_eventfd_write__doc__}, - -static PyObject * -os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value); - -static PyObject * -os_eventfd_write(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(fd), &_Py_ID(value), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"fd", "value", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "eventfd_write", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - int fd; - unsigned long long value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { - goto exit; - } - if (!_PyLong_UnsignedLongLong_Converter(args[1], &value)) { - goto exit; - } - return_value = os_eventfd_write_impl(module, fd, value); - -exit: - return return_value; -} - -#endif /* (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) */ - -#if (defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)) - -PyDoc_STRVAR(os_get_terminal_size__doc__, -"get_terminal_size($module, fd=, /)\n" -"--\n" -"\n" -"Return the size of the terminal window as (columns, lines).\n" -"\n" -"The optional argument fd (default standard output) specifies\n" -"which file descriptor should be queried.\n" -"\n" -"If the file descriptor is not connected to a terminal, an OSError\n" -"is thrown.\n" -"\n" -"This function will only be defined if an implementation is\n" -"available for this system.\n" -"\n" -"shutil.get_terminal_size is the high-level function which should\n" -"normally be used, os.get_terminal_size is the low-level implementation."); - -#define OS_GET_TERMINAL_SIZE_METHODDEF \ - {"get_terminal_size", _PyCFunction_CAST(os_get_terminal_size), METH_FASTCALL, os_get_terminal_size__doc__}, - -static PyObject * -os_get_terminal_size_impl(PyObject *module, int fd); - -static PyObject * -os_get_terminal_size(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd = fileno(stdout); - - if (!_PyArg_CheckPositional("get_terminal_size", nargs, 0, 1)) { - goto exit; - } - if (nargs < 1) { - goto skip_optional; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } -skip_optional: - return_value = os_get_terminal_size_impl(module, fd); - -exit: - return return_value; -} - -#endif /* (defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)) */ - -PyDoc_STRVAR(os_cpu_count__doc__, -"cpu_count($module, /)\n" -"--\n" -"\n" -"Return the number of CPUs in the system; return None if indeterminable.\n" -"\n" -"This number is not equivalent to the number of CPUs the current process can\n" -"use. The number of usable CPUs can be obtained with\n" -"``len(os.sched_getaffinity(0))``"); - -#define OS_CPU_COUNT_METHODDEF \ - {"cpu_count", (PyCFunction)os_cpu_count, METH_NOARGS, os_cpu_count__doc__}, - -static PyObject * -os_cpu_count_impl(PyObject *module); - -static PyObject * -os_cpu_count(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_cpu_count_impl(module); -} - -PyDoc_STRVAR(os_get_inheritable__doc__, -"get_inheritable($module, fd, /)\n" -"--\n" -"\n" -"Get the close-on-exe flag of the specified file descriptor."); - -#define OS_GET_INHERITABLE_METHODDEF \ - {"get_inheritable", (PyCFunction)os_get_inheritable, METH_O, os_get_inheritable__doc__}, - -static int -os_get_inheritable_impl(PyObject *module, int fd); - -static PyObject * -os_get_inheritable(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int fd; - int _return_value; - - fd = _PyLong_AsInt(arg); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_get_inheritable_impl(module, fd); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - -PyDoc_STRVAR(os_set_inheritable__doc__, -"set_inheritable($module, fd, inheritable, /)\n" -"--\n" -"\n" -"Set the inheritable flag of the specified file descriptor."); - -#define OS_SET_INHERITABLE_METHODDEF \ - {"set_inheritable", _PyCFunction_CAST(os_set_inheritable), METH_FASTCALL, os_set_inheritable__doc__}, - -static PyObject * -os_set_inheritable_impl(PyObject *module, int fd, int inheritable); - -static PyObject * -os_set_inheritable(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - int inheritable; - - if (!_PyArg_CheckPositional("set_inheritable", nargs, 2, 2)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - inheritable = _PyLong_AsInt(args[1]); - if (inheritable == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_set_inheritable_impl(module, fd, inheritable); - -exit: - return return_value; -} - -#if defined(MS_WINDOWS) - -PyDoc_STRVAR(os_get_handle_inheritable__doc__, -"get_handle_inheritable($module, handle, /)\n" -"--\n" -"\n" -"Get the close-on-exe flag of the specified file descriptor."); - -#define OS_GET_HANDLE_INHERITABLE_METHODDEF \ - {"get_handle_inheritable", (PyCFunction)os_get_handle_inheritable, METH_O, os_get_handle_inheritable__doc__}, - -static int -os_get_handle_inheritable_impl(PyObject *module, intptr_t handle); - -static PyObject * -os_get_handle_inheritable(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - intptr_t handle; - int _return_value; - - if (!PyArg_Parse(arg, "" _Py_PARSE_INTPTR ":get_handle_inheritable", &handle)) { - goto exit; - } - _return_value = os_get_handle_inheritable_impl(module, handle); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - -#endif /* defined(MS_WINDOWS) */ - -#if defined(MS_WINDOWS) - -PyDoc_STRVAR(os_set_handle_inheritable__doc__, -"set_handle_inheritable($module, handle, inheritable, /)\n" -"--\n" -"\n" -"Set the inheritable flag of the specified handle."); - -#define OS_SET_HANDLE_INHERITABLE_METHODDEF \ - {"set_handle_inheritable", _PyCFunction_CAST(os_set_handle_inheritable), METH_FASTCALL, os_set_handle_inheritable__doc__}, - -static PyObject * -os_set_handle_inheritable_impl(PyObject *module, intptr_t handle, - int inheritable); - -static PyObject * -os_set_handle_inheritable(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - intptr_t handle; - int inheritable; - - if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_INTPTR "p:set_handle_inheritable", - &handle, &inheritable)) { - goto exit; - } - return_value = os_set_handle_inheritable_impl(module, handle, inheritable); - -exit: - return return_value; -} - -#endif /* defined(MS_WINDOWS) */ - -#if !defined(MS_WINDOWS) - -PyDoc_STRVAR(os_get_blocking__doc__, -"get_blocking($module, fd, /)\n" -"--\n" -"\n" -"Get the blocking mode of the file descriptor.\n" -"\n" -"Return False if the O_NONBLOCK flag is set, True if the flag is cleared."); - -#define OS_GET_BLOCKING_METHODDEF \ - {"get_blocking", (PyCFunction)os_get_blocking, METH_O, os_get_blocking__doc__}, - -static int -os_get_blocking_impl(PyObject *module, int fd); - -static PyObject * -os_get_blocking(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int fd; - int _return_value; - - fd = _PyLong_AsInt(arg); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_get_blocking_impl(module, fd); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - -#endif /* !defined(MS_WINDOWS) */ - -#if !defined(MS_WINDOWS) - -PyDoc_STRVAR(os_set_blocking__doc__, -"set_blocking($module, fd, blocking, /)\n" -"--\n" -"\n" -"Set the blocking mode of the specified file descriptor.\n" -"\n" -"Set the O_NONBLOCK flag if blocking is False,\n" -"clear the O_NONBLOCK flag otherwise."); - -#define OS_SET_BLOCKING_METHODDEF \ - {"set_blocking", _PyCFunction_CAST(os_set_blocking), METH_FASTCALL, os_set_blocking__doc__}, - -static PyObject * -os_set_blocking_impl(PyObject *module, int fd, int blocking); - -static PyObject * -os_set_blocking(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - int blocking; - - if (!_PyArg_CheckPositional("set_blocking", nargs, 2, 2)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - blocking = _PyLong_AsInt(args[1]); - if (blocking == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_set_blocking_impl(module, fd, blocking); - -exit: - return return_value; -} - -#endif /* !defined(MS_WINDOWS) */ - -PyDoc_STRVAR(os_DirEntry_is_symlink__doc__, -"is_symlink($self, /)\n" -"--\n" -"\n" -"Return True if the entry is a symbolic link; cached per entry."); - -#define OS_DIRENTRY_IS_SYMLINK_METHODDEF \ - {"is_symlink", _PyCFunction_CAST(os_DirEntry_is_symlink), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, os_DirEntry_is_symlink__doc__}, - -static int -os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class); - -static PyObject * -os_DirEntry_is_symlink(DirEntry *self, PyTypeObject *defining_class, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - int _return_value; - - if (nargs) { - PyErr_SetString(PyExc_TypeError, "is_symlink() takes no arguments"); - goto exit; - } - _return_value = os_DirEntry_is_symlink_impl(self, defining_class); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - -PyDoc_STRVAR(os_DirEntry_stat__doc__, -"stat($self, /, *, follow_symlinks=True)\n" -"--\n" -"\n" -"Return stat_result object for the entry; cached per entry."); - -#define OS_DIRENTRY_STAT_METHODDEF \ - {"stat", _PyCFunction_CAST(os_DirEntry_stat), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, os_DirEntry_stat__doc__}, - -static PyObject * -os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class, - int follow_symlinks); - -static PyObject * -os_DirEntry_stat(DirEntry *self, PyTypeObject *defining_class, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "stat", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - int follow_symlinks = 1; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf); - if (!args) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - follow_symlinks = PyObject_IsTrue(args[0]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - return_value = os_DirEntry_stat_impl(self, defining_class, follow_symlinks); - -exit: - return return_value; -} - -PyDoc_STRVAR(os_DirEntry_is_dir__doc__, -"is_dir($self, /, *, follow_symlinks=True)\n" -"--\n" -"\n" -"Return True if the entry is a directory; cached per entry."); - -#define OS_DIRENTRY_IS_DIR_METHODDEF \ - {"is_dir", _PyCFunction_CAST(os_DirEntry_is_dir), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, os_DirEntry_is_dir__doc__}, - -static int -os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class, - int follow_symlinks); - -static PyObject * -os_DirEntry_is_dir(DirEntry *self, PyTypeObject *defining_class, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "is_dir", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - int follow_symlinks = 1; - int _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf); - if (!args) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - follow_symlinks = PyObject_IsTrue(args[0]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - _return_value = os_DirEntry_is_dir_impl(self, defining_class, follow_symlinks); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - -PyDoc_STRVAR(os_DirEntry_is_file__doc__, -"is_file($self, /, *, follow_symlinks=True)\n" -"--\n" -"\n" -"Return True if the entry is a file; cached per entry."); - -#define OS_DIRENTRY_IS_FILE_METHODDEF \ - {"is_file", _PyCFunction_CAST(os_DirEntry_is_file), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, os_DirEntry_is_file__doc__}, - -static int -os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class, - int follow_symlinks); - -static PyObject * -os_DirEntry_is_file(DirEntry *self, PyTypeObject *defining_class, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "is_file", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - int follow_symlinks = 1; - int _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf); - if (!args) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - follow_symlinks = PyObject_IsTrue(args[0]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - _return_value = os_DirEntry_is_file_impl(self, defining_class, follow_symlinks); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - -PyDoc_STRVAR(os_DirEntry_inode__doc__, -"inode($self, /)\n" -"--\n" -"\n" -"Return inode of the entry; cached per entry."); - -#define OS_DIRENTRY_INODE_METHODDEF \ - {"inode", (PyCFunction)os_DirEntry_inode, METH_NOARGS, os_DirEntry_inode__doc__}, - -static PyObject * -os_DirEntry_inode_impl(DirEntry *self); - -static PyObject * -os_DirEntry_inode(DirEntry *self, PyObject *Py_UNUSED(ignored)) -{ - return os_DirEntry_inode_impl(self); -} - -PyDoc_STRVAR(os_DirEntry___fspath____doc__, -"__fspath__($self, /)\n" -"--\n" -"\n" -"Returns the path for the entry."); - -#define OS_DIRENTRY___FSPATH___METHODDEF \ - {"__fspath__", (PyCFunction)os_DirEntry___fspath__, METH_NOARGS, os_DirEntry___fspath____doc__}, - -static PyObject * -os_DirEntry___fspath___impl(DirEntry *self); - -static PyObject * -os_DirEntry___fspath__(DirEntry *self, PyObject *Py_UNUSED(ignored)) -{ - return os_DirEntry___fspath___impl(self); -} - -PyDoc_STRVAR(os_scandir__doc__, -"scandir($module, /, path=None)\n" -"--\n" -"\n" -"Return an iterator of DirEntry objects for given path.\n" -"\n" -"path can be specified as either str, bytes, or a path-like object. If path\n" -"is bytes, the names of yielded DirEntry objects will also be bytes; in\n" -"all other circumstances they will be str.\n" -"\n" -"If path is None, uses the path=\'.\'."); - -#define OS_SCANDIR_METHODDEF \ - {"scandir", _PyCFunction_CAST(os_scandir), METH_FASTCALL|METH_KEYWORDS, os_scandir__doc__}, - -static PyObject * -os_scandir_impl(PyObject *module, path_t *path); - -static PyObject * -os_scandir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "scandir", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - path_t path = PATH_T_INITIALIZE("scandir", "path", 1, PATH_HAVE_FDOPENDIR); - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (!path_converter(args[0], &path)) { - goto exit; - } -skip_optional_pos: - return_value = os_scandir_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -PyDoc_STRVAR(os_fspath__doc__, -"fspath($module, /, path)\n" -"--\n" -"\n" -"Return the file system path representation of the object.\n" -"\n" -"If the object is str or bytes, then allow it to pass through as-is. If the\n" -"object defines __fspath__(), then return the result of that method. All other\n" -"types raise a TypeError."); - -#define OS_FSPATH_METHODDEF \ - {"fspath", _PyCFunction_CAST(os_fspath), METH_FASTCALL|METH_KEYWORDS, os_fspath__doc__}, - -static PyObject * -os_fspath_impl(PyObject *module, PyObject *path); - -static PyObject * -os_fspath(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "fspath", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - PyObject *path; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - path = args[0]; - return_value = os_fspath_impl(module, path); - -exit: - return return_value; -} - -#if defined(HAVE_GETRANDOM_SYSCALL) - -PyDoc_STRVAR(os_getrandom__doc__, -"getrandom($module, /, size, flags=0)\n" -"--\n" -"\n" -"Obtain a series of random bytes."); - -#define OS_GETRANDOM_METHODDEF \ - {"getrandom", _PyCFunction_CAST(os_getrandom), METH_FASTCALL|METH_KEYWORDS, os_getrandom__doc__}, - -static PyObject * -os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags); - -static PyObject * -os_getrandom(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(size), &_Py_ID(flags), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"size", "flags", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "getrandom", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - Py_ssize_t size; - int flags = 0; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); - if (!args) { - goto exit; - } - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[0]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - size = ival; - } - if (!noptargs) { - goto skip_optional_pos; - } - flags = _PyLong_AsInt(args[1]); - if (flags == -1 && PyErr_Occurred()) { - goto exit; - } -skip_optional_pos: - return_value = os_getrandom_impl(module, size, flags); - -exit: - return return_value; -} - -#endif /* defined(HAVE_GETRANDOM_SYSCALL) */ - -#if defined(MS_WINDOWS) - -PyDoc_STRVAR(os__add_dll_directory__doc__, -"_add_dll_directory($module, /, path)\n" -"--\n" -"\n" -"Add a path to the DLL search path.\n" -"\n" -"This search path is used when resolving dependencies for imported\n" -"extension modules (the module itself is resolved through sys.path),\n" -"and also by ctypes.\n" -"\n" -"Returns an opaque value that may be passed to os.remove_dll_directory\n" -"to remove this directory from the search path."); - -#define OS__ADD_DLL_DIRECTORY_METHODDEF \ - {"_add_dll_directory", _PyCFunction_CAST(os__add_dll_directory), METH_FASTCALL|METH_KEYWORDS, os__add_dll_directory__doc__}, - -static PyObject * -os__add_dll_directory_impl(PyObject *module, path_t *path); - -static PyObject * -os__add_dll_directory(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "_add_dll_directory", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_add_dll_directory", "path", 0, 0); - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - return_value = os__add_dll_directory_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(MS_WINDOWS) */ - -#if defined(MS_WINDOWS) - -PyDoc_STRVAR(os__remove_dll_directory__doc__, -"_remove_dll_directory($module, /, cookie)\n" -"--\n" -"\n" -"Removes a path from the DLL search path.\n" -"\n" -"The parameter is an opaque value that was returned from\n" -"os.add_dll_directory. You can only remove directories that you added\n" -"yourself."); - -#define OS__REMOVE_DLL_DIRECTORY_METHODDEF \ - {"_remove_dll_directory", _PyCFunction_CAST(os__remove_dll_directory), METH_FASTCALL|METH_KEYWORDS, os__remove_dll_directory__doc__}, - -static PyObject * -os__remove_dll_directory_impl(PyObject *module, PyObject *cookie); - -static PyObject * -os__remove_dll_directory(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(cookie), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"cookie", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "_remove_dll_directory", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - PyObject *cookie; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - cookie = args[0]; - return_value = os__remove_dll_directory_impl(module, cookie); - -exit: - return return_value; -} - -#endif /* defined(MS_WINDOWS) */ - -#if (defined(WIFEXITED) || defined(MS_WINDOWS)) - -PyDoc_STRVAR(os_waitstatus_to_exitcode__doc__, -"waitstatus_to_exitcode($module, /, status)\n" -"--\n" -"\n" -"Convert a wait status to an exit code.\n" -"\n" -"On Unix:\n" -"\n" -"* If WIFEXITED(status) is true, return WEXITSTATUS(status).\n" -"* If WIFSIGNALED(status) is true, return -WTERMSIG(status).\n" -"* Otherwise, raise a ValueError.\n" -"\n" -"On Windows, return status shifted right by 8 bits.\n" -"\n" -"On Unix, if the process is being traced or if waitpid() was called with\n" -"WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.\n" -"This function must not be called if WIFSTOPPED(status) is true."); - -#define OS_WAITSTATUS_TO_EXITCODE_METHODDEF \ - {"waitstatus_to_exitcode", _PyCFunction_CAST(os_waitstatus_to_exitcode), METH_FASTCALL|METH_KEYWORDS, os_waitstatus_to_exitcode__doc__}, - -static PyObject * -os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj); - -static PyObject * -os_waitstatus_to_exitcode(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(status), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"status", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "waitstatus_to_exitcode", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - PyObject *status_obj; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - status_obj = args[0]; - return_value = os_waitstatus_to_exitcode_impl(module, status_obj); - -exit: - return return_value; -} - -#endif /* (defined(WIFEXITED) || defined(MS_WINDOWS)) */ - -#ifndef OS_TTYNAME_METHODDEF - #define OS_TTYNAME_METHODDEF -#endif /* !defined(OS_TTYNAME_METHODDEF) */ - -#ifndef OS_CTERMID_METHODDEF - #define OS_CTERMID_METHODDEF -#endif /* !defined(OS_CTERMID_METHODDEF) */ - -#ifndef OS_FCHDIR_METHODDEF - #define OS_FCHDIR_METHODDEF -#endif /* !defined(OS_FCHDIR_METHODDEF) */ - -#ifndef OS_FCHMOD_METHODDEF - #define OS_FCHMOD_METHODDEF -#endif /* !defined(OS_FCHMOD_METHODDEF) */ - -#ifndef OS_LCHMOD_METHODDEF - #define OS_LCHMOD_METHODDEF -#endif /* !defined(OS_LCHMOD_METHODDEF) */ - -#ifndef OS_CHFLAGS_METHODDEF - #define OS_CHFLAGS_METHODDEF -#endif /* !defined(OS_CHFLAGS_METHODDEF) */ - -#ifndef OS_LCHFLAGS_METHODDEF - #define OS_LCHFLAGS_METHODDEF -#endif /* !defined(OS_LCHFLAGS_METHODDEF) */ - -#ifndef OS_CHROOT_METHODDEF - #define OS_CHROOT_METHODDEF -#endif /* !defined(OS_CHROOT_METHODDEF) */ - -#ifndef OS_FSYNC_METHODDEF - #define OS_FSYNC_METHODDEF -#endif /* !defined(OS_FSYNC_METHODDEF) */ - -#ifndef OS_SYNC_METHODDEF - #define OS_SYNC_METHODDEF -#endif /* !defined(OS_SYNC_METHODDEF) */ - -#ifndef OS_FDATASYNC_METHODDEF - #define OS_FDATASYNC_METHODDEF -#endif /* !defined(OS_FDATASYNC_METHODDEF) */ - -#ifndef OS_CHOWN_METHODDEF - #define OS_CHOWN_METHODDEF -#endif /* !defined(OS_CHOWN_METHODDEF) */ - -#ifndef OS_FCHOWN_METHODDEF - #define OS_FCHOWN_METHODDEF -#endif /* !defined(OS_FCHOWN_METHODDEF) */ - -#ifndef OS_LCHOWN_METHODDEF - #define OS_LCHOWN_METHODDEF -#endif /* !defined(OS_LCHOWN_METHODDEF) */ - -#ifndef OS_LINK_METHODDEF - #define OS_LINK_METHODDEF -#endif /* !defined(OS_LINK_METHODDEF) */ - -#ifndef OS__GETFULLPATHNAME_METHODDEF - #define OS__GETFULLPATHNAME_METHODDEF -#endif /* !defined(OS__GETFULLPATHNAME_METHODDEF) */ - -#ifndef OS__GETFINALPATHNAME_METHODDEF - #define OS__GETFINALPATHNAME_METHODDEF -#endif /* !defined(OS__GETFINALPATHNAME_METHODDEF) */ - -#ifndef OS__GETVOLUMEPATHNAME_METHODDEF - #define OS__GETVOLUMEPATHNAME_METHODDEF -#endif /* !defined(OS__GETVOLUMEPATHNAME_METHODDEF) */ - -#ifndef OS__PATH_SPLITROOT_METHODDEF - #define OS__PATH_SPLITROOT_METHODDEF -#endif /* !defined(OS__PATH_SPLITROOT_METHODDEF) */ - -#ifndef OS_NICE_METHODDEF - #define OS_NICE_METHODDEF -#endif /* !defined(OS_NICE_METHODDEF) */ - -#ifndef OS_GETPRIORITY_METHODDEF - #define OS_GETPRIORITY_METHODDEF -#endif /* !defined(OS_GETPRIORITY_METHODDEF) */ - -#ifndef OS_SETPRIORITY_METHODDEF - #define OS_SETPRIORITY_METHODDEF -#endif /* !defined(OS_SETPRIORITY_METHODDEF) */ - -#ifndef OS_SYSTEM_METHODDEF - #define OS_SYSTEM_METHODDEF -#endif /* !defined(OS_SYSTEM_METHODDEF) */ - -#ifndef OS_UMASK_METHODDEF - #define OS_UMASK_METHODDEF -#endif /* !defined(OS_UMASK_METHODDEF) */ - -#ifndef OS_UNAME_METHODDEF - #define OS_UNAME_METHODDEF -#endif /* !defined(OS_UNAME_METHODDEF) */ - -#ifndef OS_EXECV_METHODDEF - #define OS_EXECV_METHODDEF -#endif /* !defined(OS_EXECV_METHODDEF) */ - -#ifndef OS_EXECVE_METHODDEF - #define OS_EXECVE_METHODDEF -#endif /* !defined(OS_EXECVE_METHODDEF) */ - -#ifndef OS_POSIX_SPAWN_METHODDEF - #define OS_POSIX_SPAWN_METHODDEF -#endif /* !defined(OS_POSIX_SPAWN_METHODDEF) */ - -#ifndef OS_POSIX_SPAWNP_METHODDEF - #define OS_POSIX_SPAWNP_METHODDEF -#endif /* !defined(OS_POSIX_SPAWNP_METHODDEF) */ - -#ifndef OS_SPAWNV_METHODDEF - #define OS_SPAWNV_METHODDEF -#endif /* !defined(OS_SPAWNV_METHODDEF) */ - -#ifndef OS_SPAWNVE_METHODDEF - #define OS_SPAWNVE_METHODDEF -#endif /* !defined(OS_SPAWNVE_METHODDEF) */ - -#ifndef OS_REGISTER_AT_FORK_METHODDEF - #define OS_REGISTER_AT_FORK_METHODDEF -#endif /* !defined(OS_REGISTER_AT_FORK_METHODDEF) */ - -#ifndef OS_FORK1_METHODDEF - #define OS_FORK1_METHODDEF -#endif /* !defined(OS_FORK1_METHODDEF) */ - -#ifndef OS_FORK_METHODDEF - #define OS_FORK_METHODDEF -#endif /* !defined(OS_FORK_METHODDEF) */ - -#ifndef OS_SCHED_GET_PRIORITY_MAX_METHODDEF - #define OS_SCHED_GET_PRIORITY_MAX_METHODDEF -#endif /* !defined(OS_SCHED_GET_PRIORITY_MAX_METHODDEF) */ - -#ifndef OS_SCHED_GET_PRIORITY_MIN_METHODDEF - #define OS_SCHED_GET_PRIORITY_MIN_METHODDEF -#endif /* !defined(OS_SCHED_GET_PRIORITY_MIN_METHODDEF) */ - -#ifndef OS_SCHED_GETSCHEDULER_METHODDEF - #define OS_SCHED_GETSCHEDULER_METHODDEF -#endif /* !defined(OS_SCHED_GETSCHEDULER_METHODDEF) */ - -#ifndef OS_SCHED_SETSCHEDULER_METHODDEF - #define OS_SCHED_SETSCHEDULER_METHODDEF -#endif /* !defined(OS_SCHED_SETSCHEDULER_METHODDEF) */ - -#ifndef OS_SCHED_GETPARAM_METHODDEF - #define OS_SCHED_GETPARAM_METHODDEF -#endif /* !defined(OS_SCHED_GETPARAM_METHODDEF) */ - -#ifndef OS_SCHED_SETPARAM_METHODDEF - #define OS_SCHED_SETPARAM_METHODDEF -#endif /* !defined(OS_SCHED_SETPARAM_METHODDEF) */ - -#ifndef OS_SCHED_RR_GET_INTERVAL_METHODDEF - #define OS_SCHED_RR_GET_INTERVAL_METHODDEF -#endif /* !defined(OS_SCHED_RR_GET_INTERVAL_METHODDEF) */ - -#ifndef OS_SCHED_YIELD_METHODDEF - #define OS_SCHED_YIELD_METHODDEF -#endif /* !defined(OS_SCHED_YIELD_METHODDEF) */ - -#ifndef OS_SCHED_SETAFFINITY_METHODDEF - #define OS_SCHED_SETAFFINITY_METHODDEF -#endif /* !defined(OS_SCHED_SETAFFINITY_METHODDEF) */ - -#ifndef OS_SCHED_GETAFFINITY_METHODDEF - #define OS_SCHED_GETAFFINITY_METHODDEF -#endif /* !defined(OS_SCHED_GETAFFINITY_METHODDEF) */ - -#ifndef OS_OPENPTY_METHODDEF - #define OS_OPENPTY_METHODDEF -#endif /* !defined(OS_OPENPTY_METHODDEF) */ - -#ifndef OS_LOGIN_TTY_METHODDEF - #define OS_LOGIN_TTY_METHODDEF -#endif /* !defined(OS_LOGIN_TTY_METHODDEF) */ - -#ifndef OS_FORKPTY_METHODDEF - #define OS_FORKPTY_METHODDEF -#endif /* !defined(OS_FORKPTY_METHODDEF) */ - -#ifndef OS_GETEGID_METHODDEF - #define OS_GETEGID_METHODDEF -#endif /* !defined(OS_GETEGID_METHODDEF) */ - -#ifndef OS_GETEUID_METHODDEF - #define OS_GETEUID_METHODDEF -#endif /* !defined(OS_GETEUID_METHODDEF) */ - -#ifndef OS_GETGID_METHODDEF - #define OS_GETGID_METHODDEF -#endif /* !defined(OS_GETGID_METHODDEF) */ - -#ifndef OS_GETPID_METHODDEF - #define OS_GETPID_METHODDEF -#endif /* !defined(OS_GETPID_METHODDEF) */ - -#ifndef OS_GETGROUPLIST_METHODDEF - #define OS_GETGROUPLIST_METHODDEF -#endif /* !defined(OS_GETGROUPLIST_METHODDEF) */ - -#ifndef OS_GETGROUPS_METHODDEF - #define OS_GETGROUPS_METHODDEF -#endif /* !defined(OS_GETGROUPS_METHODDEF) */ - -#ifndef OS_INITGROUPS_METHODDEF - #define OS_INITGROUPS_METHODDEF -#endif /* !defined(OS_INITGROUPS_METHODDEF) */ - -#ifndef OS_GETPGID_METHODDEF - #define OS_GETPGID_METHODDEF -#endif /* !defined(OS_GETPGID_METHODDEF) */ - -#ifndef OS_GETPGRP_METHODDEF - #define OS_GETPGRP_METHODDEF -#endif /* !defined(OS_GETPGRP_METHODDEF) */ - -#ifndef OS_SETPGRP_METHODDEF - #define OS_SETPGRP_METHODDEF -#endif /* !defined(OS_SETPGRP_METHODDEF) */ - -#ifndef OS_GETPPID_METHODDEF - #define OS_GETPPID_METHODDEF -#endif /* !defined(OS_GETPPID_METHODDEF) */ - -#ifndef OS_GETLOGIN_METHODDEF - #define OS_GETLOGIN_METHODDEF -#endif /* !defined(OS_GETLOGIN_METHODDEF) */ - -#ifndef OS_GETUID_METHODDEF - #define OS_GETUID_METHODDEF -#endif /* !defined(OS_GETUID_METHODDEF) */ - -#ifndef OS_KILL_METHODDEF - #define OS_KILL_METHODDEF -#endif /* !defined(OS_KILL_METHODDEF) */ - -#ifndef OS_KILLPG_METHODDEF - #define OS_KILLPG_METHODDEF -#endif /* !defined(OS_KILLPG_METHODDEF) */ - -#ifndef OS_PLOCK_METHODDEF - #define OS_PLOCK_METHODDEF -#endif /* !defined(OS_PLOCK_METHODDEF) */ - -#ifndef OS_SETUID_METHODDEF - #define OS_SETUID_METHODDEF -#endif /* !defined(OS_SETUID_METHODDEF) */ - -#ifndef OS_SETEUID_METHODDEF - #define OS_SETEUID_METHODDEF -#endif /* !defined(OS_SETEUID_METHODDEF) */ - -#ifndef OS_SETEGID_METHODDEF - #define OS_SETEGID_METHODDEF -#endif /* !defined(OS_SETEGID_METHODDEF) */ - -#ifndef OS_SETREUID_METHODDEF - #define OS_SETREUID_METHODDEF -#endif /* !defined(OS_SETREUID_METHODDEF) */ - -#ifndef OS_SETREGID_METHODDEF - #define OS_SETREGID_METHODDEF -#endif /* !defined(OS_SETREGID_METHODDEF) */ - -#ifndef OS_SETGID_METHODDEF - #define OS_SETGID_METHODDEF -#endif /* !defined(OS_SETGID_METHODDEF) */ - -#ifndef OS_SETGROUPS_METHODDEF - #define OS_SETGROUPS_METHODDEF -#endif /* !defined(OS_SETGROUPS_METHODDEF) */ - -#ifndef OS_WAIT3_METHODDEF - #define OS_WAIT3_METHODDEF -#endif /* !defined(OS_WAIT3_METHODDEF) */ - -#ifndef OS_WAIT4_METHODDEF - #define OS_WAIT4_METHODDEF -#endif /* !defined(OS_WAIT4_METHODDEF) */ - -#ifndef OS_WAITID_METHODDEF - #define OS_WAITID_METHODDEF -#endif /* !defined(OS_WAITID_METHODDEF) */ - -#ifndef OS_WAITPID_METHODDEF - #define OS_WAITPID_METHODDEF -#endif /* !defined(OS_WAITPID_METHODDEF) */ - -#ifndef OS_WAIT_METHODDEF - #define OS_WAIT_METHODDEF -#endif /* !defined(OS_WAIT_METHODDEF) */ - -#ifndef OS_PIDFD_OPEN_METHODDEF - #define OS_PIDFD_OPEN_METHODDEF -#endif /* !defined(OS_PIDFD_OPEN_METHODDEF) */ - -#ifndef OS_SETNS_METHODDEF - #define OS_SETNS_METHODDEF -#endif /* !defined(OS_SETNS_METHODDEF) */ - -#ifndef OS_UNSHARE_METHODDEF - #define OS_UNSHARE_METHODDEF -#endif /* !defined(OS_UNSHARE_METHODDEF) */ - -#ifndef OS_READLINK_METHODDEF - #define OS_READLINK_METHODDEF -#endif /* !defined(OS_READLINK_METHODDEF) */ - -#ifndef OS_SYMLINK_METHODDEF - #define OS_SYMLINK_METHODDEF -#endif /* !defined(OS_SYMLINK_METHODDEF) */ - -#ifndef OS_TIMES_METHODDEF - #define OS_TIMES_METHODDEF -#endif /* !defined(OS_TIMES_METHODDEF) */ - -#ifndef OS_GETSID_METHODDEF - #define OS_GETSID_METHODDEF -#endif /* !defined(OS_GETSID_METHODDEF) */ - -#ifndef OS_SETSID_METHODDEF - #define OS_SETSID_METHODDEF -#endif /* !defined(OS_SETSID_METHODDEF) */ - -#ifndef OS_SETPGID_METHODDEF - #define OS_SETPGID_METHODDEF -#endif /* !defined(OS_SETPGID_METHODDEF) */ - -#ifndef OS_TCGETPGRP_METHODDEF - #define OS_TCGETPGRP_METHODDEF -#endif /* !defined(OS_TCGETPGRP_METHODDEF) */ - -#ifndef OS_TCSETPGRP_METHODDEF - #define OS_TCSETPGRP_METHODDEF -#endif /* !defined(OS_TCSETPGRP_METHODDEF) */ - -#ifndef OS_DUP2_METHODDEF - #define OS_DUP2_METHODDEF -#endif /* !defined(OS_DUP2_METHODDEF) */ - -#ifndef OS_LOCKF_METHODDEF - #define OS_LOCKF_METHODDEF -#endif /* !defined(OS_LOCKF_METHODDEF) */ - -#ifndef OS_READV_METHODDEF - #define OS_READV_METHODDEF -#endif /* !defined(OS_READV_METHODDEF) */ - -#ifndef OS_PREAD_METHODDEF - #define OS_PREAD_METHODDEF -#endif /* !defined(OS_PREAD_METHODDEF) */ - -#ifndef OS_PREADV_METHODDEF - #define OS_PREADV_METHODDEF -#endif /* !defined(OS_PREADV_METHODDEF) */ - -#ifndef OS_SENDFILE_METHODDEF - #define OS_SENDFILE_METHODDEF -#endif /* !defined(OS_SENDFILE_METHODDEF) */ - -#ifndef OS__FCOPYFILE_METHODDEF - #define OS__FCOPYFILE_METHODDEF -#endif /* !defined(OS__FCOPYFILE_METHODDEF) */ - -#ifndef OS_PIPE_METHODDEF - #define OS_PIPE_METHODDEF -#endif /* !defined(OS_PIPE_METHODDEF) */ - -#ifndef OS_PIPE2_METHODDEF - #define OS_PIPE2_METHODDEF -#endif /* !defined(OS_PIPE2_METHODDEF) */ - -#ifndef OS_WRITEV_METHODDEF - #define OS_WRITEV_METHODDEF -#endif /* !defined(OS_WRITEV_METHODDEF) */ - -#ifndef OS_PWRITE_METHODDEF - #define OS_PWRITE_METHODDEF -#endif /* !defined(OS_PWRITE_METHODDEF) */ - -#ifndef OS_PWRITEV_METHODDEF - #define OS_PWRITEV_METHODDEF -#endif /* !defined(OS_PWRITEV_METHODDEF) */ - -#ifndef OS_COPY_FILE_RANGE_METHODDEF - #define OS_COPY_FILE_RANGE_METHODDEF -#endif /* !defined(OS_COPY_FILE_RANGE_METHODDEF) */ - -#ifndef OS_SPLICE_METHODDEF - #define OS_SPLICE_METHODDEF -#endif /* !defined(OS_SPLICE_METHODDEF) */ - -#ifndef OS_MKFIFO_METHODDEF - #define OS_MKFIFO_METHODDEF -#endif /* !defined(OS_MKFIFO_METHODDEF) */ - -#ifndef OS_MKNOD_METHODDEF - #define OS_MKNOD_METHODDEF -#endif /* !defined(OS_MKNOD_METHODDEF) */ - -#ifndef OS_MAJOR_METHODDEF - #define OS_MAJOR_METHODDEF -#endif /* !defined(OS_MAJOR_METHODDEF) */ - -#ifndef OS_MINOR_METHODDEF - #define OS_MINOR_METHODDEF -#endif /* !defined(OS_MINOR_METHODDEF) */ - -#ifndef OS_MAKEDEV_METHODDEF - #define OS_MAKEDEV_METHODDEF -#endif /* !defined(OS_MAKEDEV_METHODDEF) */ - -#ifndef OS_FTRUNCATE_METHODDEF - #define OS_FTRUNCATE_METHODDEF -#endif /* !defined(OS_FTRUNCATE_METHODDEF) */ - -#ifndef OS_TRUNCATE_METHODDEF - #define OS_TRUNCATE_METHODDEF -#endif /* !defined(OS_TRUNCATE_METHODDEF) */ - -#ifndef OS_POSIX_FALLOCATE_METHODDEF - #define OS_POSIX_FALLOCATE_METHODDEF -#endif /* !defined(OS_POSIX_FALLOCATE_METHODDEF) */ - -#ifndef OS_POSIX_FADVISE_METHODDEF - #define OS_POSIX_FADVISE_METHODDEF -#endif /* !defined(OS_POSIX_FADVISE_METHODDEF) */ - -#ifndef OS_PUTENV_METHODDEF - #define OS_PUTENV_METHODDEF -#endif /* !defined(OS_PUTENV_METHODDEF) */ - -#ifndef OS_UNSETENV_METHODDEF - #define OS_UNSETENV_METHODDEF -#endif /* !defined(OS_UNSETENV_METHODDEF) */ - -#ifndef OS_WCOREDUMP_METHODDEF - #define OS_WCOREDUMP_METHODDEF -#endif /* !defined(OS_WCOREDUMP_METHODDEF) */ - -#ifndef OS_WIFCONTINUED_METHODDEF - #define OS_WIFCONTINUED_METHODDEF -#endif /* !defined(OS_WIFCONTINUED_METHODDEF) */ - -#ifndef OS_WIFSTOPPED_METHODDEF - #define OS_WIFSTOPPED_METHODDEF -#endif /* !defined(OS_WIFSTOPPED_METHODDEF) */ - -#ifndef OS_WIFSIGNALED_METHODDEF - #define OS_WIFSIGNALED_METHODDEF -#endif /* !defined(OS_WIFSIGNALED_METHODDEF) */ - -#ifndef OS_WIFEXITED_METHODDEF - #define OS_WIFEXITED_METHODDEF -#endif /* !defined(OS_WIFEXITED_METHODDEF) */ - -#ifndef OS_WEXITSTATUS_METHODDEF - #define OS_WEXITSTATUS_METHODDEF -#endif /* !defined(OS_WEXITSTATUS_METHODDEF) */ - -#ifndef OS_WTERMSIG_METHODDEF - #define OS_WTERMSIG_METHODDEF -#endif /* !defined(OS_WTERMSIG_METHODDEF) */ - -#ifndef OS_WSTOPSIG_METHODDEF - #define OS_WSTOPSIG_METHODDEF -#endif /* !defined(OS_WSTOPSIG_METHODDEF) */ - -#ifndef OS_FSTATVFS_METHODDEF - #define OS_FSTATVFS_METHODDEF -#endif /* !defined(OS_FSTATVFS_METHODDEF) */ - -#ifndef OS_STATVFS_METHODDEF - #define OS_STATVFS_METHODDEF -#endif /* !defined(OS_STATVFS_METHODDEF) */ - -#ifndef OS__GETDISKUSAGE_METHODDEF - #define OS__GETDISKUSAGE_METHODDEF -#endif /* !defined(OS__GETDISKUSAGE_METHODDEF) */ - -#ifndef OS_FPATHCONF_METHODDEF - #define OS_FPATHCONF_METHODDEF -#endif /* !defined(OS_FPATHCONF_METHODDEF) */ - -#ifndef OS_PATHCONF_METHODDEF - #define OS_PATHCONF_METHODDEF -#endif /* !defined(OS_PATHCONF_METHODDEF) */ - -#ifndef OS_CONFSTR_METHODDEF - #define OS_CONFSTR_METHODDEF -#endif /* !defined(OS_CONFSTR_METHODDEF) */ - -#ifndef OS_SYSCONF_METHODDEF - #define OS_SYSCONF_METHODDEF -#endif /* !defined(OS_SYSCONF_METHODDEF) */ - -#ifndef OS_STARTFILE_METHODDEF - #define OS_STARTFILE_METHODDEF -#endif /* !defined(OS_STARTFILE_METHODDEF) */ - -#ifndef OS_GETLOADAVG_METHODDEF - #define OS_GETLOADAVG_METHODDEF -#endif /* !defined(OS_GETLOADAVG_METHODDEF) */ - -#ifndef OS_SETRESUID_METHODDEF - #define OS_SETRESUID_METHODDEF -#endif /* !defined(OS_SETRESUID_METHODDEF) */ - -#ifndef OS_SETRESGID_METHODDEF - #define OS_SETRESGID_METHODDEF -#endif /* !defined(OS_SETRESGID_METHODDEF) */ - -#ifndef OS_GETRESUID_METHODDEF - #define OS_GETRESUID_METHODDEF -#endif /* !defined(OS_GETRESUID_METHODDEF) */ - -#ifndef OS_GETRESGID_METHODDEF - #define OS_GETRESGID_METHODDEF -#endif /* !defined(OS_GETRESGID_METHODDEF) */ - -#ifndef OS_GETXATTR_METHODDEF - #define OS_GETXATTR_METHODDEF -#endif /* !defined(OS_GETXATTR_METHODDEF) */ - -#ifndef OS_SETXATTR_METHODDEF - #define OS_SETXATTR_METHODDEF -#endif /* !defined(OS_SETXATTR_METHODDEF) */ - -#ifndef OS_REMOVEXATTR_METHODDEF - #define OS_REMOVEXATTR_METHODDEF -#endif /* !defined(OS_REMOVEXATTR_METHODDEF) */ - -#ifndef OS_LISTXATTR_METHODDEF - #define OS_LISTXATTR_METHODDEF -#endif /* !defined(OS_LISTXATTR_METHODDEF) */ - -#ifndef OS_MEMFD_CREATE_METHODDEF - #define OS_MEMFD_CREATE_METHODDEF -#endif /* !defined(OS_MEMFD_CREATE_METHODDEF) */ - -#ifndef OS_EVENTFD_METHODDEF - #define OS_EVENTFD_METHODDEF -#endif /* !defined(OS_EVENTFD_METHODDEF) */ - -#ifndef OS_EVENTFD_READ_METHODDEF - #define OS_EVENTFD_READ_METHODDEF -#endif /* !defined(OS_EVENTFD_READ_METHODDEF) */ - -#ifndef OS_EVENTFD_WRITE_METHODDEF - #define OS_EVENTFD_WRITE_METHODDEF -#endif /* !defined(OS_EVENTFD_WRITE_METHODDEF) */ - -#ifndef OS_GET_TERMINAL_SIZE_METHODDEF - #define OS_GET_TERMINAL_SIZE_METHODDEF -#endif /* !defined(OS_GET_TERMINAL_SIZE_METHODDEF) */ - -#ifndef OS_GET_HANDLE_INHERITABLE_METHODDEF - #define OS_GET_HANDLE_INHERITABLE_METHODDEF -#endif /* !defined(OS_GET_HANDLE_INHERITABLE_METHODDEF) */ - -#ifndef OS_SET_HANDLE_INHERITABLE_METHODDEF - #define OS_SET_HANDLE_INHERITABLE_METHODDEF -#endif /* !defined(OS_SET_HANDLE_INHERITABLE_METHODDEF) */ - -#ifndef OS_GET_BLOCKING_METHODDEF - #define OS_GET_BLOCKING_METHODDEF -#endif /* !defined(OS_GET_BLOCKING_METHODDEF) */ - -#ifndef OS_SET_BLOCKING_METHODDEF - #define OS_SET_BLOCKING_METHODDEF -#endif /* !defined(OS_SET_BLOCKING_METHODDEF) */ - -#ifndef OS_GETRANDOM_METHODDEF - #define OS_GETRANDOM_METHODDEF -#endif /* !defined(OS_GETRANDOM_METHODDEF) */ - -#ifndef OS__ADD_DLL_DIRECTORY_METHODDEF - #define OS__ADD_DLL_DIRECTORY_METHODDEF -#endif /* !defined(OS__ADD_DLL_DIRECTORY_METHODDEF) */ - -#ifndef OS__REMOVE_DLL_DIRECTORY_METHODDEF - #define OS__REMOVE_DLL_DIRECTORY_METHODDEF -#endif /* !defined(OS__REMOVE_DLL_DIRECTORY_METHODDEF) */ - -#ifndef OS_WAITSTATUS_TO_EXITCODE_METHODDEF - #define OS_WAITSTATUS_TO_EXITCODE_METHODDEF -#endif /* !defined(OS_WAITSTATUS_TO_EXITCODE_METHODDEF) */ -/*[clinic end generated code: output=90f5e6995114e5ca input=a9049054013a1b77]*/ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() +#endif + + +PyDoc_STRVAR(os_stat__doc__, +"stat($module, /, path, *, dir_fd=None, follow_symlinks=True)\n" +"--\n" +"\n" +"Perform a stat system call on the given path.\n" +"\n" +" path\n" +" Path to be examined; can be string, bytes, a path-like object or\n" +" open-file-descriptor int.\n" +" dir_fd\n" +" If not None, it should be a file descriptor open to a directory,\n" +" and path should be a relative string; path will then be relative to\n" +" that directory.\n" +" follow_symlinks\n" +" If False, and the last element of the path is a symbolic link,\n" +" stat will examine the symbolic link itself instead of the file\n" +" the link points to.\n" +"\n" +"dir_fd and follow_symlinks may not be implemented\n" +" on your platform. If they are unavailable, using them will raise a\n" +" NotImplementedError.\n" +"\n" +"It\'s an error to use dir_fd or follow_symlinks when specifying path as\n" +" an open file descriptor."); + +#define OS_STAT_METHODDEF \ + {"stat", _PyCFunction_CAST(os_stat), METH_FASTCALL|METH_KEYWORDS, os_stat__doc__}, + +static PyObject * +os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks); + +static PyObject * +os_stat(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(dir_fd), &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "dir_fd", "follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "stat", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + path_t path = PATH_T_INITIALIZE("stat", "path", 0, 1); + int dir_fd = DEFAULT_DIR_FD; + int follow_symlinks = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[1]) { + if (!FSTATAT_DIR_FD_CONVERTER(args[1], &dir_fd)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + follow_symlinks = PyObject_IsTrue(args[2]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = os_stat_impl(module, &path, dir_fd, follow_symlinks); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +PyDoc_STRVAR(os_lstat__doc__, +"lstat($module, /, path, *, dir_fd=None)\n" +"--\n" +"\n" +"Perform a stat system call on the given path, without following symbolic links.\n" +"\n" +"Like stat(), but do not follow symbolic links.\n" +"Equivalent to stat(path, follow_symlinks=False)."); + +#define OS_LSTAT_METHODDEF \ + {"lstat", _PyCFunction_CAST(os_lstat), METH_FASTCALL|METH_KEYWORDS, os_lstat__doc__}, + +static PyObject * +os_lstat_impl(PyObject *module, path_t *path, int dir_fd); + +static PyObject * +os_lstat(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(dir_fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "dir_fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "lstat", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + path_t path = PATH_T_INITIALIZE("lstat", "path", 0, 0); + int dir_fd = DEFAULT_DIR_FD; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (!FSTATAT_DIR_FD_CONVERTER(args[1], &dir_fd)) { + goto exit; + } +skip_optional_kwonly: + return_value = os_lstat_impl(module, &path, dir_fd); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +PyDoc_STRVAR(os_access__doc__, +"access($module, /, path, mode, *, dir_fd=None, effective_ids=False,\n" +" follow_symlinks=True)\n" +"--\n" +"\n" +"Use the real uid/gid to test for access to a path.\n" +"\n" +" path\n" +" Path to be tested; can be string, bytes, or a path-like object.\n" +" mode\n" +" Operating-system mode bitfield. Can be F_OK to test existence,\n" +" or the inclusive-OR of R_OK, W_OK, and X_OK.\n" +" dir_fd\n" +" If not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that\n" +" directory.\n" +" effective_ids\n" +" If True, access will use the effective uid/gid instead of\n" +" the real uid/gid.\n" +" follow_symlinks\n" +" If False, and the last element of the path is a symbolic link,\n" +" access will examine the symbolic link itself instead of the file\n" +" the link points to.\n" +"\n" +"dir_fd, effective_ids, and follow_symlinks may not be implemented\n" +" on your platform. If they are unavailable, using them will raise a\n" +" NotImplementedError.\n" +"\n" +"Note that most operations will use the effective uid/gid, therefore this\n" +" routine can be used in a suid/sgid environment to test if the invoking user\n" +" has the specified access to the path."); + +#define OS_ACCESS_METHODDEF \ + {"access", _PyCFunction_CAST(os_access), METH_FASTCALL|METH_KEYWORDS, os_access__doc__}, + +static int +os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd, + int effective_ids, int follow_symlinks); + +static PyObject * +os_access(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 5 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(mode), &_Py_ID(dir_fd), &_Py_ID(effective_ids), &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "mode", "dir_fd", "effective_ids", "follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "access", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + path_t path = PATH_T_INITIALIZE("access", "path", 0, 0); + int mode; + int dir_fd = DEFAULT_DIR_FD; + int effective_ids = 0; + int follow_symlinks = 1; + int _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + mode = _PyLong_AsInt(args[1]); + if (mode == -1 && PyErr_Occurred()) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[2]) { + if (!FACCESSAT_DIR_FD_CONVERTER(args[2], &dir_fd)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[3]) { + effective_ids = PyObject_IsTrue(args[3]); + if (effective_ids < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + follow_symlinks = PyObject_IsTrue(args[4]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + _return_value = os_access_impl(module, &path, mode, dir_fd, effective_ids, follow_symlinks); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#if defined(HAVE_TTYNAME) + +PyDoc_STRVAR(os_ttyname__doc__, +"ttyname($module, fd, /)\n" +"--\n" +"\n" +"Return the name of the terminal device connected to \'fd\'.\n" +"\n" +" fd\n" +" Integer file descriptor handle."); + +#define OS_TTYNAME_METHODDEF \ + {"ttyname", (PyCFunction)os_ttyname, METH_O, os_ttyname__doc__}, + +static PyObject * +os_ttyname_impl(PyObject *module, int fd); + +static PyObject * +os_ttyname(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int fd; + + fd = _PyLong_AsInt(arg); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_ttyname_impl(module, fd); + +exit: + return return_value; +} + +#endif /* defined(HAVE_TTYNAME) */ + +#if defined(HAVE_CTERMID) + +PyDoc_STRVAR(os_ctermid__doc__, +"ctermid($module, /)\n" +"--\n" +"\n" +"Return the name of the controlling terminal for this process."); + +#define OS_CTERMID_METHODDEF \ + {"ctermid", (PyCFunction)os_ctermid, METH_NOARGS, os_ctermid__doc__}, + +static PyObject * +os_ctermid_impl(PyObject *module); + +static PyObject * +os_ctermid(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_ctermid_impl(module); +} + +#endif /* defined(HAVE_CTERMID) */ + +PyDoc_STRVAR(os_chdir__doc__, +"chdir($module, /, path)\n" +"--\n" +"\n" +"Change the current working directory to the specified path.\n" +"\n" +"path may always be specified as a string.\n" +"On some platforms, path may also be specified as an open file descriptor.\n" +" If this functionality is unavailable, using it raises an exception."); + +#define OS_CHDIR_METHODDEF \ + {"chdir", _PyCFunction_CAST(os_chdir), METH_FASTCALL|METH_KEYWORDS, os_chdir__doc__}, + +static PyObject * +os_chdir_impl(PyObject *module, path_t *path); + +static PyObject * +os_chdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "chdir", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + path_t path = PATH_T_INITIALIZE("chdir", "path", 0, PATH_HAVE_FCHDIR); + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + return_value = os_chdir_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#if defined(HAVE_FCHDIR) + +PyDoc_STRVAR(os_fchdir__doc__, +"fchdir($module, /, fd)\n" +"--\n" +"\n" +"Change to the directory of the given file descriptor.\n" +"\n" +"fd must be opened on a directory, not a file.\n" +"Equivalent to os.chdir(fd)."); + +#define OS_FCHDIR_METHODDEF \ + {"fchdir", _PyCFunction_CAST(os_fchdir), METH_FASTCALL|METH_KEYWORDS, os_fchdir__doc__}, + +static PyObject * +os_fchdir_impl(PyObject *module, int fd); + +static PyObject * +os_fchdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "fchdir", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int fd; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + return_value = os_fchdir_impl(module, fd); + +exit: + return return_value; +} + +#endif /* defined(HAVE_FCHDIR) */ + +PyDoc_STRVAR(os_chmod__doc__, +"chmod($module, /, path, mode, *, dir_fd=None, follow_symlinks=True)\n" +"--\n" +"\n" +"Change the access permissions of a file.\n" +"\n" +" path\n" +" Path to be modified. May always be specified as a str, bytes, or a path-like object.\n" +" On some platforms, path may also be specified as an open file descriptor.\n" +" If this functionality is unavailable, using it raises an exception.\n" +" mode\n" +" Operating-system mode bitfield.\n" +" dir_fd\n" +" If not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that\n" +" directory.\n" +" follow_symlinks\n" +" If False, and the last element of the path is a symbolic link,\n" +" chmod will modify the symbolic link itself instead of the file\n" +" the link points to.\n" +"\n" +"It is an error to use dir_fd or follow_symlinks when specifying path as\n" +" an open file descriptor.\n" +"dir_fd and follow_symlinks may not be implemented on your platform.\n" +" If they are unavailable, using them will raise a NotImplementedError."); + +#define OS_CHMOD_METHODDEF \ + {"chmod", _PyCFunction_CAST(os_chmod), METH_FASTCALL|METH_KEYWORDS, os_chmod__doc__}, + +static PyObject * +os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, + int follow_symlinks); + +static PyObject * +os_chmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(mode), &_Py_ID(dir_fd), &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "mode", "dir_fd", "follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "chmod", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + path_t path = PATH_T_INITIALIZE("chmod", "path", 0, PATH_HAVE_FCHMOD); + int mode; + int dir_fd = DEFAULT_DIR_FD; + int follow_symlinks = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + mode = _PyLong_AsInt(args[1]); + if (mode == -1 && PyErr_Occurred()) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[2]) { + if (!FCHMODAT_DIR_FD_CONVERTER(args[2], &dir_fd)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + follow_symlinks = PyObject_IsTrue(args[3]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = os_chmod_impl(module, &path, mode, dir_fd, follow_symlinks); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#if defined(HAVE_FCHMOD) + +PyDoc_STRVAR(os_fchmod__doc__, +"fchmod($module, /, fd, mode)\n" +"--\n" +"\n" +"Change the access permissions of the file given by file descriptor fd.\n" +"\n" +"Equivalent to os.chmod(fd, mode)."); + +#define OS_FCHMOD_METHODDEF \ + {"fchmod", _PyCFunction_CAST(os_fchmod), METH_FASTCALL|METH_KEYWORDS, os_fchmod__doc__}, + +static PyObject * +os_fchmod_impl(PyObject *module, int fd, int mode); + +static PyObject * +os_fchmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(fd), &_Py_ID(mode), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"fd", "mode", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "fchmod", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + int fd; + int mode; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + mode = _PyLong_AsInt(args[1]); + if (mode == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_fchmod_impl(module, fd, mode); + +exit: + return return_value; +} + +#endif /* defined(HAVE_FCHMOD) */ + +#if defined(HAVE_LCHMOD) + +PyDoc_STRVAR(os_lchmod__doc__, +"lchmod($module, /, path, mode)\n" +"--\n" +"\n" +"Change the access permissions of a file, without following symbolic links.\n" +"\n" +"If path is a symlink, this affects the link itself rather than the target.\n" +"Equivalent to chmod(path, mode, follow_symlinks=False).\""); + +#define OS_LCHMOD_METHODDEF \ + {"lchmod", _PyCFunction_CAST(os_lchmod), METH_FASTCALL|METH_KEYWORDS, os_lchmod__doc__}, + +static PyObject * +os_lchmod_impl(PyObject *module, path_t *path, int mode); + +static PyObject * +os_lchmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(mode), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "mode", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "lchmod", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + path_t path = PATH_T_INITIALIZE("lchmod", "path", 0, 0); + int mode; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + mode = _PyLong_AsInt(args[1]); + if (mode == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_lchmod_impl(module, &path, mode); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(HAVE_LCHMOD) */ + +#if defined(HAVE_CHFLAGS) + +PyDoc_STRVAR(os_chflags__doc__, +"chflags($module, /, path, flags, follow_symlinks=True)\n" +"--\n" +"\n" +"Set file flags.\n" +"\n" +"If follow_symlinks is False, and the last element of the path is a symbolic\n" +" link, chflags will change flags on the symbolic link itself instead of the\n" +" file the link points to.\n" +"follow_symlinks may not be implemented on your platform. If it is\n" +"unavailable, using it will raise a NotImplementedError."); + +#define OS_CHFLAGS_METHODDEF \ + {"chflags", _PyCFunction_CAST(os_chflags), METH_FASTCALL|METH_KEYWORDS, os_chflags__doc__}, + +static PyObject * +os_chflags_impl(PyObject *module, path_t *path, unsigned long flags, + int follow_symlinks); + +static PyObject * +os_chflags(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(flags), &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "flags", "follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "chflags", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + path_t path = PATH_T_INITIALIZE("chflags", "path", 0, 0); + unsigned long flags; + int follow_symlinks = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!PyLong_Check(args[1])) { + _PyArg_BadArgument("chflags", "argument 'flags'", "int", args[1]); + goto exit; + } + flags = PyLong_AsUnsignedLongMask(args[1]); + if (!noptargs) { + goto skip_optional_pos; + } + follow_symlinks = PyObject_IsTrue(args[2]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_pos: + return_value = os_chflags_impl(module, &path, flags, follow_symlinks); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(HAVE_CHFLAGS) */ + +#if defined(HAVE_LCHFLAGS) + +PyDoc_STRVAR(os_lchflags__doc__, +"lchflags($module, /, path, flags)\n" +"--\n" +"\n" +"Set file flags.\n" +"\n" +"This function will not follow symbolic links.\n" +"Equivalent to chflags(path, flags, follow_symlinks=False)."); + +#define OS_LCHFLAGS_METHODDEF \ + {"lchflags", _PyCFunction_CAST(os_lchflags), METH_FASTCALL|METH_KEYWORDS, os_lchflags__doc__}, + +static PyObject * +os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags); + +static PyObject * +os_lchflags(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(flags), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "flags", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "lchflags", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + path_t path = PATH_T_INITIALIZE("lchflags", "path", 0, 0); + unsigned long flags; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!PyLong_Check(args[1])) { + _PyArg_BadArgument("lchflags", "argument 'flags'", "int", args[1]); + goto exit; + } + flags = PyLong_AsUnsignedLongMask(args[1]); + return_value = os_lchflags_impl(module, &path, flags); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(HAVE_LCHFLAGS) */ + +#if defined(HAVE_CHROOT) + +PyDoc_STRVAR(os_chroot__doc__, +"chroot($module, /, path)\n" +"--\n" +"\n" +"Change root directory to path."); + +#define OS_CHROOT_METHODDEF \ + {"chroot", _PyCFunction_CAST(os_chroot), METH_FASTCALL|METH_KEYWORDS, os_chroot__doc__}, + +static PyObject * +os_chroot_impl(PyObject *module, path_t *path); + +static PyObject * +os_chroot(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "chroot", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + path_t path = PATH_T_INITIALIZE("chroot", "path", 0, 0); + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + return_value = os_chroot_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(HAVE_CHROOT) */ + +#if defined(HAVE_FSYNC) + +PyDoc_STRVAR(os_fsync__doc__, +"fsync($module, /, fd)\n" +"--\n" +"\n" +"Force write of fd to disk."); + +#define OS_FSYNC_METHODDEF \ + {"fsync", _PyCFunction_CAST(os_fsync), METH_FASTCALL|METH_KEYWORDS, os_fsync__doc__}, + +static PyObject * +os_fsync_impl(PyObject *module, int fd); + +static PyObject * +os_fsync(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "fsync", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int fd; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + return_value = os_fsync_impl(module, fd); + +exit: + return return_value; +} + +#endif /* defined(HAVE_FSYNC) */ + +#if defined(HAVE_SYNC) + +PyDoc_STRVAR(os_sync__doc__, +"sync($module, /)\n" +"--\n" +"\n" +"Force write of everything to disk."); + +#define OS_SYNC_METHODDEF \ + {"sync", (PyCFunction)os_sync, METH_NOARGS, os_sync__doc__}, + +static PyObject * +os_sync_impl(PyObject *module); + +static PyObject * +os_sync(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_sync_impl(module); +} + +#endif /* defined(HAVE_SYNC) */ + +#if defined(HAVE_FDATASYNC) + +PyDoc_STRVAR(os_fdatasync__doc__, +"fdatasync($module, /, fd)\n" +"--\n" +"\n" +"Force write of fd to disk without forcing update of metadata."); + +#define OS_FDATASYNC_METHODDEF \ + {"fdatasync", _PyCFunction_CAST(os_fdatasync), METH_FASTCALL|METH_KEYWORDS, os_fdatasync__doc__}, + +static PyObject * +os_fdatasync_impl(PyObject *module, int fd); + +static PyObject * +os_fdatasync(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "fdatasync", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int fd; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + return_value = os_fdatasync_impl(module, fd); + +exit: + return return_value; +} + +#endif /* defined(HAVE_FDATASYNC) */ + +#if defined(HAVE_CHOWN) + +PyDoc_STRVAR(os_chown__doc__, +"chown($module, /, path, uid, gid, *, dir_fd=None, follow_symlinks=True)\n" +"--\n" +"\n" +"Change the owner and group id of path to the numeric uid and gid.\\\n" +"\n" +" path\n" +" Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.\n" +" dir_fd\n" +" If not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that\n" +" directory.\n" +" follow_symlinks\n" +" If False, and the last element of the path is a symbolic link,\n" +" stat will examine the symbolic link itself instead of the file\n" +" the link points to.\n" +"\n" +"path may always be specified as a string.\n" +"On some platforms, path may also be specified as an open file descriptor.\n" +" If this functionality is unavailable, using it raises an exception.\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that directory.\n" +"If follow_symlinks is False, and the last element of the path is a symbolic\n" +" link, chown will modify the symbolic link itself instead of the file the\n" +" link points to.\n" +"It is an error to use dir_fd or follow_symlinks when specifying path as\n" +" an open file descriptor.\n" +"dir_fd and follow_symlinks may not be implemented on your platform.\n" +" If they are unavailable, using them will raise a NotImplementedError."); + +#define OS_CHOWN_METHODDEF \ + {"chown", _PyCFunction_CAST(os_chown), METH_FASTCALL|METH_KEYWORDS, os_chown__doc__}, + +static PyObject * +os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid, + int dir_fd, int follow_symlinks); + +static PyObject * +os_chown(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 5 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(uid), &_Py_ID(gid), &_Py_ID(dir_fd), &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "uid", "gid", "dir_fd", "follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "chown", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; + path_t path = PATH_T_INITIALIZE("chown", "path", 0, PATH_HAVE_FCHOWN); + uid_t uid; + gid_t gid; + int dir_fd = DEFAULT_DIR_FD; + int follow_symlinks = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!_Py_Uid_Converter(args[1], &uid)) { + goto exit; + } + if (!_Py_Gid_Converter(args[2], &gid)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[3]) { + if (!FCHOWNAT_DIR_FD_CONVERTER(args[3], &dir_fd)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + follow_symlinks = PyObject_IsTrue(args[4]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = os_chown_impl(module, &path, uid, gid, dir_fd, follow_symlinks); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(HAVE_CHOWN) */ + +#if defined(HAVE_FCHOWN) + +PyDoc_STRVAR(os_fchown__doc__, +"fchown($module, /, fd, uid, gid)\n" +"--\n" +"\n" +"Change the owner and group id of the file specified by file descriptor.\n" +"\n" +"Equivalent to os.chown(fd, uid, gid)."); + +#define OS_FCHOWN_METHODDEF \ + {"fchown", _PyCFunction_CAST(os_fchown), METH_FASTCALL|METH_KEYWORDS, os_fchown__doc__}, + +static PyObject * +os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid); + +static PyObject * +os_fchown(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(fd), &_Py_ID(uid), &_Py_ID(gid), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"fd", "uid", "gid", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "fchown", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + int fd; + uid_t uid; + gid_t gid; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); + if (!args) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + if (!_Py_Uid_Converter(args[1], &uid)) { + goto exit; + } + if (!_Py_Gid_Converter(args[2], &gid)) { + goto exit; + } + return_value = os_fchown_impl(module, fd, uid, gid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_FCHOWN) */ + +#if defined(HAVE_LCHOWN) + +PyDoc_STRVAR(os_lchown__doc__, +"lchown($module, /, path, uid, gid)\n" +"--\n" +"\n" +"Change the owner and group id of path to the numeric uid and gid.\n" +"\n" +"This function will not follow symbolic links.\n" +"Equivalent to os.chown(path, uid, gid, follow_symlinks=False)."); + +#define OS_LCHOWN_METHODDEF \ + {"lchown", _PyCFunction_CAST(os_lchown), METH_FASTCALL|METH_KEYWORDS, os_lchown__doc__}, + +static PyObject * +os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid); + +static PyObject * +os_lchown(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(uid), &_Py_ID(gid), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "uid", "gid", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "lchown", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + path_t path = PATH_T_INITIALIZE("lchown", "path", 0, 0); + uid_t uid; + gid_t gid; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!_Py_Uid_Converter(args[1], &uid)) { + goto exit; + } + if (!_Py_Gid_Converter(args[2], &gid)) { + goto exit; + } + return_value = os_lchown_impl(module, &path, uid, gid); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(HAVE_LCHOWN) */ + +PyDoc_STRVAR(os_getcwd__doc__, +"getcwd($module, /)\n" +"--\n" +"\n" +"Return a unicode string representing the current working directory."); + +#define OS_GETCWD_METHODDEF \ + {"getcwd", (PyCFunction)os_getcwd, METH_NOARGS, os_getcwd__doc__}, + +static PyObject * +os_getcwd_impl(PyObject *module); + +static PyObject * +os_getcwd(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getcwd_impl(module); +} + +PyDoc_STRVAR(os_getcwdb__doc__, +"getcwdb($module, /)\n" +"--\n" +"\n" +"Return a bytes string representing the current working directory."); + +#define OS_GETCWDB_METHODDEF \ + {"getcwdb", (PyCFunction)os_getcwdb, METH_NOARGS, os_getcwdb__doc__}, + +static PyObject * +os_getcwdb_impl(PyObject *module); + +static PyObject * +os_getcwdb(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getcwdb_impl(module); +} + +#if defined(HAVE_LINK) + +PyDoc_STRVAR(os_link__doc__, +"link($module, /, src, dst, *, src_dir_fd=None, dst_dir_fd=None,\n" +" follow_symlinks=True)\n" +"--\n" +"\n" +"Create a hard link to a file.\n" +"\n" +"If either src_dir_fd or dst_dir_fd is not None, it should be a file\n" +" descriptor open to a directory, and the respective path string (src or dst)\n" +" should be relative; the path will then be relative to that directory.\n" +"If follow_symlinks is False, and the last element of src is a symbolic\n" +" link, link will create a link to the symbolic link itself instead of the\n" +" file the link points to.\n" +"src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your\n" +" platform. If they are unavailable, using them will raise a\n" +" NotImplementedError."); + +#define OS_LINK_METHODDEF \ + {"link", _PyCFunction_CAST(os_link), METH_FASTCALL|METH_KEYWORDS, os_link__doc__}, + +static PyObject * +os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, + int dst_dir_fd, int follow_symlinks); + +static PyObject * +os_link(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 5 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(src), &_Py_ID(dst), &_Py_ID(src_dir_fd), &_Py_ID(dst_dir_fd), &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", "follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "link", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + path_t src = PATH_T_INITIALIZE("link", "src", 0, 0); + path_t dst = PATH_T_INITIALIZE("link", "dst", 0, 0); + int src_dir_fd = DEFAULT_DIR_FD; + int dst_dir_fd = DEFAULT_DIR_FD; + int follow_symlinks = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &src)) { + goto exit; + } + if (!path_converter(args[1], &dst)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[2]) { + if (!dir_fd_converter(args[2], &src_dir_fd)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[3]) { + if (!dir_fd_converter(args[3], &dst_dir_fd)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + follow_symlinks = PyObject_IsTrue(args[4]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = os_link_impl(module, &src, &dst, src_dir_fd, dst_dir_fd, follow_symlinks); + +exit: + /* Cleanup for src */ + path_cleanup(&src); + /* Cleanup for dst */ + path_cleanup(&dst); + + return return_value; +} + +#endif /* defined(HAVE_LINK) */ + +PyDoc_STRVAR(os_listdir__doc__, +"listdir($module, /, path=None)\n" +"--\n" +"\n" +"Return a list containing the names of the files in the directory.\n" +"\n" +"path can be specified as either str, bytes, or a path-like object. If path is bytes,\n" +" the filenames returned will also be bytes; in all other circumstances\n" +" the filenames returned will be str.\n" +"If path is None, uses the path=\'.\'.\n" +"On some platforms, path may also be specified as an open file descriptor;\\\n" +" the file descriptor must refer to a directory.\n" +" If this functionality is unavailable, using it raises NotImplementedError.\n" +"\n" +"The list is in arbitrary order. It does not include the special\n" +"entries \'.\' and \'..\' even if they are present in the directory."); + +#define OS_LISTDIR_METHODDEF \ + {"listdir", _PyCFunction_CAST(os_listdir), METH_FASTCALL|METH_KEYWORDS, os_listdir__doc__}, + +static PyObject * +os_listdir_impl(PyObject *module, path_t *path); + +static PyObject * +os_listdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "listdir", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + path_t path = PATH_T_INITIALIZE("listdir", "path", 1, PATH_HAVE_FDOPENDIR); + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (!path_converter(args[0], &path)) { + goto exit; + } +skip_optional_pos: + return_value = os_listdir_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(os__getfullpathname__doc__, +"_getfullpathname($module, path, /)\n" +"--\n" +"\n"); + +#define OS__GETFULLPATHNAME_METHODDEF \ + {"_getfullpathname", (PyCFunction)os__getfullpathname, METH_O, os__getfullpathname__doc__}, + +static PyObject * +os__getfullpathname_impl(PyObject *module, path_t *path); + +static PyObject * +os__getfullpathname(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + path_t path = PATH_T_INITIALIZE("_getfullpathname", "path", 0, 0); + + if (!path_converter(arg, &path)) { + goto exit; + } + return_value = os__getfullpathname_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(os__getfinalpathname__doc__, +"_getfinalpathname($module, path, /)\n" +"--\n" +"\n" +"A helper function for samepath on windows."); + +#define OS__GETFINALPATHNAME_METHODDEF \ + {"_getfinalpathname", (PyCFunction)os__getfinalpathname, METH_O, os__getfinalpathname__doc__}, + +static PyObject * +os__getfinalpathname_impl(PyObject *module, path_t *path); + +static PyObject * +os__getfinalpathname(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + path_t path = PATH_T_INITIALIZE("_getfinalpathname", "path", 0, 0); + + if (!path_converter(arg, &path)) { + goto exit; + } + return_value = os__getfinalpathname_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(os__getvolumepathname__doc__, +"_getvolumepathname($module, /, path)\n" +"--\n" +"\n" +"A helper function for ismount on Win32."); + +#define OS__GETVOLUMEPATHNAME_METHODDEF \ + {"_getvolumepathname", _PyCFunction_CAST(os__getvolumepathname), METH_FASTCALL|METH_KEYWORDS, os__getvolumepathname__doc__}, + +static PyObject * +os__getvolumepathname_impl(PyObject *module, path_t *path); + +static PyObject * +os__getvolumepathname(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "_getvolumepathname", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + path_t path = PATH_T_INITIALIZE("_getvolumepathname", "path", 0, 0); + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + return_value = os__getvolumepathname_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(os__path_splitroot__doc__, +"_path_splitroot($module, /, path)\n" +"--\n" +"\n" +"Removes everything after the root on Win32."); + +#define OS__PATH_SPLITROOT_METHODDEF \ + {"_path_splitroot", _PyCFunction_CAST(os__path_splitroot), METH_FASTCALL|METH_KEYWORDS, os__path_splitroot__doc__}, + +static PyObject * +os__path_splitroot_impl(PyObject *module, path_t *path); + +static PyObject * +os__path_splitroot(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "_path_splitroot", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + path_t path = PATH_T_INITIALIZE("_path_splitroot", "path", 0, 0); + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + return_value = os__path_splitroot_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +PyDoc_STRVAR(os__path_normpath__doc__, +"_path_normpath($module, /, path)\n" +"--\n" +"\n" +"Basic path normalization."); + +#define OS__PATH_NORMPATH_METHODDEF \ + {"_path_normpath", _PyCFunction_CAST(os__path_normpath), METH_FASTCALL|METH_KEYWORDS, os__path_normpath__doc__}, + +static PyObject * +os__path_normpath_impl(PyObject *module, PyObject *path); + +static PyObject * +os__path_normpath(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "_path_normpath", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *path; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + path = args[0]; + return_value = os__path_normpath_impl(module, path); + +exit: + return return_value; +} + +PyDoc_STRVAR(os_mkdir__doc__, +"mkdir($module, /, path, mode=511, *, dir_fd=None)\n" +"--\n" +"\n" +"Create a directory.\n" +"\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that directory.\n" +"dir_fd may not be implemented on your platform.\n" +" If it is unavailable, using it will raise a NotImplementedError.\n" +"\n" +"The mode argument is ignored on Windows. Where it is used, the current umask\n" +"value is first masked out."); + +#define OS_MKDIR_METHODDEF \ + {"mkdir", _PyCFunction_CAST(os_mkdir), METH_FASTCALL|METH_KEYWORDS, os_mkdir__doc__}, + +static PyObject * +os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd); + +static PyObject * +os_mkdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(mode), &_Py_ID(dir_fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "mode", "dir_fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "mkdir", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + path_t path = PATH_T_INITIALIZE("mkdir", "path", 0, 0); + int mode = 511; + int dir_fd = DEFAULT_DIR_FD; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[1]) { + mode = _PyLong_AsInt(args[1]); + if (mode == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + if (!MKDIRAT_DIR_FD_CONVERTER(args[2], &dir_fd)) { + goto exit; + } +skip_optional_kwonly: + return_value = os_mkdir_impl(module, &path, mode, dir_fd); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#if defined(HAVE_NICE) + +PyDoc_STRVAR(os_nice__doc__, +"nice($module, increment, /)\n" +"--\n" +"\n" +"Add increment to the priority of process and return the new priority."); + +#define OS_NICE_METHODDEF \ + {"nice", (PyCFunction)os_nice, METH_O, os_nice__doc__}, + +static PyObject * +os_nice_impl(PyObject *module, int increment); + +static PyObject * +os_nice(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int increment; + + increment = _PyLong_AsInt(arg); + if (increment == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_nice_impl(module, increment); + +exit: + return return_value; +} + +#endif /* defined(HAVE_NICE) */ + +#if defined(HAVE_GETPRIORITY) + +PyDoc_STRVAR(os_getpriority__doc__, +"getpriority($module, /, which, who)\n" +"--\n" +"\n" +"Return program scheduling priority."); + +#define OS_GETPRIORITY_METHODDEF \ + {"getpriority", _PyCFunction_CAST(os_getpriority), METH_FASTCALL|METH_KEYWORDS, os_getpriority__doc__}, + +static PyObject * +os_getpriority_impl(PyObject *module, int which, int who); + +static PyObject * +os_getpriority(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(which), &_Py_ID(who), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"which", "who", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "getpriority", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + int which; + int who; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + which = _PyLong_AsInt(args[0]); + if (which == -1 && PyErr_Occurred()) { + goto exit; + } + who = _PyLong_AsInt(args[1]); + if (who == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_getpriority_impl(module, which, who); + +exit: + return return_value; +} + +#endif /* defined(HAVE_GETPRIORITY) */ + +#if defined(HAVE_SETPRIORITY) + +PyDoc_STRVAR(os_setpriority__doc__, +"setpriority($module, /, which, who, priority)\n" +"--\n" +"\n" +"Set program scheduling priority."); + +#define OS_SETPRIORITY_METHODDEF \ + {"setpriority", _PyCFunction_CAST(os_setpriority), METH_FASTCALL|METH_KEYWORDS, os_setpriority__doc__}, + +static PyObject * +os_setpriority_impl(PyObject *module, int which, int who, int priority); + +static PyObject * +os_setpriority(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(which), &_Py_ID(who), &_Py_ID(priority), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"which", "who", "priority", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "setpriority", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + int which; + int who; + int priority; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); + if (!args) { + goto exit; + } + which = _PyLong_AsInt(args[0]); + if (which == -1 && PyErr_Occurred()) { + goto exit; + } + who = _PyLong_AsInt(args[1]); + if (who == -1 && PyErr_Occurred()) { + goto exit; + } + priority = _PyLong_AsInt(args[2]); + if (priority == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_setpriority_impl(module, which, who, priority); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SETPRIORITY) */ + +PyDoc_STRVAR(os_rename__doc__, +"rename($module, /, src, dst, *, src_dir_fd=None, dst_dir_fd=None)\n" +"--\n" +"\n" +"Rename a file or directory.\n" +"\n" +"If either src_dir_fd or dst_dir_fd is not None, it should be a file\n" +" descriptor open to a directory, and the respective path string (src or dst)\n" +" should be relative; the path will then be relative to that directory.\n" +"src_dir_fd and dst_dir_fd, may not be implemented on your platform.\n" +" If they are unavailable, using them will raise a NotImplementedError."); + +#define OS_RENAME_METHODDEF \ + {"rename", _PyCFunction_CAST(os_rename), METH_FASTCALL|METH_KEYWORDS, os_rename__doc__}, + +static PyObject * +os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, + int dst_dir_fd); + +static PyObject * +os_rename(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(src), &_Py_ID(dst), &_Py_ID(src_dir_fd), &_Py_ID(dst_dir_fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "rename", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + path_t src = PATH_T_INITIALIZE("rename", "src", 0, 0); + path_t dst = PATH_T_INITIALIZE("rename", "dst", 0, 0); + int src_dir_fd = DEFAULT_DIR_FD; + int dst_dir_fd = DEFAULT_DIR_FD; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &src)) { + goto exit; + } + if (!path_converter(args[1], &dst)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[2]) { + if (!dir_fd_converter(args[2], &src_dir_fd)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (!dir_fd_converter(args[3], &dst_dir_fd)) { + goto exit; + } +skip_optional_kwonly: + return_value = os_rename_impl(module, &src, &dst, src_dir_fd, dst_dir_fd); + +exit: + /* Cleanup for src */ + path_cleanup(&src); + /* Cleanup for dst */ + path_cleanup(&dst); + + return return_value; +} + +PyDoc_STRVAR(os_replace__doc__, +"replace($module, /, src, dst, *, src_dir_fd=None, dst_dir_fd=None)\n" +"--\n" +"\n" +"Rename a file or directory, overwriting the destination.\n" +"\n" +"If either src_dir_fd or dst_dir_fd is not None, it should be a file\n" +" descriptor open to a directory, and the respective path string (src or dst)\n" +" should be relative; the path will then be relative to that directory.\n" +"src_dir_fd and dst_dir_fd, may not be implemented on your platform.\n" +" If they are unavailable, using them will raise a NotImplementedError."); + +#define OS_REPLACE_METHODDEF \ + {"replace", _PyCFunction_CAST(os_replace), METH_FASTCALL|METH_KEYWORDS, os_replace__doc__}, + +static PyObject * +os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, + int dst_dir_fd); + +static PyObject * +os_replace(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(src), &_Py_ID(dst), &_Py_ID(src_dir_fd), &_Py_ID(dst_dir_fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "replace", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + path_t src = PATH_T_INITIALIZE("replace", "src", 0, 0); + path_t dst = PATH_T_INITIALIZE("replace", "dst", 0, 0); + int src_dir_fd = DEFAULT_DIR_FD; + int dst_dir_fd = DEFAULT_DIR_FD; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &src)) { + goto exit; + } + if (!path_converter(args[1], &dst)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[2]) { + if (!dir_fd_converter(args[2], &src_dir_fd)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (!dir_fd_converter(args[3], &dst_dir_fd)) { + goto exit; + } +skip_optional_kwonly: + return_value = os_replace_impl(module, &src, &dst, src_dir_fd, dst_dir_fd); + +exit: + /* Cleanup for src */ + path_cleanup(&src); + /* Cleanup for dst */ + path_cleanup(&dst); + + return return_value; +} + +PyDoc_STRVAR(os_rmdir__doc__, +"rmdir($module, /, path, *, dir_fd=None)\n" +"--\n" +"\n" +"Remove a directory.\n" +"\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that directory.\n" +"dir_fd may not be implemented on your platform.\n" +" If it is unavailable, using it will raise a NotImplementedError."); + +#define OS_RMDIR_METHODDEF \ + {"rmdir", _PyCFunction_CAST(os_rmdir), METH_FASTCALL|METH_KEYWORDS, os_rmdir__doc__}, + +static PyObject * +os_rmdir_impl(PyObject *module, path_t *path, int dir_fd); + +static PyObject * +os_rmdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(dir_fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "dir_fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "rmdir", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + path_t path = PATH_T_INITIALIZE("rmdir", "path", 0, 0); + int dir_fd = DEFAULT_DIR_FD; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (!UNLINKAT_DIR_FD_CONVERTER(args[1], &dir_fd)) { + goto exit; + } +skip_optional_kwonly: + return_value = os_rmdir_impl(module, &path, dir_fd); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#if defined(HAVE_SYSTEM) && defined(MS_WINDOWS) + +PyDoc_STRVAR(os_system__doc__, +"system($module, /, command)\n" +"--\n" +"\n" +"Execute the command in a subshell."); + +#define OS_SYSTEM_METHODDEF \ + {"system", _PyCFunction_CAST(os_system), METH_FASTCALL|METH_KEYWORDS, os_system__doc__}, + +static long +os_system_impl(PyObject *module, const Py_UNICODE *command); + +static PyObject * +os_system(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(command), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"command", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "system", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + const Py_UNICODE *command = NULL; + long _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("system", "argument 'command'", "str", args[0]); + goto exit; + } + command = PyUnicode_AsWideCharString(args[0], NULL); + if (command == NULL) { + goto exit; + } + _return_value = os_system_impl(module, command); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong(_return_value); + +exit: + /* Cleanup for command */ + PyMem_Free((void *)command); + + return return_value; +} + +#endif /* defined(HAVE_SYSTEM) && defined(MS_WINDOWS) */ + +#if defined(HAVE_SYSTEM) && !defined(MS_WINDOWS) + +PyDoc_STRVAR(os_system__doc__, +"system($module, /, command)\n" +"--\n" +"\n" +"Execute the command in a subshell."); + +#define OS_SYSTEM_METHODDEF \ + {"system", _PyCFunction_CAST(os_system), METH_FASTCALL|METH_KEYWORDS, os_system__doc__}, + +static long +os_system_impl(PyObject *module, PyObject *command); + +static PyObject * +os_system(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(command), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"command", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "system", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *command = NULL; + long _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!PyUnicode_FSConverter(args[0], &command)) { + goto exit; + } + _return_value = os_system_impl(module, command); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong(_return_value); + +exit: + /* Cleanup for command */ + Py_XDECREF(command); + + return return_value; +} + +#endif /* defined(HAVE_SYSTEM) && !defined(MS_WINDOWS) */ + +#if defined(HAVE_UMASK) + +PyDoc_STRVAR(os_umask__doc__, +"umask($module, mask, /)\n" +"--\n" +"\n" +"Set the current numeric umask and return the previous umask."); + +#define OS_UMASK_METHODDEF \ + {"umask", (PyCFunction)os_umask, METH_O, os_umask__doc__}, + +static PyObject * +os_umask_impl(PyObject *module, int mask); + +static PyObject * +os_umask(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int mask; + + mask = _PyLong_AsInt(arg); + if (mask == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_umask_impl(module, mask); + +exit: + return return_value; +} + +#endif /* defined(HAVE_UMASK) */ + +PyDoc_STRVAR(os_unlink__doc__, +"unlink($module, /, path, *, dir_fd=None)\n" +"--\n" +"\n" +"Remove a file (same as remove()).\n" +"\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that directory.\n" +"dir_fd may not be implemented on your platform.\n" +" If it is unavailable, using it will raise a NotImplementedError."); + +#define OS_UNLINK_METHODDEF \ + {"unlink", _PyCFunction_CAST(os_unlink), METH_FASTCALL|METH_KEYWORDS, os_unlink__doc__}, + +static PyObject * +os_unlink_impl(PyObject *module, path_t *path, int dir_fd); + +static PyObject * +os_unlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(dir_fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "dir_fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "unlink", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + path_t path = PATH_T_INITIALIZE("unlink", "path", 0, 0); + int dir_fd = DEFAULT_DIR_FD; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (!UNLINKAT_DIR_FD_CONVERTER(args[1], &dir_fd)) { + goto exit; + } +skip_optional_kwonly: + return_value = os_unlink_impl(module, &path, dir_fd); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +PyDoc_STRVAR(os_remove__doc__, +"remove($module, /, path, *, dir_fd=None)\n" +"--\n" +"\n" +"Remove a file (same as unlink()).\n" +"\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that directory.\n" +"dir_fd may not be implemented on your platform.\n" +" If it is unavailable, using it will raise a NotImplementedError."); + +#define OS_REMOVE_METHODDEF \ + {"remove", _PyCFunction_CAST(os_remove), METH_FASTCALL|METH_KEYWORDS, os_remove__doc__}, + +static PyObject * +os_remove_impl(PyObject *module, path_t *path, int dir_fd); + +static PyObject * +os_remove(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(dir_fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "dir_fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "remove", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + path_t path = PATH_T_INITIALIZE("remove", "path", 0, 0); + int dir_fd = DEFAULT_DIR_FD; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (!UNLINKAT_DIR_FD_CONVERTER(args[1], &dir_fd)) { + goto exit; + } +skip_optional_kwonly: + return_value = os_remove_impl(module, &path, dir_fd); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#if defined(HAVE_UNAME) + +PyDoc_STRVAR(os_uname__doc__, +"uname($module, /)\n" +"--\n" +"\n" +"Return an object identifying the current operating system.\n" +"\n" +"The object behaves like a named tuple with the following fields:\n" +" (sysname, nodename, release, version, machine)"); + +#define OS_UNAME_METHODDEF \ + {"uname", (PyCFunction)os_uname, METH_NOARGS, os_uname__doc__}, + +static PyObject * +os_uname_impl(PyObject *module); + +static PyObject * +os_uname(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_uname_impl(module); +} + +#endif /* defined(HAVE_UNAME) */ + +PyDoc_STRVAR(os_utime__doc__, +"utime($module, /, path, times=None, *, ns=,\n" +" dir_fd=None, follow_symlinks=True)\n" +"--\n" +"\n" +"Set the access and modified time of path.\n" +"\n" +"path may always be specified as a string.\n" +"On some platforms, path may also be specified as an open file descriptor.\n" +" If this functionality is unavailable, using it raises an exception.\n" +"\n" +"If times is not None, it must be a tuple (atime, mtime);\n" +" atime and mtime should be expressed as float seconds since the epoch.\n" +"If ns is specified, it must be a tuple (atime_ns, mtime_ns);\n" +" atime_ns and mtime_ns should be expressed as integer nanoseconds\n" +" since the epoch.\n" +"If times is None and ns is unspecified, utime uses the current time.\n" +"Specifying tuples for both times and ns is an error.\n" +"\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that directory.\n" +"If follow_symlinks is False, and the last element of the path is a symbolic\n" +" link, utime will modify the symbolic link itself instead of the file the\n" +" link points to.\n" +"It is an error to use dir_fd or follow_symlinks when specifying path\n" +" as an open file descriptor.\n" +"dir_fd and follow_symlinks may not be available on your platform.\n" +" If they are unavailable, using them will raise a NotImplementedError."); + +#define OS_UTIME_METHODDEF \ + {"utime", _PyCFunction_CAST(os_utime), METH_FASTCALL|METH_KEYWORDS, os_utime__doc__}, + +static PyObject * +os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, + int dir_fd, int follow_symlinks); + +static PyObject * +os_utime(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 5 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(times), &_Py_ID(ns), &_Py_ID(dir_fd), &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "times", "ns", "dir_fd", "follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "utime", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + path_t path = PATH_T_INITIALIZE("utime", "path", 0, PATH_UTIME_HAVE_FD); + PyObject *times = Py_None; + PyObject *ns = NULL; + int dir_fd = DEFAULT_DIR_FD; + int follow_symlinks = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[1]) { + times = args[1]; + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[2]) { + ns = args[2]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[3]) { + if (!FUTIMENSAT_DIR_FD_CONVERTER(args[3], &dir_fd)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + follow_symlinks = PyObject_IsTrue(args[4]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = os_utime_impl(module, &path, times, ns, dir_fd, follow_symlinks); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +PyDoc_STRVAR(os__exit__doc__, +"_exit($module, /, status)\n" +"--\n" +"\n" +"Exit to the system with specified status, without normal exit processing."); + +#define OS__EXIT_METHODDEF \ + {"_exit", _PyCFunction_CAST(os__exit), METH_FASTCALL|METH_KEYWORDS, os__exit__doc__}, + +static PyObject * +os__exit_impl(PyObject *module, int status); + +static PyObject * +os__exit(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(status), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"status", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "_exit", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int status; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + status = _PyLong_AsInt(args[0]); + if (status == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os__exit_impl(module, status); + +exit: + return return_value; +} + +#if defined(HAVE_EXECV) + +PyDoc_STRVAR(os_execv__doc__, +"execv($module, path, argv, /)\n" +"--\n" +"\n" +"Execute an executable path with arguments, replacing current process.\n" +"\n" +" path\n" +" Path of executable file.\n" +" argv\n" +" Tuple or list of strings."); + +#define OS_EXECV_METHODDEF \ + {"execv", _PyCFunction_CAST(os_execv), METH_FASTCALL, os_execv__doc__}, + +static PyObject * +os_execv_impl(PyObject *module, path_t *path, PyObject *argv); + +static PyObject * +os_execv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + path_t path = PATH_T_INITIALIZE("execv", "path", 0, 0); + PyObject *argv; + + if (!_PyArg_CheckPositional("execv", nargs, 2, 2)) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + argv = args[1]; + return_value = os_execv_impl(module, &path, argv); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(HAVE_EXECV) */ + +#if defined(HAVE_EXECV) + +PyDoc_STRVAR(os_execve__doc__, +"execve($module, /, path, argv, env)\n" +"--\n" +"\n" +"Execute an executable path with arguments, replacing current process.\n" +"\n" +" path\n" +" Path of executable file.\n" +" argv\n" +" Tuple or list of strings.\n" +" env\n" +" Dictionary of strings mapping to strings."); + +#define OS_EXECVE_METHODDEF \ + {"execve", _PyCFunction_CAST(os_execve), METH_FASTCALL|METH_KEYWORDS, os_execve__doc__}, + +static PyObject * +os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env); + +static PyObject * +os_execve(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(argv), &_Py_ID(env), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "argv", "env", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "execve", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + path_t path = PATH_T_INITIALIZE("execve", "path", 0, PATH_HAVE_FEXECVE); + PyObject *argv; + PyObject *env; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + argv = args[1]; + env = args[2]; + return_value = os_execve_impl(module, &path, argv, env); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(HAVE_EXECV) */ + +#if defined(HAVE_POSIX_SPAWN) + +PyDoc_STRVAR(os_posix_spawn__doc__, +"posix_spawn($module, path, argv, env, /, *, file_actions=(),\n" +" setpgroup=, resetids=False, setsid=False,\n" +" setsigmask=(), setsigdef=(), scheduler=)\n" +"--\n" +"\n" +"Execute the program specified by path in a new process.\n" +"\n" +" path\n" +" Path of executable file.\n" +" argv\n" +" Tuple or list of strings.\n" +" env\n" +" Dictionary of strings mapping to strings.\n" +" file_actions\n" +" A sequence of file action tuples.\n" +" setpgroup\n" +" The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.\n" +" resetids\n" +" If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.\n" +" setsid\n" +" If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.\n" +" setsigmask\n" +" The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.\n" +" setsigdef\n" +" The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.\n" +" scheduler\n" +" A tuple with the scheduler policy (optional) and parameters."); + +#define OS_POSIX_SPAWN_METHODDEF \ + {"posix_spawn", _PyCFunction_CAST(os_posix_spawn), METH_FASTCALL|METH_KEYWORDS, os_posix_spawn__doc__}, + +static PyObject * +os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, + PyObject *env, PyObject *file_actions, + PyObject *setpgroup, int resetids, int setsid, + PyObject *setsigmask, PyObject *setsigdef, + PyObject *scheduler); + +static PyObject * +os_posix_spawn(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 7 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(file_actions), &_Py_ID(setpgroup), &_Py_ID(resetids), &_Py_ID(setsid), &_Py_ID(setsigmask), &_Py_ID(setsigdef), &_Py_ID(scheduler), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"", "", "", "file_actions", "setpgroup", "resetids", "setsid", "setsigmask", "setsigdef", "scheduler", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "posix_spawn", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[10]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; + path_t path = PATH_T_INITIALIZE("posix_spawn", "path", 0, 0); + PyObject *argv; + PyObject *env; + PyObject *file_actions = NULL; + PyObject *setpgroup = NULL; + int resetids = 0; + int setsid = 0; + PyObject *setsigmask = NULL; + PyObject *setsigdef = NULL; + PyObject *scheduler = NULL; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + argv = args[1]; + env = args[2]; + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[3]) { + file_actions = args[3]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[4]) { + setpgroup = args[4]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[5]) { + resetids = _PyLong_AsInt(args[5]); + if (resetids == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[6]) { + setsid = _PyLong_AsInt(args[6]); + if (setsid == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[7]) { + setsigmask = args[7]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[8]) { + setsigdef = args[8]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + scheduler = args[9]; +skip_optional_kwonly: + return_value = os_posix_spawn_impl(module, &path, argv, env, file_actions, setpgroup, resetids, setsid, setsigmask, setsigdef, scheduler); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(HAVE_POSIX_SPAWN) */ + +#if defined(HAVE_POSIX_SPAWNP) + +PyDoc_STRVAR(os_posix_spawnp__doc__, +"posix_spawnp($module, path, argv, env, /, *, file_actions=(),\n" +" setpgroup=, resetids=False, setsid=False,\n" +" setsigmask=(), setsigdef=(), scheduler=)\n" +"--\n" +"\n" +"Execute the program specified by path in a new process.\n" +"\n" +" path\n" +" Path of executable file.\n" +" argv\n" +" Tuple or list of strings.\n" +" env\n" +" Dictionary of strings mapping to strings.\n" +" file_actions\n" +" A sequence of file action tuples.\n" +" setpgroup\n" +" The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.\n" +" resetids\n" +" If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.\n" +" setsid\n" +" If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.\n" +" setsigmask\n" +" The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.\n" +" setsigdef\n" +" The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.\n" +" scheduler\n" +" A tuple with the scheduler policy (optional) and parameters."); + +#define OS_POSIX_SPAWNP_METHODDEF \ + {"posix_spawnp", _PyCFunction_CAST(os_posix_spawnp), METH_FASTCALL|METH_KEYWORDS, os_posix_spawnp__doc__}, + +static PyObject * +os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv, + PyObject *env, PyObject *file_actions, + PyObject *setpgroup, int resetids, int setsid, + PyObject *setsigmask, PyObject *setsigdef, + PyObject *scheduler); + +static PyObject * +os_posix_spawnp(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 7 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(file_actions), &_Py_ID(setpgroup), &_Py_ID(resetids), &_Py_ID(setsid), &_Py_ID(setsigmask), &_Py_ID(setsigdef), &_Py_ID(scheduler), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"", "", "", "file_actions", "setpgroup", "resetids", "setsid", "setsigmask", "setsigdef", "scheduler", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "posix_spawnp", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[10]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; + path_t path = PATH_T_INITIALIZE("posix_spawnp", "path", 0, 0); + PyObject *argv; + PyObject *env; + PyObject *file_actions = NULL; + PyObject *setpgroup = NULL; + int resetids = 0; + int setsid = 0; + PyObject *setsigmask = NULL; + PyObject *setsigdef = NULL; + PyObject *scheduler = NULL; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + argv = args[1]; + env = args[2]; + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[3]) { + file_actions = args[3]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[4]) { + setpgroup = args[4]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[5]) { + resetids = _PyLong_AsInt(args[5]); + if (resetids == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[6]) { + setsid = _PyLong_AsInt(args[6]); + if (setsid == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[7]) { + setsigmask = args[7]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[8]) { + setsigdef = args[8]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + scheduler = args[9]; +skip_optional_kwonly: + return_value = os_posix_spawnp_impl(module, &path, argv, env, file_actions, setpgroup, resetids, setsid, setsigmask, setsigdef, scheduler); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(HAVE_POSIX_SPAWNP) */ + +#if (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)) + +PyDoc_STRVAR(os_spawnv__doc__, +"spawnv($module, mode, path, argv, /)\n" +"--\n" +"\n" +"Execute the program specified by path in a new process.\n" +"\n" +" mode\n" +" Mode of process creation.\n" +" path\n" +" Path of executable file.\n" +" argv\n" +" Tuple or list of strings."); + +#define OS_SPAWNV_METHODDEF \ + {"spawnv", _PyCFunction_CAST(os_spawnv), METH_FASTCALL, os_spawnv__doc__}, + +static PyObject * +os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv); + +static PyObject * +os_spawnv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int mode; + path_t path = PATH_T_INITIALIZE("spawnv", "path", 0, 0); + PyObject *argv; + + if (!_PyArg_CheckPositional("spawnv", nargs, 3, 3)) { + goto exit; + } + mode = _PyLong_AsInt(args[0]); + if (mode == -1 && PyErr_Occurred()) { + goto exit; + } + if (!path_converter(args[1], &path)) { + goto exit; + } + argv = args[2]; + return_value = os_spawnv_impl(module, mode, &path, argv); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)) */ + +#if (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)) + +PyDoc_STRVAR(os_spawnve__doc__, +"spawnve($module, mode, path, argv, env, /)\n" +"--\n" +"\n" +"Execute the program specified by path in a new process.\n" +"\n" +" mode\n" +" Mode of process creation.\n" +" path\n" +" Path of executable file.\n" +" argv\n" +" Tuple or list of strings.\n" +" env\n" +" Dictionary of strings mapping to strings."); + +#define OS_SPAWNVE_METHODDEF \ + {"spawnve", _PyCFunction_CAST(os_spawnve), METH_FASTCALL, os_spawnve__doc__}, + +static PyObject * +os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv, + PyObject *env); + +static PyObject * +os_spawnve(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int mode; + path_t path = PATH_T_INITIALIZE("spawnve", "path", 0, 0); + PyObject *argv; + PyObject *env; + + if (!_PyArg_CheckPositional("spawnve", nargs, 4, 4)) { + goto exit; + } + mode = _PyLong_AsInt(args[0]); + if (mode == -1 && PyErr_Occurred()) { + goto exit; + } + if (!path_converter(args[1], &path)) { + goto exit; + } + argv = args[2]; + env = args[3]; + return_value = os_spawnve_impl(module, mode, &path, argv, env); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)) */ + +#if defined(HAVE_FORK) + +PyDoc_STRVAR(os_register_at_fork__doc__, +"register_at_fork($module, /, *, before=,\n" +" after_in_child=,\n" +" after_in_parent=)\n" +"--\n" +"\n" +"Register callables to be called when forking a new process.\n" +"\n" +" before\n" +" A callable to be called in the parent before the fork() syscall.\n" +" after_in_child\n" +" A callable to be called in the child after fork().\n" +" after_in_parent\n" +" A callable to be called in the parent after fork().\n" +"\n" +"\'before\' callbacks are called in reverse order.\n" +"\'after_in_child\' and \'after_in_parent\' callbacks are called in order."); + +#define OS_REGISTER_AT_FORK_METHODDEF \ + {"register_at_fork", _PyCFunction_CAST(os_register_at_fork), METH_FASTCALL|METH_KEYWORDS, os_register_at_fork__doc__}, + +static PyObject * +os_register_at_fork_impl(PyObject *module, PyObject *before, + PyObject *after_in_child, PyObject *after_in_parent); + +static PyObject * +os_register_at_fork(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(before), &_Py_ID(after_in_child), &_Py_ID(after_in_parent), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"before", "after_in_child", "after_in_parent", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "register_at_fork", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + PyObject *before = NULL; + PyObject *after_in_child = NULL; + PyObject *after_in_parent = NULL; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[0]) { + before = args[0]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[1]) { + after_in_child = args[1]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + after_in_parent = args[2]; +skip_optional_kwonly: + return_value = os_register_at_fork_impl(module, before, after_in_child, after_in_parent); + +exit: + return return_value; +} + +#endif /* defined(HAVE_FORK) */ + +#if defined(HAVE_FORK1) + +PyDoc_STRVAR(os_fork1__doc__, +"fork1($module, /)\n" +"--\n" +"\n" +"Fork a child process with a single multiplexed (i.e., not bound) thread.\n" +"\n" +"Return 0 to child process and PID of child to parent process."); + +#define OS_FORK1_METHODDEF \ + {"fork1", (PyCFunction)os_fork1, METH_NOARGS, os_fork1__doc__}, + +static PyObject * +os_fork1_impl(PyObject *module); + +static PyObject * +os_fork1(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_fork1_impl(module); +} + +#endif /* defined(HAVE_FORK1) */ + +#if defined(HAVE_FORK) + +PyDoc_STRVAR(os_fork__doc__, +"fork($module, /)\n" +"--\n" +"\n" +"Fork a child process.\n" +"\n" +"Return 0 to child process and PID of child to parent process."); + +#define OS_FORK_METHODDEF \ + {"fork", (PyCFunction)os_fork, METH_NOARGS, os_fork__doc__}, + +static PyObject * +os_fork_impl(PyObject *module); + +static PyObject * +os_fork(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_fork_impl(module); +} + +#endif /* defined(HAVE_FORK) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_GET_PRIORITY_MAX) + +PyDoc_STRVAR(os_sched_get_priority_max__doc__, +"sched_get_priority_max($module, /, policy)\n" +"--\n" +"\n" +"Get the maximum scheduling priority for policy."); + +#define OS_SCHED_GET_PRIORITY_MAX_METHODDEF \ + {"sched_get_priority_max", _PyCFunction_CAST(os_sched_get_priority_max), METH_FASTCALL|METH_KEYWORDS, os_sched_get_priority_max__doc__}, + +static PyObject * +os_sched_get_priority_max_impl(PyObject *module, int policy); + +static PyObject * +os_sched_get_priority_max(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(policy), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"policy", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "sched_get_priority_max", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int policy; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + policy = _PyLong_AsInt(args[0]); + if (policy == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_sched_get_priority_max_impl(module, policy); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_GET_PRIORITY_MAX) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_GET_PRIORITY_MAX) + +PyDoc_STRVAR(os_sched_get_priority_min__doc__, +"sched_get_priority_min($module, /, policy)\n" +"--\n" +"\n" +"Get the minimum scheduling priority for policy."); + +#define OS_SCHED_GET_PRIORITY_MIN_METHODDEF \ + {"sched_get_priority_min", _PyCFunction_CAST(os_sched_get_priority_min), METH_FASTCALL|METH_KEYWORDS, os_sched_get_priority_min__doc__}, + +static PyObject * +os_sched_get_priority_min_impl(PyObject *module, int policy); + +static PyObject * +os_sched_get_priority_min(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(policy), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"policy", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "sched_get_priority_min", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int policy; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + policy = _PyLong_AsInt(args[0]); + if (policy == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_sched_get_priority_min_impl(module, policy); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_GET_PRIORITY_MAX) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETSCHEDULER) + +PyDoc_STRVAR(os_sched_getscheduler__doc__, +"sched_getscheduler($module, pid, /)\n" +"--\n" +"\n" +"Get the scheduling policy for the process identified by pid.\n" +"\n" +"Passing 0 for pid returns the scheduling policy for the calling process."); + +#define OS_SCHED_GETSCHEDULER_METHODDEF \ + {"sched_getscheduler", (PyCFunction)os_sched_getscheduler, METH_O, os_sched_getscheduler__doc__}, + +static PyObject * +os_sched_getscheduler_impl(PyObject *module, pid_t pid); + +static PyObject * +os_sched_getscheduler(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + pid_t pid; + + if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":sched_getscheduler", &pid)) { + goto exit; + } + return_value = os_sched_getscheduler_impl(module, pid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETSCHEDULER) */ + +#if defined(HAVE_SCHED_H) && (defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)) + +PyDoc_STRVAR(os_sched_param__doc__, +"sched_param(sched_priority)\n" +"--\n" +"\n" +"Currently has only one field: sched_priority\n" +"\n" +" sched_priority\n" +" A scheduling parameter."); + +static PyObject * +os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority); + +static PyObject * +os_sched_param(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(sched_priority), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"sched_priority", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "sched_param", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject * const *fastargs; + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + PyObject *sched_priority; + + fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, argsbuf); + if (!fastargs) { + goto exit; + } + sched_priority = fastargs[0]; + return_value = os_sched_param_impl(type, sched_priority); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SCHED_H) && (defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETSCHEDULER) + +PyDoc_STRVAR(os_sched_setscheduler__doc__, +"sched_setscheduler($module, pid, policy, param, /)\n" +"--\n" +"\n" +"Set the scheduling policy for the process identified by pid.\n" +"\n" +"If pid is 0, the calling process is changed.\n" +"param is an instance of sched_param."); + +#define OS_SCHED_SETSCHEDULER_METHODDEF \ + {"sched_setscheduler", _PyCFunction_CAST(os_sched_setscheduler), METH_FASTCALL, os_sched_setscheduler__doc__}, + +static PyObject * +os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy, + PyObject *param_obj); + +static PyObject * +os_sched_setscheduler(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + pid_t pid; + int policy; + PyObject *param_obj; + + if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "iO:sched_setscheduler", + &pid, &policy, ¶m_obj)) { + goto exit; + } + return_value = os_sched_setscheduler_impl(module, pid, policy, param_obj); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETSCHEDULER) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETPARAM) + +PyDoc_STRVAR(os_sched_getparam__doc__, +"sched_getparam($module, pid, /)\n" +"--\n" +"\n" +"Returns scheduling parameters for the process identified by pid.\n" +"\n" +"If pid is 0, returns parameters for the calling process.\n" +"Return value is an instance of sched_param."); + +#define OS_SCHED_GETPARAM_METHODDEF \ + {"sched_getparam", (PyCFunction)os_sched_getparam, METH_O, os_sched_getparam__doc__}, + +static PyObject * +os_sched_getparam_impl(PyObject *module, pid_t pid); + +static PyObject * +os_sched_getparam(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + pid_t pid; + + if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":sched_getparam", &pid)) { + goto exit; + } + return_value = os_sched_getparam_impl(module, pid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETPARAM) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETPARAM) + +PyDoc_STRVAR(os_sched_setparam__doc__, +"sched_setparam($module, pid, param, /)\n" +"--\n" +"\n" +"Set scheduling parameters for the process identified by pid.\n" +"\n" +"If pid is 0, sets parameters for the calling process.\n" +"param should be an instance of sched_param."); + +#define OS_SCHED_SETPARAM_METHODDEF \ + {"sched_setparam", _PyCFunction_CAST(os_sched_setparam), METH_FASTCALL, os_sched_setparam__doc__}, + +static PyObject * +os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj); + +static PyObject * +os_sched_setparam(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + pid_t pid; + PyObject *param_obj; + + if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "O:sched_setparam", + &pid, ¶m_obj)) { + goto exit; + } + return_value = os_sched_setparam_impl(module, pid, param_obj); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETPARAM) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_RR_GET_INTERVAL) + +PyDoc_STRVAR(os_sched_rr_get_interval__doc__, +"sched_rr_get_interval($module, pid, /)\n" +"--\n" +"\n" +"Return the round-robin quantum for the process identified by pid, in seconds.\n" +"\n" +"Value returned is a float."); + +#define OS_SCHED_RR_GET_INTERVAL_METHODDEF \ + {"sched_rr_get_interval", (PyCFunction)os_sched_rr_get_interval, METH_O, os_sched_rr_get_interval__doc__}, + +static double +os_sched_rr_get_interval_impl(PyObject *module, pid_t pid); + +static PyObject * +os_sched_rr_get_interval(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + pid_t pid; + double _return_value; + + if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":sched_rr_get_interval", &pid)) { + goto exit; + } + _return_value = os_sched_rr_get_interval_impl(module, pid); + if ((_return_value == -1.0) && PyErr_Occurred()) { + goto exit; + } + return_value = PyFloat_FromDouble(_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_RR_GET_INTERVAL) */ + +#if defined(HAVE_SCHED_H) + +PyDoc_STRVAR(os_sched_yield__doc__, +"sched_yield($module, /)\n" +"--\n" +"\n" +"Voluntarily relinquish the CPU."); + +#define OS_SCHED_YIELD_METHODDEF \ + {"sched_yield", (PyCFunction)os_sched_yield, METH_NOARGS, os_sched_yield__doc__}, + +static PyObject * +os_sched_yield_impl(PyObject *module); + +static PyObject * +os_sched_yield(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_sched_yield_impl(module); +} + +#endif /* defined(HAVE_SCHED_H) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETAFFINITY) + +PyDoc_STRVAR(os_sched_setaffinity__doc__, +"sched_setaffinity($module, pid, mask, /)\n" +"--\n" +"\n" +"Set the CPU affinity of the process identified by pid to mask.\n" +"\n" +"mask should be an iterable of integers identifying CPUs."); + +#define OS_SCHED_SETAFFINITY_METHODDEF \ + {"sched_setaffinity", _PyCFunction_CAST(os_sched_setaffinity), METH_FASTCALL, os_sched_setaffinity__doc__}, + +static PyObject * +os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask); + +static PyObject * +os_sched_setaffinity(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + pid_t pid; + PyObject *mask; + + if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "O:sched_setaffinity", + &pid, &mask)) { + goto exit; + } + return_value = os_sched_setaffinity_impl(module, pid, mask); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETAFFINITY) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETAFFINITY) + +PyDoc_STRVAR(os_sched_getaffinity__doc__, +"sched_getaffinity($module, pid, /)\n" +"--\n" +"\n" +"Return the affinity of the process identified by pid (or the current process if zero).\n" +"\n" +"The affinity is returned as a set of CPU identifiers."); + +#define OS_SCHED_GETAFFINITY_METHODDEF \ + {"sched_getaffinity", (PyCFunction)os_sched_getaffinity, METH_O, os_sched_getaffinity__doc__}, + +static PyObject * +os_sched_getaffinity_impl(PyObject *module, pid_t pid); + +static PyObject * +os_sched_getaffinity(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + pid_t pid; + + if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":sched_getaffinity", &pid)) { + goto exit; + } + return_value = os_sched_getaffinity_impl(module, pid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETAFFINITY) */ + +#if (defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)) + +PyDoc_STRVAR(os_openpty__doc__, +"openpty($module, /)\n" +"--\n" +"\n" +"Open a pseudo-terminal.\n" +"\n" +"Return a tuple of (master_fd, slave_fd) containing open file descriptors\n" +"for both the master and slave ends."); + +#define OS_OPENPTY_METHODDEF \ + {"openpty", (PyCFunction)os_openpty, METH_NOARGS, os_openpty__doc__}, + +static PyObject * +os_openpty_impl(PyObject *module); + +static PyObject * +os_openpty(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_openpty_impl(module); +} + +#endif /* (defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)) */ + +#if (defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)) + +PyDoc_STRVAR(os_login_tty__doc__, +"login_tty($module, fd, /)\n" +"--\n" +"\n" +"Prepare the tty of which fd is a file descriptor for a new login session.\n" +"\n" +"Make the calling process a session leader; make the tty the\n" +"controlling tty, the stdin, the stdout, and the stderr of the\n" +"calling process; close fd."); + +#define OS_LOGIN_TTY_METHODDEF \ + {"login_tty", (PyCFunction)os_login_tty, METH_O, os_login_tty__doc__}, + +static PyObject * +os_login_tty_impl(PyObject *module, int fd); + +static PyObject * +os_login_tty(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int fd; + + if (!_PyLong_FileDescriptor_Converter(arg, &fd)) { + goto exit; + } + return_value = os_login_tty_impl(module, fd); + +exit: + return return_value; +} + +#endif /* (defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)) */ + +#if defined(HAVE_FORKPTY) + +PyDoc_STRVAR(os_forkpty__doc__, +"forkpty($module, /)\n" +"--\n" +"\n" +"Fork a new process with a new pseudo-terminal as controlling tty.\n" +"\n" +"Returns a tuple of (pid, master_fd).\n" +"Like fork(), return pid of 0 to the child process,\n" +"and pid of child to the parent process.\n" +"To both, return fd of newly opened pseudo-terminal."); + +#define OS_FORKPTY_METHODDEF \ + {"forkpty", (PyCFunction)os_forkpty, METH_NOARGS, os_forkpty__doc__}, + +static PyObject * +os_forkpty_impl(PyObject *module); + +static PyObject * +os_forkpty(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_forkpty_impl(module); +} + +#endif /* defined(HAVE_FORKPTY) */ + +#if defined(HAVE_GETEGID) + +PyDoc_STRVAR(os_getegid__doc__, +"getegid($module, /)\n" +"--\n" +"\n" +"Return the current process\'s effective group id."); + +#define OS_GETEGID_METHODDEF \ + {"getegid", (PyCFunction)os_getegid, METH_NOARGS, os_getegid__doc__}, + +static PyObject * +os_getegid_impl(PyObject *module); + +static PyObject * +os_getegid(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getegid_impl(module); +} + +#endif /* defined(HAVE_GETEGID) */ + +#if defined(HAVE_GETEUID) + +PyDoc_STRVAR(os_geteuid__doc__, +"geteuid($module, /)\n" +"--\n" +"\n" +"Return the current process\'s effective user id."); + +#define OS_GETEUID_METHODDEF \ + {"geteuid", (PyCFunction)os_geteuid, METH_NOARGS, os_geteuid__doc__}, + +static PyObject * +os_geteuid_impl(PyObject *module); + +static PyObject * +os_geteuid(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_geteuid_impl(module); +} + +#endif /* defined(HAVE_GETEUID) */ + +#if defined(HAVE_GETGID) + +PyDoc_STRVAR(os_getgid__doc__, +"getgid($module, /)\n" +"--\n" +"\n" +"Return the current process\'s group id."); + +#define OS_GETGID_METHODDEF \ + {"getgid", (PyCFunction)os_getgid, METH_NOARGS, os_getgid__doc__}, + +static PyObject * +os_getgid_impl(PyObject *module); + +static PyObject * +os_getgid(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getgid_impl(module); +} + +#endif /* defined(HAVE_GETGID) */ + +#if defined(HAVE_GETPID) + +PyDoc_STRVAR(os_getpid__doc__, +"getpid($module, /)\n" +"--\n" +"\n" +"Return the current process id."); + +#define OS_GETPID_METHODDEF \ + {"getpid", (PyCFunction)os_getpid, METH_NOARGS, os_getpid__doc__}, + +static PyObject * +os_getpid_impl(PyObject *module); + +static PyObject * +os_getpid(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getpid_impl(module); +} + +#endif /* defined(HAVE_GETPID) */ + +#if defined(HAVE_GETGROUPLIST) && defined(__APPLE__) + +PyDoc_STRVAR(os_getgrouplist__doc__, +"getgrouplist($module, user, group, /)\n" +"--\n" +"\n" +"Returns a list of groups to which a user belongs.\n" +"\n" +" user\n" +" username to lookup\n" +" group\n" +" base group id of the user"); + +#define OS_GETGROUPLIST_METHODDEF \ + {"getgrouplist", _PyCFunction_CAST(os_getgrouplist), METH_FASTCALL, os_getgrouplist__doc__}, + +static PyObject * +os_getgrouplist_impl(PyObject *module, const char *user, int basegid); + +static PyObject * +os_getgrouplist(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + const char *user; + int basegid; + + if (!_PyArg_CheckPositional("getgrouplist", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("getgrouplist", "argument 1", "str", args[0]); + goto exit; + } + Py_ssize_t user_length; + user = PyUnicode_AsUTF8AndSize(args[0], &user_length); + if (user == NULL) { + goto exit; + } + if (strlen(user) != (size_t)user_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + basegid = _PyLong_AsInt(args[1]); + if (basegid == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_getgrouplist_impl(module, user, basegid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_GETGROUPLIST) && defined(__APPLE__) */ + +#if defined(HAVE_GETGROUPLIST) && !defined(__APPLE__) + +PyDoc_STRVAR(os_getgrouplist__doc__, +"getgrouplist($module, user, group, /)\n" +"--\n" +"\n" +"Returns a list of groups to which a user belongs.\n" +"\n" +" user\n" +" username to lookup\n" +" group\n" +" base group id of the user"); + +#define OS_GETGROUPLIST_METHODDEF \ + {"getgrouplist", _PyCFunction_CAST(os_getgrouplist), METH_FASTCALL, os_getgrouplist__doc__}, + +static PyObject * +os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid); + +static PyObject * +os_getgrouplist(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + const char *user; + gid_t basegid; + + if (!_PyArg_CheckPositional("getgrouplist", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("getgrouplist", "argument 1", "str", args[0]); + goto exit; + } + Py_ssize_t user_length; + user = PyUnicode_AsUTF8AndSize(args[0], &user_length); + if (user == NULL) { + goto exit; + } + if (strlen(user) != (size_t)user_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + if (!_Py_Gid_Converter(args[1], &basegid)) { + goto exit; + } + return_value = os_getgrouplist_impl(module, user, basegid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_GETGROUPLIST) && !defined(__APPLE__) */ + +#if defined(HAVE_GETGROUPS) + +PyDoc_STRVAR(os_getgroups__doc__, +"getgroups($module, /)\n" +"--\n" +"\n" +"Return list of supplemental group IDs for the process."); + +#define OS_GETGROUPS_METHODDEF \ + {"getgroups", (PyCFunction)os_getgroups, METH_NOARGS, os_getgroups__doc__}, + +static PyObject * +os_getgroups_impl(PyObject *module); + +static PyObject * +os_getgroups(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getgroups_impl(module); +} + +#endif /* defined(HAVE_GETGROUPS) */ + +#if defined(HAVE_INITGROUPS) && defined(__APPLE__) + +PyDoc_STRVAR(os_initgroups__doc__, +"initgroups($module, username, gid, /)\n" +"--\n" +"\n" +"Initialize the group access list.\n" +"\n" +"Call the system initgroups() to initialize the group access list with all of\n" +"the groups of which the specified username is a member, plus the specified\n" +"group id."); + +#define OS_INITGROUPS_METHODDEF \ + {"initgroups", _PyCFunction_CAST(os_initgroups), METH_FASTCALL, os_initgroups__doc__}, + +static PyObject * +os_initgroups_impl(PyObject *module, PyObject *oname, int gid); + +static PyObject * +os_initgroups(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *oname = NULL; + int gid; + + if (!_PyArg_CheckPositional("initgroups", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_FSConverter(args[0], &oname)) { + goto exit; + } + gid = _PyLong_AsInt(args[1]); + if (gid == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_initgroups_impl(module, oname, gid); + +exit: + /* Cleanup for oname */ + Py_XDECREF(oname); + + return return_value; +} + +#endif /* defined(HAVE_INITGROUPS) && defined(__APPLE__) */ + +#if defined(HAVE_INITGROUPS) && !defined(__APPLE__) + +PyDoc_STRVAR(os_initgroups__doc__, +"initgroups($module, username, gid, /)\n" +"--\n" +"\n" +"Initialize the group access list.\n" +"\n" +"Call the system initgroups() to initialize the group access list with all of\n" +"the groups of which the specified username is a member, plus the specified\n" +"group id."); + +#define OS_INITGROUPS_METHODDEF \ + {"initgroups", _PyCFunction_CAST(os_initgroups), METH_FASTCALL, os_initgroups__doc__}, + +static PyObject * +os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid); + +static PyObject * +os_initgroups(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *oname = NULL; + gid_t gid; + + if (!_PyArg_CheckPositional("initgroups", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_FSConverter(args[0], &oname)) { + goto exit; + } + if (!_Py_Gid_Converter(args[1], &gid)) { + goto exit; + } + return_value = os_initgroups_impl(module, oname, gid); + +exit: + /* Cleanup for oname */ + Py_XDECREF(oname); + + return return_value; +} + +#endif /* defined(HAVE_INITGROUPS) && !defined(__APPLE__) */ + +#if defined(HAVE_GETPGID) + +PyDoc_STRVAR(os_getpgid__doc__, +"getpgid($module, /, pid)\n" +"--\n" +"\n" +"Call the system call getpgid(), and return the result."); + +#define OS_GETPGID_METHODDEF \ + {"getpgid", _PyCFunction_CAST(os_getpgid), METH_FASTCALL|METH_KEYWORDS, os_getpgid__doc__}, + +static PyObject * +os_getpgid_impl(PyObject *module, pid_t pid); + +static PyObject * +os_getpgid(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(pid), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"pid", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .format = "" _Py_PARSE_PID ":getpgid", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + pid_t pid; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &pid)) { + goto exit; + } + return_value = os_getpgid_impl(module, pid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_GETPGID) */ + +#if defined(HAVE_GETPGRP) + +PyDoc_STRVAR(os_getpgrp__doc__, +"getpgrp($module, /)\n" +"--\n" +"\n" +"Return the current process group id."); + +#define OS_GETPGRP_METHODDEF \ + {"getpgrp", (PyCFunction)os_getpgrp, METH_NOARGS, os_getpgrp__doc__}, + +static PyObject * +os_getpgrp_impl(PyObject *module); + +static PyObject * +os_getpgrp(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getpgrp_impl(module); +} + +#endif /* defined(HAVE_GETPGRP) */ + +#if defined(HAVE_SETPGRP) + +PyDoc_STRVAR(os_setpgrp__doc__, +"setpgrp($module, /)\n" +"--\n" +"\n" +"Make the current process the leader of its process group."); + +#define OS_SETPGRP_METHODDEF \ + {"setpgrp", (PyCFunction)os_setpgrp, METH_NOARGS, os_setpgrp__doc__}, + +static PyObject * +os_setpgrp_impl(PyObject *module); + +static PyObject * +os_setpgrp(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_setpgrp_impl(module); +} + +#endif /* defined(HAVE_SETPGRP) */ + +#if defined(HAVE_GETPPID) + +PyDoc_STRVAR(os_getppid__doc__, +"getppid($module, /)\n" +"--\n" +"\n" +"Return the parent\'s process id.\n" +"\n" +"If the parent process has already exited, Windows machines will still\n" +"return its id; others systems will return the id of the \'init\' process (1)."); + +#define OS_GETPPID_METHODDEF \ + {"getppid", (PyCFunction)os_getppid, METH_NOARGS, os_getppid__doc__}, + +static PyObject * +os_getppid_impl(PyObject *module); + +static PyObject * +os_getppid(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getppid_impl(module); +} + +#endif /* defined(HAVE_GETPPID) */ + +#if defined(HAVE_GETLOGIN) + +PyDoc_STRVAR(os_getlogin__doc__, +"getlogin($module, /)\n" +"--\n" +"\n" +"Return the actual login name."); + +#define OS_GETLOGIN_METHODDEF \ + {"getlogin", (PyCFunction)os_getlogin, METH_NOARGS, os_getlogin__doc__}, + +static PyObject * +os_getlogin_impl(PyObject *module); + +static PyObject * +os_getlogin(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getlogin_impl(module); +} + +#endif /* defined(HAVE_GETLOGIN) */ + +#if defined(HAVE_GETUID) + +PyDoc_STRVAR(os_getuid__doc__, +"getuid($module, /)\n" +"--\n" +"\n" +"Return the current process\'s user id."); + +#define OS_GETUID_METHODDEF \ + {"getuid", (PyCFunction)os_getuid, METH_NOARGS, os_getuid__doc__}, + +static PyObject * +os_getuid_impl(PyObject *module); + +static PyObject * +os_getuid(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getuid_impl(module); +} + +#endif /* defined(HAVE_GETUID) */ + +#if defined(HAVE_KILL) + +PyDoc_STRVAR(os_kill__doc__, +"kill($module, pid, signal, /)\n" +"--\n" +"\n" +"Kill a process with a signal."); + +#define OS_KILL_METHODDEF \ + {"kill", _PyCFunction_CAST(os_kill), METH_FASTCALL, os_kill__doc__}, + +static PyObject * +os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal); + +static PyObject * +os_kill(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + pid_t pid; + Py_ssize_t signal; + + if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "n:kill", + &pid, &signal)) { + goto exit; + } + return_value = os_kill_impl(module, pid, signal); + +exit: + return return_value; +} + +#endif /* defined(HAVE_KILL) */ + +#if defined(HAVE_KILLPG) + +PyDoc_STRVAR(os_killpg__doc__, +"killpg($module, pgid, signal, /)\n" +"--\n" +"\n" +"Kill a process group with a signal."); + +#define OS_KILLPG_METHODDEF \ + {"killpg", _PyCFunction_CAST(os_killpg), METH_FASTCALL, os_killpg__doc__}, + +static PyObject * +os_killpg_impl(PyObject *module, pid_t pgid, int signal); + +static PyObject * +os_killpg(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + pid_t pgid; + int signal; + + if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "i:killpg", + &pgid, &signal)) { + goto exit; + } + return_value = os_killpg_impl(module, pgid, signal); + +exit: + return return_value; +} + +#endif /* defined(HAVE_KILLPG) */ + +#if defined(HAVE_PLOCK) + +PyDoc_STRVAR(os_plock__doc__, +"plock($module, op, /)\n" +"--\n" +"\n" +"Lock program segments into memory.\");"); + +#define OS_PLOCK_METHODDEF \ + {"plock", (PyCFunction)os_plock, METH_O, os_plock__doc__}, + +static PyObject * +os_plock_impl(PyObject *module, int op); + +static PyObject * +os_plock(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int op; + + op = _PyLong_AsInt(arg); + if (op == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_plock_impl(module, op); + +exit: + return return_value; +} + +#endif /* defined(HAVE_PLOCK) */ + +#if defined(HAVE_SETUID) + +PyDoc_STRVAR(os_setuid__doc__, +"setuid($module, uid, /)\n" +"--\n" +"\n" +"Set the current process\'s user id."); + +#define OS_SETUID_METHODDEF \ + {"setuid", (PyCFunction)os_setuid, METH_O, os_setuid__doc__}, + +static PyObject * +os_setuid_impl(PyObject *module, uid_t uid); + +static PyObject * +os_setuid(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + uid_t uid; + + if (!_Py_Uid_Converter(arg, &uid)) { + goto exit; + } + return_value = os_setuid_impl(module, uid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SETUID) */ + +#if defined(HAVE_SETEUID) + +PyDoc_STRVAR(os_seteuid__doc__, +"seteuid($module, euid, /)\n" +"--\n" +"\n" +"Set the current process\'s effective user id."); + +#define OS_SETEUID_METHODDEF \ + {"seteuid", (PyCFunction)os_seteuid, METH_O, os_seteuid__doc__}, + +static PyObject * +os_seteuid_impl(PyObject *module, uid_t euid); + +static PyObject * +os_seteuid(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + uid_t euid; + + if (!_Py_Uid_Converter(arg, &euid)) { + goto exit; + } + return_value = os_seteuid_impl(module, euid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SETEUID) */ + +#if defined(HAVE_SETEGID) + +PyDoc_STRVAR(os_setegid__doc__, +"setegid($module, egid, /)\n" +"--\n" +"\n" +"Set the current process\'s effective group id."); + +#define OS_SETEGID_METHODDEF \ + {"setegid", (PyCFunction)os_setegid, METH_O, os_setegid__doc__}, + +static PyObject * +os_setegid_impl(PyObject *module, gid_t egid); + +static PyObject * +os_setegid(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + gid_t egid; + + if (!_Py_Gid_Converter(arg, &egid)) { + goto exit; + } + return_value = os_setegid_impl(module, egid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SETEGID) */ + +#if defined(HAVE_SETREUID) + +PyDoc_STRVAR(os_setreuid__doc__, +"setreuid($module, ruid, euid, /)\n" +"--\n" +"\n" +"Set the current process\'s real and effective user ids."); + +#define OS_SETREUID_METHODDEF \ + {"setreuid", _PyCFunction_CAST(os_setreuid), METH_FASTCALL, os_setreuid__doc__}, + +static PyObject * +os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid); + +static PyObject * +os_setreuid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + uid_t ruid; + uid_t euid; + + if (!_PyArg_CheckPositional("setreuid", nargs, 2, 2)) { + goto exit; + } + if (!_Py_Uid_Converter(args[0], &ruid)) { + goto exit; + } + if (!_Py_Uid_Converter(args[1], &euid)) { + goto exit; + } + return_value = os_setreuid_impl(module, ruid, euid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SETREUID) */ + +#if defined(HAVE_SETREGID) + +PyDoc_STRVAR(os_setregid__doc__, +"setregid($module, rgid, egid, /)\n" +"--\n" +"\n" +"Set the current process\'s real and effective group ids."); + +#define OS_SETREGID_METHODDEF \ + {"setregid", _PyCFunction_CAST(os_setregid), METH_FASTCALL, os_setregid__doc__}, + +static PyObject * +os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid); + +static PyObject * +os_setregid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + gid_t rgid; + gid_t egid; + + if (!_PyArg_CheckPositional("setregid", nargs, 2, 2)) { + goto exit; + } + if (!_Py_Gid_Converter(args[0], &rgid)) { + goto exit; + } + if (!_Py_Gid_Converter(args[1], &egid)) { + goto exit; + } + return_value = os_setregid_impl(module, rgid, egid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SETREGID) */ + +#if defined(HAVE_SETGID) + +PyDoc_STRVAR(os_setgid__doc__, +"setgid($module, gid, /)\n" +"--\n" +"\n" +"Set the current process\'s group id."); + +#define OS_SETGID_METHODDEF \ + {"setgid", (PyCFunction)os_setgid, METH_O, os_setgid__doc__}, + +static PyObject * +os_setgid_impl(PyObject *module, gid_t gid); + +static PyObject * +os_setgid(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + gid_t gid; + + if (!_Py_Gid_Converter(arg, &gid)) { + goto exit; + } + return_value = os_setgid_impl(module, gid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SETGID) */ + +#if defined(HAVE_SETGROUPS) + +PyDoc_STRVAR(os_setgroups__doc__, +"setgroups($module, groups, /)\n" +"--\n" +"\n" +"Set the groups of the current process to list."); + +#define OS_SETGROUPS_METHODDEF \ + {"setgroups", (PyCFunction)os_setgroups, METH_O, os_setgroups__doc__}, + +#endif /* defined(HAVE_SETGROUPS) */ + +#if defined(HAVE_WAIT3) + +PyDoc_STRVAR(os_wait3__doc__, +"wait3($module, /, options)\n" +"--\n" +"\n" +"Wait for completion of a child process.\n" +"\n" +"Returns a tuple of information about the child process:\n" +" (pid, status, rusage)"); + +#define OS_WAIT3_METHODDEF \ + {"wait3", _PyCFunction_CAST(os_wait3), METH_FASTCALL|METH_KEYWORDS, os_wait3__doc__}, + +static PyObject * +os_wait3_impl(PyObject *module, int options); + +static PyObject * +os_wait3(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(options), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"options", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "wait3", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int options; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + options = _PyLong_AsInt(args[0]); + if (options == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_wait3_impl(module, options); + +exit: + return return_value; +} + +#endif /* defined(HAVE_WAIT3) */ + +#if defined(HAVE_WAIT4) + +PyDoc_STRVAR(os_wait4__doc__, +"wait4($module, /, pid, options)\n" +"--\n" +"\n" +"Wait for completion of a specific child process.\n" +"\n" +"Returns a tuple of information about the child process:\n" +" (pid, status, rusage)"); + +#define OS_WAIT4_METHODDEF \ + {"wait4", _PyCFunction_CAST(os_wait4), METH_FASTCALL|METH_KEYWORDS, os_wait4__doc__}, + +static PyObject * +os_wait4_impl(PyObject *module, pid_t pid, int options); + +static PyObject * +os_wait4(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(pid), &_Py_ID(options), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"pid", "options", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .format = "" _Py_PARSE_PID "i:wait4", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + pid_t pid; + int options; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &pid, &options)) { + goto exit; + } + return_value = os_wait4_impl(module, pid, options); + +exit: + return return_value; +} + +#endif /* defined(HAVE_WAIT4) */ + +#if (defined(HAVE_WAITID) && !defined(__APPLE__)) + +PyDoc_STRVAR(os_waitid__doc__, +"waitid($module, idtype, id, options, /)\n" +"--\n" +"\n" +"Returns the result of waiting for a process or processes.\n" +"\n" +" idtype\n" +" Must be one of be P_PID, P_PGID or P_ALL.\n" +" id\n" +" The id to wait on.\n" +" options\n" +" Constructed from the ORing of one or more of WEXITED, WSTOPPED\n" +" or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.\n" +"\n" +"Returns either waitid_result or None if WNOHANG is specified and there are\n" +"no children in a waitable state."); + +#define OS_WAITID_METHODDEF \ + {"waitid", _PyCFunction_CAST(os_waitid), METH_FASTCALL, os_waitid__doc__}, + +static PyObject * +os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options); + +static PyObject * +os_waitid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + idtype_t idtype; + id_t id; + int options; + + if (!_PyArg_ParseStack(args, nargs, "i" _Py_PARSE_PID "i:waitid", + &idtype, &id, &options)) { + goto exit; + } + return_value = os_waitid_impl(module, idtype, id, options); + +exit: + return return_value; +} + +#endif /* (defined(HAVE_WAITID) && !defined(__APPLE__)) */ + +#if defined(HAVE_WAITPID) + +PyDoc_STRVAR(os_waitpid__doc__, +"waitpid($module, pid, options, /)\n" +"--\n" +"\n" +"Wait for completion of a given child process.\n" +"\n" +"Returns a tuple of information regarding the child process:\n" +" (pid, status)\n" +"\n" +"The options argument is ignored on Windows."); + +#define OS_WAITPID_METHODDEF \ + {"waitpid", _PyCFunction_CAST(os_waitpid), METH_FASTCALL, os_waitpid__doc__}, + +static PyObject * +os_waitpid_impl(PyObject *module, pid_t pid, int options); + +static PyObject * +os_waitpid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + pid_t pid; + int options; + + if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "i:waitpid", + &pid, &options)) { + goto exit; + } + return_value = os_waitpid_impl(module, pid, options); + +exit: + return return_value; +} + +#endif /* defined(HAVE_WAITPID) */ + +#if !defined(HAVE_WAITPID) && defined(HAVE_CWAIT) + +PyDoc_STRVAR(os_waitpid__doc__, +"waitpid($module, pid, options, /)\n" +"--\n" +"\n" +"Wait for completion of a given process.\n" +"\n" +"Returns a tuple of information regarding the process:\n" +" (pid, status << 8)\n" +"\n" +"The options argument is ignored on Windows."); + +#define OS_WAITPID_METHODDEF \ + {"waitpid", _PyCFunction_CAST(os_waitpid), METH_FASTCALL, os_waitpid__doc__}, + +static PyObject * +os_waitpid_impl(PyObject *module, intptr_t pid, int options); + +static PyObject * +os_waitpid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + intptr_t pid; + int options; + + if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_INTPTR "i:waitpid", + &pid, &options)) { + goto exit; + } + return_value = os_waitpid_impl(module, pid, options); + +exit: + return return_value; +} + +#endif /* !defined(HAVE_WAITPID) && defined(HAVE_CWAIT) */ + +#if defined(HAVE_WAIT) + +PyDoc_STRVAR(os_wait__doc__, +"wait($module, /)\n" +"--\n" +"\n" +"Wait for completion of a child process.\n" +"\n" +"Returns a tuple of information about the child process:\n" +" (pid, status)"); + +#define OS_WAIT_METHODDEF \ + {"wait", (PyCFunction)os_wait, METH_NOARGS, os_wait__doc__}, + +static PyObject * +os_wait_impl(PyObject *module); + +static PyObject * +os_wait(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_wait_impl(module); +} + +#endif /* defined(HAVE_WAIT) */ + +#if (defined(__linux__) && defined(__NR_pidfd_open)) + +PyDoc_STRVAR(os_pidfd_open__doc__, +"pidfd_open($module, /, pid, flags=0)\n" +"--\n" +"\n" +"Return a file descriptor referring to the process *pid*.\n" +"\n" +"The descriptor can be used to perform process management without races and\n" +"signals."); + +#define OS_PIDFD_OPEN_METHODDEF \ + {"pidfd_open", _PyCFunction_CAST(os_pidfd_open), METH_FASTCALL|METH_KEYWORDS, os_pidfd_open__doc__}, + +static PyObject * +os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags); + +static PyObject * +os_pidfd_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(pid), &_Py_ID(flags), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"pid", "flags", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .format = "" _Py_PARSE_PID "|O&:pidfd_open", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + pid_t pid; + unsigned int flags = 0; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &pid, _PyLong_UnsignedInt_Converter, &flags)) { + goto exit; + } + return_value = os_pidfd_open_impl(module, pid, flags); + +exit: + return return_value; +} + +#endif /* (defined(__linux__) && defined(__NR_pidfd_open)) */ + +#if defined(HAVE_SETNS) + +PyDoc_STRVAR(os_setns__doc__, +"setns($module, /, fd, nstype=0)\n" +"--\n" +"\n" +"Move the calling thread into different namespaces.\n" +"\n" +" fd\n" +" A file descriptor to a namespace.\n" +" nstype\n" +" Type of namespace."); + +#define OS_SETNS_METHODDEF \ + {"setns", _PyCFunction_CAST(os_setns), METH_FASTCALL|METH_KEYWORDS, os_setns__doc__}, + +static PyObject * +os_setns_impl(PyObject *module, int fd, int nstype); + +static PyObject * +os_setns(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(fd), &_Py_ID(nstype), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"fd", "nstype", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "setns", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + int fd; + int nstype = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + nstype = _PyLong_AsInt(args[1]); + if (nstype == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_pos: + return_value = os_setns_impl(module, fd, nstype); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SETNS) */ + +#if defined(HAVE_UNSHARE) + +PyDoc_STRVAR(os_unshare__doc__, +"unshare($module, /, flags)\n" +"--\n" +"\n" +"Disassociate parts of a process (or thread) execution context.\n" +"\n" +" flags\n" +" Namespaces to be unshared."); + +#define OS_UNSHARE_METHODDEF \ + {"unshare", _PyCFunction_CAST(os_unshare), METH_FASTCALL|METH_KEYWORDS, os_unshare__doc__}, + +static PyObject * +os_unshare_impl(PyObject *module, int flags); + +static PyObject * +os_unshare(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(flags), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"flags", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "unshare", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int flags; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + flags = _PyLong_AsInt(args[0]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_unshare_impl(module, flags); + +exit: + return return_value; +} + +#endif /* defined(HAVE_UNSHARE) */ + +#if (defined(HAVE_READLINK) || defined(MS_WINDOWS)) + +PyDoc_STRVAR(os_readlink__doc__, +"readlink($module, /, path, *, dir_fd=None)\n" +"--\n" +"\n" +"Return a string representing the path to which the symbolic link points.\n" +"\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +"and path should be relative; path will then be relative to that directory.\n" +"\n" +"dir_fd may not be implemented on your platform. If it is unavailable,\n" +"using it will raise a NotImplementedError."); + +#define OS_READLINK_METHODDEF \ + {"readlink", _PyCFunction_CAST(os_readlink), METH_FASTCALL|METH_KEYWORDS, os_readlink__doc__}, + +static PyObject * +os_readlink_impl(PyObject *module, path_t *path, int dir_fd); + +static PyObject * +os_readlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(dir_fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "dir_fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "readlink", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + path_t path = PATH_T_INITIALIZE("readlink", "path", 0, 0); + int dir_fd = DEFAULT_DIR_FD; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (!READLINKAT_DIR_FD_CONVERTER(args[1], &dir_fd)) { + goto exit; + } +skip_optional_kwonly: + return_value = os_readlink_impl(module, &path, dir_fd); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* (defined(HAVE_READLINK) || defined(MS_WINDOWS)) */ + +#if defined(HAVE_SYMLINK) + +PyDoc_STRVAR(os_symlink__doc__, +"symlink($module, /, src, dst, target_is_directory=False, *, dir_fd=None)\n" +"--\n" +"\n" +"Create a symbolic link pointing to src named dst.\n" +"\n" +"target_is_directory is required on Windows if the target is to be\n" +" interpreted as a directory. (On Windows, symlink requires\n" +" Windows 6.0 or greater, and raises a NotImplementedError otherwise.)\n" +" target_is_directory is ignored on non-Windows platforms.\n" +"\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that directory.\n" +"dir_fd may not be implemented on your platform.\n" +" If it is unavailable, using it will raise a NotImplementedError."); + +#define OS_SYMLINK_METHODDEF \ + {"symlink", _PyCFunction_CAST(os_symlink), METH_FASTCALL|METH_KEYWORDS, os_symlink__doc__}, + +static PyObject * +os_symlink_impl(PyObject *module, path_t *src, path_t *dst, + int target_is_directory, int dir_fd); + +static PyObject * +os_symlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(src), &_Py_ID(dst), &_Py_ID(target_is_directory), &_Py_ID(dir_fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"src", "dst", "target_is_directory", "dir_fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "symlink", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + path_t src = PATH_T_INITIALIZE("symlink", "src", 0, 0); + path_t dst = PATH_T_INITIALIZE("symlink", "dst", 0, 0); + int target_is_directory = 0; + int dir_fd = DEFAULT_DIR_FD; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &src)) { + goto exit; + } + if (!path_converter(args[1], &dst)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[2]) { + target_is_directory = PyObject_IsTrue(args[2]); + if (target_is_directory < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + if (!SYMLINKAT_DIR_FD_CONVERTER(args[3], &dir_fd)) { + goto exit; + } +skip_optional_kwonly: + return_value = os_symlink_impl(module, &src, &dst, target_is_directory, dir_fd); + +exit: + /* Cleanup for src */ + path_cleanup(&src); + /* Cleanup for dst */ + path_cleanup(&dst); + + return return_value; +} + +#endif /* defined(HAVE_SYMLINK) */ + +#if defined(HAVE_TIMES) + +PyDoc_STRVAR(os_times__doc__, +"times($module, /)\n" +"--\n" +"\n" +"Return a collection containing process timing information.\n" +"\n" +"The object returned behaves like a named tuple with these fields:\n" +" (utime, stime, cutime, cstime, elapsed_time)\n" +"All fields are floating point numbers."); + +#define OS_TIMES_METHODDEF \ + {"times", (PyCFunction)os_times, METH_NOARGS, os_times__doc__}, + +static PyObject * +os_times_impl(PyObject *module); + +static PyObject * +os_times(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_times_impl(module); +} + +#endif /* defined(HAVE_TIMES) */ + +#if defined(HAVE_GETSID) + +PyDoc_STRVAR(os_getsid__doc__, +"getsid($module, pid, /)\n" +"--\n" +"\n" +"Call the system call getsid(pid) and return the result."); + +#define OS_GETSID_METHODDEF \ + {"getsid", (PyCFunction)os_getsid, METH_O, os_getsid__doc__}, + +static PyObject * +os_getsid_impl(PyObject *module, pid_t pid); + +static PyObject * +os_getsid(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + pid_t pid; + + if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":getsid", &pid)) { + goto exit; + } + return_value = os_getsid_impl(module, pid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_GETSID) */ + +#if defined(HAVE_SETSID) + +PyDoc_STRVAR(os_setsid__doc__, +"setsid($module, /)\n" +"--\n" +"\n" +"Call the system call setsid()."); + +#define OS_SETSID_METHODDEF \ + {"setsid", (PyCFunction)os_setsid, METH_NOARGS, os_setsid__doc__}, + +static PyObject * +os_setsid_impl(PyObject *module); + +static PyObject * +os_setsid(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_setsid_impl(module); +} + +#endif /* defined(HAVE_SETSID) */ + +#if defined(HAVE_SETPGID) + +PyDoc_STRVAR(os_setpgid__doc__, +"setpgid($module, pid, pgrp, /)\n" +"--\n" +"\n" +"Call the system call setpgid(pid, pgrp)."); + +#define OS_SETPGID_METHODDEF \ + {"setpgid", _PyCFunction_CAST(os_setpgid), METH_FASTCALL, os_setpgid__doc__}, + +static PyObject * +os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp); + +static PyObject * +os_setpgid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + pid_t pid; + pid_t pgrp; + + if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "" _Py_PARSE_PID ":setpgid", + &pid, &pgrp)) { + goto exit; + } + return_value = os_setpgid_impl(module, pid, pgrp); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SETPGID) */ + +#if defined(HAVE_TCGETPGRP) + +PyDoc_STRVAR(os_tcgetpgrp__doc__, +"tcgetpgrp($module, fd, /)\n" +"--\n" +"\n" +"Return the process group associated with the terminal specified by fd."); + +#define OS_TCGETPGRP_METHODDEF \ + {"tcgetpgrp", (PyCFunction)os_tcgetpgrp, METH_O, os_tcgetpgrp__doc__}, + +static PyObject * +os_tcgetpgrp_impl(PyObject *module, int fd); + +static PyObject * +os_tcgetpgrp(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int fd; + + fd = _PyLong_AsInt(arg); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_tcgetpgrp_impl(module, fd); + +exit: + return return_value; +} + +#endif /* defined(HAVE_TCGETPGRP) */ + +#if defined(HAVE_TCSETPGRP) + +PyDoc_STRVAR(os_tcsetpgrp__doc__, +"tcsetpgrp($module, fd, pgid, /)\n" +"--\n" +"\n" +"Set the process group associated with the terminal specified by fd."); + +#define OS_TCSETPGRP_METHODDEF \ + {"tcsetpgrp", _PyCFunction_CAST(os_tcsetpgrp), METH_FASTCALL, os_tcsetpgrp__doc__}, + +static PyObject * +os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid); + +static PyObject * +os_tcsetpgrp(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + pid_t pgid; + + if (!_PyArg_ParseStack(args, nargs, "i" _Py_PARSE_PID ":tcsetpgrp", + &fd, &pgid)) { + goto exit; + } + return_value = os_tcsetpgrp_impl(module, fd, pgid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_TCSETPGRP) */ + +PyDoc_STRVAR(os_open__doc__, +"open($module, /, path, flags, mode=511, *, dir_fd=None)\n" +"--\n" +"\n" +"Open a file for low level IO. Returns a file descriptor (integer).\n" +"\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that directory.\n" +"dir_fd may not be implemented on your platform.\n" +" If it is unavailable, using it will raise a NotImplementedError."); + +#define OS_OPEN_METHODDEF \ + {"open", _PyCFunction_CAST(os_open), METH_FASTCALL|METH_KEYWORDS, os_open__doc__}, + +static int +os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd); + +static PyObject * +os_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(flags), &_Py_ID(mode), &_Py_ID(dir_fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "flags", "mode", "dir_fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "open", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + path_t path = PATH_T_INITIALIZE("open", "path", 0, 0); + int flags; + int mode = 511; + int dir_fd = DEFAULT_DIR_FD; + int _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + flags = _PyLong_AsInt(args[1]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[2]) { + mode = _PyLong_AsInt(args[2]); + if (mode == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + if (!OPENAT_DIR_FD_CONVERTER(args[3], &dir_fd)) { + goto exit; + } +skip_optional_kwonly: + _return_value = os_open_impl(module, &path, flags, mode, dir_fd); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong((long)_return_value); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +PyDoc_STRVAR(os_close__doc__, +"close($module, /, fd)\n" +"--\n" +"\n" +"Close a file descriptor."); + +#define OS_CLOSE_METHODDEF \ + {"close", _PyCFunction_CAST(os_close), METH_FASTCALL|METH_KEYWORDS, os_close__doc__}, + +static PyObject * +os_close_impl(PyObject *module, int fd); + +static PyObject * +os_close(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "close", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int fd; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_close_impl(module, fd); + +exit: + return return_value; +} + +PyDoc_STRVAR(os_closerange__doc__, +"closerange($module, fd_low, fd_high, /)\n" +"--\n" +"\n" +"Closes all file descriptors in [fd_low, fd_high), ignoring errors."); + +#define OS_CLOSERANGE_METHODDEF \ + {"closerange", _PyCFunction_CAST(os_closerange), METH_FASTCALL, os_closerange__doc__}, + +static PyObject * +os_closerange_impl(PyObject *module, int fd_low, int fd_high); + +static PyObject * +os_closerange(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd_low; + int fd_high; + + if (!_PyArg_CheckPositional("closerange", nargs, 2, 2)) { + goto exit; + } + fd_low = _PyLong_AsInt(args[0]); + if (fd_low == -1 && PyErr_Occurred()) { + goto exit; + } + fd_high = _PyLong_AsInt(args[1]); + if (fd_high == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_closerange_impl(module, fd_low, fd_high); + +exit: + return return_value; +} + +PyDoc_STRVAR(os_dup__doc__, +"dup($module, fd, /)\n" +"--\n" +"\n" +"Return a duplicate of a file descriptor."); + +#define OS_DUP_METHODDEF \ + {"dup", (PyCFunction)os_dup, METH_O, os_dup__doc__}, + +static int +os_dup_impl(PyObject *module, int fd); + +static PyObject * +os_dup(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int fd; + int _return_value; + + fd = _PyLong_AsInt(arg); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_dup_impl(module, fd); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + +#if ((defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))) + +PyDoc_STRVAR(os_dup2__doc__, +"dup2($module, /, fd, fd2, inheritable=True)\n" +"--\n" +"\n" +"Duplicate file descriptor."); + +#define OS_DUP2_METHODDEF \ + {"dup2", _PyCFunction_CAST(os_dup2), METH_FASTCALL|METH_KEYWORDS, os_dup2__doc__}, + +static int +os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable); + +static PyObject * +os_dup2(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(fd), &_Py_ID(fd2), &_Py_ID(inheritable), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"fd", "fd2", "inheritable", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "dup2", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + int fd; + int fd2; + int inheritable = 1; + int _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf); + if (!args) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + fd2 = _PyLong_AsInt(args[1]); + if (fd2 == -1 && PyErr_Occurred()) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + inheritable = PyObject_IsTrue(args[2]); + if (inheritable < 0) { + goto exit; + } +skip_optional_pos: + _return_value = os_dup2_impl(module, fd, fd2, inheritable); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + +#endif /* ((defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))) */ + +#if defined(HAVE_LOCKF) + +PyDoc_STRVAR(os_lockf__doc__, +"lockf($module, fd, command, length, /)\n" +"--\n" +"\n" +"Apply, test or remove a POSIX lock on an open file descriptor.\n" +"\n" +" fd\n" +" An open file descriptor.\n" +" command\n" +" One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.\n" +" length\n" +" The number of bytes to lock, starting at the current position."); + +#define OS_LOCKF_METHODDEF \ + {"lockf", _PyCFunction_CAST(os_lockf), METH_FASTCALL, os_lockf__doc__}, + +static PyObject * +os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length); + +static PyObject * +os_lockf(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + int command; + Py_off_t length; + + if (!_PyArg_CheckPositional("lockf", nargs, 3, 3)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + command = _PyLong_AsInt(args[1]); + if (command == -1 && PyErr_Occurred()) { + goto exit; + } + if (!Py_off_t_converter(args[2], &length)) { + goto exit; + } + return_value = os_lockf_impl(module, fd, command, length); + +exit: + return return_value; +} + +#endif /* defined(HAVE_LOCKF) */ + +PyDoc_STRVAR(os_lseek__doc__, +"lseek($module, fd, position, how, /)\n" +"--\n" +"\n" +"Set the position of a file descriptor. Return the new position.\n" +"\n" +"Return the new cursor position in number of bytes\n" +"relative to the beginning of the file."); + +#define OS_LSEEK_METHODDEF \ + {"lseek", _PyCFunction_CAST(os_lseek), METH_FASTCALL, os_lseek__doc__}, + +static Py_off_t +os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how); + +static PyObject * +os_lseek(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + Py_off_t position; + int how; + Py_off_t _return_value; + + if (!_PyArg_CheckPositional("lseek", nargs, 3, 3)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + if (!Py_off_t_converter(args[1], &position)) { + goto exit; + } + how = _PyLong_AsInt(args[2]); + if (how == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_lseek_impl(module, fd, position, how); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromPy_off_t(_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(os_read__doc__, +"read($module, fd, length, /)\n" +"--\n" +"\n" +"Read from a file descriptor. Returns a bytes object."); + +#define OS_READ_METHODDEF \ + {"read", _PyCFunction_CAST(os_read), METH_FASTCALL, os_read__doc__}, + +static PyObject * +os_read_impl(PyObject *module, int fd, Py_ssize_t length); + +static PyObject * +os_read(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + Py_ssize_t length; + + if (!_PyArg_CheckPositional("read", nargs, 2, 2)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[1]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + length = ival; + } + return_value = os_read_impl(module, fd, length); + +exit: + return return_value; +} + +#if defined(HAVE_READV) + +PyDoc_STRVAR(os_readv__doc__, +"readv($module, fd, buffers, /)\n" +"--\n" +"\n" +"Read from a file descriptor fd into an iterable of buffers.\n" +"\n" +"The buffers should be mutable buffers accepting bytes.\n" +"readv will transfer data into each buffer until it is full\n" +"and then move on to the next buffer in the sequence to hold\n" +"the rest of the data.\n" +"\n" +"readv returns the total number of bytes read,\n" +"which may be less than the total capacity of all the buffers."); + +#define OS_READV_METHODDEF \ + {"readv", _PyCFunction_CAST(os_readv), METH_FASTCALL, os_readv__doc__}, + +static Py_ssize_t +os_readv_impl(PyObject *module, int fd, PyObject *buffers); + +static PyObject * +os_readv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + PyObject *buffers; + Py_ssize_t _return_value; + + if (!_PyArg_CheckPositional("readv", nargs, 2, 2)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + buffers = args[1]; + _return_value = os_readv_impl(module, fd, buffers); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromSsize_t(_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_READV) */ + +#if defined(HAVE_PREAD) + +PyDoc_STRVAR(os_pread__doc__, +"pread($module, fd, length, offset, /)\n" +"--\n" +"\n" +"Read a number of bytes from a file descriptor starting at a particular offset.\n" +"\n" +"Read length bytes from file descriptor fd, starting at offset bytes from\n" +"the beginning of the file. The file offset remains unchanged."); + +#define OS_PREAD_METHODDEF \ + {"pread", _PyCFunction_CAST(os_pread), METH_FASTCALL, os_pread__doc__}, + +static PyObject * +os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset); + +static PyObject * +os_pread(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + Py_ssize_t length; + Py_off_t offset; + + if (!_PyArg_CheckPositional("pread", nargs, 3, 3)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[1]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + length = ival; + } + if (!Py_off_t_converter(args[2], &offset)) { + goto exit; + } + return_value = os_pread_impl(module, fd, length, offset); + +exit: + return return_value; +} + +#endif /* defined(HAVE_PREAD) */ + +#if (defined(HAVE_PREADV) || defined (HAVE_PREADV2)) + +PyDoc_STRVAR(os_preadv__doc__, +"preadv($module, fd, buffers, offset, flags=0, /)\n" +"--\n" +"\n" +"Reads from a file descriptor into a number of mutable bytes-like objects.\n" +"\n" +"Combines the functionality of readv() and pread(). As readv(), it will\n" +"transfer data into each buffer until it is full and then move on to the next\n" +"buffer in the sequence to hold the rest of the data. Its fourth argument,\n" +"specifies the file offset at which the input operation is to be performed. It\n" +"will return the total number of bytes read (which can be less than the total\n" +"capacity of all the objects).\n" +"\n" +"The flags argument contains a bitwise OR of zero or more of the following flags:\n" +"\n" +"- RWF_HIPRI\n" +"- RWF_NOWAIT\n" +"\n" +"Using non-zero flags requires Linux 4.6 or newer."); + +#define OS_PREADV_METHODDEF \ + {"preadv", _PyCFunction_CAST(os_preadv), METH_FASTCALL, os_preadv__doc__}, + +static Py_ssize_t +os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, + int flags); + +static PyObject * +os_preadv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + PyObject *buffers; + Py_off_t offset; + int flags = 0; + Py_ssize_t _return_value; + + if (!_PyArg_CheckPositional("preadv", nargs, 3, 4)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + buffers = args[1]; + if (!Py_off_t_converter(args[2], &offset)) { + goto exit; + } + if (nargs < 4) { + goto skip_optional; + } + flags = _PyLong_AsInt(args[3]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + _return_value = os_preadv_impl(module, fd, buffers, offset, flags); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromSsize_t(_return_value); + +exit: + return return_value; +} + +#endif /* (defined(HAVE_PREADV) || defined (HAVE_PREADV2)) */ + +PyDoc_STRVAR(os_write__doc__, +"write($module, fd, data, /)\n" +"--\n" +"\n" +"Write a bytes object to a file descriptor."); + +#define OS_WRITE_METHODDEF \ + {"write", _PyCFunction_CAST(os_write), METH_FASTCALL, os_write__doc__}, + +static Py_ssize_t +os_write_impl(PyObject *module, int fd, Py_buffer *data); + +static PyObject * +os_write(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + Py_buffer data = {NULL, NULL}; + Py_ssize_t _return_value; + + if (!_PyArg_CheckPositional("write", nargs, 2, 2)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + if (PyObject_GetBuffer(args[1], &data, PyBUF_SIMPLE) != 0) { + goto exit; + } + if (!PyBuffer_IsContiguous(&data, 'C')) { + _PyArg_BadArgument("write", "argument 2", "contiguous buffer", args[1]); + goto exit; + } + _return_value = os_write_impl(module, fd, &data); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromSsize_t(_return_value); + +exit: + /* Cleanup for data */ + if (data.obj) { + PyBuffer_Release(&data); + } + + return return_value; +} + +#if defined(HAVE_SENDFILE) && defined(__APPLE__) + +PyDoc_STRVAR(os_sendfile__doc__, +"sendfile($module, /, out_fd, in_fd, offset, count, headers=(),\n" +" trailers=(), flags=0)\n" +"--\n" +"\n" +"Copy count bytes from file descriptor in_fd to file descriptor out_fd."); + +#define OS_SENDFILE_METHODDEF \ + {"sendfile", _PyCFunction_CAST(os_sendfile), METH_FASTCALL|METH_KEYWORDS, os_sendfile__doc__}, + +static PyObject * +os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset, + Py_off_t sbytes, PyObject *headers, PyObject *trailers, + int flags); + +static PyObject * +os_sendfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 7 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(out_fd), &_Py_ID(in_fd), &_Py_ID(offset), &_Py_ID(count), &_Py_ID(headers), &_Py_ID(trailers), &_Py_ID(flags), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"out_fd", "in_fd", "offset", "count", "headers", "trailers", "flags", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "sendfile", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[7]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 4; + int out_fd; + int in_fd; + Py_off_t offset; + Py_off_t sbytes; + PyObject *headers = NULL; + PyObject *trailers = NULL; + int flags = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 4, 7, 0, argsbuf); + if (!args) { + goto exit; + } + out_fd = _PyLong_AsInt(args[0]); + if (out_fd == -1 && PyErr_Occurred()) { + goto exit; + } + in_fd = _PyLong_AsInt(args[1]); + if (in_fd == -1 && PyErr_Occurred()) { + goto exit; + } + if (!Py_off_t_converter(args[2], &offset)) { + goto exit; + } + if (!Py_off_t_converter(args[3], &sbytes)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[4]) { + headers = args[4]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[5]) { + trailers = args[5]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + flags = _PyLong_AsInt(args[6]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_pos: + return_value = os_sendfile_impl(module, out_fd, in_fd, offset, sbytes, headers, trailers, flags); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SENDFILE) && defined(__APPLE__) */ + +#if defined(HAVE_SENDFILE) && !defined(__APPLE__) && (defined(__FreeBSD__) || defined(__DragonFly__)) + +PyDoc_STRVAR(os_sendfile__doc__, +"sendfile($module, /, out_fd, in_fd, offset, count, headers=(),\n" +" trailers=(), flags=0)\n" +"--\n" +"\n" +"Copy count bytes from file descriptor in_fd to file descriptor out_fd."); + +#define OS_SENDFILE_METHODDEF \ + {"sendfile", _PyCFunction_CAST(os_sendfile), METH_FASTCALL|METH_KEYWORDS, os_sendfile__doc__}, + +static PyObject * +os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset, + Py_ssize_t count, PyObject *headers, PyObject *trailers, + int flags); + +static PyObject * +os_sendfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 7 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(out_fd), &_Py_ID(in_fd), &_Py_ID(offset), &_Py_ID(count), &_Py_ID(headers), &_Py_ID(trailers), &_Py_ID(flags), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"out_fd", "in_fd", "offset", "count", "headers", "trailers", "flags", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "sendfile", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[7]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 4; + int out_fd; + int in_fd; + Py_off_t offset; + Py_ssize_t count; + PyObject *headers = NULL; + PyObject *trailers = NULL; + int flags = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 4, 7, 0, argsbuf); + if (!args) { + goto exit; + } + out_fd = _PyLong_AsInt(args[0]); + if (out_fd == -1 && PyErr_Occurred()) { + goto exit; + } + in_fd = _PyLong_AsInt(args[1]); + if (in_fd == -1 && PyErr_Occurred()) { + goto exit; + } + if (!Py_off_t_converter(args[2], &offset)) { + goto exit; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[3]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + count = ival; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[4]) { + headers = args[4]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[5]) { + trailers = args[5]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + flags = _PyLong_AsInt(args[6]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_pos: + return_value = os_sendfile_impl(module, out_fd, in_fd, offset, count, headers, trailers, flags); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SENDFILE) && !defined(__APPLE__) && (defined(__FreeBSD__) || defined(__DragonFly__)) */ + +#if defined(HAVE_SENDFILE) && !defined(__APPLE__) && !(defined(__FreeBSD__) || defined(__DragonFly__)) + +PyDoc_STRVAR(os_sendfile__doc__, +"sendfile($module, /, out_fd, in_fd, offset, count)\n" +"--\n" +"\n" +"Copy count bytes from file descriptor in_fd to file descriptor out_fd."); + +#define OS_SENDFILE_METHODDEF \ + {"sendfile", _PyCFunction_CAST(os_sendfile), METH_FASTCALL|METH_KEYWORDS, os_sendfile__doc__}, + +static PyObject * +os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj, + Py_ssize_t count); + +static PyObject * +os_sendfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(out_fd), &_Py_ID(in_fd), &_Py_ID(offset), &_Py_ID(count), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"out_fd", "in_fd", "offset", "count", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "sendfile", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + int out_fd; + int in_fd; + PyObject *offobj; + Py_ssize_t count; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 4, 4, 0, argsbuf); + if (!args) { + goto exit; + } + out_fd = _PyLong_AsInt(args[0]); + if (out_fd == -1 && PyErr_Occurred()) { + goto exit; + } + in_fd = _PyLong_AsInt(args[1]); + if (in_fd == -1 && PyErr_Occurred()) { + goto exit; + } + offobj = args[2]; + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[3]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + count = ival; + } + return_value = os_sendfile_impl(module, out_fd, in_fd, offobj, count); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SENDFILE) && !defined(__APPLE__) && !(defined(__FreeBSD__) || defined(__DragonFly__)) */ + +#if defined(__APPLE__) + +PyDoc_STRVAR(os__fcopyfile__doc__, +"_fcopyfile($module, in_fd, out_fd, flags, /)\n" +"--\n" +"\n" +"Efficiently copy content or metadata of 2 regular file descriptors (macOS)."); + +#define OS__FCOPYFILE_METHODDEF \ + {"_fcopyfile", _PyCFunction_CAST(os__fcopyfile), METH_FASTCALL, os__fcopyfile__doc__}, + +static PyObject * +os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags); + +static PyObject * +os__fcopyfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int in_fd; + int out_fd; + int flags; + + if (!_PyArg_CheckPositional("_fcopyfile", nargs, 3, 3)) { + goto exit; + } + in_fd = _PyLong_AsInt(args[0]); + if (in_fd == -1 && PyErr_Occurred()) { + goto exit; + } + out_fd = _PyLong_AsInt(args[1]); + if (out_fd == -1 && PyErr_Occurred()) { + goto exit; + } + flags = _PyLong_AsInt(args[2]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os__fcopyfile_impl(module, in_fd, out_fd, flags); + +exit: + return return_value; +} + +#endif /* defined(__APPLE__) */ + +PyDoc_STRVAR(os_fstat__doc__, +"fstat($module, /, fd)\n" +"--\n" +"\n" +"Perform a stat system call on the given file descriptor.\n" +"\n" +"Like stat(), but for an open file descriptor.\n" +"Equivalent to os.stat(fd)."); + +#define OS_FSTAT_METHODDEF \ + {"fstat", _PyCFunction_CAST(os_fstat), METH_FASTCALL|METH_KEYWORDS, os_fstat__doc__}, + +static PyObject * +os_fstat_impl(PyObject *module, int fd); + +static PyObject * +os_fstat(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "fstat", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int fd; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_fstat_impl(module, fd); + +exit: + return return_value; +} + +PyDoc_STRVAR(os_isatty__doc__, +"isatty($module, fd, /)\n" +"--\n" +"\n" +"Return True if the fd is connected to a terminal.\n" +"\n" +"Return True if the file descriptor is an open file descriptor\n" +"connected to the slave end of a terminal."); + +#define OS_ISATTY_METHODDEF \ + {"isatty", (PyCFunction)os_isatty, METH_O, os_isatty__doc__}, + +static int +os_isatty_impl(PyObject *module, int fd); + +static PyObject * +os_isatty(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int fd; + int _return_value; + + fd = _PyLong_AsInt(arg); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_isatty_impl(module, fd); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +#if defined(HAVE_PIPE) + +PyDoc_STRVAR(os_pipe__doc__, +"pipe($module, /)\n" +"--\n" +"\n" +"Create a pipe.\n" +"\n" +"Returns a tuple of two file descriptors:\n" +" (read_fd, write_fd)"); + +#define OS_PIPE_METHODDEF \ + {"pipe", (PyCFunction)os_pipe, METH_NOARGS, os_pipe__doc__}, + +static PyObject * +os_pipe_impl(PyObject *module); + +static PyObject * +os_pipe(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_pipe_impl(module); +} + +#endif /* defined(HAVE_PIPE) */ + +#if defined(HAVE_PIPE2) + +PyDoc_STRVAR(os_pipe2__doc__, +"pipe2($module, flags, /)\n" +"--\n" +"\n" +"Create a pipe with flags set atomically.\n" +"\n" +"Returns a tuple of two file descriptors:\n" +" (read_fd, write_fd)\n" +"\n" +"flags can be constructed by ORing together one or more of these values:\n" +"O_NONBLOCK, O_CLOEXEC."); + +#define OS_PIPE2_METHODDEF \ + {"pipe2", (PyCFunction)os_pipe2, METH_O, os_pipe2__doc__}, + +static PyObject * +os_pipe2_impl(PyObject *module, int flags); + +static PyObject * +os_pipe2(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int flags; + + flags = _PyLong_AsInt(arg); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_pipe2_impl(module, flags); + +exit: + return return_value; +} + +#endif /* defined(HAVE_PIPE2) */ + +#if defined(HAVE_WRITEV) + +PyDoc_STRVAR(os_writev__doc__, +"writev($module, fd, buffers, /)\n" +"--\n" +"\n" +"Iterate over buffers, and write the contents of each to a file descriptor.\n" +"\n" +"Returns the total number of bytes written.\n" +"buffers must be a sequence of bytes-like objects."); + +#define OS_WRITEV_METHODDEF \ + {"writev", _PyCFunction_CAST(os_writev), METH_FASTCALL, os_writev__doc__}, + +static Py_ssize_t +os_writev_impl(PyObject *module, int fd, PyObject *buffers); + +static PyObject * +os_writev(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + PyObject *buffers; + Py_ssize_t _return_value; + + if (!_PyArg_CheckPositional("writev", nargs, 2, 2)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + buffers = args[1]; + _return_value = os_writev_impl(module, fd, buffers); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromSsize_t(_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_WRITEV) */ + +#if defined(HAVE_PWRITE) + +PyDoc_STRVAR(os_pwrite__doc__, +"pwrite($module, fd, buffer, offset, /)\n" +"--\n" +"\n" +"Write bytes to a file descriptor starting at a particular offset.\n" +"\n" +"Write buffer to fd, starting at offset bytes from the beginning of\n" +"the file. Returns the number of bytes writte. Does not change the\n" +"current file offset."); + +#define OS_PWRITE_METHODDEF \ + {"pwrite", _PyCFunction_CAST(os_pwrite), METH_FASTCALL, os_pwrite__doc__}, + +static Py_ssize_t +os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset); + +static PyObject * +os_pwrite(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + Py_buffer buffer = {NULL, NULL}; + Py_off_t offset; + Py_ssize_t _return_value; + + if (!_PyArg_CheckPositional("pwrite", nargs, 3, 3)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + if (PyObject_GetBuffer(args[1], &buffer, PyBUF_SIMPLE) != 0) { + goto exit; + } + if (!PyBuffer_IsContiguous(&buffer, 'C')) { + _PyArg_BadArgument("pwrite", "argument 2", "contiguous buffer", args[1]); + goto exit; + } + if (!Py_off_t_converter(args[2], &offset)) { + goto exit; + } + _return_value = os_pwrite_impl(module, fd, &buffer, offset); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromSsize_t(_return_value); + +exit: + /* Cleanup for buffer */ + if (buffer.obj) { + PyBuffer_Release(&buffer); + } + + return return_value; +} + +#endif /* defined(HAVE_PWRITE) */ + +#if (defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)) + +PyDoc_STRVAR(os_pwritev__doc__, +"pwritev($module, fd, buffers, offset, flags=0, /)\n" +"--\n" +"\n" +"Writes the contents of bytes-like objects to a file descriptor at a given offset.\n" +"\n" +"Combines the functionality of writev() and pwrite(). All buffers must be a sequence\n" +"of bytes-like objects. Buffers are processed in array order. Entire contents of first\n" +"buffer is written before proceeding to second, and so on. The operating system may\n" +"set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.\n" +"This function writes the contents of each object to the file descriptor and returns\n" +"the total number of bytes written.\n" +"\n" +"The flags argument contains a bitwise OR of zero or more of the following flags:\n" +"\n" +"- RWF_DSYNC\n" +"- RWF_SYNC\n" +"- RWF_APPEND\n" +"\n" +"Using non-zero flags requires Linux 4.7 or newer."); + +#define OS_PWRITEV_METHODDEF \ + {"pwritev", _PyCFunction_CAST(os_pwritev), METH_FASTCALL, os_pwritev__doc__}, + +static Py_ssize_t +os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, + int flags); + +static PyObject * +os_pwritev(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + PyObject *buffers; + Py_off_t offset; + int flags = 0; + Py_ssize_t _return_value; + + if (!_PyArg_CheckPositional("pwritev", nargs, 3, 4)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + buffers = args[1]; + if (!Py_off_t_converter(args[2], &offset)) { + goto exit; + } + if (nargs < 4) { + goto skip_optional; + } + flags = _PyLong_AsInt(args[3]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + _return_value = os_pwritev_impl(module, fd, buffers, offset, flags); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromSsize_t(_return_value); + +exit: + return return_value; +} + +#endif /* (defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)) */ + +#if defined(HAVE_COPY_FILE_RANGE) + +PyDoc_STRVAR(os_copy_file_range__doc__, +"copy_file_range($module, /, src, dst, count, offset_src=None,\n" +" offset_dst=None)\n" +"--\n" +"\n" +"Copy count bytes from one file descriptor to another.\n" +"\n" +" src\n" +" Source file descriptor.\n" +" dst\n" +" Destination file descriptor.\n" +" count\n" +" Number of bytes to copy.\n" +" offset_src\n" +" Starting offset in src.\n" +" offset_dst\n" +" Starting offset in dst.\n" +"\n" +"If offset_src is None, then src is read from the current position;\n" +"respectively for offset_dst."); + +#define OS_COPY_FILE_RANGE_METHODDEF \ + {"copy_file_range", _PyCFunction_CAST(os_copy_file_range), METH_FASTCALL|METH_KEYWORDS, os_copy_file_range__doc__}, + +static PyObject * +os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count, + PyObject *offset_src, PyObject *offset_dst); + +static PyObject * +os_copy_file_range(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 5 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(src), &_Py_ID(dst), &_Py_ID(count), &_Py_ID(offset_src), &_Py_ID(offset_dst), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"src", "dst", "count", "offset_src", "offset_dst", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "copy_file_range", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; + int src; + int dst; + Py_ssize_t count; + PyObject *offset_src = Py_None; + PyObject *offset_dst = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 5, 0, argsbuf); + if (!args) { + goto exit; + } + src = _PyLong_AsInt(args[0]); + if (src == -1 && PyErr_Occurred()) { + goto exit; + } + dst = _PyLong_AsInt(args[1]); + if (dst == -1 && PyErr_Occurred()) { + goto exit; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[2]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + count = ival; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[3]) { + offset_src = args[3]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + offset_dst = args[4]; +skip_optional_pos: + return_value = os_copy_file_range_impl(module, src, dst, count, offset_src, offset_dst); + +exit: + return return_value; +} + +#endif /* defined(HAVE_COPY_FILE_RANGE) */ + +#if ((defined(HAVE_SPLICE) && !defined(_AIX))) + +PyDoc_STRVAR(os_splice__doc__, +"splice($module, /, src, dst, count, offset_src=None, offset_dst=None,\n" +" flags=0)\n" +"--\n" +"\n" +"Transfer count bytes from one pipe to a descriptor or vice versa.\n" +"\n" +" src\n" +" Source file descriptor.\n" +" dst\n" +" Destination file descriptor.\n" +" count\n" +" Number of bytes to copy.\n" +" offset_src\n" +" Starting offset in src.\n" +" offset_dst\n" +" Starting offset in dst.\n" +" flags\n" +" Flags to modify the semantics of the call.\n" +"\n" +"If offset_src is None, then src is read from the current position;\n" +"respectively for offset_dst. The offset associated to the file\n" +"descriptor that refers to a pipe must be None."); + +#define OS_SPLICE_METHODDEF \ + {"splice", _PyCFunction_CAST(os_splice), METH_FASTCALL|METH_KEYWORDS, os_splice__doc__}, + +static PyObject * +os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count, + PyObject *offset_src, PyObject *offset_dst, + unsigned int flags); + +static PyObject * +os_splice(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 6 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(src), &_Py_ID(dst), &_Py_ID(count), &_Py_ID(offset_src), &_Py_ID(offset_dst), &_Py_ID(flags), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"src", "dst", "count", "offset_src", "offset_dst", "flags", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "splice", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[6]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; + int src; + int dst; + Py_ssize_t count; + PyObject *offset_src = Py_None; + PyObject *offset_dst = Py_None; + unsigned int flags = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 6, 0, argsbuf); + if (!args) { + goto exit; + } + src = _PyLong_AsInt(args[0]); + if (src == -1 && PyErr_Occurred()) { + goto exit; + } + dst = _PyLong_AsInt(args[1]); + if (dst == -1 && PyErr_Occurred()) { + goto exit; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[2]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + count = ival; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[3]) { + offset_src = args[3]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[4]) { + offset_dst = args[4]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (!_PyLong_UnsignedInt_Converter(args[5], &flags)) { + goto exit; + } +skip_optional_pos: + return_value = os_splice_impl(module, src, dst, count, offset_src, offset_dst, flags); + +exit: + return return_value; +} + +#endif /* ((defined(HAVE_SPLICE) && !defined(_AIX))) */ + +#if defined(HAVE_MKFIFO) + +PyDoc_STRVAR(os_mkfifo__doc__, +"mkfifo($module, /, path, mode=438, *, dir_fd=None)\n" +"--\n" +"\n" +"Create a \"fifo\" (a POSIX named pipe).\n" +"\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that directory.\n" +"dir_fd may not be implemented on your platform.\n" +" If it is unavailable, using it will raise a NotImplementedError."); + +#define OS_MKFIFO_METHODDEF \ + {"mkfifo", _PyCFunction_CAST(os_mkfifo), METH_FASTCALL|METH_KEYWORDS, os_mkfifo__doc__}, + +static PyObject * +os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd); + +static PyObject * +os_mkfifo(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(mode), &_Py_ID(dir_fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "mode", "dir_fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "mkfifo", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + path_t path = PATH_T_INITIALIZE("mkfifo", "path", 0, 0); + int mode = 438; + int dir_fd = DEFAULT_DIR_FD; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[1]) { + mode = _PyLong_AsInt(args[1]); + if (mode == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + if (!MKFIFOAT_DIR_FD_CONVERTER(args[2], &dir_fd)) { + goto exit; + } +skip_optional_kwonly: + return_value = os_mkfifo_impl(module, &path, mode, dir_fd); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(HAVE_MKFIFO) */ + +#if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) + +PyDoc_STRVAR(os_mknod__doc__, +"mknod($module, /, path, mode=384, device=0, *, dir_fd=None)\n" +"--\n" +"\n" +"Create a node in the file system.\n" +"\n" +"Create a node in the file system (file, device special file or named pipe)\n" +"at path. mode specifies both the permissions to use and the\n" +"type of node to be created, being combined (bitwise OR) with one of\n" +"S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode,\n" +"device defines the newly created device special file (probably using\n" +"os.makedev()). Otherwise device is ignored.\n" +"\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that directory.\n" +"dir_fd may not be implemented on your platform.\n" +" If it is unavailable, using it will raise a NotImplementedError."); + +#define OS_MKNOD_METHODDEF \ + {"mknod", _PyCFunction_CAST(os_mknod), METH_FASTCALL|METH_KEYWORDS, os_mknod__doc__}, + +static PyObject * +os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device, + int dir_fd); + +static PyObject * +os_mknod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(mode), &_Py_ID(device), &_Py_ID(dir_fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "mode", "device", "dir_fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "mknod", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + path_t path = PATH_T_INITIALIZE("mknod", "path", 0, 0); + int mode = 384; + dev_t device = 0; + int dir_fd = DEFAULT_DIR_FD; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[1]) { + mode = _PyLong_AsInt(args[1]); + if (mode == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[2]) { + if (!_Py_Dev_Converter(args[2], &device)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + if (!MKNODAT_DIR_FD_CONVERTER(args[3], &dir_fd)) { + goto exit; + } +skip_optional_kwonly: + return_value = os_mknod_impl(module, &path, mode, device, dir_fd); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) */ + +#if defined(HAVE_DEVICE_MACROS) + +PyDoc_STRVAR(os_major__doc__, +"major($module, device, /)\n" +"--\n" +"\n" +"Extracts a device major number from a raw device number."); + +#define OS_MAJOR_METHODDEF \ + {"major", (PyCFunction)os_major, METH_O, os_major__doc__}, + +static unsigned int +os_major_impl(PyObject *module, dev_t device); + +static PyObject * +os_major(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + dev_t device; + unsigned int _return_value; + + if (!_Py_Dev_Converter(arg, &device)) { + goto exit; + } + _return_value = os_major_impl(module, device); + if ((_return_value == (unsigned int)-1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromUnsignedLong((unsigned long)_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_DEVICE_MACROS) */ + +#if defined(HAVE_DEVICE_MACROS) + +PyDoc_STRVAR(os_minor__doc__, +"minor($module, device, /)\n" +"--\n" +"\n" +"Extracts a device minor number from a raw device number."); + +#define OS_MINOR_METHODDEF \ + {"minor", (PyCFunction)os_minor, METH_O, os_minor__doc__}, + +static unsigned int +os_minor_impl(PyObject *module, dev_t device); + +static PyObject * +os_minor(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + dev_t device; + unsigned int _return_value; + + if (!_Py_Dev_Converter(arg, &device)) { + goto exit; + } + _return_value = os_minor_impl(module, device); + if ((_return_value == (unsigned int)-1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromUnsignedLong((unsigned long)_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_DEVICE_MACROS) */ + +#if defined(HAVE_DEVICE_MACROS) + +PyDoc_STRVAR(os_makedev__doc__, +"makedev($module, major, minor, /)\n" +"--\n" +"\n" +"Composes a raw device number from the major and minor device numbers."); + +#define OS_MAKEDEV_METHODDEF \ + {"makedev", _PyCFunction_CAST(os_makedev), METH_FASTCALL, os_makedev__doc__}, + +static dev_t +os_makedev_impl(PyObject *module, int major, int minor); + +static PyObject * +os_makedev(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int major; + int minor; + dev_t _return_value; + + if (!_PyArg_CheckPositional("makedev", nargs, 2, 2)) { + goto exit; + } + major = _PyLong_AsInt(args[0]); + if (major == -1 && PyErr_Occurred()) { + goto exit; + } + minor = _PyLong_AsInt(args[1]); + if (minor == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_makedev_impl(module, major, minor); + if ((_return_value == (dev_t)-1) && PyErr_Occurred()) { + goto exit; + } + return_value = _PyLong_FromDev(_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_DEVICE_MACROS) */ + +#if (defined HAVE_FTRUNCATE || defined MS_WINDOWS) + +PyDoc_STRVAR(os_ftruncate__doc__, +"ftruncate($module, fd, length, /)\n" +"--\n" +"\n" +"Truncate a file, specified by file descriptor, to a specific length."); + +#define OS_FTRUNCATE_METHODDEF \ + {"ftruncate", _PyCFunction_CAST(os_ftruncate), METH_FASTCALL, os_ftruncate__doc__}, + +static PyObject * +os_ftruncate_impl(PyObject *module, int fd, Py_off_t length); + +static PyObject * +os_ftruncate(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + Py_off_t length; + + if (!_PyArg_CheckPositional("ftruncate", nargs, 2, 2)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + if (!Py_off_t_converter(args[1], &length)) { + goto exit; + } + return_value = os_ftruncate_impl(module, fd, length); + +exit: + return return_value; +} + +#endif /* (defined HAVE_FTRUNCATE || defined MS_WINDOWS) */ + +#if (defined HAVE_TRUNCATE || defined MS_WINDOWS) + +PyDoc_STRVAR(os_truncate__doc__, +"truncate($module, /, path, length)\n" +"--\n" +"\n" +"Truncate a file, specified by path, to a specific length.\n" +"\n" +"On some platforms, path may also be specified as an open file descriptor.\n" +" If this functionality is unavailable, using it raises an exception."); + +#define OS_TRUNCATE_METHODDEF \ + {"truncate", _PyCFunction_CAST(os_truncate), METH_FASTCALL|METH_KEYWORDS, os_truncate__doc__}, + +static PyObject * +os_truncate_impl(PyObject *module, path_t *path, Py_off_t length); + +static PyObject * +os_truncate(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(length), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "length", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "truncate", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + path_t path = PATH_T_INITIALIZE("truncate", "path", 0, PATH_HAVE_FTRUNCATE); + Py_off_t length; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!Py_off_t_converter(args[1], &length)) { + goto exit; + } + return_value = os_truncate_impl(module, &path, length); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* (defined HAVE_TRUNCATE || defined MS_WINDOWS) */ + +#if (defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)) + +PyDoc_STRVAR(os_posix_fallocate__doc__, +"posix_fallocate($module, fd, offset, length, /)\n" +"--\n" +"\n" +"Ensure a file has allocated at least a particular number of bytes on disk.\n" +"\n" +"Ensure that the file specified by fd encompasses a range of bytes\n" +"starting at offset bytes from the beginning and continuing for length bytes."); + +#define OS_POSIX_FALLOCATE_METHODDEF \ + {"posix_fallocate", _PyCFunction_CAST(os_posix_fallocate), METH_FASTCALL, os_posix_fallocate__doc__}, + +static PyObject * +os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset, + Py_off_t length); + +static PyObject * +os_posix_fallocate(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + Py_off_t offset; + Py_off_t length; + + if (!_PyArg_CheckPositional("posix_fallocate", nargs, 3, 3)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + if (!Py_off_t_converter(args[1], &offset)) { + goto exit; + } + if (!Py_off_t_converter(args[2], &length)) { + goto exit; + } + return_value = os_posix_fallocate_impl(module, fd, offset, length); + +exit: + return return_value; +} + +#endif /* (defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)) */ + +#if (defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)) + +PyDoc_STRVAR(os_posix_fadvise__doc__, +"posix_fadvise($module, fd, offset, length, advice, /)\n" +"--\n" +"\n" +"Announce an intention to access data in a specific pattern.\n" +"\n" +"Announce an intention to access data in a specific pattern, thus allowing\n" +"the kernel to make optimizations.\n" +"The advice applies to the region of the file specified by fd starting at\n" +"offset and continuing for length bytes.\n" +"advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,\n" +"POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or\n" +"POSIX_FADV_DONTNEED."); + +#define OS_POSIX_FADVISE_METHODDEF \ + {"posix_fadvise", _PyCFunction_CAST(os_posix_fadvise), METH_FASTCALL, os_posix_fadvise__doc__}, + +static PyObject * +os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset, + Py_off_t length, int advice); + +static PyObject * +os_posix_fadvise(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + Py_off_t offset; + Py_off_t length; + int advice; + + if (!_PyArg_CheckPositional("posix_fadvise", nargs, 4, 4)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + if (!Py_off_t_converter(args[1], &offset)) { + goto exit; + } + if (!Py_off_t_converter(args[2], &length)) { + goto exit; + } + advice = _PyLong_AsInt(args[3]); + if (advice == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_posix_fadvise_impl(module, fd, offset, length, advice); + +exit: + return return_value; +} + +#endif /* (defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)) */ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(os_putenv__doc__, +"putenv($module, name, value, /)\n" +"--\n" +"\n" +"Change or add an environment variable."); + +#define OS_PUTENV_METHODDEF \ + {"putenv", _PyCFunction_CAST(os_putenv), METH_FASTCALL, os_putenv__doc__}, + +static PyObject * +os_putenv_impl(PyObject *module, PyObject *name, PyObject *value); + +static PyObject * +os_putenv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *name; + PyObject *value; + + if (!_PyArg_CheckPositional("putenv", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("putenv", "argument 1", "str", args[0]); + goto exit; + } + if (PyUnicode_READY(args[0]) == -1) { + goto exit; + } + name = args[0]; + if (!PyUnicode_Check(args[1])) { + _PyArg_BadArgument("putenv", "argument 2", "str", args[1]); + goto exit; + } + if (PyUnicode_READY(args[1]) == -1) { + goto exit; + } + value = args[1]; + return_value = os_putenv_impl(module, name, value); + +exit: + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if !defined(MS_WINDOWS) + +PyDoc_STRVAR(os_putenv__doc__, +"putenv($module, name, value, /)\n" +"--\n" +"\n" +"Change or add an environment variable."); + +#define OS_PUTENV_METHODDEF \ + {"putenv", _PyCFunction_CAST(os_putenv), METH_FASTCALL, os_putenv__doc__}, + +static PyObject * +os_putenv_impl(PyObject *module, PyObject *name, PyObject *value); + +static PyObject * +os_putenv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *name = NULL; + PyObject *value = NULL; + + if (!_PyArg_CheckPositional("putenv", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_FSConverter(args[0], &name)) { + goto exit; + } + if (!PyUnicode_FSConverter(args[1], &value)) { + goto exit; + } + return_value = os_putenv_impl(module, name, value); + +exit: + /* Cleanup for name */ + Py_XDECREF(name); + /* Cleanup for value */ + Py_XDECREF(value); + + return return_value; +} + +#endif /* !defined(MS_WINDOWS) */ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(os_unsetenv__doc__, +"unsetenv($module, name, /)\n" +"--\n" +"\n" +"Delete an environment variable."); + +#define OS_UNSETENV_METHODDEF \ + {"unsetenv", (PyCFunction)os_unsetenv, METH_O, os_unsetenv__doc__}, + +static PyObject * +os_unsetenv_impl(PyObject *module, PyObject *name); + +static PyObject * +os_unsetenv(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyObject *name; + + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("unsetenv", "argument", "str", arg); + goto exit; + } + if (PyUnicode_READY(arg) == -1) { + goto exit; + } + name = arg; + return_value = os_unsetenv_impl(module, name); + +exit: + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if !defined(MS_WINDOWS) + +PyDoc_STRVAR(os_unsetenv__doc__, +"unsetenv($module, name, /)\n" +"--\n" +"\n" +"Delete an environment variable."); + +#define OS_UNSETENV_METHODDEF \ + {"unsetenv", (PyCFunction)os_unsetenv, METH_O, os_unsetenv__doc__}, + +static PyObject * +os_unsetenv_impl(PyObject *module, PyObject *name); + +static PyObject * +os_unsetenv(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyObject *name = NULL; + + if (!PyUnicode_FSConverter(arg, &name)) { + goto exit; + } + return_value = os_unsetenv_impl(module, name); + +exit: + /* Cleanup for name */ + Py_XDECREF(name); + + return return_value; +} + +#endif /* !defined(MS_WINDOWS) */ + +PyDoc_STRVAR(os_strerror__doc__, +"strerror($module, code, /)\n" +"--\n" +"\n" +"Translate an error code to a message string."); + +#define OS_STRERROR_METHODDEF \ + {"strerror", (PyCFunction)os_strerror, METH_O, os_strerror__doc__}, + +static PyObject * +os_strerror_impl(PyObject *module, int code); + +static PyObject * +os_strerror(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int code; + + code = _PyLong_AsInt(arg); + if (code == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_strerror_impl(module, code); + +exit: + return return_value; +} + +#if defined(HAVE_SYS_WAIT_H) && defined(WCOREDUMP) + +PyDoc_STRVAR(os_WCOREDUMP__doc__, +"WCOREDUMP($module, status, /)\n" +"--\n" +"\n" +"Return True if the process returning status was dumped to a core file."); + +#define OS_WCOREDUMP_METHODDEF \ + {"WCOREDUMP", (PyCFunction)os_WCOREDUMP, METH_O, os_WCOREDUMP__doc__}, + +static int +os_WCOREDUMP_impl(PyObject *module, int status); + +static PyObject * +os_WCOREDUMP(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int status; + int _return_value; + + status = _PyLong_AsInt(arg); + if (status == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_WCOREDUMP_impl(module, status); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SYS_WAIT_H) && defined(WCOREDUMP) */ + +#if defined(HAVE_SYS_WAIT_H) && defined(WIFCONTINUED) + +PyDoc_STRVAR(os_WIFCONTINUED__doc__, +"WIFCONTINUED($module, /, status)\n" +"--\n" +"\n" +"Return True if a particular process was continued from a job control stop.\n" +"\n" +"Return True if the process returning status was continued from a\n" +"job control stop."); + +#define OS_WIFCONTINUED_METHODDEF \ + {"WIFCONTINUED", _PyCFunction_CAST(os_WIFCONTINUED), METH_FASTCALL|METH_KEYWORDS, os_WIFCONTINUED__doc__}, + +static int +os_WIFCONTINUED_impl(PyObject *module, int status); + +static PyObject * +os_WIFCONTINUED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(status), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"status", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "WIFCONTINUED", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int status; + int _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + status = _PyLong_AsInt(args[0]); + if (status == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_WIFCONTINUED_impl(module, status); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SYS_WAIT_H) && defined(WIFCONTINUED) */ + +#if defined(HAVE_SYS_WAIT_H) && defined(WIFSTOPPED) + +PyDoc_STRVAR(os_WIFSTOPPED__doc__, +"WIFSTOPPED($module, /, status)\n" +"--\n" +"\n" +"Return True if the process returning status was stopped."); + +#define OS_WIFSTOPPED_METHODDEF \ + {"WIFSTOPPED", _PyCFunction_CAST(os_WIFSTOPPED), METH_FASTCALL|METH_KEYWORDS, os_WIFSTOPPED__doc__}, + +static int +os_WIFSTOPPED_impl(PyObject *module, int status); + +static PyObject * +os_WIFSTOPPED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(status), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"status", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "WIFSTOPPED", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int status; + int _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + status = _PyLong_AsInt(args[0]); + if (status == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_WIFSTOPPED_impl(module, status); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SYS_WAIT_H) && defined(WIFSTOPPED) */ + +#if defined(HAVE_SYS_WAIT_H) && defined(WIFSIGNALED) + +PyDoc_STRVAR(os_WIFSIGNALED__doc__, +"WIFSIGNALED($module, /, status)\n" +"--\n" +"\n" +"Return True if the process returning status was terminated by a signal."); + +#define OS_WIFSIGNALED_METHODDEF \ + {"WIFSIGNALED", _PyCFunction_CAST(os_WIFSIGNALED), METH_FASTCALL|METH_KEYWORDS, os_WIFSIGNALED__doc__}, + +static int +os_WIFSIGNALED_impl(PyObject *module, int status); + +static PyObject * +os_WIFSIGNALED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(status), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"status", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "WIFSIGNALED", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int status; + int _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + status = _PyLong_AsInt(args[0]); + if (status == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_WIFSIGNALED_impl(module, status); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SYS_WAIT_H) && defined(WIFSIGNALED) */ + +#if defined(HAVE_SYS_WAIT_H) && defined(WIFEXITED) + +PyDoc_STRVAR(os_WIFEXITED__doc__, +"WIFEXITED($module, /, status)\n" +"--\n" +"\n" +"Return True if the process returning status exited via the exit() system call."); + +#define OS_WIFEXITED_METHODDEF \ + {"WIFEXITED", _PyCFunction_CAST(os_WIFEXITED), METH_FASTCALL|METH_KEYWORDS, os_WIFEXITED__doc__}, + +static int +os_WIFEXITED_impl(PyObject *module, int status); + +static PyObject * +os_WIFEXITED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(status), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"status", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "WIFEXITED", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int status; + int _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + status = _PyLong_AsInt(args[0]); + if (status == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_WIFEXITED_impl(module, status); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SYS_WAIT_H) && defined(WIFEXITED) */ + +#if defined(HAVE_SYS_WAIT_H) && defined(WEXITSTATUS) + +PyDoc_STRVAR(os_WEXITSTATUS__doc__, +"WEXITSTATUS($module, /, status)\n" +"--\n" +"\n" +"Return the process return code from status."); + +#define OS_WEXITSTATUS_METHODDEF \ + {"WEXITSTATUS", _PyCFunction_CAST(os_WEXITSTATUS), METH_FASTCALL|METH_KEYWORDS, os_WEXITSTATUS__doc__}, + +static int +os_WEXITSTATUS_impl(PyObject *module, int status); + +static PyObject * +os_WEXITSTATUS(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(status), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"status", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "WEXITSTATUS", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int status; + int _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + status = _PyLong_AsInt(args[0]); + if (status == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_WEXITSTATUS_impl(module, status); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SYS_WAIT_H) && defined(WEXITSTATUS) */ + +#if defined(HAVE_SYS_WAIT_H) && defined(WTERMSIG) + +PyDoc_STRVAR(os_WTERMSIG__doc__, +"WTERMSIG($module, /, status)\n" +"--\n" +"\n" +"Return the signal that terminated the process that provided the status value."); + +#define OS_WTERMSIG_METHODDEF \ + {"WTERMSIG", _PyCFunction_CAST(os_WTERMSIG), METH_FASTCALL|METH_KEYWORDS, os_WTERMSIG__doc__}, + +static int +os_WTERMSIG_impl(PyObject *module, int status); + +static PyObject * +os_WTERMSIG(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(status), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"status", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "WTERMSIG", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int status; + int _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + status = _PyLong_AsInt(args[0]); + if (status == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_WTERMSIG_impl(module, status); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SYS_WAIT_H) && defined(WTERMSIG) */ + +#if defined(HAVE_SYS_WAIT_H) && defined(WSTOPSIG) + +PyDoc_STRVAR(os_WSTOPSIG__doc__, +"WSTOPSIG($module, /, status)\n" +"--\n" +"\n" +"Return the signal that stopped the process that provided the status value."); + +#define OS_WSTOPSIG_METHODDEF \ + {"WSTOPSIG", _PyCFunction_CAST(os_WSTOPSIG), METH_FASTCALL|METH_KEYWORDS, os_WSTOPSIG__doc__}, + +static int +os_WSTOPSIG_impl(PyObject *module, int status); + +static PyObject * +os_WSTOPSIG(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(status), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"status", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "WSTOPSIG", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int status; + int _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + status = _PyLong_AsInt(args[0]); + if (status == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_WSTOPSIG_impl(module, status); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SYS_WAIT_H) && defined(WSTOPSIG) */ + +#if (defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)) + +PyDoc_STRVAR(os_fstatvfs__doc__, +"fstatvfs($module, fd, /)\n" +"--\n" +"\n" +"Perform an fstatvfs system call on the given fd.\n" +"\n" +"Equivalent to statvfs(fd)."); + +#define OS_FSTATVFS_METHODDEF \ + {"fstatvfs", (PyCFunction)os_fstatvfs, METH_O, os_fstatvfs__doc__}, + +static PyObject * +os_fstatvfs_impl(PyObject *module, int fd); + +static PyObject * +os_fstatvfs(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int fd; + + fd = _PyLong_AsInt(arg); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_fstatvfs_impl(module, fd); + +exit: + return return_value; +} + +#endif /* (defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)) */ + +#if (defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)) + +PyDoc_STRVAR(os_statvfs__doc__, +"statvfs($module, /, path)\n" +"--\n" +"\n" +"Perform a statvfs system call on the given path.\n" +"\n" +"path may always be specified as a string.\n" +"On some platforms, path may also be specified as an open file descriptor.\n" +" If this functionality is unavailable, using it raises an exception."); + +#define OS_STATVFS_METHODDEF \ + {"statvfs", _PyCFunction_CAST(os_statvfs), METH_FASTCALL|METH_KEYWORDS, os_statvfs__doc__}, + +static PyObject * +os_statvfs_impl(PyObject *module, path_t *path); + +static PyObject * +os_statvfs(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "statvfs", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + path_t path = PATH_T_INITIALIZE("statvfs", "path", 0, PATH_HAVE_FSTATVFS); + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + return_value = os_statvfs_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* (defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)) */ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(os__getdiskusage__doc__, +"_getdiskusage($module, /, path)\n" +"--\n" +"\n" +"Return disk usage statistics about the given path as a (total, free) tuple."); + +#define OS__GETDISKUSAGE_METHODDEF \ + {"_getdiskusage", _PyCFunction_CAST(os__getdiskusage), METH_FASTCALL|METH_KEYWORDS, os__getdiskusage__doc__}, + +static PyObject * +os__getdiskusage_impl(PyObject *module, path_t *path); + +static PyObject * +os__getdiskusage(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "_getdiskusage", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + path_t path = PATH_T_INITIALIZE("_getdiskusage", "path", 0, 0); + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + return_value = os__getdiskusage_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if defined(HAVE_FPATHCONF) + +PyDoc_STRVAR(os_fpathconf__doc__, +"fpathconf($module, fd, name, /)\n" +"--\n" +"\n" +"Return the configuration limit name for the file descriptor fd.\n" +"\n" +"If there is no limit, return -1."); + +#define OS_FPATHCONF_METHODDEF \ + {"fpathconf", _PyCFunction_CAST(os_fpathconf), METH_FASTCALL, os_fpathconf__doc__}, + +static long +os_fpathconf_impl(PyObject *module, int fd, int name); + +static PyObject * +os_fpathconf(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + int name; + long _return_value; + + if (!_PyArg_CheckPositional("fpathconf", nargs, 2, 2)) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + if (!conv_path_confname(args[1], &name)) { + goto exit; + } + _return_value = os_fpathconf_impl(module, fd, name); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong(_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_FPATHCONF) */ + +#if defined(HAVE_PATHCONF) + +PyDoc_STRVAR(os_pathconf__doc__, +"pathconf($module, /, path, name)\n" +"--\n" +"\n" +"Return the configuration limit name for the file or directory path.\n" +"\n" +"If there is no limit, return -1.\n" +"On some platforms, path may also be specified as an open file descriptor.\n" +" If this functionality is unavailable, using it raises an exception."); + +#define OS_PATHCONF_METHODDEF \ + {"pathconf", _PyCFunction_CAST(os_pathconf), METH_FASTCALL|METH_KEYWORDS, os_pathconf__doc__}, + +static long +os_pathconf_impl(PyObject *module, path_t *path, int name); + +static PyObject * +os_pathconf(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(name), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "name", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "pathconf", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + path_t path = PATH_T_INITIALIZE("pathconf", "path", 0, PATH_HAVE_FPATHCONF); + int name; + long _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!conv_path_confname(args[1], &name)) { + goto exit; + } + _return_value = os_pathconf_impl(module, &path, name); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong(_return_value); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(HAVE_PATHCONF) */ + +#if defined(HAVE_CONFSTR) + +PyDoc_STRVAR(os_confstr__doc__, +"confstr($module, name, /)\n" +"--\n" +"\n" +"Return a string-valued system configuration variable."); + +#define OS_CONFSTR_METHODDEF \ + {"confstr", (PyCFunction)os_confstr, METH_O, os_confstr__doc__}, + +static PyObject * +os_confstr_impl(PyObject *module, int name); + +static PyObject * +os_confstr(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int name; + + if (!conv_confstr_confname(arg, &name)) { + goto exit; + } + return_value = os_confstr_impl(module, name); + +exit: + return return_value; +} + +#endif /* defined(HAVE_CONFSTR) */ + +#if defined(HAVE_SYSCONF) + +PyDoc_STRVAR(os_sysconf__doc__, +"sysconf($module, name, /)\n" +"--\n" +"\n" +"Return an integer-valued system configuration variable."); + +#define OS_SYSCONF_METHODDEF \ + {"sysconf", (PyCFunction)os_sysconf, METH_O, os_sysconf__doc__}, + +static long +os_sysconf_impl(PyObject *module, int name); + +static PyObject * +os_sysconf(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int name; + long _return_value; + + if (!conv_sysconf_confname(arg, &name)) { + goto exit; + } + _return_value = os_sysconf_impl(module, name); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong(_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SYSCONF) */ + +PyDoc_STRVAR(os_abort__doc__, +"abort($module, /)\n" +"--\n" +"\n" +"Abort the interpreter immediately.\n" +"\n" +"This function \'dumps core\' or otherwise fails in the hardest way possible\n" +"on the hosting operating system. This function never returns."); + +#define OS_ABORT_METHODDEF \ + {"abort", (PyCFunction)os_abort, METH_NOARGS, os_abort__doc__}, + +static PyObject * +os_abort_impl(PyObject *module); + +static PyObject * +os_abort(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_abort_impl(module); +} + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(os_startfile__doc__, +"startfile($module, /, filepath, operation=,\n" +" arguments=, cwd=None, show_cmd=1)\n" +"--\n" +"\n" +"Start a file with its associated application.\n" +"\n" +"When \"operation\" is not specified or \"open\", this acts like\n" +"double-clicking the file in Explorer, or giving the file name as an\n" +"argument to the DOS \"start\" command: the file is opened with whatever\n" +"application (if any) its extension is associated.\n" +"When another \"operation\" is given, it specifies what should be done with\n" +"the file. A typical operation is \"print\".\n" +"\n" +"\"arguments\" is passed to the application, but should be omitted if the\n" +"file is a document.\n" +"\n" +"\"cwd\" is the working directory for the operation. If \"filepath\" is\n" +"relative, it will be resolved against this directory. This argument\n" +"should usually be an absolute path.\n" +"\n" +"\"show_cmd\" can be used to override the recommended visibility option.\n" +"See the Windows ShellExecute documentation for values.\n" +"\n" +"startfile returns as soon as the associated application is launched.\n" +"There is no option to wait for the application to close, and no way\n" +"to retrieve the application\'s exit status.\n" +"\n" +"The filepath is relative to the current directory. If you want to use\n" +"an absolute path, make sure the first character is not a slash (\"/\");\n" +"the underlying Win32 ShellExecute function doesn\'t work if it is."); + +#define OS_STARTFILE_METHODDEF \ + {"startfile", _PyCFunction_CAST(os_startfile), METH_FASTCALL|METH_KEYWORDS, os_startfile__doc__}, + +static PyObject * +os_startfile_impl(PyObject *module, path_t *filepath, + const Py_UNICODE *operation, const Py_UNICODE *arguments, + path_t *cwd, int show_cmd); + +static PyObject * +os_startfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 5 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(filepath), &_Py_ID(operation), &_Py_ID(arguments), &_Py_ID(cwd), &_Py_ID(show_cmd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"filepath", "operation", "arguments", "cwd", "show_cmd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "startfile", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + path_t filepath = PATH_T_INITIALIZE("startfile", "filepath", 0, 0); + const Py_UNICODE *operation = NULL; + const Py_UNICODE *arguments = NULL; + path_t cwd = PATH_T_INITIALIZE("startfile", "cwd", 1, 0); + int show_cmd = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 5, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &filepath)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[1]) { + if (!PyUnicode_Check(args[1])) { + _PyArg_BadArgument("startfile", "argument 'operation'", "str", args[1]); + goto exit; + } + operation = PyUnicode_AsWideCharString(args[1], NULL); + if (operation == NULL) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[2]) { + if (!PyUnicode_Check(args[2])) { + _PyArg_BadArgument("startfile", "argument 'arguments'", "str", args[2]); + goto exit; + } + arguments = PyUnicode_AsWideCharString(args[2], NULL); + if (arguments == NULL) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[3]) { + if (!path_converter(args[3], &cwd)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + show_cmd = _PyLong_AsInt(args[4]); + if (show_cmd == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_pos: + return_value = os_startfile_impl(module, &filepath, operation, arguments, &cwd, show_cmd); + +exit: + /* Cleanup for filepath */ + path_cleanup(&filepath); + /* Cleanup for operation */ + PyMem_Free((void *)operation); + /* Cleanup for arguments */ + PyMem_Free((void *)arguments); + /* Cleanup for cwd */ + path_cleanup(&cwd); + + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if defined(HAVE_GETLOADAVG) + +PyDoc_STRVAR(os_getloadavg__doc__, +"getloadavg($module, /)\n" +"--\n" +"\n" +"Return average recent system load information.\n" +"\n" +"Return the number of processes in the system run queue averaged over\n" +"the last 1, 5, and 15 minutes as a tuple of three floats.\n" +"Raises OSError if the load average was unobtainable."); + +#define OS_GETLOADAVG_METHODDEF \ + {"getloadavg", (PyCFunction)os_getloadavg, METH_NOARGS, os_getloadavg__doc__}, + +static PyObject * +os_getloadavg_impl(PyObject *module); + +static PyObject * +os_getloadavg(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getloadavg_impl(module); +} + +#endif /* defined(HAVE_GETLOADAVG) */ + +PyDoc_STRVAR(os_device_encoding__doc__, +"device_encoding($module, /, fd)\n" +"--\n" +"\n" +"Return a string describing the encoding of a terminal\'s file descriptor.\n" +"\n" +"The file descriptor must be attached to a terminal.\n" +"If the device is not a terminal, return None."); + +#define OS_DEVICE_ENCODING_METHODDEF \ + {"device_encoding", _PyCFunction_CAST(os_device_encoding), METH_FASTCALL|METH_KEYWORDS, os_device_encoding__doc__}, + +static PyObject * +os_device_encoding_impl(PyObject *module, int fd); + +static PyObject * +os_device_encoding(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "device_encoding", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int fd; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_device_encoding_impl(module, fd); + +exit: + return return_value; +} + +#if defined(HAVE_SETRESUID) + +PyDoc_STRVAR(os_setresuid__doc__, +"setresuid($module, ruid, euid, suid, /)\n" +"--\n" +"\n" +"Set the current process\'s real, effective, and saved user ids."); + +#define OS_SETRESUID_METHODDEF \ + {"setresuid", _PyCFunction_CAST(os_setresuid), METH_FASTCALL, os_setresuid__doc__}, + +static PyObject * +os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid); + +static PyObject * +os_setresuid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + uid_t ruid; + uid_t euid; + uid_t suid; + + if (!_PyArg_CheckPositional("setresuid", nargs, 3, 3)) { + goto exit; + } + if (!_Py_Uid_Converter(args[0], &ruid)) { + goto exit; + } + if (!_Py_Uid_Converter(args[1], &euid)) { + goto exit; + } + if (!_Py_Uid_Converter(args[2], &suid)) { + goto exit; + } + return_value = os_setresuid_impl(module, ruid, euid, suid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SETRESUID) */ + +#if defined(HAVE_SETRESGID) + +PyDoc_STRVAR(os_setresgid__doc__, +"setresgid($module, rgid, egid, sgid, /)\n" +"--\n" +"\n" +"Set the current process\'s real, effective, and saved group ids."); + +#define OS_SETRESGID_METHODDEF \ + {"setresgid", _PyCFunction_CAST(os_setresgid), METH_FASTCALL, os_setresgid__doc__}, + +static PyObject * +os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid); + +static PyObject * +os_setresgid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + gid_t rgid; + gid_t egid; + gid_t sgid; + + if (!_PyArg_CheckPositional("setresgid", nargs, 3, 3)) { + goto exit; + } + if (!_Py_Gid_Converter(args[0], &rgid)) { + goto exit; + } + if (!_Py_Gid_Converter(args[1], &egid)) { + goto exit; + } + if (!_Py_Gid_Converter(args[2], &sgid)) { + goto exit; + } + return_value = os_setresgid_impl(module, rgid, egid, sgid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SETRESGID) */ + +#if defined(HAVE_GETRESUID) + +PyDoc_STRVAR(os_getresuid__doc__, +"getresuid($module, /)\n" +"--\n" +"\n" +"Return a tuple of the current process\'s real, effective, and saved user ids."); + +#define OS_GETRESUID_METHODDEF \ + {"getresuid", (PyCFunction)os_getresuid, METH_NOARGS, os_getresuid__doc__}, + +static PyObject * +os_getresuid_impl(PyObject *module); + +static PyObject * +os_getresuid(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getresuid_impl(module); +} + +#endif /* defined(HAVE_GETRESUID) */ + +#if defined(HAVE_GETRESGID) + +PyDoc_STRVAR(os_getresgid__doc__, +"getresgid($module, /)\n" +"--\n" +"\n" +"Return a tuple of the current process\'s real, effective, and saved group ids."); + +#define OS_GETRESGID_METHODDEF \ + {"getresgid", (PyCFunction)os_getresgid, METH_NOARGS, os_getresgid__doc__}, + +static PyObject * +os_getresgid_impl(PyObject *module); + +static PyObject * +os_getresgid(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getresgid_impl(module); +} + +#endif /* defined(HAVE_GETRESGID) */ + +#if defined(USE_XATTRS) + +PyDoc_STRVAR(os_getxattr__doc__, +"getxattr($module, /, path, attribute, *, follow_symlinks=True)\n" +"--\n" +"\n" +"Return the value of extended attribute attribute on path.\n" +"\n" +"path may be either a string, a path-like object, or an open file descriptor.\n" +"If follow_symlinks is False, and the last element of the path is a symbolic\n" +" link, getxattr will examine the symbolic link itself instead of the file\n" +" the link points to."); + +#define OS_GETXATTR_METHODDEF \ + {"getxattr", _PyCFunction_CAST(os_getxattr), METH_FASTCALL|METH_KEYWORDS, os_getxattr__doc__}, + +static PyObject * +os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute, + int follow_symlinks); + +static PyObject * +os_getxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(attribute), &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "attribute", "follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "getxattr", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + path_t path = PATH_T_INITIALIZE("getxattr", "path", 0, 1); + path_t attribute = PATH_T_INITIALIZE("getxattr", "attribute", 0, 0); + int follow_symlinks = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!path_converter(args[1], &attribute)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + follow_symlinks = PyObject_IsTrue(args[2]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = os_getxattr_impl(module, &path, &attribute, follow_symlinks); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + /* Cleanup for attribute */ + path_cleanup(&attribute); + + return return_value; +} + +#endif /* defined(USE_XATTRS) */ + +#if defined(USE_XATTRS) + +PyDoc_STRVAR(os_setxattr__doc__, +"setxattr($module, /, path, attribute, value, flags=0, *,\n" +" follow_symlinks=True)\n" +"--\n" +"\n" +"Set extended attribute attribute on path to value.\n" +"\n" +"path may be either a string, a path-like object, or an open file descriptor.\n" +"If follow_symlinks is False, and the last element of the path is a symbolic\n" +" link, setxattr will modify the symbolic link itself instead of the file\n" +" the link points to."); + +#define OS_SETXATTR_METHODDEF \ + {"setxattr", _PyCFunction_CAST(os_setxattr), METH_FASTCALL|METH_KEYWORDS, os_setxattr__doc__}, + +static PyObject * +os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute, + Py_buffer *value, int flags, int follow_symlinks); + +static PyObject * +os_setxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 5 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(attribute), &_Py_ID(value), &_Py_ID(flags), &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "attribute", "value", "flags", "follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "setxattr", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; + path_t path = PATH_T_INITIALIZE("setxattr", "path", 0, 1); + path_t attribute = PATH_T_INITIALIZE("setxattr", "attribute", 0, 0); + Py_buffer value = {NULL, NULL}; + int flags = 0; + int follow_symlinks = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 4, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!path_converter(args[1], &attribute)) { + goto exit; + } + if (PyObject_GetBuffer(args[2], &value, PyBUF_SIMPLE) != 0) { + goto exit; + } + if (!PyBuffer_IsContiguous(&value, 'C')) { + _PyArg_BadArgument("setxattr", "argument 'value'", "contiguous buffer", args[2]); + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[3]) { + flags = _PyLong_AsInt(args[3]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + follow_symlinks = PyObject_IsTrue(args[4]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = os_setxattr_impl(module, &path, &attribute, &value, flags, follow_symlinks); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + /* Cleanup for attribute */ + path_cleanup(&attribute); + /* Cleanup for value */ + if (value.obj) { + PyBuffer_Release(&value); + } + + return return_value; +} + +#endif /* defined(USE_XATTRS) */ + +#if defined(USE_XATTRS) + +PyDoc_STRVAR(os_removexattr__doc__, +"removexattr($module, /, path, attribute, *, follow_symlinks=True)\n" +"--\n" +"\n" +"Remove extended attribute attribute on path.\n" +"\n" +"path may be either a string, a path-like object, or an open file descriptor.\n" +"If follow_symlinks is False, and the last element of the path is a symbolic\n" +" link, removexattr will modify the symbolic link itself instead of the file\n" +" the link points to."); + +#define OS_REMOVEXATTR_METHODDEF \ + {"removexattr", _PyCFunction_CAST(os_removexattr), METH_FASTCALL|METH_KEYWORDS, os_removexattr__doc__}, + +static PyObject * +os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute, + int follow_symlinks); + +static PyObject * +os_removexattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(attribute), &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "attribute", "follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "removexattr", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + path_t path = PATH_T_INITIALIZE("removexattr", "path", 0, 1); + path_t attribute = PATH_T_INITIALIZE("removexattr", "attribute", 0, 0); + int follow_symlinks = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!path_converter(args[1], &attribute)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + follow_symlinks = PyObject_IsTrue(args[2]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = os_removexattr_impl(module, &path, &attribute, follow_symlinks); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + /* Cleanup for attribute */ + path_cleanup(&attribute); + + return return_value; +} + +#endif /* defined(USE_XATTRS) */ + +#if defined(USE_XATTRS) + +PyDoc_STRVAR(os_listxattr__doc__, +"listxattr($module, /, path=None, *, follow_symlinks=True)\n" +"--\n" +"\n" +"Return a list of extended attributes on path.\n" +"\n" +"path may be either None, a string, a path-like object, or an open file descriptor.\n" +"if path is None, listxattr will examine the current directory.\n" +"If follow_symlinks is False, and the last element of the path is a symbolic\n" +" link, listxattr will examine the symbolic link itself instead of the file\n" +" the link points to."); + +#define OS_LISTXATTR_METHODDEF \ + {"listxattr", _PyCFunction_CAST(os_listxattr), METH_FASTCALL|METH_KEYWORDS, os_listxattr__doc__}, + +static PyObject * +os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks); + +static PyObject * +os_listxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "listxattr", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + path_t path = PATH_T_INITIALIZE("listxattr", "path", 1, 1); + int follow_symlinks = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[0]) { + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + follow_symlinks = PyObject_IsTrue(args[1]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = os_listxattr_impl(module, &path, follow_symlinks); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(USE_XATTRS) */ + +PyDoc_STRVAR(os_urandom__doc__, +"urandom($module, size, /)\n" +"--\n" +"\n" +"Return a bytes object containing random bytes suitable for cryptographic use."); + +#define OS_URANDOM_METHODDEF \ + {"urandom", (PyCFunction)os_urandom, METH_O, os_urandom__doc__}, + +static PyObject * +os_urandom_impl(PyObject *module, Py_ssize_t size); + +static PyObject * +os_urandom(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + Py_ssize_t size; + + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(arg); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + size = ival; + } + return_value = os_urandom_impl(module, size); + +exit: + return return_value; +} + +#if defined(HAVE_MEMFD_CREATE) + +PyDoc_STRVAR(os_memfd_create__doc__, +"memfd_create($module, /, name, flags=MFD_CLOEXEC)\n" +"--\n" +"\n"); + +#define OS_MEMFD_CREATE_METHODDEF \ + {"memfd_create", _PyCFunction_CAST(os_memfd_create), METH_FASTCALL|METH_KEYWORDS, os_memfd_create__doc__}, + +static PyObject * +os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags); + +static PyObject * +os_memfd_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(name), &_Py_ID(flags), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"name", "flags", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "memfd_create", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *name = NULL; + unsigned int flags = MFD_CLOEXEC; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!PyUnicode_FSConverter(args[0], &name)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + flags = (unsigned int)PyLong_AsUnsignedLongMask(args[1]); + if (flags == (unsigned int)-1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_pos: + return_value = os_memfd_create_impl(module, name, flags); + +exit: + /* Cleanup for name */ + Py_XDECREF(name); + + return return_value; +} + +#endif /* defined(HAVE_MEMFD_CREATE) */ + +#if (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) + +PyDoc_STRVAR(os_eventfd__doc__, +"eventfd($module, /, initval, flags=EFD_CLOEXEC)\n" +"--\n" +"\n" +"Creates and returns an event notification file descriptor."); + +#define OS_EVENTFD_METHODDEF \ + {"eventfd", _PyCFunction_CAST(os_eventfd), METH_FASTCALL|METH_KEYWORDS, os_eventfd__doc__}, + +static PyObject * +os_eventfd_impl(PyObject *module, unsigned int initval, int flags); + +static PyObject * +os_eventfd(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(initval), &_Py_ID(flags), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"initval", "flags", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "eventfd", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + unsigned int initval; + int flags = EFD_CLOEXEC; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!_PyLong_UnsignedInt_Converter(args[0], &initval)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + flags = _PyLong_AsInt(args[1]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_pos: + return_value = os_eventfd_impl(module, initval, flags); + +exit: + return return_value; +} + +#endif /* (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) */ + +#if (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) + +PyDoc_STRVAR(os_eventfd_read__doc__, +"eventfd_read($module, /, fd)\n" +"--\n" +"\n" +"Read eventfd value"); + +#define OS_EVENTFD_READ_METHODDEF \ + {"eventfd_read", _PyCFunction_CAST(os_eventfd_read), METH_FASTCALL|METH_KEYWORDS, os_eventfd_read__doc__}, + +static PyObject * +os_eventfd_read_impl(PyObject *module, int fd); + +static PyObject * +os_eventfd_read(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "eventfd_read", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int fd; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + return_value = os_eventfd_read_impl(module, fd); + +exit: + return return_value; +} + +#endif /* (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) */ + +#if (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) + +PyDoc_STRVAR(os_eventfd_write__doc__, +"eventfd_write($module, /, fd, value)\n" +"--\n" +"\n" +"Write eventfd value."); + +#define OS_EVENTFD_WRITE_METHODDEF \ + {"eventfd_write", _PyCFunction_CAST(os_eventfd_write), METH_FASTCALL|METH_KEYWORDS, os_eventfd_write__doc__}, + +static PyObject * +os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value); + +static PyObject * +os_eventfd_write(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(fd), &_Py_ID(value), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"fd", "value", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "eventfd_write", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + int fd; + unsigned long long value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + if (!_PyLong_UnsignedLongLong_Converter(args[1], &value)) { + goto exit; + } + return_value = os_eventfd_write_impl(module, fd, value); + +exit: + return return_value; +} + +#endif /* (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) */ + +#if (defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)) + +PyDoc_STRVAR(os_get_terminal_size__doc__, +"get_terminal_size($module, fd=, /)\n" +"--\n" +"\n" +"Return the size of the terminal window as (columns, lines).\n" +"\n" +"The optional argument fd (default standard output) specifies\n" +"which file descriptor should be queried.\n" +"\n" +"If the file descriptor is not connected to a terminal, an OSError\n" +"is thrown.\n" +"\n" +"This function will only be defined if an implementation is\n" +"available for this system.\n" +"\n" +"shutil.get_terminal_size is the high-level function which should\n" +"normally be used, os.get_terminal_size is the low-level implementation."); + +#define OS_GET_TERMINAL_SIZE_METHODDEF \ + {"get_terminal_size", _PyCFunction_CAST(os_get_terminal_size), METH_FASTCALL, os_get_terminal_size__doc__}, + +static PyObject * +os_get_terminal_size_impl(PyObject *module, int fd); + +static PyObject * +os_get_terminal_size(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd = fileno(stdout); + + if (!_PyArg_CheckPositional("get_terminal_size", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = os_get_terminal_size_impl(module, fd); + +exit: + return return_value; +} + +#endif /* (defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)) */ + +PyDoc_STRVAR(os_cpu_count__doc__, +"cpu_count($module, /)\n" +"--\n" +"\n" +"Return the number of CPUs in the system; return None if indeterminable.\n" +"\n" +"This number is not equivalent to the number of CPUs the current process can\n" +"use. The number of usable CPUs can be obtained with\n" +"``len(os.sched_getaffinity(0))``"); + +#define OS_CPU_COUNT_METHODDEF \ + {"cpu_count", (PyCFunction)os_cpu_count, METH_NOARGS, os_cpu_count__doc__}, + +static PyObject * +os_cpu_count_impl(PyObject *module); + +static PyObject * +os_cpu_count(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_cpu_count_impl(module); +} + +PyDoc_STRVAR(os_get_inheritable__doc__, +"get_inheritable($module, fd, /)\n" +"--\n" +"\n" +"Get the close-on-exe flag of the specified file descriptor."); + +#define OS_GET_INHERITABLE_METHODDEF \ + {"get_inheritable", (PyCFunction)os_get_inheritable, METH_O, os_get_inheritable__doc__}, + +static int +os_get_inheritable_impl(PyObject *module, int fd); + +static PyObject * +os_get_inheritable(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int fd; + int _return_value; + + fd = _PyLong_AsInt(arg); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_get_inheritable_impl(module, fd); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(os_set_inheritable__doc__, +"set_inheritable($module, fd, inheritable, /)\n" +"--\n" +"\n" +"Set the inheritable flag of the specified file descriptor."); + +#define OS_SET_INHERITABLE_METHODDEF \ + {"set_inheritable", _PyCFunction_CAST(os_set_inheritable), METH_FASTCALL, os_set_inheritable__doc__}, + +static PyObject * +os_set_inheritable_impl(PyObject *module, int fd, int inheritable); + +static PyObject * +os_set_inheritable(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + int inheritable; + + if (!_PyArg_CheckPositional("set_inheritable", nargs, 2, 2)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + inheritable = _PyLong_AsInt(args[1]); + if (inheritable == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_set_inheritable_impl(module, fd, inheritable); + +exit: + return return_value; +} + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(os_get_handle_inheritable__doc__, +"get_handle_inheritable($module, handle, /)\n" +"--\n" +"\n" +"Get the close-on-exe flag of the specified file descriptor."); + +#define OS_GET_HANDLE_INHERITABLE_METHODDEF \ + {"get_handle_inheritable", (PyCFunction)os_get_handle_inheritable, METH_O, os_get_handle_inheritable__doc__}, + +static int +os_get_handle_inheritable_impl(PyObject *module, intptr_t handle); + +static PyObject * +os_get_handle_inheritable(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + intptr_t handle; + int _return_value; + + if (!PyArg_Parse(arg, "" _Py_PARSE_INTPTR ":get_handle_inheritable", &handle)) { + goto exit; + } + _return_value = os_get_handle_inheritable_impl(module, handle); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(os_set_handle_inheritable__doc__, +"set_handle_inheritable($module, handle, inheritable, /)\n" +"--\n" +"\n" +"Set the inheritable flag of the specified handle."); + +#define OS_SET_HANDLE_INHERITABLE_METHODDEF \ + {"set_handle_inheritable", _PyCFunction_CAST(os_set_handle_inheritable), METH_FASTCALL, os_set_handle_inheritable__doc__}, + +static PyObject * +os_set_handle_inheritable_impl(PyObject *module, intptr_t handle, + int inheritable); + +static PyObject * +os_set_handle_inheritable(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + intptr_t handle; + int inheritable; + + if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_INTPTR "p:set_handle_inheritable", + &handle, &inheritable)) { + goto exit; + } + return_value = os_set_handle_inheritable_impl(module, handle, inheritable); + +exit: + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if !defined(MS_WINDOWS) + +PyDoc_STRVAR(os_get_blocking__doc__, +"get_blocking($module, fd, /)\n" +"--\n" +"\n" +"Get the blocking mode of the file descriptor.\n" +"\n" +"Return False if the O_NONBLOCK flag is set, True if the flag is cleared."); + +#define OS_GET_BLOCKING_METHODDEF \ + {"get_blocking", (PyCFunction)os_get_blocking, METH_O, os_get_blocking__doc__}, + +static int +os_get_blocking_impl(PyObject *module, int fd); + +static PyObject * +os_get_blocking(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int fd; + int _return_value; + + fd = _PyLong_AsInt(arg); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_get_blocking_impl(module, fd); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +#endif /* !defined(MS_WINDOWS) */ + +#if !defined(MS_WINDOWS) + +PyDoc_STRVAR(os_set_blocking__doc__, +"set_blocking($module, fd, blocking, /)\n" +"--\n" +"\n" +"Set the blocking mode of the specified file descriptor.\n" +"\n" +"Set the O_NONBLOCK flag if blocking is False,\n" +"clear the O_NONBLOCK flag otherwise."); + +#define OS_SET_BLOCKING_METHODDEF \ + {"set_blocking", _PyCFunction_CAST(os_set_blocking), METH_FASTCALL, os_set_blocking__doc__}, + +static PyObject * +os_set_blocking_impl(PyObject *module, int fd, int blocking); + +static PyObject * +os_set_blocking(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + int blocking; + + if (!_PyArg_CheckPositional("set_blocking", nargs, 2, 2)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + blocking = _PyLong_AsInt(args[1]); + if (blocking == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_set_blocking_impl(module, fd, blocking); + +exit: + return return_value; +} + +#endif /* !defined(MS_WINDOWS) */ + +PyDoc_STRVAR(os_DirEntry_is_symlink__doc__, +"is_symlink($self, /)\n" +"--\n" +"\n" +"Return True if the entry is a symbolic link; cached per entry."); + +#define OS_DIRENTRY_IS_SYMLINK_METHODDEF \ + {"is_symlink", _PyCFunction_CAST(os_DirEntry_is_symlink), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, os_DirEntry_is_symlink__doc__}, + +static int +os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class); + +static PyObject * +os_DirEntry_is_symlink(DirEntry *self, PyTypeObject *defining_class, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + int _return_value; + + if (nargs) { + PyErr_SetString(PyExc_TypeError, "is_symlink() takes no arguments"); + goto exit; + } + _return_value = os_DirEntry_is_symlink_impl(self, defining_class); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(os_DirEntry_is_junction__doc__, +"is_junction($self, /)\n" +"--\n" +"\n" +"Return True if the entry is a junction; cached per entry."); + +#define OS_DIRENTRY_IS_JUNCTION_METHODDEF \ + {"is_junction", _PyCFunction_CAST(os_DirEntry_is_junction), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, os_DirEntry_is_junction__doc__}, + +static int +os_DirEntry_is_junction_impl(DirEntry *self, PyTypeObject *defining_class); + +static PyObject * +os_DirEntry_is_junction(DirEntry *self, PyTypeObject *defining_class, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + int _return_value; + + if (nargs) { + PyErr_SetString(PyExc_TypeError, "is_junction() takes no arguments"); + goto exit; + } + _return_value = os_DirEntry_is_junction_impl(self, defining_class); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(os_DirEntry_stat__doc__, +"stat($self, /, *, follow_symlinks=True)\n" +"--\n" +"\n" +"Return stat_result object for the entry; cached per entry."); + +#define OS_DIRENTRY_STAT_METHODDEF \ + {"stat", _PyCFunction_CAST(os_DirEntry_stat), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, os_DirEntry_stat__doc__}, + +static PyObject * +os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class, + int follow_symlinks); + +static PyObject * +os_DirEntry_stat(DirEntry *self, PyTypeObject *defining_class, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "stat", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + int follow_symlinks = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + follow_symlinks = PyObject_IsTrue(args[0]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = os_DirEntry_stat_impl(self, defining_class, follow_symlinks); + +exit: + return return_value; +} + +PyDoc_STRVAR(os_DirEntry_is_dir__doc__, +"is_dir($self, /, *, follow_symlinks=True)\n" +"--\n" +"\n" +"Return True if the entry is a directory; cached per entry."); + +#define OS_DIRENTRY_IS_DIR_METHODDEF \ + {"is_dir", _PyCFunction_CAST(os_DirEntry_is_dir), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, os_DirEntry_is_dir__doc__}, + +static int +os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class, + int follow_symlinks); + +static PyObject * +os_DirEntry_is_dir(DirEntry *self, PyTypeObject *defining_class, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "is_dir", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + int follow_symlinks = 1; + int _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + follow_symlinks = PyObject_IsTrue(args[0]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + _return_value = os_DirEntry_is_dir_impl(self, defining_class, follow_symlinks); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(os_DirEntry_is_file__doc__, +"is_file($self, /, *, follow_symlinks=True)\n" +"--\n" +"\n" +"Return True if the entry is a file; cached per entry."); + +#define OS_DIRENTRY_IS_FILE_METHODDEF \ + {"is_file", _PyCFunction_CAST(os_DirEntry_is_file), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, os_DirEntry_is_file__doc__}, + +static int +os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class, + int follow_symlinks); + +static PyObject * +os_DirEntry_is_file(DirEntry *self, PyTypeObject *defining_class, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "is_file", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + int follow_symlinks = 1; + int _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + follow_symlinks = PyObject_IsTrue(args[0]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + _return_value = os_DirEntry_is_file_impl(self, defining_class, follow_symlinks); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(os_DirEntry_inode__doc__, +"inode($self, /)\n" +"--\n" +"\n" +"Return inode of the entry; cached per entry."); + +#define OS_DIRENTRY_INODE_METHODDEF \ + {"inode", (PyCFunction)os_DirEntry_inode, METH_NOARGS, os_DirEntry_inode__doc__}, + +static PyObject * +os_DirEntry_inode_impl(DirEntry *self); + +static PyObject * +os_DirEntry_inode(DirEntry *self, PyObject *Py_UNUSED(ignored)) +{ + return os_DirEntry_inode_impl(self); +} + +PyDoc_STRVAR(os_DirEntry___fspath____doc__, +"__fspath__($self, /)\n" +"--\n" +"\n" +"Returns the path for the entry."); + +#define OS_DIRENTRY___FSPATH___METHODDEF \ + {"__fspath__", (PyCFunction)os_DirEntry___fspath__, METH_NOARGS, os_DirEntry___fspath____doc__}, + +static PyObject * +os_DirEntry___fspath___impl(DirEntry *self); + +static PyObject * +os_DirEntry___fspath__(DirEntry *self, PyObject *Py_UNUSED(ignored)) +{ + return os_DirEntry___fspath___impl(self); +} + +PyDoc_STRVAR(os_scandir__doc__, +"scandir($module, /, path=None)\n" +"--\n" +"\n" +"Return an iterator of DirEntry objects for given path.\n" +"\n" +"path can be specified as either str, bytes, or a path-like object. If path\n" +"is bytes, the names of yielded DirEntry objects will also be bytes; in\n" +"all other circumstances they will be str.\n" +"\n" +"If path is None, uses the path=\'.\'."); + +#define OS_SCANDIR_METHODDEF \ + {"scandir", _PyCFunction_CAST(os_scandir), METH_FASTCALL|METH_KEYWORDS, os_scandir__doc__}, + +static PyObject * +os_scandir_impl(PyObject *module, path_t *path); + +static PyObject * +os_scandir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "scandir", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + path_t path = PATH_T_INITIALIZE("scandir", "path", 1, PATH_HAVE_FDOPENDIR); + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (!path_converter(args[0], &path)) { + goto exit; + } +skip_optional_pos: + return_value = os_scandir_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +PyDoc_STRVAR(os_fspath__doc__, +"fspath($module, /, path)\n" +"--\n" +"\n" +"Return the file system path representation of the object.\n" +"\n" +"If the object is str or bytes, then allow it to pass through as-is. If the\n" +"object defines __fspath__(), then return the result of that method. All other\n" +"types raise a TypeError."); + +#define OS_FSPATH_METHODDEF \ + {"fspath", _PyCFunction_CAST(os_fspath), METH_FASTCALL|METH_KEYWORDS, os_fspath__doc__}, + +static PyObject * +os_fspath_impl(PyObject *module, PyObject *path); + +static PyObject * +os_fspath(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "fspath", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *path; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + path = args[0]; + return_value = os_fspath_impl(module, path); + +exit: + return return_value; +} + +#if defined(HAVE_GETRANDOM_SYSCALL) + +PyDoc_STRVAR(os_getrandom__doc__, +"getrandom($module, /, size, flags=0)\n" +"--\n" +"\n" +"Obtain a series of random bytes."); + +#define OS_GETRANDOM_METHODDEF \ + {"getrandom", _PyCFunction_CAST(os_getrandom), METH_FASTCALL|METH_KEYWORDS, os_getrandom__doc__}, + +static PyObject * +os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags); + +static PyObject * +os_getrandom(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(size), &_Py_ID(flags), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"size", "flags", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "getrandom", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + Py_ssize_t size; + int flags = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[0]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + size = ival; + } + if (!noptargs) { + goto skip_optional_pos; + } + flags = _PyLong_AsInt(args[1]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_pos: + return_value = os_getrandom_impl(module, size, flags); + +exit: + return return_value; +} + +#endif /* defined(HAVE_GETRANDOM_SYSCALL) */ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(os__add_dll_directory__doc__, +"_add_dll_directory($module, /, path)\n" +"--\n" +"\n" +"Add a path to the DLL search path.\n" +"\n" +"This search path is used when resolving dependencies for imported\n" +"extension modules (the module itself is resolved through sys.path),\n" +"and also by ctypes.\n" +"\n" +"Returns an opaque value that may be passed to os.remove_dll_directory\n" +"to remove this directory from the search path."); + +#define OS__ADD_DLL_DIRECTORY_METHODDEF \ + {"_add_dll_directory", _PyCFunction_CAST(os__add_dll_directory), METH_FASTCALL|METH_KEYWORDS, os__add_dll_directory__doc__}, + +static PyObject * +os__add_dll_directory_impl(PyObject *module, path_t *path); + +static PyObject * +os__add_dll_directory(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "_add_dll_directory", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + path_t path = PATH_T_INITIALIZE("_add_dll_directory", "path", 0, 0); + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + return_value = os__add_dll_directory_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(os__remove_dll_directory__doc__, +"_remove_dll_directory($module, /, cookie)\n" +"--\n" +"\n" +"Removes a path from the DLL search path.\n" +"\n" +"The parameter is an opaque value that was returned from\n" +"os.add_dll_directory. You can only remove directories that you added\n" +"yourself."); + +#define OS__REMOVE_DLL_DIRECTORY_METHODDEF \ + {"_remove_dll_directory", _PyCFunction_CAST(os__remove_dll_directory), METH_FASTCALL|METH_KEYWORDS, os__remove_dll_directory__doc__}, + +static PyObject * +os__remove_dll_directory_impl(PyObject *module, PyObject *cookie); + +static PyObject * +os__remove_dll_directory(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(cookie), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"cookie", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "_remove_dll_directory", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *cookie; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + cookie = args[0]; + return_value = os__remove_dll_directory_impl(module, cookie); + +exit: + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if (defined(WIFEXITED) || defined(MS_WINDOWS)) + +PyDoc_STRVAR(os_waitstatus_to_exitcode__doc__, +"waitstatus_to_exitcode($module, /, status)\n" +"--\n" +"\n" +"Convert a wait status to an exit code.\n" +"\n" +"On Unix:\n" +"\n" +"* If WIFEXITED(status) is true, return WEXITSTATUS(status).\n" +"* If WIFSIGNALED(status) is true, return -WTERMSIG(status).\n" +"* Otherwise, raise a ValueError.\n" +"\n" +"On Windows, return status shifted right by 8 bits.\n" +"\n" +"On Unix, if the process is being traced or if waitpid() was called with\n" +"WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.\n" +"This function must not be called if WIFSTOPPED(status) is true."); + +#define OS_WAITSTATUS_TO_EXITCODE_METHODDEF \ + {"waitstatus_to_exitcode", _PyCFunction_CAST(os_waitstatus_to_exitcode), METH_FASTCALL|METH_KEYWORDS, os_waitstatus_to_exitcode__doc__}, + +static PyObject * +os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj); + +static PyObject * +os_waitstatus_to_exitcode(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(status), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"status", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "waitstatus_to_exitcode", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *status_obj; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + status_obj = args[0]; + return_value = os_waitstatus_to_exitcode_impl(module, status_obj); + +exit: + return return_value; +} + +#endif /* (defined(WIFEXITED) || defined(MS_WINDOWS)) */ + +#ifndef OS_TTYNAME_METHODDEF + #define OS_TTYNAME_METHODDEF +#endif /* !defined(OS_TTYNAME_METHODDEF) */ + +#ifndef OS_CTERMID_METHODDEF + #define OS_CTERMID_METHODDEF +#endif /* !defined(OS_CTERMID_METHODDEF) */ + +#ifndef OS_FCHDIR_METHODDEF + #define OS_FCHDIR_METHODDEF +#endif /* !defined(OS_FCHDIR_METHODDEF) */ + +#ifndef OS_FCHMOD_METHODDEF + #define OS_FCHMOD_METHODDEF +#endif /* !defined(OS_FCHMOD_METHODDEF) */ + +#ifndef OS_LCHMOD_METHODDEF + #define OS_LCHMOD_METHODDEF +#endif /* !defined(OS_LCHMOD_METHODDEF) */ + +#ifndef OS_CHFLAGS_METHODDEF + #define OS_CHFLAGS_METHODDEF +#endif /* !defined(OS_CHFLAGS_METHODDEF) */ + +#ifndef OS_LCHFLAGS_METHODDEF + #define OS_LCHFLAGS_METHODDEF +#endif /* !defined(OS_LCHFLAGS_METHODDEF) */ + +#ifndef OS_CHROOT_METHODDEF + #define OS_CHROOT_METHODDEF +#endif /* !defined(OS_CHROOT_METHODDEF) */ + +#ifndef OS_FSYNC_METHODDEF + #define OS_FSYNC_METHODDEF +#endif /* !defined(OS_FSYNC_METHODDEF) */ + +#ifndef OS_SYNC_METHODDEF + #define OS_SYNC_METHODDEF +#endif /* !defined(OS_SYNC_METHODDEF) */ + +#ifndef OS_FDATASYNC_METHODDEF + #define OS_FDATASYNC_METHODDEF +#endif /* !defined(OS_FDATASYNC_METHODDEF) */ + +#ifndef OS_CHOWN_METHODDEF + #define OS_CHOWN_METHODDEF +#endif /* !defined(OS_CHOWN_METHODDEF) */ + +#ifndef OS_FCHOWN_METHODDEF + #define OS_FCHOWN_METHODDEF +#endif /* !defined(OS_FCHOWN_METHODDEF) */ + +#ifndef OS_LCHOWN_METHODDEF + #define OS_LCHOWN_METHODDEF +#endif /* !defined(OS_LCHOWN_METHODDEF) */ + +#ifndef OS_LINK_METHODDEF + #define OS_LINK_METHODDEF +#endif /* !defined(OS_LINK_METHODDEF) */ + +#ifndef OS__GETFULLPATHNAME_METHODDEF + #define OS__GETFULLPATHNAME_METHODDEF +#endif /* !defined(OS__GETFULLPATHNAME_METHODDEF) */ + +#ifndef OS__GETFINALPATHNAME_METHODDEF + #define OS__GETFINALPATHNAME_METHODDEF +#endif /* !defined(OS__GETFINALPATHNAME_METHODDEF) */ + +#ifndef OS__GETVOLUMEPATHNAME_METHODDEF + #define OS__GETVOLUMEPATHNAME_METHODDEF +#endif /* !defined(OS__GETVOLUMEPATHNAME_METHODDEF) */ + +#ifndef OS__PATH_SPLITROOT_METHODDEF + #define OS__PATH_SPLITROOT_METHODDEF +#endif /* !defined(OS__PATH_SPLITROOT_METHODDEF) */ + +#ifndef OS_NICE_METHODDEF + #define OS_NICE_METHODDEF +#endif /* !defined(OS_NICE_METHODDEF) */ + +#ifndef OS_GETPRIORITY_METHODDEF + #define OS_GETPRIORITY_METHODDEF +#endif /* !defined(OS_GETPRIORITY_METHODDEF) */ + +#ifndef OS_SETPRIORITY_METHODDEF + #define OS_SETPRIORITY_METHODDEF +#endif /* !defined(OS_SETPRIORITY_METHODDEF) */ + +#ifndef OS_SYSTEM_METHODDEF + #define OS_SYSTEM_METHODDEF +#endif /* !defined(OS_SYSTEM_METHODDEF) */ + +#ifndef OS_UMASK_METHODDEF + #define OS_UMASK_METHODDEF +#endif /* !defined(OS_UMASK_METHODDEF) */ + +#ifndef OS_UNAME_METHODDEF + #define OS_UNAME_METHODDEF +#endif /* !defined(OS_UNAME_METHODDEF) */ + +#ifndef OS_EXECV_METHODDEF + #define OS_EXECV_METHODDEF +#endif /* !defined(OS_EXECV_METHODDEF) */ + +#ifndef OS_EXECVE_METHODDEF + #define OS_EXECVE_METHODDEF +#endif /* !defined(OS_EXECVE_METHODDEF) */ + +#ifndef OS_POSIX_SPAWN_METHODDEF + #define OS_POSIX_SPAWN_METHODDEF +#endif /* !defined(OS_POSIX_SPAWN_METHODDEF) */ + +#ifndef OS_POSIX_SPAWNP_METHODDEF + #define OS_POSIX_SPAWNP_METHODDEF +#endif /* !defined(OS_POSIX_SPAWNP_METHODDEF) */ + +#ifndef OS_SPAWNV_METHODDEF + #define OS_SPAWNV_METHODDEF +#endif /* !defined(OS_SPAWNV_METHODDEF) */ + +#ifndef OS_SPAWNVE_METHODDEF + #define OS_SPAWNVE_METHODDEF +#endif /* !defined(OS_SPAWNVE_METHODDEF) */ + +#ifndef OS_REGISTER_AT_FORK_METHODDEF + #define OS_REGISTER_AT_FORK_METHODDEF +#endif /* !defined(OS_REGISTER_AT_FORK_METHODDEF) */ + +#ifndef OS_FORK1_METHODDEF + #define OS_FORK1_METHODDEF +#endif /* !defined(OS_FORK1_METHODDEF) */ + +#ifndef OS_FORK_METHODDEF + #define OS_FORK_METHODDEF +#endif /* !defined(OS_FORK_METHODDEF) */ + +#ifndef OS_SCHED_GET_PRIORITY_MAX_METHODDEF + #define OS_SCHED_GET_PRIORITY_MAX_METHODDEF +#endif /* !defined(OS_SCHED_GET_PRIORITY_MAX_METHODDEF) */ + +#ifndef OS_SCHED_GET_PRIORITY_MIN_METHODDEF + #define OS_SCHED_GET_PRIORITY_MIN_METHODDEF +#endif /* !defined(OS_SCHED_GET_PRIORITY_MIN_METHODDEF) */ + +#ifndef OS_SCHED_GETSCHEDULER_METHODDEF + #define OS_SCHED_GETSCHEDULER_METHODDEF +#endif /* !defined(OS_SCHED_GETSCHEDULER_METHODDEF) */ + +#ifndef OS_SCHED_SETSCHEDULER_METHODDEF + #define OS_SCHED_SETSCHEDULER_METHODDEF +#endif /* !defined(OS_SCHED_SETSCHEDULER_METHODDEF) */ + +#ifndef OS_SCHED_GETPARAM_METHODDEF + #define OS_SCHED_GETPARAM_METHODDEF +#endif /* !defined(OS_SCHED_GETPARAM_METHODDEF) */ + +#ifndef OS_SCHED_SETPARAM_METHODDEF + #define OS_SCHED_SETPARAM_METHODDEF +#endif /* !defined(OS_SCHED_SETPARAM_METHODDEF) */ + +#ifndef OS_SCHED_RR_GET_INTERVAL_METHODDEF + #define OS_SCHED_RR_GET_INTERVAL_METHODDEF +#endif /* !defined(OS_SCHED_RR_GET_INTERVAL_METHODDEF) */ + +#ifndef OS_SCHED_YIELD_METHODDEF + #define OS_SCHED_YIELD_METHODDEF +#endif /* !defined(OS_SCHED_YIELD_METHODDEF) */ + +#ifndef OS_SCHED_SETAFFINITY_METHODDEF + #define OS_SCHED_SETAFFINITY_METHODDEF +#endif /* !defined(OS_SCHED_SETAFFINITY_METHODDEF) */ + +#ifndef OS_SCHED_GETAFFINITY_METHODDEF + #define OS_SCHED_GETAFFINITY_METHODDEF +#endif /* !defined(OS_SCHED_GETAFFINITY_METHODDEF) */ + +#ifndef OS_OPENPTY_METHODDEF + #define OS_OPENPTY_METHODDEF +#endif /* !defined(OS_OPENPTY_METHODDEF) */ + +#ifndef OS_LOGIN_TTY_METHODDEF + #define OS_LOGIN_TTY_METHODDEF +#endif /* !defined(OS_LOGIN_TTY_METHODDEF) */ + +#ifndef OS_FORKPTY_METHODDEF + #define OS_FORKPTY_METHODDEF +#endif /* !defined(OS_FORKPTY_METHODDEF) */ + +#ifndef OS_GETEGID_METHODDEF + #define OS_GETEGID_METHODDEF +#endif /* !defined(OS_GETEGID_METHODDEF) */ + +#ifndef OS_GETEUID_METHODDEF + #define OS_GETEUID_METHODDEF +#endif /* !defined(OS_GETEUID_METHODDEF) */ + +#ifndef OS_GETGID_METHODDEF + #define OS_GETGID_METHODDEF +#endif /* !defined(OS_GETGID_METHODDEF) */ + +#ifndef OS_GETPID_METHODDEF + #define OS_GETPID_METHODDEF +#endif /* !defined(OS_GETPID_METHODDEF) */ + +#ifndef OS_GETGROUPLIST_METHODDEF + #define OS_GETGROUPLIST_METHODDEF +#endif /* !defined(OS_GETGROUPLIST_METHODDEF) */ + +#ifndef OS_GETGROUPS_METHODDEF + #define OS_GETGROUPS_METHODDEF +#endif /* !defined(OS_GETGROUPS_METHODDEF) */ + +#ifndef OS_INITGROUPS_METHODDEF + #define OS_INITGROUPS_METHODDEF +#endif /* !defined(OS_INITGROUPS_METHODDEF) */ + +#ifndef OS_GETPGID_METHODDEF + #define OS_GETPGID_METHODDEF +#endif /* !defined(OS_GETPGID_METHODDEF) */ + +#ifndef OS_GETPGRP_METHODDEF + #define OS_GETPGRP_METHODDEF +#endif /* !defined(OS_GETPGRP_METHODDEF) */ + +#ifndef OS_SETPGRP_METHODDEF + #define OS_SETPGRP_METHODDEF +#endif /* !defined(OS_SETPGRP_METHODDEF) */ + +#ifndef OS_GETPPID_METHODDEF + #define OS_GETPPID_METHODDEF +#endif /* !defined(OS_GETPPID_METHODDEF) */ + +#ifndef OS_GETLOGIN_METHODDEF + #define OS_GETLOGIN_METHODDEF +#endif /* !defined(OS_GETLOGIN_METHODDEF) */ + +#ifndef OS_GETUID_METHODDEF + #define OS_GETUID_METHODDEF +#endif /* !defined(OS_GETUID_METHODDEF) */ + +#ifndef OS_KILL_METHODDEF + #define OS_KILL_METHODDEF +#endif /* !defined(OS_KILL_METHODDEF) */ + +#ifndef OS_KILLPG_METHODDEF + #define OS_KILLPG_METHODDEF +#endif /* !defined(OS_KILLPG_METHODDEF) */ + +#ifndef OS_PLOCK_METHODDEF + #define OS_PLOCK_METHODDEF +#endif /* !defined(OS_PLOCK_METHODDEF) */ + +#ifndef OS_SETUID_METHODDEF + #define OS_SETUID_METHODDEF +#endif /* !defined(OS_SETUID_METHODDEF) */ + +#ifndef OS_SETEUID_METHODDEF + #define OS_SETEUID_METHODDEF +#endif /* !defined(OS_SETEUID_METHODDEF) */ + +#ifndef OS_SETEGID_METHODDEF + #define OS_SETEGID_METHODDEF +#endif /* !defined(OS_SETEGID_METHODDEF) */ + +#ifndef OS_SETREUID_METHODDEF + #define OS_SETREUID_METHODDEF +#endif /* !defined(OS_SETREUID_METHODDEF) */ + +#ifndef OS_SETREGID_METHODDEF + #define OS_SETREGID_METHODDEF +#endif /* !defined(OS_SETREGID_METHODDEF) */ + +#ifndef OS_SETGID_METHODDEF + #define OS_SETGID_METHODDEF +#endif /* !defined(OS_SETGID_METHODDEF) */ + +#ifndef OS_SETGROUPS_METHODDEF + #define OS_SETGROUPS_METHODDEF +#endif /* !defined(OS_SETGROUPS_METHODDEF) */ + +#ifndef OS_WAIT3_METHODDEF + #define OS_WAIT3_METHODDEF +#endif /* !defined(OS_WAIT3_METHODDEF) */ + +#ifndef OS_WAIT4_METHODDEF + #define OS_WAIT4_METHODDEF +#endif /* !defined(OS_WAIT4_METHODDEF) */ + +#ifndef OS_WAITID_METHODDEF + #define OS_WAITID_METHODDEF +#endif /* !defined(OS_WAITID_METHODDEF) */ + +#ifndef OS_WAITPID_METHODDEF + #define OS_WAITPID_METHODDEF +#endif /* !defined(OS_WAITPID_METHODDEF) */ + +#ifndef OS_WAIT_METHODDEF + #define OS_WAIT_METHODDEF +#endif /* !defined(OS_WAIT_METHODDEF) */ + +#ifndef OS_PIDFD_OPEN_METHODDEF + #define OS_PIDFD_OPEN_METHODDEF +#endif /* !defined(OS_PIDFD_OPEN_METHODDEF) */ + +#ifndef OS_SETNS_METHODDEF + #define OS_SETNS_METHODDEF +#endif /* !defined(OS_SETNS_METHODDEF) */ + +#ifndef OS_UNSHARE_METHODDEF + #define OS_UNSHARE_METHODDEF +#endif /* !defined(OS_UNSHARE_METHODDEF) */ + +#ifndef OS_READLINK_METHODDEF + #define OS_READLINK_METHODDEF +#endif /* !defined(OS_READLINK_METHODDEF) */ + +#ifndef OS_SYMLINK_METHODDEF + #define OS_SYMLINK_METHODDEF +#endif /* !defined(OS_SYMLINK_METHODDEF) */ + +#ifndef OS_TIMES_METHODDEF + #define OS_TIMES_METHODDEF +#endif /* !defined(OS_TIMES_METHODDEF) */ + +#ifndef OS_GETSID_METHODDEF + #define OS_GETSID_METHODDEF +#endif /* !defined(OS_GETSID_METHODDEF) */ + +#ifndef OS_SETSID_METHODDEF + #define OS_SETSID_METHODDEF +#endif /* !defined(OS_SETSID_METHODDEF) */ + +#ifndef OS_SETPGID_METHODDEF + #define OS_SETPGID_METHODDEF +#endif /* !defined(OS_SETPGID_METHODDEF) */ + +#ifndef OS_TCGETPGRP_METHODDEF + #define OS_TCGETPGRP_METHODDEF +#endif /* !defined(OS_TCGETPGRP_METHODDEF) */ + +#ifndef OS_TCSETPGRP_METHODDEF + #define OS_TCSETPGRP_METHODDEF +#endif /* !defined(OS_TCSETPGRP_METHODDEF) */ + +#ifndef OS_DUP2_METHODDEF + #define OS_DUP2_METHODDEF +#endif /* !defined(OS_DUP2_METHODDEF) */ + +#ifndef OS_LOCKF_METHODDEF + #define OS_LOCKF_METHODDEF +#endif /* !defined(OS_LOCKF_METHODDEF) */ + +#ifndef OS_READV_METHODDEF + #define OS_READV_METHODDEF +#endif /* !defined(OS_READV_METHODDEF) */ + +#ifndef OS_PREAD_METHODDEF + #define OS_PREAD_METHODDEF +#endif /* !defined(OS_PREAD_METHODDEF) */ + +#ifndef OS_PREADV_METHODDEF + #define OS_PREADV_METHODDEF +#endif /* !defined(OS_PREADV_METHODDEF) */ + +#ifndef OS_SENDFILE_METHODDEF + #define OS_SENDFILE_METHODDEF +#endif /* !defined(OS_SENDFILE_METHODDEF) */ + +#ifndef OS__FCOPYFILE_METHODDEF + #define OS__FCOPYFILE_METHODDEF +#endif /* !defined(OS__FCOPYFILE_METHODDEF) */ + +#ifndef OS_PIPE_METHODDEF + #define OS_PIPE_METHODDEF +#endif /* !defined(OS_PIPE_METHODDEF) */ + +#ifndef OS_PIPE2_METHODDEF + #define OS_PIPE2_METHODDEF +#endif /* !defined(OS_PIPE2_METHODDEF) */ + +#ifndef OS_WRITEV_METHODDEF + #define OS_WRITEV_METHODDEF +#endif /* !defined(OS_WRITEV_METHODDEF) */ + +#ifndef OS_PWRITE_METHODDEF + #define OS_PWRITE_METHODDEF +#endif /* !defined(OS_PWRITE_METHODDEF) */ + +#ifndef OS_PWRITEV_METHODDEF + #define OS_PWRITEV_METHODDEF +#endif /* !defined(OS_PWRITEV_METHODDEF) */ + +#ifndef OS_COPY_FILE_RANGE_METHODDEF + #define OS_COPY_FILE_RANGE_METHODDEF +#endif /* !defined(OS_COPY_FILE_RANGE_METHODDEF) */ + +#ifndef OS_SPLICE_METHODDEF + #define OS_SPLICE_METHODDEF +#endif /* !defined(OS_SPLICE_METHODDEF) */ + +#ifndef OS_MKFIFO_METHODDEF + #define OS_MKFIFO_METHODDEF +#endif /* !defined(OS_MKFIFO_METHODDEF) */ + +#ifndef OS_MKNOD_METHODDEF + #define OS_MKNOD_METHODDEF +#endif /* !defined(OS_MKNOD_METHODDEF) */ + +#ifndef OS_MAJOR_METHODDEF + #define OS_MAJOR_METHODDEF +#endif /* !defined(OS_MAJOR_METHODDEF) */ + +#ifndef OS_MINOR_METHODDEF + #define OS_MINOR_METHODDEF +#endif /* !defined(OS_MINOR_METHODDEF) */ + +#ifndef OS_MAKEDEV_METHODDEF + #define OS_MAKEDEV_METHODDEF +#endif /* !defined(OS_MAKEDEV_METHODDEF) */ + +#ifndef OS_FTRUNCATE_METHODDEF + #define OS_FTRUNCATE_METHODDEF +#endif /* !defined(OS_FTRUNCATE_METHODDEF) */ + +#ifndef OS_TRUNCATE_METHODDEF + #define OS_TRUNCATE_METHODDEF +#endif /* !defined(OS_TRUNCATE_METHODDEF) */ + +#ifndef OS_POSIX_FALLOCATE_METHODDEF + #define OS_POSIX_FALLOCATE_METHODDEF +#endif /* !defined(OS_POSIX_FALLOCATE_METHODDEF) */ + +#ifndef OS_POSIX_FADVISE_METHODDEF + #define OS_POSIX_FADVISE_METHODDEF +#endif /* !defined(OS_POSIX_FADVISE_METHODDEF) */ + +#ifndef OS_PUTENV_METHODDEF + #define OS_PUTENV_METHODDEF +#endif /* !defined(OS_PUTENV_METHODDEF) */ + +#ifndef OS_UNSETENV_METHODDEF + #define OS_UNSETENV_METHODDEF +#endif /* !defined(OS_UNSETENV_METHODDEF) */ + +#ifndef OS_WCOREDUMP_METHODDEF + #define OS_WCOREDUMP_METHODDEF +#endif /* !defined(OS_WCOREDUMP_METHODDEF) */ + +#ifndef OS_WIFCONTINUED_METHODDEF + #define OS_WIFCONTINUED_METHODDEF +#endif /* !defined(OS_WIFCONTINUED_METHODDEF) */ + +#ifndef OS_WIFSTOPPED_METHODDEF + #define OS_WIFSTOPPED_METHODDEF +#endif /* !defined(OS_WIFSTOPPED_METHODDEF) */ + +#ifndef OS_WIFSIGNALED_METHODDEF + #define OS_WIFSIGNALED_METHODDEF +#endif /* !defined(OS_WIFSIGNALED_METHODDEF) */ + +#ifndef OS_WIFEXITED_METHODDEF + #define OS_WIFEXITED_METHODDEF +#endif /* !defined(OS_WIFEXITED_METHODDEF) */ + +#ifndef OS_WEXITSTATUS_METHODDEF + #define OS_WEXITSTATUS_METHODDEF +#endif /* !defined(OS_WEXITSTATUS_METHODDEF) */ + +#ifndef OS_WTERMSIG_METHODDEF + #define OS_WTERMSIG_METHODDEF +#endif /* !defined(OS_WTERMSIG_METHODDEF) */ + +#ifndef OS_WSTOPSIG_METHODDEF + #define OS_WSTOPSIG_METHODDEF +#endif /* !defined(OS_WSTOPSIG_METHODDEF) */ + +#ifndef OS_FSTATVFS_METHODDEF + #define OS_FSTATVFS_METHODDEF +#endif /* !defined(OS_FSTATVFS_METHODDEF) */ + +#ifndef OS_STATVFS_METHODDEF + #define OS_STATVFS_METHODDEF +#endif /* !defined(OS_STATVFS_METHODDEF) */ + +#ifndef OS__GETDISKUSAGE_METHODDEF + #define OS__GETDISKUSAGE_METHODDEF +#endif /* !defined(OS__GETDISKUSAGE_METHODDEF) */ + +#ifndef OS_FPATHCONF_METHODDEF + #define OS_FPATHCONF_METHODDEF +#endif /* !defined(OS_FPATHCONF_METHODDEF) */ + +#ifndef OS_PATHCONF_METHODDEF + #define OS_PATHCONF_METHODDEF +#endif /* !defined(OS_PATHCONF_METHODDEF) */ + +#ifndef OS_CONFSTR_METHODDEF + #define OS_CONFSTR_METHODDEF +#endif /* !defined(OS_CONFSTR_METHODDEF) */ + +#ifndef OS_SYSCONF_METHODDEF + #define OS_SYSCONF_METHODDEF +#endif /* !defined(OS_SYSCONF_METHODDEF) */ + +#ifndef OS_STARTFILE_METHODDEF + #define OS_STARTFILE_METHODDEF +#endif /* !defined(OS_STARTFILE_METHODDEF) */ + +#ifndef OS_GETLOADAVG_METHODDEF + #define OS_GETLOADAVG_METHODDEF +#endif /* !defined(OS_GETLOADAVG_METHODDEF) */ + +#ifndef OS_SETRESUID_METHODDEF + #define OS_SETRESUID_METHODDEF +#endif /* !defined(OS_SETRESUID_METHODDEF) */ + +#ifndef OS_SETRESGID_METHODDEF + #define OS_SETRESGID_METHODDEF +#endif /* !defined(OS_SETRESGID_METHODDEF) */ + +#ifndef OS_GETRESUID_METHODDEF + #define OS_GETRESUID_METHODDEF +#endif /* !defined(OS_GETRESUID_METHODDEF) */ + +#ifndef OS_GETRESGID_METHODDEF + #define OS_GETRESGID_METHODDEF +#endif /* !defined(OS_GETRESGID_METHODDEF) */ + +#ifndef OS_GETXATTR_METHODDEF + #define OS_GETXATTR_METHODDEF +#endif /* !defined(OS_GETXATTR_METHODDEF) */ + +#ifndef OS_SETXATTR_METHODDEF + #define OS_SETXATTR_METHODDEF +#endif /* !defined(OS_SETXATTR_METHODDEF) */ + +#ifndef OS_REMOVEXATTR_METHODDEF + #define OS_REMOVEXATTR_METHODDEF +#endif /* !defined(OS_REMOVEXATTR_METHODDEF) */ + +#ifndef OS_LISTXATTR_METHODDEF + #define OS_LISTXATTR_METHODDEF +#endif /* !defined(OS_LISTXATTR_METHODDEF) */ + +#ifndef OS_MEMFD_CREATE_METHODDEF + #define OS_MEMFD_CREATE_METHODDEF +#endif /* !defined(OS_MEMFD_CREATE_METHODDEF) */ + +#ifndef OS_EVENTFD_METHODDEF + #define OS_EVENTFD_METHODDEF +#endif /* !defined(OS_EVENTFD_METHODDEF) */ + +#ifndef OS_EVENTFD_READ_METHODDEF + #define OS_EVENTFD_READ_METHODDEF +#endif /* !defined(OS_EVENTFD_READ_METHODDEF) */ + +#ifndef OS_EVENTFD_WRITE_METHODDEF + #define OS_EVENTFD_WRITE_METHODDEF +#endif /* !defined(OS_EVENTFD_WRITE_METHODDEF) */ + +#ifndef OS_GET_TERMINAL_SIZE_METHODDEF + #define OS_GET_TERMINAL_SIZE_METHODDEF +#endif /* !defined(OS_GET_TERMINAL_SIZE_METHODDEF) */ + +#ifndef OS_GET_HANDLE_INHERITABLE_METHODDEF + #define OS_GET_HANDLE_INHERITABLE_METHODDEF +#endif /* !defined(OS_GET_HANDLE_INHERITABLE_METHODDEF) */ + +#ifndef OS_SET_HANDLE_INHERITABLE_METHODDEF + #define OS_SET_HANDLE_INHERITABLE_METHODDEF +#endif /* !defined(OS_SET_HANDLE_INHERITABLE_METHODDEF) */ + +#ifndef OS_GET_BLOCKING_METHODDEF + #define OS_GET_BLOCKING_METHODDEF +#endif /* !defined(OS_GET_BLOCKING_METHODDEF) */ + +#ifndef OS_SET_BLOCKING_METHODDEF + #define OS_SET_BLOCKING_METHODDEF +#endif /* !defined(OS_SET_BLOCKING_METHODDEF) */ + +#ifndef OS_GETRANDOM_METHODDEF + #define OS_GETRANDOM_METHODDEF +#endif /* !defined(OS_GETRANDOM_METHODDEF) */ + +#ifndef OS__ADD_DLL_DIRECTORY_METHODDEF + #define OS__ADD_DLL_DIRECTORY_METHODDEF +#endif /* !defined(OS__ADD_DLL_DIRECTORY_METHODDEF) */ + +#ifndef OS__REMOVE_DLL_DIRECTORY_METHODDEF + #define OS__REMOVE_DLL_DIRECTORY_METHODDEF +#endif /* !defined(OS__REMOVE_DLL_DIRECTORY_METHODDEF) */ + +#ifndef OS_WAITSTATUS_TO_EXITCODE_METHODDEF + #define OS_WAITSTATUS_TO_EXITCODE_METHODDEF +#endif /* !defined(OS_WAITSTATUS_TO_EXITCODE_METHODDEF) */ +/*[clinic end generated code: output=4192d8e09e216300 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 5968c1940e76f4..39c2ca1a9b4bc4 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1,16036 +1,16056 @@ -/* POSIX module implementation */ - -/* This file is also used for Windows NT/MS-Win. In that case the - module actually calls itself 'nt', not 'posix', and a few - functions are either unimplemented or implemented differently. The source - assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent - of the compiler used. Different compilers define their own feature - test macro, e.g. '_MSC_VER'. */ - -#define PY_SSIZE_T_CLEAN - -#include "Python.h" -// Include before pycore internal headers. FSCTL_GET_REPARSE_POINT -// is not exported by if the WIN32_LEAN_AND_MEAN macro is defined, -// whereas pycore_condvar.h defines the WIN32_LEAN_AND_MEAN macro. -#ifdef MS_WINDOWS -# include -# include -#endif - -#ifdef __VXWORKS__ -# include "pycore_bitutils.h" // _Py_popcount32() -#endif -#include "pycore_call.h" // _PyObject_CallNoArgs() -#include "pycore_ceval.h" // _PyEval_ReInitThreads() -#include "pycore_fileutils.h" // _Py_closerange() -#include "pycore_import.h" // _PyImport_ReInitLock() -#include "pycore_initconfig.h" // _PyStatus_EXCEPTION() -#include "pycore_moduleobject.h" // _PyModule_GetState() -#include "pycore_object.h" // _PyObject_LookupSpecial() -#include "pycore_pystate.h" // _PyInterpreterState_GET() -#include "pycore_signal.h" // Py_NSIG - -#include "structmember.h" // PyMemberDef -#ifndef MS_WINDOWS -# include "posixmodule.h" -#else -# include "winreparse.h" -#endif - -#if !defined(EX_OK) && defined(EXIT_SUCCESS) -# define EX_OK EXIT_SUCCESS -#endif - -/* On android API level 21, 'AT_EACCESS' is not declared although - * HAVE_FACCESSAT is defined. */ -#ifdef __ANDROID__ -# undef HAVE_FACCESSAT -#endif - -#include // ctermid() -#include // system() - -/* - * A number of APIs are available on macOS from a certain macOS version. - * To support building with a new SDK while deploying to older versions - * the availability test is split into two: - * - HAVE_: The configure check for compile time availability - * - HAVE__RUNTIME: Runtime check for availability - * - * The latter is always true when not on macOS, or when using a compiler - * that does not support __has_builtin (older versions of Xcode). - * - * Due to compiler restrictions there is one valid use of HAVE__RUNTIME: - * if (HAVE__RUNTIME) { ... } - * - * In mixing the test with other tests or using negations will result in compile - * errors. - */ -#if defined(__APPLE__) - -#if defined(__has_builtin) -#if __has_builtin(__builtin_available) -#define HAVE_BUILTIN_AVAILABLE 1 -#endif -#endif - -#ifdef HAVE_BUILTIN_AVAILABLE -# define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) -# define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) -# define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) -# define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) -# define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) -# define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) -# define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) -# define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) -# define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) -# define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) -# define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) -# define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) -# define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *) -# define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *) -# define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *) -# define HAVE_MKFIFOAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *) -# define HAVE_MKNODAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *) - -# define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *) - -#else /* Xcode 8 or earlier */ - - /* __builtin_available is not present in these compilers, but - * some of the symbols might be weak linked (10.10 SDK or later - * deploying on 10.9. - * - * Fall back to the older style of availability checking for - * symbols introduced in macOS 10.10. - */ - -# ifdef HAVE_FSTATAT -# define HAVE_FSTATAT_RUNTIME (fstatat != NULL) -# endif - -# ifdef HAVE_FACCESSAT -# define HAVE_FACCESSAT_RUNTIME (faccessat != NULL) -# endif - -# ifdef HAVE_FCHMODAT -# define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL) -# endif - -# ifdef HAVE_FCHOWNAT -# define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL) -# endif - -# ifdef HAVE_LINKAT -# define HAVE_LINKAT_RUNTIME (linkat != NULL) -# endif - -# ifdef HAVE_FDOPENDIR -# define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL) -# endif - -# ifdef HAVE_MKDIRAT -# define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL) -# endif - -# ifdef HAVE_RENAMEAT -# define HAVE_RENAMEAT_RUNTIME (renameat != NULL) -# endif - -# ifdef HAVE_UNLINKAT -# define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL) -# endif - -# ifdef HAVE_OPENAT -# define HAVE_OPENAT_RUNTIME (openat != NULL) -# endif - -# ifdef HAVE_READLINKAT -# define HAVE_READLINKAT_RUNTIME (readlinkat != NULL) -# endif - -# ifdef HAVE_SYMLINKAT -# define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL) -# endif - -#endif - -#ifdef HAVE_FUTIMESAT -/* Some of the logic for weak linking depends on this assertion */ -# error "HAVE_FUTIMESAT unexpectedly defined" -#endif - -#else -# define HAVE_FSTATAT_RUNTIME 1 -# define HAVE_FACCESSAT_RUNTIME 1 -# define HAVE_FCHMODAT_RUNTIME 1 -# define HAVE_FCHOWNAT_RUNTIME 1 -# define HAVE_LINKAT_RUNTIME 1 -# define HAVE_FDOPENDIR_RUNTIME 1 -# define HAVE_MKDIRAT_RUNTIME 1 -# define HAVE_RENAMEAT_RUNTIME 1 -# define HAVE_UNLINKAT_RUNTIME 1 -# define HAVE_OPENAT_RUNTIME 1 -# define HAVE_READLINKAT_RUNTIME 1 -# define HAVE_SYMLINKAT_RUNTIME 1 -# define HAVE_FUTIMENS_RUNTIME 1 -# define HAVE_UTIMENSAT_RUNTIME 1 -# define HAVE_PWRITEV_RUNTIME 1 -# define HAVE_MKFIFOAT_RUNTIME 1 -# define HAVE_MKNODAT_RUNTIME 1 -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - -PyDoc_STRVAR(posix__doc__, -"This module provides access to operating system functionality that is\n\ -standardized by the C Standard and the POSIX standard (a thinly\n\ -disguised Unix interface). Refer to the library manual and\n\ -corresponding Unix manual entries for more information on calls."); - - -#ifdef HAVE_SYS_UIO_H -# include -#endif - -#ifdef HAVE_SYS_SYSMACROS_H -/* GNU C Library: major(), minor(), makedev() */ -# include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif /* HAVE_SYS_TYPES_H */ - -#ifdef HAVE_SYS_STAT_H -# include -#endif /* HAVE_SYS_STAT_H */ - -#ifdef HAVE_SYS_WAIT_H -# include // WNOHANG -#endif -#ifdef HAVE_LINUX_WAIT_H -# include // P_PIDFD -#endif - -#ifdef HAVE_SIGNAL_H -# include -#endif - -#ifdef HAVE_FCNTL_H -# include -#endif - -#ifdef HAVE_GRP_H -# include -#endif - -#ifdef HAVE_SYSEXITS_H -# include -#endif - -#ifdef HAVE_SYS_LOADAVG_H -# include -#endif - -#ifdef HAVE_SYS_SENDFILE_H -# include -#endif - -#if defined(__APPLE__) -# include -#endif - -#ifdef HAVE_SCHED_H -# include -#endif - -#ifdef HAVE_COPY_FILE_RANGE -# include -#endif - -#if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY) -# undef HAVE_SCHED_SETAFFINITY -#endif - -#if defined(HAVE_SYS_XATTR_H) && defined(__GLIBC__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__) -# define USE_XATTRS -#endif - -#ifdef USE_XATTRS -# include -#endif - -#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) -# ifdef HAVE_SYS_SOCKET_H -# include -# endif -#endif - -#ifdef HAVE_DLFCN_H -# include -#endif - -#ifdef __hpux -# include -#endif - -#if defined(__DragonFly__) || \ - defined(__OpenBSD__) || \ - defined(__FreeBSD__) || \ - defined(__NetBSD__) || \ - defined(__APPLE__) -# include -#endif - -#ifdef HAVE_LINUX_RANDOM_H -# include -#endif -#ifdef HAVE_GETRANDOM_SYSCALL -# include -#endif - -#if defined(MS_WINDOWS) -# define TERMSIZE_USE_CONIO -#elif defined(HAVE_SYS_IOCTL_H) -# include -# if defined(HAVE_TERMIOS_H) -# include -# endif -# if defined(TIOCGWINSZ) -# define TERMSIZE_USE_IOCTL -# endif -#endif /* MS_WINDOWS */ - -/* Various compilers have only certain posix functions */ -/* XXX Gosh I wish these were all moved into pyconfig.h */ -#if defined(__WATCOMC__) && !defined(__QNX__) /* Watcom compiler */ -# define HAVE_OPENDIR 1 -# define HAVE_SYSTEM 1 -# include -#else -# ifdef _MSC_VER - /* Microsoft compiler */ -# define HAVE_GETPPID 1 -# define HAVE_GETLOGIN 1 -# define HAVE_SPAWNV 1 -# define HAVE_EXECV 1 -# define HAVE_WSPAWNV 1 -# define HAVE_WEXECV 1 -# define HAVE_PIPE 1 -# define HAVE_SYSTEM 1 -# define HAVE_CWAIT 1 -# define HAVE_FSYNC 1 -# define fsync _commit -# endif /* _MSC_VER */ -#endif /* ! __WATCOMC__ || __QNX__ */ - -/*[clinic input] -# one of the few times we lie about this name! -module os -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/ - -#ifndef _MSC_VER - -#if defined(__sgi)&&_COMPILER_VERSION>=700 -/* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode - (default) */ -extern char *ctermid_r(char *); -#endif - -#endif /* !_MSC_VER */ - -#if defined(__VXWORKS__) -# include -# include -# include -# include -# ifndef _P_WAIT -# define _P_WAIT 0 -# define _P_NOWAIT 1 -# define _P_NOWAITO 1 -# endif -#endif /* __VXWORKS__ */ - -#ifdef HAVE_POSIX_SPAWN -# include -#endif - -#ifdef HAVE_UTIME_H -# include -#endif /* HAVE_UTIME_H */ - -#ifdef HAVE_SYS_UTIME_H -# include -# define HAVE_UTIME_H /* pretend we do for the rest of this file */ -#endif /* HAVE_SYS_UTIME_H */ - -#ifdef HAVE_SYS_TIMES_H -# include -#endif /* HAVE_SYS_TIMES_H */ - -#ifdef HAVE_SYS_PARAM_H -# include -#endif /* HAVE_SYS_PARAM_H */ - -#ifdef HAVE_SYS_UTSNAME_H -# include -#endif /* HAVE_SYS_UTSNAME_H */ - -#ifdef HAVE_DIRENT_H -# include -# define NAMLEN(dirent) strlen((dirent)->d_name) -#else -# if defined(__WATCOMC__) && !defined(__QNX__) -# include -# define NAMLEN(dirent) strlen((dirent)->d_name) -# else -# define dirent direct -# define NAMLEN(dirent) (dirent)->d_namlen -# endif -# ifdef HAVE_SYS_NDIR_H -# include -# endif -# ifdef HAVE_SYS_DIR_H -# include -# endif -# ifdef HAVE_NDIR_H -# include -# endif -#endif - -#ifdef _MSC_VER -# ifdef HAVE_DIRECT_H -# include -# endif -# ifdef HAVE_IO_H -# include -# endif -# ifdef HAVE_PROCESS_H -# include -# endif -# ifndef IO_REPARSE_TAG_SYMLINK -# define IO_REPARSE_TAG_SYMLINK (0xA000000CL) -# endif -# ifndef IO_REPARSE_TAG_MOUNT_POINT -# define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) -# endif -# include "osdefs.h" // SEP -# include -# include -# include // ShellExecute() -# include // UNLEN -# define HAVE_SYMLINK -#endif /* _MSC_VER */ - -#ifndef MAXPATHLEN -# if defined(PATH_MAX) && PATH_MAX > 1024 -# define MAXPATHLEN PATH_MAX -# else -# define MAXPATHLEN 1024 -# endif -#endif /* MAXPATHLEN */ - -#ifdef UNION_WAIT - /* Emulate some macros on systems that have a union instead of macros */ -# ifndef WIFEXITED -# define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump) -# endif -# ifndef WEXITSTATUS -# define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1) -# endif -# ifndef WTERMSIG -# define WTERMSIG(u_wait) ((u_wait).w_termsig) -# endif -# define WAIT_TYPE union wait -# define WAIT_STATUS_INT(s) (s.w_status) -#else - /* !UNION_WAIT */ -# define WAIT_TYPE int -# define WAIT_STATUS_INT(s) (s) -#endif /* UNION_WAIT */ - -/* Don't use the "_r" form if we don't need it (also, won't have a - prototype for it, at least on Solaris -- maybe others as well?). */ -#if defined(HAVE_CTERMID_R) -# define USE_CTERMID_R -#endif - -/* choose the appropriate stat and fstat functions and return structs */ -#undef STAT -#undef FSTAT -#undef STRUCT_STAT -#ifdef MS_WINDOWS -# define STAT win32_stat -# define LSTAT win32_lstat -# define FSTAT _Py_fstat_noraise -# define STRUCT_STAT struct _Py_stat_struct -#else -# define STAT stat -# define LSTAT lstat -# define FSTAT fstat -# define STRUCT_STAT struct stat -#endif - -#if defined(MAJOR_IN_MKDEV) -# include -#else -# if defined(MAJOR_IN_SYSMACROS) -# include -# endif -# if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H) -# include -# endif -#endif - -#ifdef MS_WINDOWS -# define INITFUNC PyInit_nt -# define MODNAME "nt" -#else -# define INITFUNC PyInit_posix -# define MODNAME "posix" -#endif - -#if defined(__sun) -/* Something to implement in autoconf, not present in autoconf 2.69 */ -# define HAVE_STRUCT_STAT_ST_FSTYPE 1 -#endif - -/* memfd_create is either defined in sys/mman.h or sys/memfd.h - * linux/memfd.h defines additional flags - */ -#ifdef HAVE_SYS_MMAN_H -# include -#endif -#ifdef HAVE_SYS_MEMFD_H -# include -#endif -#ifdef HAVE_LINUX_MEMFD_H -# include -#endif - -/* eventfd() */ -#ifdef HAVE_SYS_EVENTFD_H -# include -#endif - -#ifdef _Py_MEMORY_SANITIZER -# include -#endif - -#ifdef HAVE_FORK -static void -run_at_forkers(PyObject *lst, int reverse) -{ - Py_ssize_t i; - PyObject *cpy; - - if (lst != NULL) { - assert(PyList_CheckExact(lst)); - - /* Use a list copy in case register_at_fork() is called from - * one of the callbacks. - */ - cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst)); - if (cpy == NULL) - PyErr_WriteUnraisable(lst); - else { - if (reverse) - PyList_Reverse(cpy); - for (i = 0; i < PyList_GET_SIZE(cpy); i++) { - PyObject *func, *res; - func = PyList_GET_ITEM(cpy, i); - res = _PyObject_CallNoArgs(func); - if (res == NULL) - PyErr_WriteUnraisable(func); - else - Py_DECREF(res); - } - Py_DECREF(cpy); - } - } -} - -void -PyOS_BeforeFork(void) -{ - run_at_forkers(_PyInterpreterState_GET()->before_forkers, 1); - - _PyImport_AcquireLock(); -} - -void -PyOS_AfterFork_Parent(void) -{ - if (_PyImport_ReleaseLock() <= 0) - Py_FatalError("failed releasing import lock after fork"); - - run_at_forkers(_PyInterpreterState_GET()->after_forkers_parent, 0); -} - -void -PyOS_AfterFork_Child(void) -{ - PyStatus status; - _PyRuntimeState *runtime = &_PyRuntime; - - status = _PyGILState_Reinit(runtime); - if (_PyStatus_EXCEPTION(status)) { - goto fatal_error; - } - - PyThreadState *tstate = _PyThreadState_GET(); - _Py_EnsureTstateNotNULL(tstate); - - status = _PyEval_ReInitThreads(tstate); - if (_PyStatus_EXCEPTION(status)) { - goto fatal_error; - } - - status = _PyImport_ReInitLock(); - if (_PyStatus_EXCEPTION(status)) { - goto fatal_error; - } - - _PySignal_AfterFork(); - - status = _PyRuntimeState_ReInitThreads(runtime); - if (_PyStatus_EXCEPTION(status)) { - goto fatal_error; - } - - status = _PyInterpreterState_DeleteExceptMain(runtime); - if (_PyStatus_EXCEPTION(status)) { - goto fatal_error; - } - assert(_PyThreadState_GET() == tstate); - - status = _PyPerfTrampoline_AfterFork_Child(); - if (_PyStatus_EXCEPTION(status)) { - goto fatal_error; - } - - run_at_forkers(tstate->interp->after_forkers_child, 0); - return; - -fatal_error: - Py_ExitStatusException(status); -} - -static int -register_at_forker(PyObject **lst, PyObject *func) -{ - if (func == NULL) /* nothing to register? do nothing. */ - return 0; - if (*lst == NULL) { - *lst = PyList_New(0); - if (*lst == NULL) - return -1; - } - return PyList_Append(*lst, func); -} -#endif /* HAVE_FORK */ - - -/* Legacy wrapper */ -void -PyOS_AfterFork(void) -{ -#ifdef HAVE_FORK - PyOS_AfterFork_Child(); -#endif -} - - -#ifdef MS_WINDOWS -/* defined in fileutils.c */ -void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *); -void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *, - ULONG, struct _Py_stat_struct *); -#endif - - -#ifndef MS_WINDOWS -PyObject * -_PyLong_FromUid(uid_t uid) -{ - if (uid == (uid_t)-1) - return PyLong_FromLong(-1); - return PyLong_FromUnsignedLong(uid); -} - -PyObject * -_PyLong_FromGid(gid_t gid) -{ - if (gid == (gid_t)-1) - return PyLong_FromLong(-1); - return PyLong_FromUnsignedLong(gid); -} - -int -_Py_Uid_Converter(PyObject *obj, uid_t *p) -{ - uid_t uid; - PyObject *index; - int overflow; - long result; - unsigned long uresult; - - index = _PyNumber_Index(obj); - if (index == NULL) { - PyErr_Format(PyExc_TypeError, - "uid should be integer, not %.200s", - _PyType_Name(Py_TYPE(obj))); - return 0; - } - - /* - * Handling uid_t is complicated for two reasons: - * * Although uid_t is (always?) unsigned, it still - * accepts -1. - * * We don't know its size in advance--it may be - * bigger than an int, or it may be smaller than - * a long. - * - * So a bit of defensive programming is in order. - * Start with interpreting the value passed - * in as a signed long and see if it works. - */ - - result = PyLong_AsLongAndOverflow(index, &overflow); - - if (!overflow) { - uid = (uid_t)result; - - if (result == -1) { - if (PyErr_Occurred()) - goto fail; - /* It's a legitimate -1, we're done. */ - goto success; - } - - /* Any other negative number is disallowed. */ - if (result < 0) - goto underflow; - - /* Ensure the value wasn't truncated. */ - if (sizeof(uid_t) < sizeof(long) && - (long)uid != result) - goto underflow; - goto success; - } - - if (overflow < 0) - goto underflow; - - /* - * Okay, the value overflowed a signed long. If it - * fits in an *unsigned* long, it may still be okay, - * as uid_t may be unsigned long on this platform. - */ - uresult = PyLong_AsUnsignedLong(index); - if (PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) - goto overflow; - goto fail; - } - - uid = (uid_t)uresult; - - /* - * If uid == (uid_t)-1, the user actually passed in ULONG_MAX, - * but this value would get interpreted as (uid_t)-1 by chown - * and its siblings. That's not what the user meant! So we - * throw an overflow exception instead. (We already - * handled a real -1 with PyLong_AsLongAndOverflow() above.) - */ - if (uid == (uid_t)-1) - goto overflow; - - /* Ensure the value wasn't truncated. */ - if (sizeof(uid_t) < sizeof(long) && - (unsigned long)uid != uresult) - goto overflow; - /* fallthrough */ - -success: - Py_DECREF(index); - *p = uid; - return 1; - -underflow: - PyErr_SetString(PyExc_OverflowError, - "uid is less than minimum"); - goto fail; - -overflow: - PyErr_SetString(PyExc_OverflowError, - "uid is greater than maximum"); - /* fallthrough */ - -fail: - Py_DECREF(index); - return 0; -} - -int -_Py_Gid_Converter(PyObject *obj, gid_t *p) -{ - gid_t gid; - PyObject *index; - int overflow; - long result; - unsigned long uresult; - - index = _PyNumber_Index(obj); - if (index == NULL) { - PyErr_Format(PyExc_TypeError, - "gid should be integer, not %.200s", - _PyType_Name(Py_TYPE(obj))); - return 0; - } - - /* - * Handling gid_t is complicated for two reasons: - * * Although gid_t is (always?) unsigned, it still - * accepts -1. - * * We don't know its size in advance--it may be - * bigger than an int, or it may be smaller than - * a long. - * - * So a bit of defensive programming is in order. - * Start with interpreting the value passed - * in as a signed long and see if it works. - */ - - result = PyLong_AsLongAndOverflow(index, &overflow); - - if (!overflow) { - gid = (gid_t)result; - - if (result == -1) { - if (PyErr_Occurred()) - goto fail; - /* It's a legitimate -1, we're done. */ - goto success; - } - - /* Any other negative number is disallowed. */ - if (result < 0) { - goto underflow; - } - - /* Ensure the value wasn't truncated. */ - if (sizeof(gid_t) < sizeof(long) && - (long)gid != result) - goto underflow; - goto success; - } - - if (overflow < 0) - goto underflow; - - /* - * Okay, the value overflowed a signed long. If it - * fits in an *unsigned* long, it may still be okay, - * as gid_t may be unsigned long on this platform. - */ - uresult = PyLong_AsUnsignedLong(index); - if (PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) - goto overflow; - goto fail; - } - - gid = (gid_t)uresult; - - /* - * If gid == (gid_t)-1, the user actually passed in ULONG_MAX, - * but this value would get interpreted as (gid_t)-1 by chown - * and its siblings. That's not what the user meant! So we - * throw an overflow exception instead. (We already - * handled a real -1 with PyLong_AsLongAndOverflow() above.) - */ - if (gid == (gid_t)-1) - goto overflow; - - /* Ensure the value wasn't truncated. */ - if (sizeof(gid_t) < sizeof(long) && - (unsigned long)gid != uresult) - goto overflow; - /* fallthrough */ - -success: - Py_DECREF(index); - *p = gid; - return 1; - -underflow: - PyErr_SetString(PyExc_OverflowError, - "gid is less than minimum"); - goto fail; - -overflow: - PyErr_SetString(PyExc_OverflowError, - "gid is greater than maximum"); - /* fallthrough */ - -fail: - Py_DECREF(index); - return 0; -} -#endif /* MS_WINDOWS */ - - -#define _PyLong_FromDev PyLong_FromLongLong - - -#if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) || defined(HAVE_DEVICE_MACROS) -static int -_Py_Dev_Converter(PyObject *obj, void *p) -{ - *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj); - if (PyErr_Occurred()) - return 0; - return 1; -} -#endif /* (HAVE_MKNOD && HAVE_MAKEDEV) || HAVE_DEVICE_MACROS */ - - -#ifdef AT_FDCWD -/* - * Why the (int) cast? Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965); - * without the int cast, the value gets interpreted as uint (4291925331), - * which doesn't play nicely with all the initializer lines in this file that - * look like this: - * int dir_fd = DEFAULT_DIR_FD; - */ -#define DEFAULT_DIR_FD (int)AT_FDCWD -#else -#define DEFAULT_DIR_FD (-100) -#endif - -static int -_fd_converter(PyObject *o, int *p) -{ - int overflow; - long long_value; - - PyObject *index = _PyNumber_Index(o); - if (index == NULL) { - return 0; - } - - assert(PyLong_Check(index)); - long_value = PyLong_AsLongAndOverflow(index, &overflow); - Py_DECREF(index); - assert(!PyErr_Occurred()); - if (overflow > 0 || long_value > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "fd is greater than maximum"); - return 0; - } - if (overflow < 0 || long_value < INT_MIN) { - PyErr_SetString(PyExc_OverflowError, - "fd is less than minimum"); - return 0; - } - - *p = (int)long_value; - return 1; -} - -static int -dir_fd_converter(PyObject *o, void *p) -{ - if (o == Py_None) { - *(int *)p = DEFAULT_DIR_FD; - return 1; - } - else if (PyIndex_Check(o)) { - return _fd_converter(o, (int *)p); - } - else { - PyErr_Format(PyExc_TypeError, - "argument should be integer or None, not %.200s", - _PyType_Name(Py_TYPE(o))); - return 0; - } -} - -typedef struct { - PyObject *billion; - PyObject *DirEntryType; - PyObject *ScandirIteratorType; -#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) - PyObject *SchedParamType; -#endif - PyObject *StatResultType; - PyObject *StatVFSResultType; - PyObject *TerminalSizeType; - PyObject *TimesResultType; - PyObject *UnameResultType; -#if defined(HAVE_WAITID) && !defined(__APPLE__) - PyObject *WaitidResultType; -#endif -#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) - PyObject *struct_rusage; -#endif - PyObject *st_mode; -} _posixstate; - - -static inline _posixstate* -get_posix_state(PyObject *module) -{ - void *state = _PyModule_GetState(module); - assert(state != NULL); - return (_posixstate *)state; -} - -/* - * A PyArg_ParseTuple "converter" function - * that handles filesystem paths in the manner - * preferred by the os module. - * - * path_converter accepts (Unicode) strings and their - * subclasses, and bytes and their subclasses. What - * it does with the argument depends on the platform: - * - * * On Windows, if we get a (Unicode) string we - * extract the wchar_t * and return it; if we get - * bytes we decode to wchar_t * and return that. - * - * * On all other platforms, strings are encoded - * to bytes using PyUnicode_FSConverter, then we - * extract the char * from the bytes object and - * return that. - * - * path_converter also optionally accepts signed - * integers (representing open file descriptors) instead - * of path strings. - * - * Input fields: - * path.nullable - * If nonzero, the path is permitted to be None. - * path.allow_fd - * If nonzero, the path is permitted to be a file handle - * (a signed int) instead of a string. - * path.function_name - * If non-NULL, path_converter will use that as the name - * of the function in error messages. - * (If path.function_name is NULL it omits the function name.) - * path.argument_name - * If non-NULL, path_converter will use that as the name - * of the parameter in error messages. - * (If path.argument_name is NULL it uses "path".) - * - * Output fields: - * path.wide - * Points to the path if it was expressed as Unicode - * and was not encoded. (Only used on Windows.) - * path.narrow - * Points to the path if it was expressed as bytes, - * or it was Unicode and was encoded to bytes. (On Windows, - * is a non-zero integer if the path was expressed as bytes. - * The type is deliberately incompatible to prevent misuse.) - * path.fd - * Contains a file descriptor if path.accept_fd was true - * and the caller provided a signed integer instead of any - * sort of string. - * - * WARNING: if your "path" parameter is optional, and is - * unspecified, path_converter will never get called. - * So if you set allow_fd, you *MUST* initialize path.fd = -1 - * yourself! - * path.length - * The length of the path in characters, if specified as - * a string. - * path.object - * The original object passed in (if get a PathLike object, - * the result of PyOS_FSPath() is treated as the original object). - * Own a reference to the object. - * path.cleanup - * For internal use only. May point to a temporary object. - * (Pay no attention to the man behind the curtain.) - * - * At most one of path.wide or path.narrow will be non-NULL. - * If path was None and path.nullable was set, - * or if path was an integer and path.allow_fd was set, - * both path.wide and path.narrow will be NULL - * and path.length will be 0. - * - * path_converter takes care to not write to the path_t - * unless it's successful. However it must reset the - * "cleanup" field each time it's called. - * - * Use as follows: - * path_t path; - * memset(&path, 0, sizeof(path)); - * PyArg_ParseTuple(args, "O&", path_converter, &path); - * // ... use values from path ... - * path_cleanup(&path); - * - * (Note that if PyArg_Parse fails you don't need to call - * path_cleanup(). However it is safe to do so.) - */ -typedef struct { - const char *function_name; - const char *argument_name; - int nullable; - int allow_fd; - const wchar_t *wide; -#ifdef MS_WINDOWS - BOOL narrow; -#else - const char *narrow; -#endif - int fd; - Py_ssize_t length; - PyObject *object; - PyObject *cleanup; -} path_t; - -#ifdef MS_WINDOWS -#define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \ - {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL} -#else -#define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \ - {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL} -#endif - -static void -path_cleanup(path_t *path) -{ - wchar_t *wide = (wchar_t *)path->wide; - path->wide = NULL; - PyMem_Free(wide); - Py_CLEAR(path->object); - Py_CLEAR(path->cleanup); -} - -static int -path_converter(PyObject *o, void *p) -{ - path_t *path = (path_t *)p; - PyObject *bytes = NULL; - Py_ssize_t length = 0; - int is_index, is_bytes, is_unicode; - const char *narrow; -#ifdef MS_WINDOWS - PyObject *wo = NULL; - wchar_t *wide = NULL; -#endif - -#define FORMAT_EXCEPTION(exc, fmt) \ - PyErr_Format(exc, "%s%s" fmt, \ - path->function_name ? path->function_name : "", \ - path->function_name ? ": " : "", \ - path->argument_name ? path->argument_name : "path") - - /* Py_CLEANUP_SUPPORTED support */ - if (o == NULL) { - path_cleanup(path); - return 1; - } - - /* Ensure it's always safe to call path_cleanup(). */ - path->object = path->cleanup = NULL; - /* path->object owns a reference to the original object */ - Py_INCREF(o); - - if ((o == Py_None) && path->nullable) { - path->wide = NULL; -#ifdef MS_WINDOWS - path->narrow = FALSE; -#else - path->narrow = NULL; -#endif - path->fd = -1; - goto success_exit; - } - - /* Only call this here so that we don't treat the return value of - os.fspath() as an fd or buffer. */ - is_index = path->allow_fd && PyIndex_Check(o); - is_bytes = PyBytes_Check(o); - is_unicode = PyUnicode_Check(o); - - if (!is_index && !is_unicode && !is_bytes) { - /* Inline PyOS_FSPath() for better error messages. */ - PyObject *func, *res; - - func = _PyObject_LookupSpecial(o, &_Py_ID(__fspath__)); - if (NULL == func) { - goto error_format; - } - res = _PyObject_CallNoArgs(func); - Py_DECREF(func); - if (NULL == res) { - goto error_exit; - } - else if (PyUnicode_Check(res)) { - is_unicode = 1; - } - else if (PyBytes_Check(res)) { - is_bytes = 1; - } - else { - PyErr_Format(PyExc_TypeError, - "expected %.200s.__fspath__() to return str or bytes, " - "not %.200s", _PyType_Name(Py_TYPE(o)), - _PyType_Name(Py_TYPE(res))); - Py_DECREF(res); - goto error_exit; - } - - /* still owns a reference to the original object */ - Py_DECREF(o); - o = res; - } - - if (is_unicode) { -#ifdef MS_WINDOWS - wide = PyUnicode_AsWideCharString(o, &length); - if (!wide) { - goto error_exit; - } - if (length > 32767) { - FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); - goto error_exit; - } - if (wcslen(wide) != length) { - FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); - goto error_exit; - } - - path->wide = wide; - path->narrow = FALSE; - path->fd = -1; - wide = NULL; - goto success_exit; -#else - if (!PyUnicode_FSConverter(o, &bytes)) { - goto error_exit; - } -#endif - } - else if (is_bytes) { - bytes = Py_NewRef(o); - } - else if (is_index) { - if (!_fd_converter(o, &path->fd)) { - goto error_exit; - } - path->wide = NULL; -#ifdef MS_WINDOWS - path->narrow = FALSE; -#else - path->narrow = NULL; -#endif - goto success_exit; - } - else { - error_format: - PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s", - path->function_name ? path->function_name : "", - path->function_name ? ": " : "", - path->argument_name ? path->argument_name : "path", - path->allow_fd && path->nullable ? "string, bytes, os.PathLike, " - "integer or None" : - path->allow_fd ? "string, bytes, os.PathLike or integer" : - path->nullable ? "string, bytes, os.PathLike or None" : - "string, bytes or os.PathLike", - _PyType_Name(Py_TYPE(o))); - goto error_exit; - } - - length = PyBytes_GET_SIZE(bytes); - narrow = PyBytes_AS_STRING(bytes); - if ((size_t)length != strlen(narrow)) { - FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); - goto error_exit; - } - -#ifdef MS_WINDOWS - wo = PyUnicode_DecodeFSDefaultAndSize( - narrow, - length - ); - if (!wo) { - goto error_exit; - } - - wide = PyUnicode_AsWideCharString(wo, &length); - Py_DECREF(wo); - if (!wide) { - goto error_exit; - } - if (length > 32767) { - FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); - goto error_exit; - } - if (wcslen(wide) != length) { - FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); - goto error_exit; - } - path->wide = wide; - path->narrow = TRUE; - Py_DECREF(bytes); - wide = NULL; -#else - path->wide = NULL; - path->narrow = narrow; - if (bytes == o) { - /* Still a reference owned by path->object, don't have to - worry about path->narrow is used after free. */ - Py_DECREF(bytes); - } - else { - path->cleanup = bytes; - } -#endif - path->fd = -1; - - success_exit: - path->length = length; - path->object = o; - return Py_CLEANUP_SUPPORTED; - - error_exit: - Py_XDECREF(o); - Py_XDECREF(bytes); -#ifdef MS_WINDOWS - PyMem_Free(wide); -#endif - return 0; -} - -static void -argument_unavailable_error(const char *function_name, const char *argument_name) -{ - PyErr_Format(PyExc_NotImplementedError, - "%s%s%s unavailable on this platform", - (function_name != NULL) ? function_name : "", - (function_name != NULL) ? ": ": "", - argument_name); -} - -static int -dir_fd_unavailable(PyObject *o, void *p) -{ - int dir_fd; - if (!dir_fd_converter(o, &dir_fd)) - return 0; - if (dir_fd != DEFAULT_DIR_FD) { - argument_unavailable_error(NULL, "dir_fd"); - return 0; - } - *(int *)p = dir_fd; - return 1; -} - -static int -fd_specified(const char *function_name, int fd) -{ - if (fd == -1) - return 0; - - argument_unavailable_error(function_name, "fd"); - return 1; -} - -static int -follow_symlinks_specified(const char *function_name, int follow_symlinks) -{ - if (follow_symlinks) - return 0; - - argument_unavailable_error(function_name, "follow_symlinks"); - return 1; -} - -static int -path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd) -{ - if (!path->wide && (dir_fd != DEFAULT_DIR_FD) -#ifndef MS_WINDOWS - && !path->narrow -#endif - ) { - PyErr_Format(PyExc_ValueError, - "%s: can't specify dir_fd without matching path", - function_name); - return 1; - } - return 0; -} - -static int -dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd) -{ - if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) { - PyErr_Format(PyExc_ValueError, - "%s: can't specify both dir_fd and fd", - function_name); - return 1; - } - return 0; -} - -static int -fd_and_follow_symlinks_invalid(const char *function_name, int fd, - int follow_symlinks) -{ - if ((fd > 0) && (!follow_symlinks)) { - PyErr_Format(PyExc_ValueError, - "%s: cannot use fd and follow_symlinks together", - function_name); - return 1; - } - return 0; -} - -static int -dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd, - int follow_symlinks) -{ - if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) { - PyErr_Format(PyExc_ValueError, - "%s: cannot use dir_fd and follow_symlinks together", - function_name); - return 1; - } - return 0; -} - -#ifdef MS_WINDOWS - typedef long long Py_off_t; -#else - typedef off_t Py_off_t; -#endif - -static int -Py_off_t_converter(PyObject *arg, void *addr) -{ -#ifdef HAVE_LARGEFILE_SUPPORT - *((Py_off_t *)addr) = PyLong_AsLongLong(arg); -#else - *((Py_off_t *)addr) = PyLong_AsLong(arg); -#endif - if (PyErr_Occurred()) - return 0; - return 1; -} - -static PyObject * -PyLong_FromPy_off_t(Py_off_t offset) -{ -#ifdef HAVE_LARGEFILE_SUPPORT - return PyLong_FromLongLong(offset); -#else - return PyLong_FromLong(offset); -#endif -} - -#ifdef HAVE_SIGSET_T -/* Convert an iterable of integers to a sigset. - Return 1 on success, return 0 and raise an exception on error. */ -int -_Py_Sigset_Converter(PyObject *obj, void *addr) -{ - sigset_t *mask = (sigset_t *)addr; - PyObject *iterator, *item; - long signum; - int overflow; - - // The extra parens suppress the unreachable-code warning with clang on MacOS - if (sigemptyset(mask) < (0)) { - /* Probably only if mask == NULL. */ - PyErr_SetFromErrno(PyExc_OSError); - return 0; - } - - iterator = PyObject_GetIter(obj); - if (iterator == NULL) { - return 0; - } - - while ((item = PyIter_Next(iterator)) != NULL) { - signum = PyLong_AsLongAndOverflow(item, &overflow); - Py_DECREF(item); - if (signum <= 0 || signum >= Py_NSIG) { - if (overflow || signum != -1 || !PyErr_Occurred()) { - PyErr_Format(PyExc_ValueError, - "signal number %ld out of range [1; %i]", - signum, Py_NSIG - 1); - } - goto error; - } - if (sigaddset(mask, (int)signum)) { - if (errno != EINVAL) { - /* Probably impossible */ - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - /* For backwards compatibility, allow idioms such as - * `range(1, NSIG)` but warn about invalid signal numbers - */ - const char msg[] = - "invalid signal number %ld, please use valid_signals()"; - if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) { - goto error; - } - } - } - if (!PyErr_Occurred()) { - Py_DECREF(iterator); - return 1; - } - -error: - Py_DECREF(iterator); - return 0; -} -#endif /* HAVE_SIGSET_T */ - -#ifdef MS_WINDOWS - -static int -win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag) -{ - char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; - _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer; - DWORD n_bytes_returned; - - if (0 == DeviceIoControl( - reparse_point_handle, - FSCTL_GET_REPARSE_POINT, - NULL, 0, /* in buffer */ - target_buffer, sizeof(target_buffer), - &n_bytes_returned, - NULL)) /* we're not using OVERLAPPED_IO */ - return FALSE; - - if (reparse_tag) - *reparse_tag = rdb->ReparseTag; - - return TRUE; -} - -#endif /* MS_WINDOWS */ - -/* Return a dictionary corresponding to the POSIX environment table */ -#if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED)) -/* On Darwin/MacOSX a shared library or framework has no access to -** environ directly, we must obtain it with _NSGetEnviron(). See also -** man environ(7). -*/ -#include -#elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__)) -extern char **environ; -#endif /* !_MSC_VER */ - -static PyObject * -convertenviron(void) -{ - PyObject *d; -#ifdef MS_WINDOWS - wchar_t **e; -#else - char **e; -#endif - - d = PyDict_New(); - if (d == NULL) - return NULL; -#ifdef MS_WINDOWS - /* _wenviron must be initialized in this way if the program is started - through main() instead of wmain(). */ - _wgetenv(L""); - e = _wenviron; -#elif defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED)) - /* environ is not accessible as an extern in a shared object on OSX; use - _NSGetEnviron to resolve it. The value changes if you add environment - variables between calls to Py_Initialize, so don't cache the value. */ - e = *_NSGetEnviron(); -#else - e = environ; -#endif - if (e == NULL) - return d; - for (; *e != NULL; e++) { - PyObject *k; - PyObject *v; -#ifdef MS_WINDOWS - const wchar_t *p = wcschr(*e, L'='); -#else - const char *p = strchr(*e, '='); -#endif - if (p == NULL) - continue; -#ifdef MS_WINDOWS - k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e)); -#else - k = PyBytes_FromStringAndSize(*e, (int)(p-*e)); -#endif - if (k == NULL) { - Py_DECREF(d); - return NULL; - } -#ifdef MS_WINDOWS - v = PyUnicode_FromWideChar(p+1, wcslen(p+1)); -#else - v = PyBytes_FromStringAndSize(p+1, strlen(p+1)); -#endif - if (v == NULL) { - Py_DECREF(k); - Py_DECREF(d); - return NULL; - } - if (PyDict_SetDefault(d, k, v) == NULL) { - Py_DECREF(v); - Py_DECREF(k); - Py_DECREF(d); - return NULL; - } - Py_DECREF(k); - Py_DECREF(v); - } - return d; -} - -/* Set a POSIX-specific error from errno, and return NULL */ - -static PyObject * -posix_error(void) -{ - return PyErr_SetFromErrno(PyExc_OSError); -} - -#ifdef MS_WINDOWS -static PyObject * -win32_error(const char* function, const char* filename) -{ - /* XXX We should pass the function name along in the future. - (winreg.c also wants to pass the function name.) - This would however require an additional param to the - Windows error object, which is non-trivial. - */ - errno = GetLastError(); - if (filename) - return PyErr_SetFromWindowsErrWithFilename(errno, filename); - else - return PyErr_SetFromWindowsErr(errno); -} - -static PyObject * -win32_error_object_err(const char* function, PyObject* filename, DWORD err) -{ - /* XXX - see win32_error for comments on 'function' */ - if (filename) - return PyErr_SetExcFromWindowsErrWithFilenameObject( - PyExc_OSError, - err, - filename); - else - return PyErr_SetFromWindowsErr(err); -} - -static PyObject * -win32_error_object(const char* function, PyObject* filename) -{ - errno = GetLastError(); - return win32_error_object_err(function, filename, errno); -} - -#endif /* MS_WINDOWS */ - -static PyObject * -posix_path_object_error(PyObject *path) -{ - return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path); -} - -static PyObject * -path_object_error(PyObject *path) -{ -#ifdef MS_WINDOWS - return PyErr_SetExcFromWindowsErrWithFilenameObject( - PyExc_OSError, 0, path); -#else - return posix_path_object_error(path); -#endif -} - -static PyObject * -path_object_error2(PyObject *path, PyObject *path2) -{ -#ifdef MS_WINDOWS - return PyErr_SetExcFromWindowsErrWithFilenameObjects( - PyExc_OSError, 0, path, path2); -#else - return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2); -#endif -} - -static PyObject * -path_error(path_t *path) -{ - return path_object_error(path->object); -} - -static PyObject * -posix_path_error(path_t *path) -{ - return posix_path_object_error(path->object); -} - -static PyObject * -path_error2(path_t *path, path_t *path2) -{ - return path_object_error2(path->object, path2->object); -} - - -/* POSIX generic methods */ - -static PyObject * -posix_fildes_fd(int fd, int (*func)(int)) -{ - int res; - int async_err = 0; - - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - res = (*func)(fd); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (res != 0) - return (!async_err) ? posix_error() : NULL; - Py_RETURN_NONE; -} - - -#ifdef MS_WINDOWS -/* This is a reimplementation of the C library's chdir function, - but one that produces Win32 errors instead of DOS error codes. - chdir is essentially a wrapper around SetCurrentDirectory; however, - it also needs to set "magic" environment variables indicating - the per-drive current directory, which are of the form =: */ -static BOOL __stdcall -win32_wchdir(LPCWSTR path) -{ - wchar_t path_buf[MAX_PATH], *new_path = path_buf; - int result; - wchar_t env[4] = L"=x:"; - - if(!SetCurrentDirectoryW(path)) - return FALSE; - result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path); - if (!result) - return FALSE; - if (result > Py_ARRAY_LENGTH(path_buf)) { - new_path = PyMem_RawMalloc(result * sizeof(wchar_t)); - if (!new_path) { - SetLastError(ERROR_OUTOFMEMORY); - return FALSE; - } - result = GetCurrentDirectoryW(result, new_path); - if (!result) { - PyMem_RawFree(new_path); - return FALSE; - } - } - int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 || - wcsncmp(new_path, L"//", 2) == 0); - if (!is_unc_like_path) { - env[1] = new_path[0]; - result = SetEnvironmentVariableW(env, new_path); - } - if (new_path != path_buf) - PyMem_RawFree(new_path); - return result ? TRUE : FALSE; -} -#endif - -#ifdef MS_WINDOWS -/* The CRT of Windows has a number of flaws wrt. its stat() implementation: - - time stamps are restricted to second resolution - - file modification times suffer from forth-and-back conversions between - UTC and local time - Therefore, we implement our own stat, based on the Win32 API directly. -*/ -#define HAVE_STAT_NSEC 1 -#define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1 -#define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1 - -static void -find_data_to_file_info(WIN32_FIND_DATAW *pFileData, - BY_HANDLE_FILE_INFORMATION *info, - ULONG *reparse_tag) -{ - memset(info, 0, sizeof(*info)); - info->dwFileAttributes = pFileData->dwFileAttributes; - info->ftCreationTime = pFileData->ftCreationTime; - info->ftLastAccessTime = pFileData->ftLastAccessTime; - info->ftLastWriteTime = pFileData->ftLastWriteTime; - info->nFileSizeHigh = pFileData->nFileSizeHigh; - info->nFileSizeLow = pFileData->nFileSizeLow; -/* info->nNumberOfLinks = 1; */ - if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) - *reparse_tag = pFileData->dwReserved0; - else - *reparse_tag = 0; -} - -static BOOL -attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag) -{ - HANDLE hFindFile; - WIN32_FIND_DATAW FileData; - LPCWSTR filename = pszFile; - size_t n = wcslen(pszFile); - if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) { - // cannot use PyMem_Malloc here because we do not hold the GIL - filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0])); - wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n); - while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) { - ((LPWSTR)filename)[n] = L'\0'; - } - if (!n || (n == 1 && filename[1] == L':')) { - // Nothing left to query - free((void *)filename); - return FALSE; - } - } - hFindFile = FindFirstFileW(filename, &FileData); - if (pszFile != filename) { - free((void *)filename); - } - if (hFindFile == INVALID_HANDLE_VALUE) { - return FALSE; - } - FindClose(hFindFile); - find_data_to_file_info(&FileData, info, reparse_tag); - return TRUE; -} - -static int -win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result, - BOOL traverse) -{ - HANDLE hFile; - BY_HANDLE_FILE_INFORMATION fileInfo; - FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 }; - DWORD fileType, error; - BOOL isUnhandledTag = FALSE; - int retval = 0; - - DWORD access = FILE_READ_ATTRIBUTES; - DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */ - if (!traverse) { - flags |= FILE_FLAG_OPEN_REPARSE_POINT; - } - - hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL); - if (hFile == INVALID_HANDLE_VALUE) { - /* Either the path doesn't exist, or the caller lacks access. */ - error = GetLastError(); - switch (error) { - case ERROR_ACCESS_DENIED: /* Cannot sync or read attributes. */ - case ERROR_SHARING_VIOLATION: /* It's a paging file. */ - /* Try reading the parent directory. */ - if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) { - /* Cannot read the parent directory. */ - switch (GetLastError()) { - case ERROR_FILE_NOT_FOUND: /* File cannot be found */ - case ERROR_PATH_NOT_FOUND: /* File parent directory cannot be found */ - case ERROR_NOT_READY: /* Drive exists but unavailable */ - case ERROR_BAD_NET_NAME: /* Remote drive unavailable */ - break; - /* Restore the error from CreateFileW(). */ - default: - SetLastError(error); - } - - return -1; - } - if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - if (traverse || - !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) { - /* The stat call has to traverse but cannot, so fail. */ - SetLastError(error); - return -1; - } - } - break; - - case ERROR_INVALID_PARAMETER: - /* \\.\con requires read or write access. */ - hFile = CreateFileW(path, access | GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, - OPEN_EXISTING, flags, NULL); - if (hFile == INVALID_HANDLE_VALUE) { - SetLastError(error); - return -1; - } - break; - - case ERROR_CANT_ACCESS_FILE: - /* bpo37834: open unhandled reparse points if traverse fails. */ - if (traverse) { - traverse = FALSE; - isUnhandledTag = TRUE; - hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, - flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL); - } - if (hFile == INVALID_HANDLE_VALUE) { - SetLastError(error); - return -1; - } - break; - - default: - return -1; - } - } - - if (hFile != INVALID_HANDLE_VALUE) { - /* Handle types other than files on disk. */ - fileType = GetFileType(hFile); - if (fileType != FILE_TYPE_DISK) { - if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) { - retval = -1; - goto cleanup; - } - DWORD fileAttributes = GetFileAttributesW(path); - memset(result, 0, sizeof(*result)); - if (fileAttributes != INVALID_FILE_ATTRIBUTES && - fileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - /* \\.\pipe\ or \\.\mailslot\ */ - result->st_mode = _S_IFDIR; - } else if (fileType == FILE_TYPE_CHAR) { - /* \\.\nul */ - result->st_mode = _S_IFCHR; - } else if (fileType == FILE_TYPE_PIPE) { - /* \\.\pipe\spam */ - result->st_mode = _S_IFIFO; - } - /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */ - goto cleanup; - } - - /* Query the reparse tag, and traverse a non-link. */ - if (!traverse) { - if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo, - &tagInfo, sizeof(tagInfo))) { - /* Allow devices that do not support FileAttributeTagInfo. */ - switch (GetLastError()) { - case ERROR_INVALID_PARAMETER: - case ERROR_INVALID_FUNCTION: - case ERROR_NOT_SUPPORTED: - tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL; - tagInfo.ReparseTag = 0; - break; - default: - retval = -1; - goto cleanup; - } - } else if (tagInfo.FileAttributes & - FILE_ATTRIBUTE_REPARSE_POINT) { - if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) { - if (isUnhandledTag) { - /* Traversing previously failed for either this link - or its target. */ - SetLastError(ERROR_CANT_ACCESS_FILE); - retval = -1; - goto cleanup; - } - /* Traverse a non-link, but not if traversing already failed - for an unhandled tag. */ - } else if (!isUnhandledTag) { - CloseHandle(hFile); - return win32_xstat_impl(path, result, TRUE); - } - } - } - - if (!GetFileInformationByHandle(hFile, &fileInfo)) { - switch (GetLastError()) { - case ERROR_INVALID_PARAMETER: - case ERROR_INVALID_FUNCTION: - case ERROR_NOT_SUPPORTED: - /* Volumes and physical disks are block devices, e.g. - \\.\C: and \\.\PhysicalDrive0. */ - memset(result, 0, sizeof(*result)); - result->st_mode = 0x6000; /* S_IFBLK */ - goto cleanup; - } - retval = -1; - goto cleanup; - } - } - - _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, result); - - if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { - /* Fix the file execute permissions. This hack sets S_IEXEC if - the filename has an extension that is commonly used by files - that CreateProcessW can execute. A real implementation calls - GetSecurityInfo, OpenThreadToken/OpenProcessToken, and - AccessCheck to check for generic read, write, and execute - access. */ - const wchar_t *fileExtension = wcsrchr(path, '.'); - if (fileExtension) { - if (_wcsicmp(fileExtension, L".exe") == 0 || - _wcsicmp(fileExtension, L".bat") == 0 || - _wcsicmp(fileExtension, L".cmd") == 0 || - _wcsicmp(fileExtension, L".com") == 0) { - result->st_mode |= 0111; - } - } - } - -cleanup: - if (hFile != INVALID_HANDLE_VALUE) { - /* Preserve last error if we are failing */ - error = retval ? GetLastError() : 0; - if (!CloseHandle(hFile)) { - retval = -1; - } else if (retval) { - /* Restore last error */ - SetLastError(error); - } - } - - return retval; -} - -static int -win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse) -{ - /* Protocol violation: we explicitly clear errno, instead of - setting it to a POSIX error. Callers should use GetLastError. */ - int code = win32_xstat_impl(path, result, traverse); - errno = 0; - return code; -} -/* About the following functions: win32_lstat_w, win32_stat, win32_stat_w - - In Posix, stat automatically traverses symlinks and returns the stat - structure for the target. In Windows, the equivalent GetFileAttributes by - default does not traverse symlinks and instead returns attributes for - the symlink. - - Instead, we will open the file (which *does* traverse symlinks by default) - and GetFileInformationByHandle(). */ - -static int -win32_lstat(const wchar_t* path, struct _Py_stat_struct *result) -{ - return win32_xstat(path, result, FALSE); -} - -static int -win32_stat(const wchar_t* path, struct _Py_stat_struct *result) -{ - return win32_xstat(path, result, TRUE); -} - -#endif /* MS_WINDOWS */ - -PyDoc_STRVAR(stat_result__doc__, -"stat_result: Result from stat, fstat, or lstat.\n\n\ -This object may be accessed either as a tuple of\n\ - (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\ -or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\ -\n\ -Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\ -or st_flags, they are available as attributes only.\n\ -\n\ -See os.stat for more information."); - -static PyStructSequence_Field stat_result_fields[] = { - {"st_mode", "protection bits"}, - {"st_ino", "inode"}, - {"st_dev", "device"}, - {"st_nlink", "number of hard links"}, - {"st_uid", "user ID of owner"}, - {"st_gid", "group ID of owner"}, - {"st_size", "total size, in bytes"}, - /* The NULL is replaced with PyStructSequence_UnnamedField later. */ - {NULL, "integer time of last access"}, - {NULL, "integer time of last modification"}, - {NULL, "integer time of last change"}, - {"st_atime", "time of last access"}, - {"st_mtime", "time of last modification"}, - {"st_ctime", "time of last change"}, - {"st_atime_ns", "time of last access in nanoseconds"}, - {"st_mtime_ns", "time of last modification in nanoseconds"}, - {"st_ctime_ns", "time of last change in nanoseconds"}, -#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE - {"st_blksize", "blocksize for filesystem I/O"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_BLOCKS - {"st_blocks", "number of blocks allocated"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_RDEV - {"st_rdev", "device type (if inode device)"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_FLAGS - {"st_flags", "user defined flags for file"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_GEN - {"st_gen", "generation number"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME - {"st_birthtime", "time of creation"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES - {"st_file_attributes", "Windows file attribute bits"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_FSTYPE - {"st_fstype", "Type of filesystem"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG - {"st_reparse_tag", "Windows reparse tag"}, -#endif - {0} -}; - -#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE -#define ST_BLKSIZE_IDX 16 -#else -#define ST_BLKSIZE_IDX 15 -#endif - -#ifdef HAVE_STRUCT_STAT_ST_BLOCKS -#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1) -#else -#define ST_BLOCKS_IDX ST_BLKSIZE_IDX -#endif - -#ifdef HAVE_STRUCT_STAT_ST_RDEV -#define ST_RDEV_IDX (ST_BLOCKS_IDX+1) -#else -#define ST_RDEV_IDX ST_BLOCKS_IDX -#endif - -#ifdef HAVE_STRUCT_STAT_ST_FLAGS -#define ST_FLAGS_IDX (ST_RDEV_IDX+1) -#else -#define ST_FLAGS_IDX ST_RDEV_IDX -#endif - -#ifdef HAVE_STRUCT_STAT_ST_GEN -#define ST_GEN_IDX (ST_FLAGS_IDX+1) -#else -#define ST_GEN_IDX ST_FLAGS_IDX -#endif - -#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME -#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1) -#else -#define ST_BIRTHTIME_IDX ST_GEN_IDX -#endif - -#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES -#define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1) -#else -#define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX -#endif - -#ifdef HAVE_STRUCT_STAT_ST_FSTYPE -#define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1) -#else -#define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX -#endif - -#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG -#define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1) -#else -#define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX -#endif - -static PyStructSequence_Desc stat_result_desc = { - "stat_result", /* name */ - stat_result__doc__, /* doc */ - stat_result_fields, - 10 -}; - -PyDoc_STRVAR(statvfs_result__doc__, -"statvfs_result: Result from statvfs or fstatvfs.\n\n\ -This object may be accessed either as a tuple of\n\ - (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\ -or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\ -\n\ -See os.statvfs for more information."); - -static PyStructSequence_Field statvfs_result_fields[] = { - {"f_bsize", }, - {"f_frsize", }, - {"f_blocks", }, - {"f_bfree", }, - {"f_bavail", }, - {"f_files", }, - {"f_ffree", }, - {"f_favail", }, - {"f_flag", }, - {"f_namemax",}, - {"f_fsid", }, - {0} -}; - -static PyStructSequence_Desc statvfs_result_desc = { - "statvfs_result", /* name */ - statvfs_result__doc__, /* doc */ - statvfs_result_fields, - 10 -}; - -#if defined(HAVE_WAITID) && !defined(__APPLE__) -PyDoc_STRVAR(waitid_result__doc__, -"waitid_result: Result from waitid.\n\n\ -This object may be accessed either as a tuple of\n\ - (si_pid, si_uid, si_signo, si_status, si_code),\n\ -or via the attributes si_pid, si_uid, and so on.\n\ -\n\ -See os.waitid for more information."); - -static PyStructSequence_Field waitid_result_fields[] = { - {"si_pid", }, - {"si_uid", }, - {"si_signo", }, - {"si_status", }, - {"si_code", }, - {0} -}; - -static PyStructSequence_Desc waitid_result_desc = { - "waitid_result", /* name */ - waitid_result__doc__, /* doc */ - waitid_result_fields, - 5 -}; -#endif -static newfunc structseq_new; - -static PyObject * -statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyStructSequence *result; - int i; - - result = (PyStructSequence*)structseq_new(type, args, kwds); - if (!result) - return NULL; - /* If we have been initialized from a tuple, - st_?time might be set to None. Initialize it - from the int slots. */ - for (i = 7; i <= 9; i++) { - if (result->ob_item[i+3] == Py_None) { - Py_DECREF(Py_None); - result->ob_item[i+3] = Py_NewRef(result->ob_item[i]); - } - } - return (PyObject*)result; -} - -static int -_posix_clear(PyObject *module) -{ - _posixstate *state = get_posix_state(module); - Py_CLEAR(state->billion); - Py_CLEAR(state->DirEntryType); - Py_CLEAR(state->ScandirIteratorType); -#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) - Py_CLEAR(state->SchedParamType); -#endif - Py_CLEAR(state->StatResultType); - Py_CLEAR(state->StatVFSResultType); - Py_CLEAR(state->TerminalSizeType); - Py_CLEAR(state->TimesResultType); - Py_CLEAR(state->UnameResultType); -#if defined(HAVE_WAITID) && !defined(__APPLE__) - Py_CLEAR(state->WaitidResultType); -#endif -#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) - Py_CLEAR(state->struct_rusage); -#endif - Py_CLEAR(state->st_mode); - return 0; -} - -static int -_posix_traverse(PyObject *module, visitproc visit, void *arg) -{ - _posixstate *state = get_posix_state(module); - Py_VISIT(state->billion); - Py_VISIT(state->DirEntryType); - Py_VISIT(state->ScandirIteratorType); -#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) - Py_VISIT(state->SchedParamType); -#endif - Py_VISIT(state->StatResultType); - Py_VISIT(state->StatVFSResultType); - Py_VISIT(state->TerminalSizeType); - Py_VISIT(state->TimesResultType); - Py_VISIT(state->UnameResultType); -#if defined(HAVE_WAITID) && !defined(__APPLE__) - Py_VISIT(state->WaitidResultType); -#endif -#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) - Py_VISIT(state->struct_rusage); -#endif - Py_VISIT(state->st_mode); - return 0; -} - -static void -_posix_free(void *module) -{ - _posix_clear((PyObject *)module); -} - -static void -fill_time(PyObject *module, PyObject *v, int index, time_t sec, unsigned long nsec) -{ - PyObject *s = _PyLong_FromTime_t(sec); - PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec); - PyObject *s_in_ns = NULL; - PyObject *ns_total = NULL; - PyObject *float_s = NULL; - - if (!(s && ns_fractional)) - goto exit; - - s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion); - if (!s_in_ns) - goto exit; - - ns_total = PyNumber_Add(s_in_ns, ns_fractional); - if (!ns_total) - goto exit; - - float_s = PyFloat_FromDouble(sec + 1e-9*nsec); - if (!float_s) { - goto exit; - } - - PyStructSequence_SET_ITEM(v, index, s); - PyStructSequence_SET_ITEM(v, index+3, float_s); - PyStructSequence_SET_ITEM(v, index+6, ns_total); - s = NULL; - float_s = NULL; - ns_total = NULL; -exit: - Py_XDECREF(s); - Py_XDECREF(ns_fractional); - Py_XDECREF(s_in_ns); - Py_XDECREF(ns_total); - Py_XDECREF(float_s); -} - -/* pack a system stat C structure into the Python stat tuple - (used by posix_stat() and posix_fstat()) */ -static PyObject* -_pystat_fromstructstat(PyObject *module, STRUCT_STAT *st) -{ - unsigned long ansec, mnsec, cnsec; - PyObject *StatResultType = get_posix_state(module)->StatResultType; - PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType); - if (v == NULL) - return NULL; - - PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode)); - static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino), - "stat.st_ino is larger than unsigned long long"); - PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLongLong(st->st_ino)); -#ifdef MS_WINDOWS - PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev)); -#else - PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev)); -#endif - PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink)); -#if defined(MS_WINDOWS) - PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0)); - PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0)); -#else - PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid)); - PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid)); -#endif - static_assert(sizeof(long long) >= sizeof(st->st_size), - "stat.st_size is larger than long long"); - PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size)); - -#if defined(HAVE_STAT_TV_NSEC) - ansec = st->st_atim.tv_nsec; - mnsec = st->st_mtim.tv_nsec; - cnsec = st->st_ctim.tv_nsec; -#elif defined(HAVE_STAT_TV_NSEC2) - ansec = st->st_atimespec.tv_nsec; - mnsec = st->st_mtimespec.tv_nsec; - cnsec = st->st_ctimespec.tv_nsec; -#elif defined(HAVE_STAT_NSEC) - ansec = st->st_atime_nsec; - mnsec = st->st_mtime_nsec; - cnsec = st->st_ctime_nsec; -#else - ansec = mnsec = cnsec = 0; -#endif - fill_time(module, v, 7, st->st_atime, ansec); - fill_time(module, v, 8, st->st_mtime, mnsec); - fill_time(module, v, 9, st->st_ctime, cnsec); - -#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE - PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX, - PyLong_FromLong((long)st->st_blksize)); -#endif -#ifdef HAVE_STRUCT_STAT_ST_BLOCKS - PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX, - PyLong_FromLong((long)st->st_blocks)); -#endif -#ifdef HAVE_STRUCT_STAT_ST_RDEV - PyStructSequence_SET_ITEM(v, ST_RDEV_IDX, - PyLong_FromLong((long)st->st_rdev)); -#endif -#ifdef HAVE_STRUCT_STAT_ST_GEN - PyStructSequence_SET_ITEM(v, ST_GEN_IDX, - PyLong_FromLong((long)st->st_gen)); -#endif -#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME - { - PyObject *val; - unsigned long bsec,bnsec; - bsec = (long)st->st_birthtime; -#ifdef HAVE_STAT_TV_NSEC2 - bnsec = st->st_birthtimespec.tv_nsec; -#else - bnsec = 0; -#endif - val = PyFloat_FromDouble(bsec + 1e-9*bnsec); - PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX, - val); - } -#endif -#ifdef HAVE_STRUCT_STAT_ST_FLAGS - PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX, - PyLong_FromLong((long)st->st_flags)); -#endif -#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES - PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX, - PyLong_FromUnsignedLong(st->st_file_attributes)); -#endif -#ifdef HAVE_STRUCT_STAT_ST_FSTYPE - PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX, - PyUnicode_FromString(st->st_fstype)); -#endif -#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG - PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX, - PyLong_FromUnsignedLong(st->st_reparse_tag)); -#endif - - if (PyErr_Occurred()) { - Py_DECREF(v); - return NULL; - } - - return v; -} - -/* POSIX methods */ - - -static PyObject * -posix_do_stat(PyObject *module, const char *function_name, path_t *path, - int dir_fd, int follow_symlinks) -{ - STRUCT_STAT st; - int result; - -#ifdef HAVE_FSTATAT - int fstatat_unavailable = 0; -#endif - -#if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT) - if (follow_symlinks_specified(function_name, follow_symlinks)) - return NULL; -#endif - - if (path_and_dir_fd_invalid("stat", path, dir_fd) || - dir_fd_and_fd_invalid("stat", dir_fd, path->fd) || - fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - if (path->fd != -1) - result = FSTAT(path->fd, &st); -#ifdef MS_WINDOWS - else if (follow_symlinks) - result = win32_stat(path->wide, &st); - else - result = win32_lstat(path->wide, &st); -#else - else -#if defined(HAVE_LSTAT) - if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) - result = LSTAT(path->narrow, &st); - else -#endif /* HAVE_LSTAT */ -#ifdef HAVE_FSTATAT - if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) { - if (HAVE_FSTATAT_RUNTIME) { - result = fstatat(dir_fd, path->narrow, &st, - follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); - - } else { - fstatat_unavailable = 1; - } - } else -#endif /* HAVE_FSTATAT */ - result = STAT(path->narrow, &st); -#endif /* MS_WINDOWS */ - Py_END_ALLOW_THREADS - -#ifdef HAVE_FSTATAT - if (fstatat_unavailable) { - argument_unavailable_error("stat", "dir_fd"); - return NULL; - } -#endif - - if (result != 0) { - return path_error(path); - } - - return _pystat_fromstructstat(module, &st); -} - -/*[python input] - -for s in """ - -FACCESSAT -FCHMODAT -FCHOWNAT -FSTATAT -LINKAT -MKDIRAT -MKFIFOAT -MKNODAT -OPENAT -READLINKAT -SYMLINKAT -UNLINKAT - -""".strip().split(): - s = s.strip() - print(""" -#ifdef HAVE_{s} - #define {s}_DIR_FD_CONVERTER dir_fd_converter -#else - #define {s}_DIR_FD_CONVERTER dir_fd_unavailable -#endif -""".rstrip().format(s=s)) - -for s in """ - -FCHDIR -FCHMOD -FCHOWN -FDOPENDIR -FEXECVE -FPATHCONF -FSTATVFS -FTRUNCATE - -""".strip().split(): - s = s.strip() - print(""" -#ifdef HAVE_{s} - #define PATH_HAVE_{s} 1 -#else - #define PATH_HAVE_{s} 0 -#endif - -""".rstrip().format(s=s)) -[python start generated code]*/ - -#ifdef HAVE_FACCESSAT - #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_FCHMODAT - #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_FCHOWNAT - #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_FSTATAT - #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_LINKAT - #define LINKAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_MKDIRAT - #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_MKFIFOAT - #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_MKNODAT - #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_OPENAT - #define OPENAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_READLINKAT - #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_SYMLINKAT - #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_UNLINKAT - #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_FCHDIR - #define PATH_HAVE_FCHDIR 1 -#else - #define PATH_HAVE_FCHDIR 0 -#endif - -#ifdef HAVE_FCHMOD - #define PATH_HAVE_FCHMOD 1 -#else - #define PATH_HAVE_FCHMOD 0 -#endif - -#ifdef HAVE_FCHOWN - #define PATH_HAVE_FCHOWN 1 -#else - #define PATH_HAVE_FCHOWN 0 -#endif - -#ifdef HAVE_FDOPENDIR - #define PATH_HAVE_FDOPENDIR 1 -#else - #define PATH_HAVE_FDOPENDIR 0 -#endif - -#ifdef HAVE_FEXECVE - #define PATH_HAVE_FEXECVE 1 -#else - #define PATH_HAVE_FEXECVE 0 -#endif - -#ifdef HAVE_FPATHCONF - #define PATH_HAVE_FPATHCONF 1 -#else - #define PATH_HAVE_FPATHCONF 0 -#endif - -#ifdef HAVE_FSTATVFS - #define PATH_HAVE_FSTATVFS 1 -#else - #define PATH_HAVE_FSTATVFS 0 -#endif - -#ifdef HAVE_FTRUNCATE - #define PATH_HAVE_FTRUNCATE 1 -#else - #define PATH_HAVE_FTRUNCATE 0 -#endif -/*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/ - -#ifdef MS_WINDOWS - #undef PATH_HAVE_FTRUNCATE - #define PATH_HAVE_FTRUNCATE 1 -#endif - -/*[python input] - -class path_t_converter(CConverter): - - type = "path_t" - impl_by_reference = True - parse_by_reference = True - - converter = 'path_converter' - - def converter_init(self, *, allow_fd=False, nullable=False): - # right now path_t doesn't support default values. - # to support a default value, you'll need to override initialize(). - if self.default not in (unspecified, None): - fail("Can't specify a default to the path_t converter!") - - if self.c_default not in (None, 'Py_None'): - raise RuntimeError("Can't specify a c_default to the path_t converter!") - - self.nullable = nullable - self.allow_fd = allow_fd - - def pre_render(self): - def strify(value): - if isinstance(value, str): - return value - return str(int(bool(value))) - - # add self.py_name here when merging with posixmodule conversion - self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format( - self.function.name, - self.name, - strify(self.nullable), - strify(self.allow_fd), - ) - - def cleanup(self): - return "path_cleanup(&" + self.name + ");\n" - - -class dir_fd_converter(CConverter): - type = 'int' - - def converter_init(self, requires=None): - if self.default in (unspecified, None): - self.c_default = 'DEFAULT_DIR_FD' - if isinstance(requires, str): - self.converter = requires.upper() + '_DIR_FD_CONVERTER' - else: - self.converter = 'dir_fd_converter' - -class uid_t_converter(CConverter): - type = "uid_t" - converter = '_Py_Uid_Converter' - -class gid_t_converter(CConverter): - type = "gid_t" - converter = '_Py_Gid_Converter' - -class dev_t_converter(CConverter): - type = 'dev_t' - converter = '_Py_Dev_Converter' - -class dev_t_return_converter(unsigned_long_return_converter): - type = 'dev_t' - conversion_fn = '_PyLong_FromDev' - unsigned_cast = '(dev_t)' - -class FSConverter_converter(CConverter): - type = 'PyObject *' - converter = 'PyUnicode_FSConverter' - def converter_init(self): - if self.default is not unspecified: - fail("FSConverter_converter does not support default values") - self.c_default = 'NULL' - - def cleanup(self): - return "Py_XDECREF(" + self.name + ");\n" - -class pid_t_converter(CConverter): - type = 'pid_t' - format_unit = '" _Py_PARSE_PID "' - -class idtype_t_converter(int_converter): - type = 'idtype_t' - -class id_t_converter(CConverter): - type = 'id_t' - format_unit = '" _Py_PARSE_PID "' - -class intptr_t_converter(CConverter): - type = 'intptr_t' - format_unit = '" _Py_PARSE_INTPTR "' - -class Py_off_t_converter(CConverter): - type = 'Py_off_t' - converter = 'Py_off_t_converter' - -class Py_off_t_return_converter(long_return_converter): - type = 'Py_off_t' - conversion_fn = 'PyLong_FromPy_off_t' - -class path_confname_converter(CConverter): - type="int" - converter="conv_path_confname" - -class confstr_confname_converter(path_confname_converter): - converter='conv_confstr_confname' - -class sysconf_confname_converter(path_confname_converter): - converter="conv_sysconf_confname" - -[python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=3338733161aa7879]*/ - -/*[clinic input] - -os.stat - - path : path_t(allow_fd=True) - Path to be examined; can be string, bytes, a path-like object or - open-file-descriptor int. - - * - - dir_fd : dir_fd(requires='fstatat') = None - If not None, it should be a file descriptor open to a directory, - and path should be a relative string; path will then be relative to - that directory. - - follow_symlinks: bool = True - If False, and the last element of the path is a symbolic link, - stat will examine the symbolic link itself instead of the file - the link points to. - -Perform a stat system call on the given path. - -dir_fd and follow_symlinks may not be implemented - on your platform. If they are unavailable, using them will raise a - NotImplementedError. - -It's an error to use dir_fd or follow_symlinks when specifying path as - an open file descriptor. - -[clinic start generated code]*/ - -static PyObject * -os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks) -/*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/ -{ - return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks); -} - - -/*[clinic input] -os.lstat - - path : path_t - - * - - dir_fd : dir_fd(requires='fstatat') = None - -Perform a stat system call on the given path, without following symbolic links. - -Like stat(), but do not follow symbolic links. -Equivalent to stat(path, follow_symlinks=False). -[clinic start generated code]*/ - -static PyObject * -os_lstat_impl(PyObject *module, path_t *path, int dir_fd) -/*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/ -{ - int follow_symlinks = 0; - return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks); -} - - -/*[clinic input] -os.access -> bool - - path: path_t - Path to be tested; can be string, bytes, or a path-like object. - - mode: int - Operating-system mode bitfield. Can be F_OK to test existence, - or the inclusive-OR of R_OK, W_OK, and X_OK. - - * - - dir_fd : dir_fd(requires='faccessat') = None - If not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that - directory. - - effective_ids: bool = False - If True, access will use the effective uid/gid instead of - the real uid/gid. - - follow_symlinks: bool = True - If False, and the last element of the path is a symbolic link, - access will examine the symbolic link itself instead of the file - the link points to. - -Use the real uid/gid to test for access to a path. - -{parameters} -dir_fd, effective_ids, and follow_symlinks may not be implemented - on your platform. If they are unavailable, using them will raise a - NotImplementedError. - -Note that most operations will use the effective uid/gid, therefore this - routine can be used in a suid/sgid environment to test if the invoking user - has the specified access to the path. - -[clinic start generated code]*/ - -static int -os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd, - int effective_ids, int follow_symlinks) -/*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/ -{ - int return_value; - -#ifdef MS_WINDOWS - DWORD attr; -#else - int result; -#endif - -#ifdef HAVE_FACCESSAT - int faccessat_unavailable = 0; -#endif - -#ifndef HAVE_FACCESSAT - if (follow_symlinks_specified("access", follow_symlinks)) - return -1; - - if (effective_ids) { - argument_unavailable_error("access", "effective_ids"); - return -1; - } -#endif - -#ifdef MS_WINDOWS - Py_BEGIN_ALLOW_THREADS - attr = GetFileAttributesW(path->wide); - Py_END_ALLOW_THREADS - - /* - * Access is possible if - * * we didn't get a -1, and - * * write access wasn't requested, - * * or the file isn't read-only, - * * or it's a directory. - * (Directories cannot be read-only on Windows.) - */ - return_value = (attr != INVALID_FILE_ATTRIBUTES) && - (!(mode & 2) || - !(attr & FILE_ATTRIBUTE_READONLY) || - (attr & FILE_ATTRIBUTE_DIRECTORY)); -#else - - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_FACCESSAT - if ((dir_fd != DEFAULT_DIR_FD) || - effective_ids || - !follow_symlinks) { - - if (HAVE_FACCESSAT_RUNTIME) { - int flags = 0; - if (!follow_symlinks) - flags |= AT_SYMLINK_NOFOLLOW; - if (effective_ids) - flags |= AT_EACCESS; - result = faccessat(dir_fd, path->narrow, mode, flags); - } else { - faccessat_unavailable = 1; - } - } - else -#endif - result = access(path->narrow, mode); - Py_END_ALLOW_THREADS - -#ifdef HAVE_FACCESSAT - if (faccessat_unavailable) { - if (dir_fd != DEFAULT_DIR_FD) { - argument_unavailable_error("access", "dir_fd"); - return -1; - } - if (follow_symlinks_specified("access", follow_symlinks)) - return -1; - - if (effective_ids) { - argument_unavailable_error("access", "effective_ids"); - return -1; - } - /* should be unreachable */ - return -1; - } -#endif - return_value = !result; -#endif - - return return_value; -} - -#ifndef F_OK -#define F_OK 0 -#endif -#ifndef R_OK -#define R_OK 4 -#endif -#ifndef W_OK -#define W_OK 2 -#endif -#ifndef X_OK -#define X_OK 1 -#endif - - -#ifdef HAVE_TTYNAME -/*[clinic input] -os.ttyname - - fd: int - Integer file descriptor handle. - - / - -Return the name of the terminal device connected to 'fd'. -[clinic start generated code]*/ - -static PyObject * -os_ttyname_impl(PyObject *module, int fd) -/*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/ -{ - - long size = sysconf(_SC_TTY_NAME_MAX); - if (size == -1) { - return posix_error(); - } - char *buffer = (char *)PyMem_RawMalloc(size); - if (buffer == NULL) { - return PyErr_NoMemory(); - } - int ret = ttyname_r(fd, buffer, size); - if (ret != 0) { - PyMem_RawFree(buffer); - errno = ret; - return posix_error(); - } - PyObject *res = PyUnicode_DecodeFSDefault(buffer); - PyMem_RawFree(buffer); - return res; -} -#endif - -#ifdef HAVE_CTERMID -/*[clinic input] -os.ctermid - -Return the name of the controlling terminal for this process. -[clinic start generated code]*/ - -static PyObject * -os_ctermid_impl(PyObject *module) -/*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/ -{ - char *ret; - char buffer[L_ctermid]; - -#ifdef USE_CTERMID_R - ret = ctermid_r(buffer); -#else - ret = ctermid(buffer); -#endif - if (ret == NULL) - return posix_error(); - return PyUnicode_DecodeFSDefault(buffer); -} -#endif /* HAVE_CTERMID */ - - -/*[clinic input] -os.chdir - - path: path_t(allow_fd='PATH_HAVE_FCHDIR') - -Change the current working directory to the specified path. - -path may always be specified as a string. -On some platforms, path may also be specified as an open file descriptor. - If this functionality is unavailable, using it raises an exception. -[clinic start generated code]*/ - -static PyObject * -os_chdir_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/ -{ - int result; - - if (PySys_Audit("os.chdir", "(O)", path->object) < 0) { - return NULL; - } - - Py_BEGIN_ALLOW_THREADS -#ifdef MS_WINDOWS - /* on unix, success = 0, on windows, success = !0 */ - result = !win32_wchdir(path->wide); -#else -#ifdef HAVE_FCHDIR - if (path->fd != -1) - result = fchdir(path->fd); - else -#endif - result = chdir(path->narrow); -#endif - Py_END_ALLOW_THREADS - - if (result) { - return path_error(path); - } - - Py_RETURN_NONE; -} - - -#ifdef HAVE_FCHDIR -/*[clinic input] -os.fchdir - - fd: fildes - -Change to the directory of the given file descriptor. - -fd must be opened on a directory, not a file. -Equivalent to os.chdir(fd). - -[clinic start generated code]*/ - -static PyObject * -os_fchdir_impl(PyObject *module, int fd) -/*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/ -{ - if (PySys_Audit("os.chdir", "(i)", fd) < 0) { - return NULL; - } - return posix_fildes_fd(fd, fchdir); -} -#endif /* HAVE_FCHDIR */ - - -/*[clinic input] -os.chmod - - path: path_t(allow_fd='PATH_HAVE_FCHMOD') - Path to be modified. May always be specified as a str, bytes, or a path-like object. - On some platforms, path may also be specified as an open file descriptor. - If this functionality is unavailable, using it raises an exception. - - mode: int - Operating-system mode bitfield. - - * - - dir_fd : dir_fd(requires='fchmodat') = None - If not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that - directory. - - follow_symlinks: bool = True - If False, and the last element of the path is a symbolic link, - chmod will modify the symbolic link itself instead of the file - the link points to. - -Change the access permissions of a file. - -It is an error to use dir_fd or follow_symlinks when specifying path as - an open file descriptor. -dir_fd and follow_symlinks may not be implemented on your platform. - If they are unavailable, using them will raise a NotImplementedError. - -[clinic start generated code]*/ - -static PyObject * -os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, - int follow_symlinks) -/*[clinic end generated code: output=5cf6a94915cc7bff input=989081551c00293b]*/ -{ - int result; - -#ifdef MS_WINDOWS - DWORD attr; -#endif - -#ifdef HAVE_FCHMODAT - int fchmodat_nofollow_unsupported = 0; - int fchmodat_unsupported = 0; -#endif - -#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD)) - if (follow_symlinks_specified("chmod", follow_symlinks)) - return NULL; -#endif - - if (PySys_Audit("os.chmod", "Oii", path->object, mode, - dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { - return NULL; - } - -#ifdef MS_WINDOWS - Py_BEGIN_ALLOW_THREADS - attr = GetFileAttributesW(path->wide); - if (attr == INVALID_FILE_ATTRIBUTES) - result = 0; - else { - if (mode & _S_IWRITE) - attr &= ~FILE_ATTRIBUTE_READONLY; - else - attr |= FILE_ATTRIBUTE_READONLY; - result = SetFileAttributesW(path->wide, attr); - } - Py_END_ALLOW_THREADS - - if (!result) { - return path_error(path); - } -#else /* MS_WINDOWS */ - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_FCHMOD - if (path->fd != -1) - result = fchmod(path->fd, mode); - else -#endif /* HAVE_CHMOD */ -#ifdef HAVE_LCHMOD - if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) - result = lchmod(path->narrow, mode); - else -#endif /* HAVE_LCHMOD */ -#ifdef HAVE_FCHMODAT - if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) { - if (HAVE_FCHMODAT_RUNTIME) { - /* - * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW! - * The documentation specifically shows how to use it, - * and then says it isn't implemented yet. - * (true on linux with glibc 2.15, and openindiana 3.x) - * - * Once it is supported, os.chmod will automatically - * support dir_fd and follow_symlinks=False. (Hopefully.) - * Until then, we need to be careful what exception we raise. - */ - result = fchmodat(dir_fd, path->narrow, mode, - follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); - /* - * But wait! We can't throw the exception without allowing threads, - * and we can't do that in this nested scope. (Macro trickery, sigh.) - */ - fchmodat_nofollow_unsupported = - result && - ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) && - !follow_symlinks; - } else { - fchmodat_unsupported = 1; - fchmodat_nofollow_unsupported = 1; - - result = -1; - } - } - else -#endif /* HAVE_FHCMODAT */ - { -#ifdef HAVE_CHMOD - result = chmod(path->narrow, mode); -#elif defined(__wasi__) - // WASI SDK 15.0 does not support chmod. - // Ignore missing syscall for now. - result = 0; -#else - result = -1; - errno = ENOSYS; -#endif - } - Py_END_ALLOW_THREADS - - if (result) { -#ifdef HAVE_FCHMODAT - if (fchmodat_unsupported) { - if (dir_fd != DEFAULT_DIR_FD) { - argument_unavailable_error("chmod", "dir_fd"); - return NULL; - } - } - - if (fchmodat_nofollow_unsupported) { - if (dir_fd != DEFAULT_DIR_FD) - dir_fd_and_follow_symlinks_invalid("chmod", - dir_fd, follow_symlinks); - else - follow_symlinks_specified("chmod", follow_symlinks); - return NULL; - } - else -#endif /* HAVE_FCHMODAT */ - return path_error(path); - } -#endif /* MS_WINDOWS */ - - Py_RETURN_NONE; -} - - -#ifdef HAVE_FCHMOD -/*[clinic input] -os.fchmod - - fd: int - mode: int - -Change the access permissions of the file given by file descriptor fd. - -Equivalent to os.chmod(fd, mode). -[clinic start generated code]*/ - -static PyObject * -os_fchmod_impl(PyObject *module, int fd, int mode) -/*[clinic end generated code: output=afd9bc05b4e426b3 input=8ab11975ca01ee5b]*/ -{ - int res; - int async_err = 0; - - if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) { - return NULL; - } - - do { - Py_BEGIN_ALLOW_THREADS - res = fchmod(fd, mode); - Py_END_ALLOW_THREADS - } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (res != 0) - return (!async_err) ? posix_error() : NULL; - - Py_RETURN_NONE; -} -#endif /* HAVE_FCHMOD */ - - -#ifdef HAVE_LCHMOD -/*[clinic input] -os.lchmod - - path: path_t - mode: int - -Change the access permissions of a file, without following symbolic links. - -If path is a symlink, this affects the link itself rather than the target. -Equivalent to chmod(path, mode, follow_symlinks=False)." -[clinic start generated code]*/ - -static PyObject * -os_lchmod_impl(PyObject *module, path_t *path, int mode) -/*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/ -{ - int res; - if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) { - return NULL; - } - Py_BEGIN_ALLOW_THREADS - res = lchmod(path->narrow, mode); - Py_END_ALLOW_THREADS - if (res < 0) { - path_error(path); - return NULL; - } - Py_RETURN_NONE; -} -#endif /* HAVE_LCHMOD */ - - -#ifdef HAVE_CHFLAGS -/*[clinic input] -os.chflags - - path: path_t - flags: unsigned_long(bitwise=True) - follow_symlinks: bool=True - -Set file flags. - -If follow_symlinks is False, and the last element of the path is a symbolic - link, chflags will change flags on the symbolic link itself instead of the - file the link points to. -follow_symlinks may not be implemented on your platform. If it is -unavailable, using it will raise a NotImplementedError. - -[clinic start generated code]*/ - -static PyObject * -os_chflags_impl(PyObject *module, path_t *path, unsigned long flags, - int follow_symlinks) -/*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/ -{ - int result; - -#ifndef HAVE_LCHFLAGS - if (follow_symlinks_specified("chflags", follow_symlinks)) - return NULL; -#endif - - if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) { - return NULL; - } - - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_LCHFLAGS - if (!follow_symlinks) - result = lchflags(path->narrow, flags); - else -#endif - result = chflags(path->narrow, flags); - Py_END_ALLOW_THREADS - - if (result) - return path_error(path); - - Py_RETURN_NONE; -} -#endif /* HAVE_CHFLAGS */ - - -#ifdef HAVE_LCHFLAGS -/*[clinic input] -os.lchflags - - path: path_t - flags: unsigned_long(bitwise=True) - -Set file flags. - -This function will not follow symbolic links. -Equivalent to chflags(path, flags, follow_symlinks=False). -[clinic start generated code]*/ - -static PyObject * -os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags) -/*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/ -{ - int res; - if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) { - return NULL; - } - Py_BEGIN_ALLOW_THREADS - res = lchflags(path->narrow, flags); - Py_END_ALLOW_THREADS - if (res < 0) { - return path_error(path); - } - Py_RETURN_NONE; -} -#endif /* HAVE_LCHFLAGS */ - - -#ifdef HAVE_CHROOT -/*[clinic input] -os.chroot - path: path_t - -Change root directory to path. - -[clinic start generated code]*/ - -static PyObject * -os_chroot_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/ -{ - int res; - Py_BEGIN_ALLOW_THREADS - res = chroot(path->narrow); - Py_END_ALLOW_THREADS - if (res < 0) - return path_error(path); - Py_RETURN_NONE; -} -#endif /* HAVE_CHROOT */ - - -#ifdef HAVE_FSYNC -/*[clinic input] -os.fsync - - fd: fildes - -Force write of fd to disk. -[clinic start generated code]*/ - -static PyObject * -os_fsync_impl(PyObject *module, int fd) -/*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/ -{ - return posix_fildes_fd(fd, fsync); -} -#endif /* HAVE_FSYNC */ - - -#ifdef HAVE_SYNC -/*[clinic input] -os.sync - -Force write of everything to disk. -[clinic start generated code]*/ - -static PyObject * -os_sync_impl(PyObject *module) -/*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/ -{ - Py_BEGIN_ALLOW_THREADS - sync(); - Py_END_ALLOW_THREADS - Py_RETURN_NONE; -} -#endif /* HAVE_SYNC */ - - -#ifdef HAVE_FDATASYNC -#ifdef __hpux -extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */ -#endif - -/*[clinic input] -os.fdatasync - - fd: fildes - -Force write of fd to disk without forcing update of metadata. -[clinic start generated code]*/ - -static PyObject * -os_fdatasync_impl(PyObject *module, int fd) -/*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/ -{ - return posix_fildes_fd(fd, fdatasync); -} -#endif /* HAVE_FDATASYNC */ - - -#ifdef HAVE_CHOWN -/*[clinic input] -os.chown - - path : path_t(allow_fd='PATH_HAVE_FCHOWN') - Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int. - - uid: uid_t - - gid: gid_t - - * - - dir_fd : dir_fd(requires='fchownat') = None - If not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that - directory. - - follow_symlinks: bool = True - If False, and the last element of the path is a symbolic link, - stat will examine the symbolic link itself instead of the file - the link points to. - -Change the owner and group id of path to the numeric uid and gid.\ - -path may always be specified as a string. -On some platforms, path may also be specified as an open file descriptor. - If this functionality is unavailable, using it raises an exception. -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -If follow_symlinks is False, and the last element of the path is a symbolic - link, chown will modify the symbolic link itself instead of the file the - link points to. -It is an error to use dir_fd or follow_symlinks when specifying path as - an open file descriptor. -dir_fd and follow_symlinks may not be implemented on your platform. - If they are unavailable, using them will raise a NotImplementedError. - -[clinic start generated code]*/ - -static PyObject * -os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid, - int dir_fd, int follow_symlinks) -/*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/ -{ - int result; - -#if defined(HAVE_FCHOWNAT) - int fchownat_unsupported = 0; -#endif - -#if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT)) - if (follow_symlinks_specified("chown", follow_symlinks)) - return NULL; -#endif - if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) || - fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks)) - return NULL; - - if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, - dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { - return NULL; - } - - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_FCHOWN - if (path->fd != -1) - result = fchown(path->fd, uid, gid); - else -#endif -#ifdef HAVE_LCHOWN - if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) - result = lchown(path->narrow, uid, gid); - else -#endif -#ifdef HAVE_FCHOWNAT - if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) { - if (HAVE_FCHOWNAT_RUNTIME) { - result = fchownat(dir_fd, path->narrow, uid, gid, - follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); - } else { - fchownat_unsupported = 1; - } - } else -#endif - result = chown(path->narrow, uid, gid); - Py_END_ALLOW_THREADS - -#ifdef HAVE_FCHOWNAT - if (fchownat_unsupported) { - /* This would be incorrect if the current platform - * doesn't support lchown. - */ - argument_unavailable_error(NULL, "dir_fd"); - return NULL; - } -#endif - - if (result) - return path_error(path); - - Py_RETURN_NONE; -} -#endif /* HAVE_CHOWN */ - - -#ifdef HAVE_FCHOWN -/*[clinic input] -os.fchown - - fd: int - uid: uid_t - gid: gid_t - -Change the owner and group id of the file specified by file descriptor. - -Equivalent to os.chown(fd, uid, gid). - -[clinic start generated code]*/ - -static PyObject * -os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid) -/*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/ -{ - int res; - int async_err = 0; - - if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) { - return NULL; - } - - do { - Py_BEGIN_ALLOW_THREADS - res = fchown(fd, uid, gid); - Py_END_ALLOW_THREADS - } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (res != 0) - return (!async_err) ? posix_error() : NULL; - - Py_RETURN_NONE; -} -#endif /* HAVE_FCHOWN */ - - -#ifdef HAVE_LCHOWN -/*[clinic input] -os.lchown - - path : path_t - uid: uid_t - gid: gid_t - -Change the owner and group id of path to the numeric uid and gid. - -This function will not follow symbolic links. -Equivalent to os.chown(path, uid, gid, follow_symlinks=False). -[clinic start generated code]*/ - -static PyObject * -os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid) -/*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/ -{ - int res; - if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) { - return NULL; - } - Py_BEGIN_ALLOW_THREADS - res = lchown(path->narrow, uid, gid); - Py_END_ALLOW_THREADS - if (res < 0) { - return path_error(path); - } - Py_RETURN_NONE; -} -#endif /* HAVE_LCHOWN */ - - -static PyObject * -posix_getcwd(int use_bytes) -{ -#ifdef MS_WINDOWS - wchar_t wbuf[MAXPATHLEN]; - wchar_t *wbuf2 = wbuf; - DWORD len; - - Py_BEGIN_ALLOW_THREADS - len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf); - /* If the buffer is large enough, len does not include the - terminating \0. If the buffer is too small, len includes - the space needed for the terminator. */ - if (len >= Py_ARRAY_LENGTH(wbuf)) { - if (len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) { - wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t)); - } - else { - wbuf2 = NULL; - } - if (wbuf2) { - len = GetCurrentDirectoryW(len, wbuf2); - } - } - Py_END_ALLOW_THREADS - - if (!wbuf2) { - PyErr_NoMemory(); - return NULL; - } - if (!len) { - if (wbuf2 != wbuf) - PyMem_RawFree(wbuf2); - return PyErr_SetFromWindowsErr(0); - } - - PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len); - if (wbuf2 != wbuf) { - PyMem_RawFree(wbuf2); - } - - if (use_bytes) { - if (resobj == NULL) { - return NULL; - } - Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj)); - } - - return resobj; -#else - const size_t chunk = 1024; - - char *buf = NULL; - char *cwd = NULL; - size_t buflen = 0; - - Py_BEGIN_ALLOW_THREADS - do { - char *newbuf; - if (buflen <= PY_SSIZE_T_MAX - chunk) { - buflen += chunk; - newbuf = PyMem_RawRealloc(buf, buflen); - } - else { - newbuf = NULL; - } - if (newbuf == NULL) { - PyMem_RawFree(buf); - buf = NULL; - break; - } - buf = newbuf; - - cwd = getcwd(buf, buflen); - } while (cwd == NULL && errno == ERANGE); - Py_END_ALLOW_THREADS - - if (buf == NULL) { - return PyErr_NoMemory(); - } - if (cwd == NULL) { - PyMem_RawFree(buf); - return posix_error(); - } - - PyObject *obj; - if (use_bytes) { - obj = PyBytes_FromStringAndSize(buf, strlen(buf)); - } - else { - obj = PyUnicode_DecodeFSDefault(buf); - } - PyMem_RawFree(buf); - - return obj; -#endif /* !MS_WINDOWS */ -} - - -/*[clinic input] -os.getcwd - -Return a unicode string representing the current working directory. -[clinic start generated code]*/ - -static PyObject * -os_getcwd_impl(PyObject *module) -/*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/ -{ - return posix_getcwd(0); -} - - -/*[clinic input] -os.getcwdb - -Return a bytes string representing the current working directory. -[clinic start generated code]*/ - -static PyObject * -os_getcwdb_impl(PyObject *module) -/*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/ -{ - return posix_getcwd(1); -} - - -#if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS)) -#define HAVE_LINK 1 -#endif - -#ifdef HAVE_LINK -/*[clinic input] - -os.link - - src : path_t - dst : path_t - * - src_dir_fd : dir_fd = None - dst_dir_fd : dir_fd = None - follow_symlinks: bool = True - -Create a hard link to a file. - -If either src_dir_fd or dst_dir_fd is not None, it should be a file - descriptor open to a directory, and the respective path string (src or dst) - should be relative; the path will then be relative to that directory. -If follow_symlinks is False, and the last element of src is a symbolic - link, link will create a link to the symbolic link itself instead of the - file the link points to. -src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your - platform. If they are unavailable, using them will raise a - NotImplementedError. -[clinic start generated code]*/ - -static PyObject * -os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, - int dst_dir_fd, int follow_symlinks) -/*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/ -{ -#ifdef MS_WINDOWS - BOOL result = FALSE; -#else - int result; -#endif -#if defined(HAVE_LINKAT) - int linkat_unavailable = 0; -#endif - -#ifndef HAVE_LINKAT - if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) { - argument_unavailable_error("link", "src_dir_fd and dst_dir_fd"); - return NULL; - } -#endif - -#ifndef MS_WINDOWS - if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { - PyErr_SetString(PyExc_NotImplementedError, - "link: src and dst must be the same type"); - return NULL; - } -#endif - - if (PySys_Audit("os.link", "OOii", src->object, dst->object, - src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd, - dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) { - return NULL; - } - -#ifdef MS_WINDOWS - Py_BEGIN_ALLOW_THREADS - result = CreateHardLinkW(dst->wide, src->wide, NULL); - Py_END_ALLOW_THREADS - - if (!result) - return path_error2(src, dst); -#else - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_LINKAT - if ((src_dir_fd != DEFAULT_DIR_FD) || - (dst_dir_fd != DEFAULT_DIR_FD) || - (!follow_symlinks)) { - - if (HAVE_LINKAT_RUNTIME) { - - result = linkat(src_dir_fd, src->narrow, - dst_dir_fd, dst->narrow, - follow_symlinks ? AT_SYMLINK_FOLLOW : 0); - - } -#ifdef __APPLE__ - else { - if (src_dir_fd == DEFAULT_DIR_FD && dst_dir_fd == DEFAULT_DIR_FD) { - /* See issue 41355: This matches the behaviour of !HAVE_LINKAT */ - result = link(src->narrow, dst->narrow); - } else { - linkat_unavailable = 1; - } - } -#endif - } - else -#endif /* HAVE_LINKAT */ - result = link(src->narrow, dst->narrow); - Py_END_ALLOW_THREADS - -#ifdef HAVE_LINKAT - if (linkat_unavailable) { - /* Either or both dir_fd arguments were specified */ - if (src_dir_fd != DEFAULT_DIR_FD) { - argument_unavailable_error("link", "src_dir_fd"); - } else { - argument_unavailable_error("link", "dst_dir_fd"); - } - return NULL; - } -#endif - - if (result) - return path_error2(src, dst); -#endif /* MS_WINDOWS */ - - Py_RETURN_NONE; -} -#endif - - -#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR) -static PyObject * -_listdir_windows_no_opendir(path_t *path, PyObject *list) -{ - PyObject *v; - HANDLE hFindFile = INVALID_HANDLE_VALUE; - BOOL result; - wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */ - /* only claim to have space for MAX_PATH */ - Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4; - wchar_t *wnamebuf = NULL; - - WIN32_FIND_DATAW wFileData; - const wchar_t *po_wchars; - - if (!path->wide) { /* Default arg: "." */ - po_wchars = L"."; - len = 1; - } else { - po_wchars = path->wide; - len = wcslen(path->wide); - } - /* The +5 is so we can append "\\*.*\0" */ - wnamebuf = PyMem_New(wchar_t, len + 5); - if (!wnamebuf) { - PyErr_NoMemory(); - goto exit; - } - wcscpy(wnamebuf, po_wchars); - if (len > 0) { - wchar_t wch = wnamebuf[len-1]; - if (wch != SEP && wch != ALTSEP && wch != L':') - wnamebuf[len++] = SEP; - wcscpy(wnamebuf + len, L"*.*"); - } - if ((list = PyList_New(0)) == NULL) { - goto exit; - } - Py_BEGIN_ALLOW_THREADS - hFindFile = FindFirstFileW(wnamebuf, &wFileData); - Py_END_ALLOW_THREADS - if (hFindFile == INVALID_HANDLE_VALUE) { - int error = GetLastError(); - if (error == ERROR_FILE_NOT_FOUND) - goto exit; - Py_DECREF(list); - list = path_error(path); - goto exit; - } - do { - /* Skip over . and .. */ - if (wcscmp(wFileData.cFileName, L".") != 0 && - wcscmp(wFileData.cFileName, L"..") != 0) { - v = PyUnicode_FromWideChar(wFileData.cFileName, - wcslen(wFileData.cFileName)); - if (path->narrow && v) { - Py_SETREF(v, PyUnicode_EncodeFSDefault(v)); - } - if (v == NULL) { - Py_DECREF(list); - list = NULL; - break; - } - if (PyList_Append(list, v) != 0) { - Py_DECREF(v); - Py_DECREF(list); - list = NULL; - break; - } - Py_DECREF(v); - } - Py_BEGIN_ALLOW_THREADS - result = FindNextFileW(hFindFile, &wFileData); - Py_END_ALLOW_THREADS - /* FindNextFile sets error to ERROR_NO_MORE_FILES if - it got to the end of the directory. */ - if (!result && GetLastError() != ERROR_NO_MORE_FILES) { - Py_DECREF(list); - list = path_error(path); - goto exit; - } - } while (result == TRUE); - -exit: - if (hFindFile != INVALID_HANDLE_VALUE) { - if (FindClose(hFindFile) == FALSE) { - if (list != NULL) { - Py_DECREF(list); - list = path_error(path); - } - } - } - PyMem_Free(wnamebuf); - - return list; -} /* end of _listdir_windows_no_opendir */ - -#else /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */ - -static PyObject * -_posix_listdir(path_t *path, PyObject *list) -{ - PyObject *v; - DIR *dirp = NULL; - struct dirent *ep; - int return_str; /* if false, return bytes */ -#ifdef HAVE_FDOPENDIR - int fd = -1; -#endif - - errno = 0; -#ifdef HAVE_FDOPENDIR - if (path->fd != -1) { - if (HAVE_FDOPENDIR_RUNTIME) { - /* closedir() closes the FD, so we duplicate it */ - fd = _Py_dup(path->fd); - if (fd == -1) - return NULL; - - return_str = 1; - - Py_BEGIN_ALLOW_THREADS - dirp = fdopendir(fd); - Py_END_ALLOW_THREADS - } else { - PyErr_SetString(PyExc_TypeError, - "listdir: path should be string, bytes, os.PathLike or None, not int"); - return NULL; - } - } - else -#endif - { - const char *name; - if (path->narrow) { - name = path->narrow; - /* only return bytes if they specified a bytes object */ - return_str = !PyBytes_Check(path->object); - } - else { - name = "."; - return_str = 1; - } - - Py_BEGIN_ALLOW_THREADS - dirp = opendir(name); - Py_END_ALLOW_THREADS - } - - if (dirp == NULL) { - list = path_error(path); -#ifdef HAVE_FDOPENDIR - if (fd != -1) { - Py_BEGIN_ALLOW_THREADS - close(fd); - Py_END_ALLOW_THREADS - } -#endif - goto exit; - } - if ((list = PyList_New(0)) == NULL) { - goto exit; - } - for (;;) { - errno = 0; - Py_BEGIN_ALLOW_THREADS - ep = readdir(dirp); - Py_END_ALLOW_THREADS - if (ep == NULL) { - if (errno == 0) { - break; - } else { - Py_DECREF(list); - list = path_error(path); - goto exit; - } - } - if (ep->d_name[0] == '.' && - (NAMLEN(ep) == 1 || - (ep->d_name[1] == '.' && NAMLEN(ep) == 2))) - continue; - if (return_str) - v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep)); - else - v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep)); - if (v == NULL) { - Py_CLEAR(list); - break; - } - if (PyList_Append(list, v) != 0) { - Py_DECREF(v); - Py_CLEAR(list); - break; - } - Py_DECREF(v); - } - -exit: - if (dirp != NULL) { - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_FDOPENDIR - if (fd > -1) - rewinddir(dirp); -#endif - closedir(dirp); - Py_END_ALLOW_THREADS - } - - return list; -} /* end of _posix_listdir */ -#endif /* which OS */ - - -/*[clinic input] -os.listdir - - path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None - -Return a list containing the names of the files in the directory. - -path can be specified as either str, bytes, or a path-like object. If path is bytes, - the filenames returned will also be bytes; in all other circumstances - the filenames returned will be str. -If path is None, uses the path='.'. -On some platforms, path may also be specified as an open file descriptor;\ - the file descriptor must refer to a directory. - If this functionality is unavailable, using it raises NotImplementedError. - -The list is in arbitrary order. It does not include the special -entries '.' and '..' even if they are present in the directory. - - -[clinic start generated code]*/ - -static PyObject * -os_listdir_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/ -{ - if (PySys_Audit("os.listdir", "O", - path->object ? path->object : Py_None) < 0) { - return NULL; - } -#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR) - return _listdir_windows_no_opendir(path, NULL); -#else - return _posix_listdir(path, NULL); -#endif -} - -#ifdef MS_WINDOWS -int -_PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p) -{ - wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf; - DWORD result; - - result = GetFullPathNameW(path, - Py_ARRAY_LENGTH(woutbuf), woutbuf, - NULL); - if (!result) { - return -1; - } - - if (result >= Py_ARRAY_LENGTH(woutbuf)) { - if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) { - woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t)); - } - else { - woutbufp = NULL; - } - if (!woutbufp) { - *abspath_p = NULL; - return 0; - } - - result = GetFullPathNameW(path, result, woutbufp, NULL); - if (!result) { - PyMem_RawFree(woutbufp); - return -1; - } - } - - if (woutbufp != woutbuf) { - *abspath_p = woutbufp; - return 0; - } - - *abspath_p = _PyMem_RawWcsdup(woutbufp); - return 0; -} - - -/* A helper function for abspath on win32 */ -/*[clinic input] -os._getfullpathname - - path: path_t - / - -[clinic start generated code]*/ - -static PyObject * -os__getfullpathname_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/ -{ - wchar_t *abspath; - - if (_PyOS_getfullpathname(path->wide, &abspath) < 0) { - return win32_error_object("GetFullPathNameW", path->object); - } - if (abspath == NULL) { - return PyErr_NoMemory(); - } - - PyObject *str = PyUnicode_FromWideChar(abspath, wcslen(abspath)); - PyMem_RawFree(abspath); - if (str == NULL) { - return NULL; - } - if (path->narrow) { - Py_SETREF(str, PyUnicode_EncodeFSDefault(str)); - } - return str; -} - - -/*[clinic input] -os._getfinalpathname - - path: path_t - / - -A helper function for samepath on windows. -[clinic start generated code]*/ - -static PyObject * -os__getfinalpathname_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/ -{ - HANDLE hFile; - wchar_t buf[MAXPATHLEN], *target_path = buf; - int buf_size = Py_ARRAY_LENGTH(buf); - int result_length; - PyObject *result; - - Py_BEGIN_ALLOW_THREADS - hFile = CreateFileW( - path->wide, - 0, /* desired access */ - 0, /* share mode */ - NULL, /* security attributes */ - OPEN_EXISTING, - /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ - FILE_FLAG_BACKUP_SEMANTICS, - NULL); - Py_END_ALLOW_THREADS - - if (hFile == INVALID_HANDLE_VALUE) { - return win32_error_object("CreateFileW", path->object); - } - - /* We have a good handle to the target, use it to determine the - target path name. */ - while (1) { - Py_BEGIN_ALLOW_THREADS - result_length = GetFinalPathNameByHandleW(hFile, target_path, - buf_size, VOLUME_NAME_DOS); - Py_END_ALLOW_THREADS - - if (!result_length) { - result = win32_error_object("GetFinalPathNameByHandleW", - path->object); - goto cleanup; - } - - if (result_length < buf_size) { - break; - } - - wchar_t *tmp; - tmp = PyMem_Realloc(target_path != buf ? target_path : NULL, - result_length * sizeof(*tmp)); - if (!tmp) { - result = PyErr_NoMemory(); - goto cleanup; - } - - buf_size = result_length; - target_path = tmp; - } - - result = PyUnicode_FromWideChar(target_path, result_length); - if (result && path->narrow) { - Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); - } - -cleanup: - if (target_path != buf) { - PyMem_Free(target_path); - } - CloseHandle(hFile); - return result; -} - - -/*[clinic input] -os._getvolumepathname - - path: path_t - -A helper function for ismount on Win32. -[clinic start generated code]*/ - -static PyObject * -os__getvolumepathname_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/ -{ - PyObject *result; - wchar_t *mountpath=NULL; - size_t buflen; - BOOL ret; - - /* Volume path should be shorter than entire path */ - buflen = Py_MAX(path->length, MAX_PATH); - - if (buflen > PY_DWORD_MAX) { - PyErr_SetString(PyExc_OverflowError, "path too long"); - return NULL; - } - - mountpath = PyMem_New(wchar_t, buflen); - if (mountpath == NULL) - return PyErr_NoMemory(); - - Py_BEGIN_ALLOW_THREADS - ret = GetVolumePathNameW(path->wide, mountpath, - Py_SAFE_DOWNCAST(buflen, size_t, DWORD)); - Py_END_ALLOW_THREADS - - if (!ret) { - result = win32_error_object("_getvolumepathname", path->object); - goto exit; - } - result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath)); - if (path->narrow) - Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); - -exit: - PyMem_Free(mountpath); - return result; -} - - -/*[clinic input] -os._path_splitroot - - path: path_t - -Removes everything after the root on Win32. -[clinic start generated code]*/ - -static PyObject * -os__path_splitroot_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=ab7f1a88b654581c input=dc93b1d3984cffb6]*/ -{ - wchar_t *buffer; - wchar_t *end; - PyObject *result = NULL; - HRESULT ret; - - buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1)); - if (!buffer) { - return NULL; - } - wcscpy(buffer, path->wide); - for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) { - *p = L'\\'; - } - - Py_BEGIN_ALLOW_THREADS - ret = PathCchSkipRoot(buffer, &end); - Py_END_ALLOW_THREADS - if (FAILED(ret)) { - result = Py_BuildValue("sO", "", path->object); - } else if (end != buffer) { - size_t rootLen = (size_t)(end - buffer); - result = Py_BuildValue("NN", - PyUnicode_FromWideChar(path->wide, rootLen), - PyUnicode_FromWideChar(path->wide + rootLen, -1) - ); - } else { - result = Py_BuildValue("Os", path->object, ""); - } - PyMem_Free(buffer); - - return result; -} - - -#endif /* MS_WINDOWS */ - - -/*[clinic input] -os._path_normpath - - path: object - -Basic path normalization. -[clinic start generated code]*/ - -static PyObject * -os__path_normpath_impl(PyObject *module, PyObject *path) -/*[clinic end generated code: output=b94d696d828019da input=5e90c39e12549dc0]*/ -{ - if (!PyUnicode_Check(path)) { - PyErr_Format(PyExc_TypeError, "expected 'str', not '%.200s'", - Py_TYPE(path)->tp_name); - return NULL; - } - Py_ssize_t len; - wchar_t *buffer = PyUnicode_AsWideCharString(path, &len); - if (!buffer) { - return NULL; - } - PyObject *result = PyUnicode_FromWideChar(_Py_normpath(buffer, len), -1); - PyMem_Free(buffer); - return result; -} - -/*[clinic input] -os.mkdir - - path : path_t - - mode: int = 0o777 - - * - - dir_fd : dir_fd(requires='mkdirat') = None - -# "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\ - -Create a directory. - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -dir_fd may not be implemented on your platform. - If it is unavailable, using it will raise a NotImplementedError. - -The mode argument is ignored on Windows. Where it is used, the current umask -value is first masked out. -[clinic start generated code]*/ - -static PyObject * -os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd) -/*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/ -{ - int result; -#ifdef HAVE_MKDIRAT - int mkdirat_unavailable = 0; -#endif - - if (PySys_Audit("os.mkdir", "Oii", path->object, mode, - dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { - return NULL; - } - -#ifdef MS_WINDOWS - Py_BEGIN_ALLOW_THREADS - result = CreateDirectoryW(path->wide, NULL); - Py_END_ALLOW_THREADS - - if (!result) - return path_error(path); -#else - Py_BEGIN_ALLOW_THREADS -#if HAVE_MKDIRAT - if (dir_fd != DEFAULT_DIR_FD) { - if (HAVE_MKDIRAT_RUNTIME) { - result = mkdirat(dir_fd, path->narrow, mode); - - } else { - mkdirat_unavailable = 1; - } - } else -#endif -#if defined(__WATCOMC__) && !defined(__QNX__) - result = mkdir(path->narrow); -#else - result = mkdir(path->narrow, mode); -#endif - Py_END_ALLOW_THREADS - -#if HAVE_MKDIRAT - if (mkdirat_unavailable) { - argument_unavailable_error(NULL, "dir_fd"); - return NULL; - } -#endif - - if (result < 0) - return path_error(path); -#endif /* MS_WINDOWS */ - Py_RETURN_NONE; -} - - -/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */ -#if defined(HAVE_SYS_RESOURCE_H) -#include -#endif - - -#ifdef HAVE_NICE -/*[clinic input] -os.nice - - increment: int - / - -Add increment to the priority of process and return the new priority. -[clinic start generated code]*/ - -static PyObject * -os_nice_impl(PyObject *module, int increment) -/*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/ -{ - int value; - - /* There are two flavours of 'nice': one that returns the new - priority (as required by almost all standards out there) and the - Linux/FreeBSD one, which returns '0' on success and advices - the use of getpriority() to get the new priority. - - If we are of the nice family that returns the new priority, we - need to clear errno before the call, and check if errno is filled - before calling posix_error() on a returnvalue of -1, because the - -1 may be the actual new priority! */ - - errno = 0; - value = nice(increment); -#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY) - if (value == 0) - value = getpriority(PRIO_PROCESS, 0); -#endif - if (value == -1 && errno != 0) - /* either nice() or getpriority() returned an error */ - return posix_error(); - return PyLong_FromLong((long) value); -} -#endif /* HAVE_NICE */ - - -#ifdef HAVE_GETPRIORITY -/*[clinic input] -os.getpriority - - which: int - who: int - -Return program scheduling priority. -[clinic start generated code]*/ - -static PyObject * -os_getpriority_impl(PyObject *module, int which, int who) -/*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/ -{ - int retval; - - errno = 0; - retval = getpriority(which, who); - if (errno != 0) - return posix_error(); - return PyLong_FromLong((long)retval); -} -#endif /* HAVE_GETPRIORITY */ - - -#ifdef HAVE_SETPRIORITY -/*[clinic input] -os.setpriority - - which: int - who: int - priority: int - -Set program scheduling priority. -[clinic start generated code]*/ - -static PyObject * -os_setpriority_impl(PyObject *module, int which, int who, int priority) -/*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/ -{ - int retval; - - retval = setpriority(which, who, priority); - if (retval == -1) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETPRIORITY */ - - -static PyObject * -internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace) -{ - const char *function_name = is_replace ? "replace" : "rename"; - int dir_fd_specified; - -#ifdef HAVE_RENAMEAT - int renameat_unavailable = 0; -#endif - -#ifdef MS_WINDOWS - BOOL result; - int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0; -#else - int result; -#endif - - dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) || - (dst_dir_fd != DEFAULT_DIR_FD); -#ifndef HAVE_RENAMEAT - if (dir_fd_specified) { - argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd"); - return NULL; - } -#endif - - if (PySys_Audit("os.rename", "OOii", src->object, dst->object, - src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd, - dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) { - return NULL; - } - -#ifdef MS_WINDOWS - Py_BEGIN_ALLOW_THREADS - result = MoveFileExW(src->wide, dst->wide, flags); - Py_END_ALLOW_THREADS - - if (!result) - return path_error2(src, dst); - -#else - if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { - PyErr_Format(PyExc_ValueError, - "%s: src and dst must be the same type", function_name); - return NULL; - } - - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_RENAMEAT - if (dir_fd_specified) { - if (HAVE_RENAMEAT_RUNTIME) { - result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow); - } else { - renameat_unavailable = 1; - } - } else -#endif - result = rename(src->narrow, dst->narrow); - Py_END_ALLOW_THREADS - - -#ifdef HAVE_RENAMEAT - if (renameat_unavailable) { - argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd"); - return NULL; - } -#endif - - if (result) - return path_error2(src, dst); -#endif - Py_RETURN_NONE; -} - - -/*[clinic input] -os.rename - - src : path_t - dst : path_t - * - src_dir_fd : dir_fd = None - dst_dir_fd : dir_fd = None - -Rename a file or directory. - -If either src_dir_fd or dst_dir_fd is not None, it should be a file - descriptor open to a directory, and the respective path string (src or dst) - should be relative; the path will then be relative to that directory. -src_dir_fd and dst_dir_fd, may not be implemented on your platform. - If they are unavailable, using them will raise a NotImplementedError. -[clinic start generated code]*/ - -static PyObject * -os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, - int dst_dir_fd) -/*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/ -{ - return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0); -} - - -/*[clinic input] -os.replace = os.rename - -Rename a file or directory, overwriting the destination. - -If either src_dir_fd or dst_dir_fd is not None, it should be a file - descriptor open to a directory, and the respective path string (src or dst) - should be relative; the path will then be relative to that directory. -src_dir_fd and dst_dir_fd, may not be implemented on your platform. - If they are unavailable, using them will raise a NotImplementedError. -[clinic start generated code]*/ - -static PyObject * -os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, - int dst_dir_fd) -/*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/ -{ - return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1); -} - - -/*[clinic input] -os.rmdir - - path: path_t - * - dir_fd: dir_fd(requires='unlinkat') = None - -Remove a directory. - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -dir_fd may not be implemented on your platform. - If it is unavailable, using it will raise a NotImplementedError. -[clinic start generated code]*/ - -static PyObject * -os_rmdir_impl(PyObject *module, path_t *path, int dir_fd) -/*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/ -{ - int result; -#ifdef HAVE_UNLINKAT - int unlinkat_unavailable = 0; -#endif - - if (PySys_Audit("os.rmdir", "Oi", path->object, - dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { - return NULL; - } - - Py_BEGIN_ALLOW_THREADS -#ifdef MS_WINDOWS - /* Windows, success=1, UNIX, success=0 */ - result = !RemoveDirectoryW(path->wide); -#else -#ifdef HAVE_UNLINKAT - if (dir_fd != DEFAULT_DIR_FD) { - if (HAVE_UNLINKAT_RUNTIME) { - result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR); - } else { - unlinkat_unavailable = 1; - result = -1; - } - } else -#endif - result = rmdir(path->narrow); -#endif - Py_END_ALLOW_THREADS - -#ifdef HAVE_UNLINKAT - if (unlinkat_unavailable) { - argument_unavailable_error("rmdir", "dir_fd"); - return NULL; - } -#endif - - if (result) - return path_error(path); - - Py_RETURN_NONE; -} - - -#ifdef HAVE_SYSTEM -#ifdef MS_WINDOWS -/*[clinic input] -os.system -> long - - command: Py_UNICODE - -Execute the command in a subshell. -[clinic start generated code]*/ - -static long -os_system_impl(PyObject *module, const Py_UNICODE *command) -/*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/ -{ - long result; - - if (PySys_Audit("os.system", "(u)", command) < 0) { - return -1; - } - - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - result = _wsystem(command); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - return result; -} -#else /* MS_WINDOWS */ -/*[clinic input] -os.system -> long - - command: FSConverter - -Execute the command in a subshell. -[clinic start generated code]*/ - -static long -os_system_impl(PyObject *module, PyObject *command) -/*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/ -{ - long result; - const char *bytes = PyBytes_AsString(command); - - if (PySys_Audit("os.system", "(O)", command) < 0) { - return -1; - } - - Py_BEGIN_ALLOW_THREADS - result = system(bytes); - Py_END_ALLOW_THREADS - return result; -} -#endif -#endif /* HAVE_SYSTEM */ - - -#ifdef HAVE_UMASK -/*[clinic input] -os.umask - - mask: int - / - -Set the current numeric umask and return the previous umask. -[clinic start generated code]*/ - -static PyObject * -os_umask_impl(PyObject *module, int mask) -/*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/ -{ - int i = (int)umask(mask); - if (i < 0) - return posix_error(); - return PyLong_FromLong((long)i); -} -#endif - -#ifdef MS_WINDOWS - -/* override the default DeleteFileW behavior so that directory -symlinks can be removed with this function, the same as with -Unix symlinks */ -BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName) -{ - WIN32_FILE_ATTRIBUTE_DATA info; - WIN32_FIND_DATAW find_data; - HANDLE find_data_handle; - int is_directory = 0; - int is_link = 0; - - if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) { - is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; - - /* Get WIN32_FIND_DATA structure for the path to determine if - it is a symlink */ - if(is_directory && - info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - find_data_handle = FindFirstFileW(lpFileName, &find_data); - - if(find_data_handle != INVALID_HANDLE_VALUE) { - /* IO_REPARSE_TAG_SYMLINK if it is a symlink and - IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */ - is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK || - find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT; - FindClose(find_data_handle); - } - } - } - - if (is_directory && is_link) - return RemoveDirectoryW(lpFileName); - - return DeleteFileW(lpFileName); -} -#endif /* MS_WINDOWS */ - - -/*[clinic input] -os.unlink - - path: path_t - * - dir_fd: dir_fd(requires='unlinkat')=None - -Remove a file (same as remove()). - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -dir_fd may not be implemented on your platform. - If it is unavailable, using it will raise a NotImplementedError. - -[clinic start generated code]*/ - -static PyObject * -os_unlink_impl(PyObject *module, path_t *path, int dir_fd) -/*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/ -{ - int result; -#ifdef HAVE_UNLINKAT - int unlinkat_unavailable = 0; -#endif - - if (PySys_Audit("os.remove", "Oi", path->object, - dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH -#ifdef MS_WINDOWS - /* Windows, success=1, UNIX, success=0 */ - result = !Py_DeleteFileW(path->wide); -#else -#ifdef HAVE_UNLINKAT - if (dir_fd != DEFAULT_DIR_FD) { - if (HAVE_UNLINKAT_RUNTIME) { - - result = unlinkat(dir_fd, path->narrow, 0); - } else { - unlinkat_unavailable = 1; - } - } else -#endif /* HAVE_UNLINKAT */ - result = unlink(path->narrow); -#endif - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - -#ifdef HAVE_UNLINKAT - if (unlinkat_unavailable) { - argument_unavailable_error(NULL, "dir_fd"); - return NULL; - } -#endif - - if (result) - return path_error(path); - - Py_RETURN_NONE; -} - - -/*[clinic input] -os.remove = os.unlink - -Remove a file (same as unlink()). - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -dir_fd may not be implemented on your platform. - If it is unavailable, using it will raise a NotImplementedError. -[clinic start generated code]*/ - -static PyObject * -os_remove_impl(PyObject *module, path_t *path, int dir_fd) -/*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/ -{ - return os_unlink_impl(module, path, dir_fd); -} - - -static PyStructSequence_Field uname_result_fields[] = { - {"sysname", "operating system name"}, - {"nodename", "name of machine on network (implementation-defined)"}, - {"release", "operating system release"}, - {"version", "operating system version"}, - {"machine", "hardware identifier"}, - {NULL} -}; - -PyDoc_STRVAR(uname_result__doc__, -"uname_result: Result from os.uname().\n\n\ -This object may be accessed either as a tuple of\n\ - (sysname, nodename, release, version, machine),\n\ -or via the attributes sysname, nodename, release, version, and machine.\n\ -\n\ -See os.uname for more information."); - -static PyStructSequence_Desc uname_result_desc = { - MODNAME ".uname_result", /* name */ - uname_result__doc__, /* doc */ - uname_result_fields, - 5 -}; - -#ifdef HAVE_UNAME -/*[clinic input] -os.uname - -Return an object identifying the current operating system. - -The object behaves like a named tuple with the following fields: - (sysname, nodename, release, version, machine) - -[clinic start generated code]*/ - -static PyObject * -os_uname_impl(PyObject *module) -/*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/ -{ - struct utsname u; - int res; - PyObject *value; - - Py_BEGIN_ALLOW_THREADS - res = uname(&u); - Py_END_ALLOW_THREADS - if (res < 0) - return posix_error(); - - PyObject *UnameResultType = get_posix_state(module)->UnameResultType; - value = PyStructSequence_New((PyTypeObject *)UnameResultType); - if (value == NULL) - return NULL; - -#define SET(i, field) \ - { \ - PyObject *o = PyUnicode_DecodeFSDefault(field); \ - if (!o) { \ - Py_DECREF(value); \ - return NULL; \ - } \ - PyStructSequence_SET_ITEM(value, i, o); \ - } \ - - SET(0, u.sysname); - SET(1, u.nodename); - SET(2, u.release); - SET(3, u.version); - SET(4, u.machine); - -#undef SET - - return value; -} -#endif /* HAVE_UNAME */ - - - -typedef struct { - int now; - time_t atime_s; - long atime_ns; - time_t mtime_s; - long mtime_ns; -} utime_t; - -/* - * these macros assume that "ut" is a pointer to a utime_t - * they also intentionally leak the declaration of a pointer named "time" - */ -#define UTIME_TO_TIMESPEC \ - struct timespec ts[2]; \ - struct timespec *time; \ - if (ut->now) \ - time = NULL; \ - else { \ - ts[0].tv_sec = ut->atime_s; \ - ts[0].tv_nsec = ut->atime_ns; \ - ts[1].tv_sec = ut->mtime_s; \ - ts[1].tv_nsec = ut->mtime_ns; \ - time = ts; \ - } \ - -#define UTIME_TO_TIMEVAL \ - struct timeval tv[2]; \ - struct timeval *time; \ - if (ut->now) \ - time = NULL; \ - else { \ - tv[0].tv_sec = ut->atime_s; \ - tv[0].tv_usec = ut->atime_ns / 1000; \ - tv[1].tv_sec = ut->mtime_s; \ - tv[1].tv_usec = ut->mtime_ns / 1000; \ - time = tv; \ - } \ - -#define UTIME_TO_UTIMBUF \ - struct utimbuf u; \ - struct utimbuf *time; \ - if (ut->now) \ - time = NULL; \ - else { \ - u.actime = ut->atime_s; \ - u.modtime = ut->mtime_s; \ - time = &u; \ - } - -#define UTIME_TO_TIME_T \ - time_t timet[2]; \ - time_t *time; \ - if (ut->now) \ - time = NULL; \ - else { \ - timet[0] = ut->atime_s; \ - timet[1] = ut->mtime_s; \ - time = timet; \ - } \ - - -#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT) - -static int -utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks) -{ -#if defined(__APPLE__) && defined(HAVE_UTIMENSAT) - if (HAVE_UTIMENSAT_RUNTIME) { - int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW; - UTIME_TO_TIMESPEC; - return utimensat(dir_fd, path, time, flags); - } else { - errno = ENOSYS; - return -1; - } -#elif defined(HAVE_UTIMENSAT) - int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW; - UTIME_TO_TIMESPEC; - return utimensat(dir_fd, path, time, flags); -#elif defined(HAVE_FUTIMESAT) - UTIME_TO_TIMEVAL; - /* - * follow_symlinks will never be false here; - * we only allow !follow_symlinks and dir_fd together - * if we have utimensat() - */ - assert(follow_symlinks); - return futimesat(dir_fd, path, time); -#endif -} - - #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS) - -static int -utime_fd(utime_t *ut, int fd) -{ -#ifdef HAVE_FUTIMENS - - if (HAVE_FUTIMENS_RUNTIME) { - - UTIME_TO_TIMESPEC; - return futimens(fd, time); - - } else -#ifndef HAVE_FUTIMES - { - /* Not sure if this can happen */ - PyErr_SetString( - PyExc_RuntimeError, - "neither futimens nor futimes are supported" - " on this system"); - return -1; - } -#endif - -#endif -#ifdef HAVE_FUTIMES - { - UTIME_TO_TIMEVAL; - return futimes(fd, time); - } -#endif -} - - #define PATH_UTIME_HAVE_FD 1 -#else - #define PATH_UTIME_HAVE_FD 0 -#endif - -#if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES) -# define UTIME_HAVE_NOFOLLOW_SYMLINKS -#endif - -#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS - -static int -utime_nofollow_symlinks(utime_t *ut, const char *path) -{ -#ifdef HAVE_UTIMENSAT - if (HAVE_UTIMENSAT_RUNTIME) { - UTIME_TO_TIMESPEC; - return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW); - } else -#ifndef HAVE_LUTIMES - { - /* Not sure if this can happen */ - PyErr_SetString( - PyExc_RuntimeError, - "neither utimensat nor lutimes are supported" - " on this system"); - return -1; - } -#endif -#endif - -#ifdef HAVE_LUTIMES - { - UTIME_TO_TIMEVAL; - return lutimes(path, time); - } -#endif -} - -#endif - -#ifndef MS_WINDOWS - -static int -utime_default(utime_t *ut, const char *path) -{ -#if defined(__APPLE__) && defined(HAVE_UTIMENSAT) - if (HAVE_UTIMENSAT_RUNTIME) { - UTIME_TO_TIMESPEC; - return utimensat(DEFAULT_DIR_FD, path, time, 0); - } else { - UTIME_TO_TIMEVAL; - return utimes(path, time); - } -#elif defined(HAVE_UTIMENSAT) - UTIME_TO_TIMESPEC; - return utimensat(DEFAULT_DIR_FD, path, time, 0); -#elif defined(HAVE_UTIMES) - UTIME_TO_TIMEVAL; - return utimes(path, time); -#elif defined(HAVE_UTIME_H) - UTIME_TO_UTIMBUF; - return utime(path, time); -#else - UTIME_TO_TIME_T; - return utime(path, time); -#endif -} - -#endif - -static int -split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns) -{ - int result = 0; - PyObject *divmod; - divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion); - if (!divmod) - goto exit; - if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) { - PyErr_Format(PyExc_TypeError, - "%.200s.__divmod__() must return a 2-tuple, not %.200s", - _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod))); - goto exit; - } - *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0)); - if ((*s == -1) && PyErr_Occurred()) - goto exit; - *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1)); - if ((*ns == -1) && PyErr_Occurred()) - goto exit; - - result = 1; -exit: - Py_XDECREF(divmod); - return result; -} - - -/*[clinic input] -os.utime - - path: path_t(allow_fd='PATH_UTIME_HAVE_FD') - times: object = None - * - ns: object = NULL - dir_fd: dir_fd(requires='futimensat') = None - follow_symlinks: bool=True - -# "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\ - -Set the access and modified time of path. - -path may always be specified as a string. -On some platforms, path may also be specified as an open file descriptor. - If this functionality is unavailable, using it raises an exception. - -If times is not None, it must be a tuple (atime, mtime); - atime and mtime should be expressed as float seconds since the epoch. -If ns is specified, it must be a tuple (atime_ns, mtime_ns); - atime_ns and mtime_ns should be expressed as integer nanoseconds - since the epoch. -If times is None and ns is unspecified, utime uses the current time. -Specifying tuples for both times and ns is an error. - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -If follow_symlinks is False, and the last element of the path is a symbolic - link, utime will modify the symbolic link itself instead of the file the - link points to. -It is an error to use dir_fd or follow_symlinks when specifying path - as an open file descriptor. -dir_fd and follow_symlinks may not be available on your platform. - If they are unavailable, using them will raise a NotImplementedError. - -[clinic start generated code]*/ - -static PyObject * -os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, - int dir_fd, int follow_symlinks) -/*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/ -{ -#ifdef MS_WINDOWS - HANDLE hFile; - FILETIME atime, mtime; -#else - int result; -#endif - - utime_t utime; - - memset(&utime, 0, sizeof(utime_t)); - - if (times != Py_None && ns) { - PyErr_SetString(PyExc_ValueError, - "utime: you may specify either 'times'" - " or 'ns' but not both"); - return NULL; - } - - if (times != Py_None) { - time_t a_sec, m_sec; - long a_nsec, m_nsec; - if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) { - PyErr_SetString(PyExc_TypeError, - "utime: 'times' must be either" - " a tuple of two ints or None"); - return NULL; - } - utime.now = 0; - if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0), - &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 || - _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1), - &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) { - return NULL; - } - utime.atime_s = a_sec; - utime.atime_ns = a_nsec; - utime.mtime_s = m_sec; - utime.mtime_ns = m_nsec; - } - else if (ns) { - if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) { - PyErr_SetString(PyExc_TypeError, - "utime: 'ns' must be a tuple of two ints"); - return NULL; - } - utime.now = 0; - if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0), - &utime.atime_s, &utime.atime_ns) || - !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1), - &utime.mtime_s, &utime.mtime_ns)) { - return NULL; - } - } - else { - /* times and ns are both None/unspecified. use "now". */ - utime.now = 1; - } - -#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS) - if (follow_symlinks_specified("utime", follow_symlinks)) - return NULL; -#endif - - if (path_and_dir_fd_invalid("utime", path, dir_fd) || - dir_fd_and_fd_invalid("utime", dir_fd, path->fd) || - fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks)) - return NULL; - -#if !defined(HAVE_UTIMENSAT) - if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) { - PyErr_SetString(PyExc_ValueError, - "utime: cannot use dir_fd and follow_symlinks " - "together on this platform"); - return NULL; - } -#endif - - if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None, - dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { - return NULL; - } - -#ifdef MS_WINDOWS - Py_BEGIN_ALLOW_THREADS - hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0, - NULL, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, NULL); - Py_END_ALLOW_THREADS - if (hFile == INVALID_HANDLE_VALUE) { - path_error(path); - return NULL; - } - - if (utime.now) { - GetSystemTimeAsFileTime(&mtime); - atime = mtime; - } - else { - _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime); - _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime); - } - if (!SetFileTime(hFile, NULL, &atime, &mtime)) { - /* Avoid putting the file name into the error here, - as that may confuse the user into believing that - something is wrong with the file, when it also - could be the time stamp that gives a problem. */ - PyErr_SetFromWindowsErr(0); - CloseHandle(hFile); - return NULL; - } - CloseHandle(hFile); -#else /* MS_WINDOWS */ - Py_BEGIN_ALLOW_THREADS - -#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS - if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) - result = utime_nofollow_symlinks(&utime, path->narrow); - else -#endif - -#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT) - if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) { - result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks); - - } else -#endif - -#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS) - if (path->fd != -1) - result = utime_fd(&utime, path->fd); - else -#endif - - result = utime_default(&utime, path->narrow); - - Py_END_ALLOW_THREADS - -#if defined(__APPLE__) && defined(HAVE_UTIMENSAT) - /* See utime_dir_fd implementation */ - if (result == -1 && errno == ENOSYS) { - argument_unavailable_error(NULL, "dir_fd"); - return NULL; - } -#endif - - if (result < 0) { - /* see previous comment about not putting filename in error here */ - posix_error(); - return NULL; - } - -#endif /* MS_WINDOWS */ - - Py_RETURN_NONE; -} - -/* Process operations */ - - -/*[clinic input] -os._exit - - status: int - -Exit to the system with specified status, without normal exit processing. -[clinic start generated code]*/ - -static PyObject * -os__exit_impl(PyObject *module, int status) -/*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/ -{ - _exit(status); - return NULL; /* Make gcc -Wall happy */ -} - -#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV) -#define EXECV_CHAR wchar_t -#else -#define EXECV_CHAR char -#endif - -#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN) -static void -free_string_array(EXECV_CHAR **array, Py_ssize_t count) -{ - Py_ssize_t i; - for (i = 0; i < count; i++) - PyMem_Free(array[i]); - PyMem_Free(array); -} - -static int -fsconvert_strdup(PyObject *o, EXECV_CHAR **out) -{ - Py_ssize_t size; - PyObject *ub; - int result = 0; -#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV) - if (!PyUnicode_FSDecoder(o, &ub)) - return 0; - *out = PyUnicode_AsWideCharString(ub, &size); - if (*out) - result = 1; -#else - if (!PyUnicode_FSConverter(o, &ub)) - return 0; - size = PyBytes_GET_SIZE(ub); - *out = PyMem_Malloc(size + 1); - if (*out) { - memcpy(*out, PyBytes_AS_STRING(ub), size + 1); - result = 1; - } else - PyErr_NoMemory(); -#endif - Py_DECREF(ub); - return result; -} -#endif - -#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN) -static EXECV_CHAR** -parse_envlist(PyObject* env, Py_ssize_t *envc_ptr) -{ - Py_ssize_t i, pos, envc; - PyObject *keys=NULL, *vals=NULL; - PyObject *key, *val, *key2, *val2, *keyval; - EXECV_CHAR **envlist; - - i = PyMapping_Size(env); - if (i < 0) - return NULL; - envlist = PyMem_NEW(EXECV_CHAR *, i + 1); - if (envlist == NULL) { - PyErr_NoMemory(); - return NULL; - } - envc = 0; - keys = PyMapping_Keys(env); - if (!keys) - goto error; - vals = PyMapping_Values(env); - if (!vals) - goto error; - if (!PyList_Check(keys) || !PyList_Check(vals)) { - PyErr_Format(PyExc_TypeError, - "env.keys() or env.values() is not a list"); - goto error; - } - - for (pos = 0; pos < i; pos++) { - key = PyList_GetItem(keys, pos); - val = PyList_GetItem(vals, pos); - if (!key || !val) - goto error; - -#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV) - if (!PyUnicode_FSDecoder(key, &key2)) - goto error; - if (!PyUnicode_FSDecoder(val, &val2)) { - Py_DECREF(key2); - goto error; - } - /* Search from index 1 because on Windows starting '=' is allowed for - defining hidden environment variables. */ - if (PyUnicode_GET_LENGTH(key2) == 0 || - PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1) - { - PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); - Py_DECREF(key2); - Py_DECREF(val2); - goto error; - } - keyval = PyUnicode_FromFormat("%U=%U", key2, val2); -#else - if (!PyUnicode_FSConverter(key, &key2)) - goto error; - if (!PyUnicode_FSConverter(val, &val2)) { - Py_DECREF(key2); - goto error; - } - if (PyBytes_GET_SIZE(key2) == 0 || - strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL) - { - PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); - Py_DECREF(key2); - Py_DECREF(val2); - goto error; - } - keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2), - PyBytes_AS_STRING(val2)); -#endif - Py_DECREF(key2); - Py_DECREF(val2); - if (!keyval) - goto error; - - if (!fsconvert_strdup(keyval, &envlist[envc++])) { - Py_DECREF(keyval); - goto error; - } - - Py_DECREF(keyval); - } - Py_DECREF(vals); - Py_DECREF(keys); - - envlist[envc] = 0; - *envc_ptr = envc; - return envlist; - -error: - Py_XDECREF(keys); - Py_XDECREF(vals); - free_string_array(envlist, envc); - return NULL; -} - -static EXECV_CHAR** -parse_arglist(PyObject* argv, Py_ssize_t *argc) -{ - int i; - EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1); - if (argvlist == NULL) { - PyErr_NoMemory(); - return NULL; - } - for (i = 0; i < *argc; i++) { - PyObject* item = PySequence_ITEM(argv, i); - if (item == NULL) - goto fail; - if (!fsconvert_strdup(item, &argvlist[i])) { - Py_DECREF(item); - goto fail; - } - Py_DECREF(item); - } - argvlist[*argc] = NULL; - return argvlist; -fail: - *argc = i; - free_string_array(argvlist, *argc); - return NULL; -} - -#endif - - -#ifdef HAVE_EXECV -/*[clinic input] -os.execv - - path: path_t - Path of executable file. - argv: object - Tuple or list of strings. - / - -Execute an executable path with arguments, replacing current process. -[clinic start generated code]*/ - -static PyObject * -os_execv_impl(PyObject *module, path_t *path, PyObject *argv) -/*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/ -{ - EXECV_CHAR **argvlist; - Py_ssize_t argc; - - PyInterpreterState *interp = _PyInterpreterState_GET(); - if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) { - PyErr_SetString(PyExc_RuntimeError, - "exec not supported for isolated subinterpreters"); - return NULL; - } - - /* execv has two arguments: (path, argv), where - argv is a list or tuple of strings. */ - - if (!PyList_Check(argv) && !PyTuple_Check(argv)) { - PyErr_SetString(PyExc_TypeError, - "execv() arg 2 must be a tuple or list"); - return NULL; - } - argc = PySequence_Size(argv); - if (argc < 1) { - PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty"); - return NULL; - } - - argvlist = parse_arglist(argv, &argc); - if (argvlist == NULL) { - return NULL; - } - if (!argvlist[0][0]) { - PyErr_SetString(PyExc_ValueError, - "execv() arg 2 first element cannot be empty"); - free_string_array(argvlist, argc); - return NULL; - } - - if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) { - free_string_array(argvlist, argc); - return NULL; - } - - _Py_BEGIN_SUPPRESS_IPH -#ifdef HAVE_WEXECV - _wexecv(path->wide, argvlist); -#else - execv(path->narrow, argvlist); -#endif - _Py_END_SUPPRESS_IPH - - /* If we get here it's definitely an error */ - - free_string_array(argvlist, argc); - return posix_error(); -} - - -/*[clinic input] -os.execve - - path: path_t(allow_fd='PATH_HAVE_FEXECVE') - Path of executable file. - argv: object - Tuple or list of strings. - env: object - Dictionary of strings mapping to strings. - -Execute an executable path with arguments, replacing current process. -[clinic start generated code]*/ - -static PyObject * -os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env) -/*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/ -{ - EXECV_CHAR **argvlist = NULL; - EXECV_CHAR **envlist; - Py_ssize_t argc, envc; - - PyInterpreterState *interp = _PyInterpreterState_GET(); - if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) { - PyErr_SetString(PyExc_RuntimeError, - "exec not supported for isolated subinterpreters"); - return NULL; - } - - /* execve has three arguments: (path, argv, env), where - argv is a list or tuple of strings and env is a dictionary - like posix.environ. */ - - if (!PyList_Check(argv) && !PyTuple_Check(argv)) { - PyErr_SetString(PyExc_TypeError, - "execve: argv must be a tuple or list"); - goto fail_0; - } - argc = PySequence_Size(argv); - if (argc < 1) { - PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty"); - return NULL; - } - - if (!PyMapping_Check(env)) { - PyErr_SetString(PyExc_TypeError, - "execve: environment must be a mapping object"); - goto fail_0; - } - - argvlist = parse_arglist(argv, &argc); - if (argvlist == NULL) { - goto fail_0; - } - if (!argvlist[0][0]) { - PyErr_SetString(PyExc_ValueError, - "execve: argv first element cannot be empty"); - goto fail_0; - } - - envlist = parse_envlist(env, &envc); - if (envlist == NULL) - goto fail_0; - - if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) { - goto fail_1; - } - - _Py_BEGIN_SUPPRESS_IPH -#ifdef HAVE_FEXECVE - if (path->fd > -1) - fexecve(path->fd, argvlist, envlist); - else -#endif -#ifdef HAVE_WEXECV - _wexecve(path->wide, argvlist, envlist); -#else - execve(path->narrow, argvlist, envlist); -#endif - _Py_END_SUPPRESS_IPH - - /* If we get here it's definitely an error */ - - posix_path_error(path); - fail_1: - free_string_array(envlist, envc); - fail_0: - if (argvlist) - free_string_array(argvlist, argc); - return NULL; -} - -#endif /* HAVE_EXECV */ - -#ifdef HAVE_POSIX_SPAWN - -enum posix_spawn_file_actions_identifier { - POSIX_SPAWN_OPEN, - POSIX_SPAWN_CLOSE, - POSIX_SPAWN_DUP2 -}; - -#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) -static int -convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res); -#endif - -static int -parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup, - int resetids, int setsid, PyObject *setsigmask, - PyObject *setsigdef, PyObject *scheduler, - posix_spawnattr_t *attrp) -{ - long all_flags = 0; - - errno = posix_spawnattr_init(attrp); - if (errno) { - posix_error(); - return -1; - } - - if (setpgroup) { - pid_t pgid = PyLong_AsPid(setpgroup); - if (pgid == (pid_t)-1 && PyErr_Occurred()) { - goto fail; - } - errno = posix_spawnattr_setpgroup(attrp, pgid); - if (errno) { - posix_error(); - goto fail; - } - all_flags |= POSIX_SPAWN_SETPGROUP; - } - - if (resetids) { - all_flags |= POSIX_SPAWN_RESETIDS; - } - - if (setsid) { -#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME - if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) { -#endif -#ifdef POSIX_SPAWN_SETSID - all_flags |= POSIX_SPAWN_SETSID; -#elif defined(POSIX_SPAWN_SETSID_NP) - all_flags |= POSIX_SPAWN_SETSID_NP; -#else - argument_unavailable_error(func_name, "setsid"); - return -1; -#endif - -#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME - } else { - argument_unavailable_error(func_name, "setsid"); - return -1; - } -#endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */ - - } - -#ifdef HAVE_SIGSET_T - if (setsigmask) { - sigset_t set; - if (!_Py_Sigset_Converter(setsigmask, &set)) { - goto fail; - } - errno = posix_spawnattr_setsigmask(attrp, &set); - if (errno) { - posix_error(); - goto fail; - } - all_flags |= POSIX_SPAWN_SETSIGMASK; - } - - if (setsigdef) { - sigset_t set; - if (!_Py_Sigset_Converter(setsigdef, &set)) { - goto fail; - } - errno = posix_spawnattr_setsigdefault(attrp, &set); - if (errno) { - posix_error(); - goto fail; - } - all_flags |= POSIX_SPAWN_SETSIGDEF; - } -#else - if (setsigmask || setsigdef) { - PyErr_SetString(PyExc_NotImplementedError, - "sigset is not supported on this platform"); - goto fail; - } -#endif - - if (scheduler) { -#ifdef POSIX_SPAWN_SETSCHEDULER - PyObject *py_schedpolicy; - PyObject *schedparam_obj; - struct sched_param schedparam; - - if (!PyArg_ParseTuple(scheduler, "OO" - ";A scheduler tuple must have two elements", - &py_schedpolicy, &schedparam_obj)) { - goto fail; - } - if (!convert_sched_param(module, schedparam_obj, &schedparam)) { - goto fail; - } - if (py_schedpolicy != Py_None) { - int schedpolicy = _PyLong_AsInt(py_schedpolicy); - - if (schedpolicy == -1 && PyErr_Occurred()) { - goto fail; - } - errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy); - if (errno) { - posix_error(); - goto fail; - } - all_flags |= POSIX_SPAWN_SETSCHEDULER; - } - errno = posix_spawnattr_setschedparam(attrp, &schedparam); - if (errno) { - posix_error(); - goto fail; - } - all_flags |= POSIX_SPAWN_SETSCHEDPARAM; -#else - PyErr_SetString(PyExc_NotImplementedError, - "The scheduler option is not supported in this system."); - goto fail; -#endif - } - - errno = posix_spawnattr_setflags(attrp, all_flags); - if (errno) { - posix_error(); - goto fail; - } - - return 0; - -fail: - (void)posix_spawnattr_destroy(attrp); - return -1; -} - -static int -parse_file_actions(PyObject *file_actions, - posix_spawn_file_actions_t *file_actionsp, - PyObject *temp_buffer) -{ - PyObject *seq; - PyObject *file_action = NULL; - PyObject *tag_obj; - - seq = PySequence_Fast(file_actions, - "file_actions must be a sequence or None"); - if (seq == NULL) { - return -1; - } - - errno = posix_spawn_file_actions_init(file_actionsp); - if (errno) { - posix_error(); - Py_DECREF(seq); - return -1; - } - - for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) { - file_action = PySequence_Fast_GET_ITEM(seq, i); - Py_INCREF(file_action); - if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) { - PyErr_SetString(PyExc_TypeError, - "Each file_actions element must be a non-empty tuple"); - goto fail; - } - long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0)); - if (tag == -1 && PyErr_Occurred()) { - goto fail; - } - - /* Populate the file_actions object */ - switch (tag) { - case POSIX_SPAWN_OPEN: { - int fd, oflag; - PyObject *path; - unsigned long mode; - if (!PyArg_ParseTuple(file_action, "OiO&ik" - ";A open file_action tuple must have 5 elements", - &tag_obj, &fd, PyUnicode_FSConverter, &path, - &oflag, &mode)) - { - goto fail; - } - if (PyList_Append(temp_buffer, path)) { - Py_DECREF(path); - goto fail; - } - errno = posix_spawn_file_actions_addopen(file_actionsp, - fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode); - Py_DECREF(path); - if (errno) { - posix_error(); - goto fail; - } - break; - } - case POSIX_SPAWN_CLOSE: { - int fd; - if (!PyArg_ParseTuple(file_action, "Oi" - ";A close file_action tuple must have 2 elements", - &tag_obj, &fd)) - { - goto fail; - } - errno = posix_spawn_file_actions_addclose(file_actionsp, fd); - if (errno) { - posix_error(); - goto fail; - } - break; - } - case POSIX_SPAWN_DUP2: { - int fd1, fd2; - if (!PyArg_ParseTuple(file_action, "Oii" - ";A dup2 file_action tuple must have 3 elements", - &tag_obj, &fd1, &fd2)) - { - goto fail; - } - errno = posix_spawn_file_actions_adddup2(file_actionsp, - fd1, fd2); - if (errno) { - posix_error(); - goto fail; - } - break; - } - default: { - PyErr_SetString(PyExc_TypeError, - "Unknown file_actions identifier"); - goto fail; - } - } - Py_DECREF(file_action); - } - - Py_DECREF(seq); - return 0; - -fail: - Py_DECREF(seq); - Py_DECREF(file_action); - (void)posix_spawn_file_actions_destroy(file_actionsp); - return -1; -} - - -static PyObject * -py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv, - PyObject *env, PyObject *file_actions, - PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask, - PyObject *setsigdef, PyObject *scheduler) -{ - const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn"; - EXECV_CHAR **argvlist = NULL; - EXECV_CHAR **envlist = NULL; - posix_spawn_file_actions_t file_actions_buf; - posix_spawn_file_actions_t *file_actionsp = NULL; - posix_spawnattr_t attr; - posix_spawnattr_t *attrp = NULL; - Py_ssize_t argc, envc; - PyObject *result = NULL; - PyObject *temp_buffer = NULL; - pid_t pid; - int err_code; - - /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where - argv is a list or tuple of strings and env is a dictionary - like posix.environ. */ - - if (!PyList_Check(argv) && !PyTuple_Check(argv)) { - PyErr_Format(PyExc_TypeError, - "%s: argv must be a tuple or list", func_name); - goto exit; - } - argc = PySequence_Size(argv); - if (argc < 1) { - PyErr_Format(PyExc_ValueError, - "%s: argv must not be empty", func_name); - return NULL; - } - - if (!PyMapping_Check(env)) { - PyErr_Format(PyExc_TypeError, - "%s: environment must be a mapping object", func_name); - goto exit; - } - - argvlist = parse_arglist(argv, &argc); - if (argvlist == NULL) { - goto exit; - } - if (!argvlist[0][0]) { - PyErr_Format(PyExc_ValueError, - "%s: argv first element cannot be empty", func_name); - goto exit; - } - - envlist = parse_envlist(env, &envc); - if (envlist == NULL) { - goto exit; - } - - if (file_actions != NULL && file_actions != Py_None) { - /* There is a bug in old versions of glibc that makes some of the - * helper functions for manipulating file actions not copy the provided - * buffers. The problem is that posix_spawn_file_actions_addopen does not - * copy the value of path for some old versions of glibc (<2.20). - * The use of temp_buffer here is a workaround that keeps the - * python objects that own the buffers alive until posix_spawn gets called. - * Check https://bugs.python.org/issue33630 and - * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/ - temp_buffer = PyList_New(0); - if (!temp_buffer) { - goto exit; - } - if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) { - goto exit; - } - file_actionsp = &file_actions_buf; - } - - if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid, - setsigmask, setsigdef, scheduler, &attr)) { - goto exit; - } - attrp = &attr; - - if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) { - goto exit; - } - - _Py_BEGIN_SUPPRESS_IPH -#ifdef HAVE_POSIX_SPAWNP - if (use_posix_spawnp) { - err_code = posix_spawnp(&pid, path->narrow, - file_actionsp, attrp, argvlist, envlist); - } - else -#endif /* HAVE_POSIX_SPAWNP */ - { - err_code = posix_spawn(&pid, path->narrow, - file_actionsp, attrp, argvlist, envlist); - } - _Py_END_SUPPRESS_IPH - - if (err_code) { - errno = err_code; - PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object); - goto exit; - } -#ifdef _Py_MEMORY_SANITIZER - __msan_unpoison(&pid, sizeof(pid)); -#endif - result = PyLong_FromPid(pid); - -exit: - if (file_actionsp) { - (void)posix_spawn_file_actions_destroy(file_actionsp); - } - if (attrp) { - (void)posix_spawnattr_destroy(attrp); - } - if (envlist) { - free_string_array(envlist, envc); - } - if (argvlist) { - free_string_array(argvlist, argc); - } - Py_XDECREF(temp_buffer); - return result; -} - - -/*[clinic input] - -os.posix_spawn - path: path_t - Path of executable file. - argv: object - Tuple or list of strings. - env: object - Dictionary of strings mapping to strings. - / - * - file_actions: object(c_default='NULL') = () - A sequence of file action tuples. - setpgroup: object = NULL - The pgroup to use with the POSIX_SPAWN_SETPGROUP flag. - resetids: bool(accept={int}) = False - If the value is `true` the POSIX_SPAWN_RESETIDS will be activated. - setsid: bool(accept={int}) = False - If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated. - setsigmask: object(c_default='NULL') = () - The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag. - setsigdef: object(c_default='NULL') = () - The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag. - scheduler: object = NULL - A tuple with the scheduler policy (optional) and parameters. - -Execute the program specified by path in a new process. -[clinic start generated code]*/ - -static PyObject * -os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, - PyObject *env, PyObject *file_actions, - PyObject *setpgroup, int resetids, int setsid, - PyObject *setsigmask, PyObject *setsigdef, - PyObject *scheduler) -/*[clinic end generated code: output=14a1098c566bc675 input=8c6305619a00ad04]*/ -{ - return py_posix_spawn(0, module, path, argv, env, file_actions, - setpgroup, resetids, setsid, setsigmask, setsigdef, - scheduler); -} - #endif /* HAVE_POSIX_SPAWN */ - - - -#ifdef HAVE_POSIX_SPAWNP -/*[clinic input] - -os.posix_spawnp - path: path_t - Path of executable file. - argv: object - Tuple or list of strings. - env: object - Dictionary of strings mapping to strings. - / - * - file_actions: object(c_default='NULL') = () - A sequence of file action tuples. - setpgroup: object = NULL - The pgroup to use with the POSIX_SPAWN_SETPGROUP flag. - resetids: bool(accept={int}) = False - If the value is `True` the POSIX_SPAWN_RESETIDS will be activated. - setsid: bool(accept={int}) = False - If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated. - setsigmask: object(c_default='NULL') = () - The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag. - setsigdef: object(c_default='NULL') = () - The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag. - scheduler: object = NULL - A tuple with the scheduler policy (optional) and parameters. - -Execute the program specified by path in a new process. -[clinic start generated code]*/ - -static PyObject * -os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv, - PyObject *env, PyObject *file_actions, - PyObject *setpgroup, int resetids, int setsid, - PyObject *setsigmask, PyObject *setsigdef, - PyObject *scheduler) -/*[clinic end generated code: output=7b9aaefe3031238d input=c1911043a22028da]*/ -{ - return py_posix_spawn(1, module, path, argv, env, file_actions, - setpgroup, resetids, setsid, setsigmask, setsigdef, - scheduler); -} -#endif /* HAVE_POSIX_SPAWNP */ - -#ifdef HAVE_RTPSPAWN -static intptr_t -_rtp_spawn(int mode, const char *rtpFileName, const char *argv[], - const char *envp[]) -{ - RTP_ID rtpid; - int status; - pid_t res; - int async_err = 0; - - /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes. - uStackSize=0 cannot be used, the default stack size is too small for - Python. */ - if (envp) { - rtpid = rtpSpawn(rtpFileName, argv, envp, - 100, 0x1000000, 0, VX_FP_TASK); - } - else { - rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ, - 100, 0x1000000, 0, VX_FP_TASK); - } - if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) { - do { - res = waitpid((pid_t)rtpid, &status, 0); - } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - - if (res < 0) - return RTP_ID_ERROR; - return ((intptr_t)status); - } - return ((intptr_t)rtpid); -} -#endif - -#if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN) -/*[clinic input] -os.spawnv - - mode: int - Mode of process creation. - path: path_t - Path of executable file. - argv: object - Tuple or list of strings. - / - -Execute the program specified by path in a new process. -[clinic start generated code]*/ - -static PyObject * -os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv) -/*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/ -{ - EXECV_CHAR **argvlist; - int i; - Py_ssize_t argc; - intptr_t spawnval; - PyObject *(*getitem)(PyObject *, Py_ssize_t); - - /* spawnv has three arguments: (mode, path, argv), where - argv is a list or tuple of strings. */ - - if (PyList_Check(argv)) { - argc = PyList_Size(argv); - getitem = PyList_GetItem; - } - else if (PyTuple_Check(argv)) { - argc = PyTuple_Size(argv); - getitem = PyTuple_GetItem; - } - else { - PyErr_SetString(PyExc_TypeError, - "spawnv() arg 2 must be a tuple or list"); - return NULL; - } - if (argc == 0) { - PyErr_SetString(PyExc_ValueError, - "spawnv() arg 2 cannot be empty"); - return NULL; - } - - argvlist = PyMem_NEW(EXECV_CHAR *, argc+1); - if (argvlist == NULL) { - return PyErr_NoMemory(); - } - for (i = 0; i < argc; i++) { - if (!fsconvert_strdup((*getitem)(argv, i), - &argvlist[i])) { - free_string_array(argvlist, i); - PyErr_SetString( - PyExc_TypeError, - "spawnv() arg 2 must contain only strings"); - return NULL; - } - if (i == 0 && !argvlist[0][0]) { - free_string_array(argvlist, i + 1); - PyErr_SetString( - PyExc_ValueError, - "spawnv() arg 2 first element cannot be empty"); - return NULL; - } - } - argvlist[argc] = NULL; - -#if !defined(HAVE_RTPSPAWN) - if (mode == _OLD_P_OVERLAY) - mode = _P_OVERLAY; -#endif - - if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, - Py_None) < 0) { - free_string_array(argvlist, argc); - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH -#ifdef HAVE_WSPAWNV - spawnval = _wspawnv(mode, path->wide, argvlist); -#elif defined(HAVE_RTPSPAWN) - spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL); -#else - spawnval = _spawnv(mode, path->narrow, argvlist); -#endif - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - - free_string_array(argvlist, argc); - - if (spawnval == -1) - return posix_error(); - else - return Py_BuildValue(_Py_PARSE_INTPTR, spawnval); -} - -/*[clinic input] -os.spawnve - - mode: int - Mode of process creation. - path: path_t - Path of executable file. - argv: object - Tuple or list of strings. - env: object - Dictionary of strings mapping to strings. - / - -Execute the program specified by path in a new process. -[clinic start generated code]*/ - -static PyObject * -os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv, - PyObject *env) -/*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/ -{ - EXECV_CHAR **argvlist; - EXECV_CHAR **envlist; - PyObject *res = NULL; - Py_ssize_t argc, i, envc; - intptr_t spawnval; - PyObject *(*getitem)(PyObject *, Py_ssize_t); - Py_ssize_t lastarg = 0; - - /* spawnve has four arguments: (mode, path, argv, env), where - argv is a list or tuple of strings and env is a dictionary - like posix.environ. */ - - if (PyList_Check(argv)) { - argc = PyList_Size(argv); - getitem = PyList_GetItem; - } - else if (PyTuple_Check(argv)) { - argc = PyTuple_Size(argv); - getitem = PyTuple_GetItem; - } - else { - PyErr_SetString(PyExc_TypeError, - "spawnve() arg 2 must be a tuple or list"); - goto fail_0; - } - if (argc == 0) { - PyErr_SetString(PyExc_ValueError, - "spawnve() arg 2 cannot be empty"); - goto fail_0; - } - if (!PyMapping_Check(env)) { - PyErr_SetString(PyExc_TypeError, - "spawnve() arg 3 must be a mapping object"); - goto fail_0; - } - - argvlist = PyMem_NEW(EXECV_CHAR *, argc+1); - if (argvlist == NULL) { - PyErr_NoMemory(); - goto fail_0; - } - for (i = 0; i < argc; i++) { - if (!fsconvert_strdup((*getitem)(argv, i), - &argvlist[i])) - { - lastarg = i; - goto fail_1; - } - if (i == 0 && !argvlist[0][0]) { - lastarg = i + 1; - PyErr_SetString( - PyExc_ValueError, - "spawnv() arg 2 first element cannot be empty"); - goto fail_1; - } - } - lastarg = argc; - argvlist[argc] = NULL; - - envlist = parse_envlist(env, &envc); - if (envlist == NULL) - goto fail_1; - -#if !defined(HAVE_RTPSPAWN) - if (mode == _OLD_P_OVERLAY) - mode = _P_OVERLAY; -#endif - - if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) { - goto fail_2; - } - - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH -#ifdef HAVE_WSPAWNV - spawnval = _wspawnve(mode, path->wide, argvlist, envlist); -#elif defined(HAVE_RTPSPAWN) - spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, - (const char **)envlist); -#else - spawnval = _spawnve(mode, path->narrow, argvlist, envlist); -#endif - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - - if (spawnval == -1) - (void) posix_error(); - else - res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval); - - fail_2: - while (--envc >= 0) { - PyMem_Free(envlist[envc]); - } - PyMem_Free(envlist); - fail_1: - free_string_array(argvlist, lastarg); - fail_0: - return res; -} - -#endif /* HAVE_SPAWNV */ - -#ifdef HAVE_FORK - -/* Helper function to validate arguments. - Returns 0 on success. non-zero on failure with a TypeError raised. - If obj is non-NULL it must be callable. */ -static int -check_null_or_callable(PyObject *obj, const char* obj_name) -{ - if (obj && !PyCallable_Check(obj)) { - PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s", - obj_name, _PyType_Name(Py_TYPE(obj))); - return -1; - } - return 0; -} - -/*[clinic input] -os.register_at_fork - - * - before: object=NULL - A callable to be called in the parent before the fork() syscall. - after_in_child: object=NULL - A callable to be called in the child after fork(). - after_in_parent: object=NULL - A callable to be called in the parent after fork(). - -Register callables to be called when forking a new process. - -'before' callbacks are called in reverse order. -'after_in_child' and 'after_in_parent' callbacks are called in order. - -[clinic start generated code]*/ - -static PyObject * -os_register_at_fork_impl(PyObject *module, PyObject *before, - PyObject *after_in_child, PyObject *after_in_parent) -/*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/ -{ - PyInterpreterState *interp; - - if (!before && !after_in_child && !after_in_parent) { - PyErr_SetString(PyExc_TypeError, "At least one argument is required."); - return NULL; - } - if (check_null_or_callable(before, "before") || - check_null_or_callable(after_in_child, "after_in_child") || - check_null_or_callable(after_in_parent, "after_in_parent")) { - return NULL; - } - interp = _PyInterpreterState_GET(); - - if (register_at_forker(&interp->before_forkers, before)) { - return NULL; - } - if (register_at_forker(&interp->after_forkers_child, after_in_child)) { - return NULL; - } - if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) { - return NULL; - } - Py_RETURN_NONE; -} -#endif /* HAVE_FORK */ - - -#ifdef HAVE_FORK1 -/*[clinic input] -os.fork1 - -Fork a child process with a single multiplexed (i.e., not bound) thread. - -Return 0 to child process and PID of child to parent process. -[clinic start generated code]*/ - -static PyObject * -os_fork1_impl(PyObject *module) -/*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/ -{ - pid_t pid; - - if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) { - PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters"); - return NULL; - } - PyOS_BeforeFork(); - pid = fork1(); - if (pid == 0) { - /* child: this clobbers and resets the import lock. */ - PyOS_AfterFork_Child(); - } else { - /* parent: release the import lock. */ - PyOS_AfterFork_Parent(); - } - if (pid == -1) - return posix_error(); - return PyLong_FromPid(pid); -} -#endif /* HAVE_FORK1 */ - - -#ifdef HAVE_FORK -/*[clinic input] -os.fork - -Fork a child process. - -Return 0 to child process and PID of child to parent process. -[clinic start generated code]*/ - -static PyObject * -os_fork_impl(PyObject *module) -/*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/ -{ - pid_t pid; - PyInterpreterState *interp = _PyInterpreterState_GET(); - if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_FORK)) { - PyErr_SetString(PyExc_RuntimeError, - "fork not supported for isolated subinterpreters"); - return NULL; - } - if (PySys_Audit("os.fork", NULL) < 0) { - return NULL; - } - PyOS_BeforeFork(); - pid = fork(); - if (pid == 0) { - /* child: this clobbers and resets the import lock. */ - PyOS_AfterFork_Child(); - } else { - /* parent: release the import lock. */ - PyOS_AfterFork_Parent(); - } - if (pid == -1) - return posix_error(); - return PyLong_FromPid(pid); -} -#endif /* HAVE_FORK */ - - -#ifdef HAVE_SCHED_H -#ifdef HAVE_SCHED_GET_PRIORITY_MAX -/*[clinic input] -os.sched_get_priority_max - - policy: int - -Get the maximum scheduling priority for policy. -[clinic start generated code]*/ - -static PyObject * -os_sched_get_priority_max_impl(PyObject *module, int policy) -/*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/ -{ - int max; - - max = sched_get_priority_max(policy); - if (max < 0) - return posix_error(); - return PyLong_FromLong(max); -} - - -/*[clinic input] -os.sched_get_priority_min - - policy: int - -Get the minimum scheduling priority for policy. -[clinic start generated code]*/ - -static PyObject * -os_sched_get_priority_min_impl(PyObject *module, int policy) -/*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/ -{ - int min = sched_get_priority_min(policy); - if (min < 0) - return posix_error(); - return PyLong_FromLong(min); -} -#endif /* HAVE_SCHED_GET_PRIORITY_MAX */ - - -#ifdef HAVE_SCHED_SETSCHEDULER -/*[clinic input] -os.sched_getscheduler - pid: pid_t - / - -Get the scheduling policy for the process identified by pid. - -Passing 0 for pid returns the scheduling policy for the calling process. -[clinic start generated code]*/ - -static PyObject * -os_sched_getscheduler_impl(PyObject *module, pid_t pid) -/*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/ -{ - int policy; - - policy = sched_getscheduler(pid); - if (policy < 0) - return posix_error(); - return PyLong_FromLong(policy); -} -#endif /* HAVE_SCHED_SETSCHEDULER */ - - -#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) -/*[clinic input] -class os.sched_param "PyObject *" "SchedParamType" - -@classmethod -os.sched_param.__new__ - - sched_priority: object - A scheduling parameter. - -Currently has only one field: sched_priority -[clinic start generated code]*/ - -static PyObject * -os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority) -/*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/ -{ - PyObject *res; - - res = PyStructSequence_New(type); - if (!res) - return NULL; - PyStructSequence_SET_ITEM(res, 0, Py_NewRef(sched_priority)); - return res; -} - -PyDoc_VAR(os_sched_param__doc__); - -static PyStructSequence_Field sched_param_fields[] = { - {"sched_priority", "the scheduling priority"}, - {0} -}; - -static PyStructSequence_Desc sched_param_desc = { - "sched_param", /* name */ - os_sched_param__doc__, /* doc */ - sched_param_fields, - 1 -}; - -static int -convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res) -{ - long priority; - - if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) { - PyErr_SetString(PyExc_TypeError, "must have a sched_param object"); - return 0; - } - priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0)); - if (priority == -1 && PyErr_Occurred()) - return 0; - if (priority > INT_MAX || priority < INT_MIN) { - PyErr_SetString(PyExc_OverflowError, "sched_priority out of range"); - return 0; - } - res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int); - return 1; -} -#endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */ - - -#ifdef HAVE_SCHED_SETSCHEDULER -/*[clinic input] -os.sched_setscheduler - - pid: pid_t - policy: int - param as param_obj: object - / - -Set the scheduling policy for the process identified by pid. - -If pid is 0, the calling process is changed. -param is an instance of sched_param. -[clinic start generated code]*/ - -static PyObject * -os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy, - PyObject *param_obj) -/*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/ -{ - struct sched_param param; - if (!convert_sched_param(module, param_obj, ¶m)) { - return NULL; - } - - /* - ** sched_setscheduler() returns 0 in Linux, but the previous - ** scheduling policy under Solaris/Illumos, and others. - ** On error, -1 is returned in all Operating Systems. - */ - if (sched_setscheduler(pid, policy, ¶m) == -1) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SCHED_SETSCHEDULER*/ - - -#ifdef HAVE_SCHED_SETPARAM -/*[clinic input] -os.sched_getparam - pid: pid_t - / - -Returns scheduling parameters for the process identified by pid. - -If pid is 0, returns parameters for the calling process. -Return value is an instance of sched_param. -[clinic start generated code]*/ - -static PyObject * -os_sched_getparam_impl(PyObject *module, pid_t pid) -/*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/ -{ - struct sched_param param; - PyObject *result; - PyObject *priority; - - if (sched_getparam(pid, ¶m)) - return posix_error(); - PyObject *SchedParamType = get_posix_state(module)->SchedParamType; - result = PyStructSequence_New((PyTypeObject *)SchedParamType); - if (!result) - return NULL; - priority = PyLong_FromLong(param.sched_priority); - if (!priority) { - Py_DECREF(result); - return NULL; - } - PyStructSequence_SET_ITEM(result, 0, priority); - return result; -} - - -/*[clinic input] -os.sched_setparam - pid: pid_t - param as param_obj: object - / - -Set scheduling parameters for the process identified by pid. - -If pid is 0, sets parameters for the calling process. -param should be an instance of sched_param. -[clinic start generated code]*/ - -static PyObject * -os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj) -/*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/ -{ - struct sched_param param; - if (!convert_sched_param(module, param_obj, ¶m)) { - return NULL; - } - - if (sched_setparam(pid, ¶m)) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SCHED_SETPARAM */ - - -#ifdef HAVE_SCHED_RR_GET_INTERVAL -/*[clinic input] -os.sched_rr_get_interval -> double - pid: pid_t - / - -Return the round-robin quantum for the process identified by pid, in seconds. - -Value returned is a float. -[clinic start generated code]*/ - -static double -os_sched_rr_get_interval_impl(PyObject *module, pid_t pid) -/*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/ -{ - struct timespec interval; - if (sched_rr_get_interval(pid, &interval)) { - posix_error(); - return -1.0; - } -#ifdef _Py_MEMORY_SANITIZER - __msan_unpoison(&interval, sizeof(interval)); -#endif - return (double)interval.tv_sec + 1e-9*interval.tv_nsec; -} -#endif /* HAVE_SCHED_RR_GET_INTERVAL */ - - -/*[clinic input] -os.sched_yield - -Voluntarily relinquish the CPU. -[clinic start generated code]*/ - -static PyObject * -os_sched_yield_impl(PyObject *module) -/*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/ -{ - int result; - Py_BEGIN_ALLOW_THREADS - result = sched_yield(); - Py_END_ALLOW_THREADS - if (result < 0) { - return posix_error(); - } - Py_RETURN_NONE; -} - -#ifdef HAVE_SCHED_SETAFFINITY -/* The minimum number of CPUs allocated in a cpu_set_t */ -static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT; - -/*[clinic input] -os.sched_setaffinity - pid: pid_t - mask : object - / - -Set the CPU affinity of the process identified by pid to mask. - -mask should be an iterable of integers identifying CPUs. -[clinic start generated code]*/ - -static PyObject * -os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask) -/*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/ -{ - int ncpus; - size_t setsize; - cpu_set_t *cpu_set = NULL; - PyObject *iterator = NULL, *item; - - iterator = PyObject_GetIter(mask); - if (iterator == NULL) - return NULL; - - ncpus = NCPUS_START; - setsize = CPU_ALLOC_SIZE(ncpus); - cpu_set = CPU_ALLOC(ncpus); - if (cpu_set == NULL) { - PyErr_NoMemory(); - goto error; - } - CPU_ZERO_S(setsize, cpu_set); - - while ((item = PyIter_Next(iterator))) { - long cpu; - if (!PyLong_Check(item)) { - PyErr_Format(PyExc_TypeError, - "expected an iterator of ints, " - "but iterator yielded %R", - Py_TYPE(item)); - Py_DECREF(item); - goto error; - } - cpu = PyLong_AsLong(item); - Py_DECREF(item); - if (cpu < 0) { - if (!PyErr_Occurred()) - PyErr_SetString(PyExc_ValueError, "negative CPU number"); - goto error; - } - if (cpu > INT_MAX - 1) { - PyErr_SetString(PyExc_OverflowError, "CPU number too large"); - goto error; - } - if (cpu >= ncpus) { - /* Grow CPU mask to fit the CPU number */ - int newncpus = ncpus; - cpu_set_t *newmask; - size_t newsetsize; - while (newncpus <= cpu) { - if (newncpus > INT_MAX / 2) - newncpus = cpu + 1; - else - newncpus = newncpus * 2; - } - newmask = CPU_ALLOC(newncpus); - if (newmask == NULL) { - PyErr_NoMemory(); - goto error; - } - newsetsize = CPU_ALLOC_SIZE(newncpus); - CPU_ZERO_S(newsetsize, newmask); - memcpy(newmask, cpu_set, setsize); - CPU_FREE(cpu_set); - setsize = newsetsize; - cpu_set = newmask; - ncpus = newncpus; - } - CPU_SET_S(cpu, setsize, cpu_set); - } - if (PyErr_Occurred()) { - goto error; - } - Py_CLEAR(iterator); - - if (sched_setaffinity(pid, setsize, cpu_set)) { - posix_error(); - goto error; - } - CPU_FREE(cpu_set); - Py_RETURN_NONE; - -error: - if (cpu_set) - CPU_FREE(cpu_set); - Py_XDECREF(iterator); - return NULL; -} - - -/*[clinic input] -os.sched_getaffinity - pid: pid_t - / - -Return the affinity of the process identified by pid (or the current process if zero). - -The affinity is returned as a set of CPU identifiers. -[clinic start generated code]*/ - -static PyObject * -os_sched_getaffinity_impl(PyObject *module, pid_t pid) -/*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/ -{ - int cpu, ncpus, count; - size_t setsize; - cpu_set_t *mask = NULL; - PyObject *res = NULL; - - ncpus = NCPUS_START; - while (1) { - setsize = CPU_ALLOC_SIZE(ncpus); - mask = CPU_ALLOC(ncpus); - if (mask == NULL) - return PyErr_NoMemory(); - if (sched_getaffinity(pid, setsize, mask) == 0) - break; - CPU_FREE(mask); - if (errno != EINVAL) - return posix_error(); - if (ncpus > INT_MAX / 2) { - PyErr_SetString(PyExc_OverflowError, "could not allocate " - "a large enough CPU set"); - return NULL; - } - ncpus = ncpus * 2; - } - - res = PySet_New(NULL); - if (res == NULL) - goto error; - for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) { - if (CPU_ISSET_S(cpu, setsize, mask)) { - PyObject *cpu_num = PyLong_FromLong(cpu); - --count; - if (cpu_num == NULL) - goto error; - if (PySet_Add(res, cpu_num)) { - Py_DECREF(cpu_num); - goto error; - } - Py_DECREF(cpu_num); - } - } - CPU_FREE(mask); - return res; - -error: - if (mask) - CPU_FREE(mask); - Py_XDECREF(res); - return NULL; -} - -#endif /* HAVE_SCHED_SETAFFINITY */ - -#endif /* HAVE_SCHED_H */ - - -/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */ -#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX) -# define DEV_PTY_FILE "/dev/ptc" -# define HAVE_DEV_PTMX -#else -# define DEV_PTY_FILE "/dev/ptmx" -#endif - -#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) -#ifdef HAVE_PTY_H -#include -#ifdef HAVE_UTMP_H -#include -#endif /* HAVE_UTMP_H */ -#elif defined(HAVE_LIBUTIL_H) -#include -#elif defined(HAVE_UTIL_H) -#include -#endif /* HAVE_PTY_H */ -#ifdef HAVE_STROPTS_H -#include -#endif -#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */ - - -#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) -/*[clinic input] -os.openpty - -Open a pseudo-terminal. - -Return a tuple of (master_fd, slave_fd) containing open file descriptors -for both the master and slave ends. -[clinic start generated code]*/ - -static PyObject * -os_openpty_impl(PyObject *module) -/*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/ -{ - int master_fd = -1, slave_fd = -1; -#ifndef HAVE_OPENPTY - char * slave_name; -#endif -#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY) - PyOS_sighandler_t sig_saved; -#if defined(__sun) && defined(__SVR4) - extern char *ptsname(int fildes); -#endif -#endif - -#ifdef HAVE_OPENPTY - if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0) - goto posix_error; - - if (_Py_set_inheritable(master_fd, 0, NULL) < 0) - goto error; - if (_Py_set_inheritable(slave_fd, 0, NULL) < 0) - goto error; - -#elif defined(HAVE__GETPTY) - slave_name = _getpty(&master_fd, O_RDWR, 0666, 0); - if (slave_name == NULL) - goto posix_error; - if (_Py_set_inheritable(master_fd, 0, NULL) < 0) - goto error; - - slave_fd = _Py_open(slave_name, O_RDWR); - if (slave_fd < 0) - goto error; - -#else - master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */ - if (master_fd < 0) - goto posix_error; - - sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL); - - /* change permission of slave */ - if (grantpt(master_fd) < 0) { - PyOS_setsig(SIGCHLD, sig_saved); - goto posix_error; - } - - /* unlock slave */ - if (unlockpt(master_fd) < 0) { - PyOS_setsig(SIGCHLD, sig_saved); - goto posix_error; - } - - PyOS_setsig(SIGCHLD, sig_saved); - - slave_name = ptsname(master_fd); /* get name of slave */ - if (slave_name == NULL) - goto posix_error; - - slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */ - if (slave_fd == -1) - goto error; - - if (_Py_set_inheritable(master_fd, 0, NULL) < 0) - goto posix_error; - -#if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC) - ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */ - ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */ -#ifndef __hpux - ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */ -#endif /* __hpux */ -#endif /* HAVE_CYGWIN */ -#endif /* HAVE_OPENPTY */ - - return Py_BuildValue("(ii)", master_fd, slave_fd); - -posix_error: - posix_error(); -error: - if (master_fd != -1) - close(master_fd); - if (slave_fd != -1) - close(slave_fd); - return NULL; -} -#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */ - - -#if defined(HAVE_SETSID) && defined(TIOCSCTTY) -#define HAVE_FALLBACK_LOGIN_TTY 1 -#endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */ - -#if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) -/*[clinic input] -os.login_tty - - fd: fildes - / - -Prepare the tty of which fd is a file descriptor for a new login session. - -Make the calling process a session leader; make the tty the -controlling tty, the stdin, the stdout, and the stderr of the -calling process; close fd. -[clinic start generated code]*/ - -static PyObject * -os_login_tty_impl(PyObject *module, int fd) -/*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/ -{ -#ifdef HAVE_LOGIN_TTY - if (login_tty(fd) == -1) { - return posix_error(); - } -#else /* defined(HAVE_FALLBACK_LOGIN_TTY) */ - /* Establish a new session. */ - if (setsid() == -1) { - return posix_error(); - } - - /* The tty becomes the controlling terminal. */ - if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) { - return posix_error(); - } - - /* The tty becomes stdin/stdout/stderr */ - if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) { - return posix_error(); - } - if (fd > 2) { - close(fd); - } -#endif /* HAVE_LOGIN_TTY */ - Py_RETURN_NONE; -} -#endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */ - - -#ifdef HAVE_FORKPTY -/*[clinic input] -os.forkpty - -Fork a new process with a new pseudo-terminal as controlling tty. - -Returns a tuple of (pid, master_fd). -Like fork(), return pid of 0 to the child process, -and pid of child to the parent process. -To both, return fd of newly opened pseudo-terminal. -[clinic start generated code]*/ - -static PyObject * -os_forkpty_impl(PyObject *module) -/*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/ -{ - int master_fd = -1; - pid_t pid; - - if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) { - PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters"); - return NULL; - } - if (PySys_Audit("os.forkpty", NULL) < 0) { - return NULL; - } - PyOS_BeforeFork(); - pid = forkpty(&master_fd, NULL, NULL, NULL); - if (pid == 0) { - /* child: this clobbers and resets the import lock. */ - PyOS_AfterFork_Child(); - } else { - /* parent: release the import lock. */ - PyOS_AfterFork_Parent(); - } - if (pid == -1) { - return posix_error(); - } - return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd); -} -#endif /* HAVE_FORKPTY */ - - -#ifdef HAVE_GETEGID -/*[clinic input] -os.getegid - -Return the current process's effective group id. -[clinic start generated code]*/ - -static PyObject * -os_getegid_impl(PyObject *module) -/*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/ -{ - return _PyLong_FromGid(getegid()); -} -#endif /* HAVE_GETEGID */ - - -#ifdef HAVE_GETEUID -/*[clinic input] -os.geteuid - -Return the current process's effective user id. -[clinic start generated code]*/ - -static PyObject * -os_geteuid_impl(PyObject *module) -/*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/ -{ - return _PyLong_FromUid(geteuid()); -} -#endif /* HAVE_GETEUID */ - - -#ifdef HAVE_GETGID -/*[clinic input] -os.getgid - -Return the current process's group id. -[clinic start generated code]*/ - -static PyObject * -os_getgid_impl(PyObject *module) -/*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/ -{ - return _PyLong_FromGid(getgid()); -} -#endif /* HAVE_GETGID */ - - -#ifdef HAVE_GETPID -/*[clinic input] -os.getpid - -Return the current process id. -[clinic start generated code]*/ - -static PyObject * -os_getpid_impl(PyObject *module) -/*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/ -{ - return PyLong_FromPid(getpid()); -} -#endif /* HAVE_GETPID */ - -#ifdef NGROUPS_MAX -#define MAX_GROUPS NGROUPS_MAX -#else - /* defined to be 16 on Solaris7, so this should be a small number */ -#define MAX_GROUPS 64 -#endif - -#ifdef HAVE_GETGROUPLIST - -#ifdef __APPLE__ -/*[clinic input] -os.getgrouplist - - user: str - username to lookup - group as basegid: int - base group id of the user - / - -Returns a list of groups to which a user belongs. -[clinic start generated code]*/ - -static PyObject * -os_getgrouplist_impl(PyObject *module, const char *user, int basegid) -/*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/ -#else -/*[clinic input] -os.getgrouplist - - user: str - username to lookup - group as basegid: gid_t - base group id of the user - / - -Returns a list of groups to which a user belongs. -[clinic start generated code]*/ - -static PyObject * -os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid) -/*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/ -#endif -{ - int i, ngroups; - PyObject *list; -#ifdef __APPLE__ - int *groups; -#else - gid_t *groups; -#endif - - /* - * NGROUPS_MAX is defined by POSIX.1 as the maximum - * number of supplimental groups a users can belong to. - * We have to increment it by one because - * getgrouplist() returns both the supplemental groups - * and the primary group, i.e. all of the groups the - * user belongs to. - */ - ngroups = 1 + MAX_GROUPS; - - while (1) { -#ifdef __APPLE__ - groups = PyMem_New(int, ngroups); -#else - groups = PyMem_New(gid_t, ngroups); -#endif - if (groups == NULL) { - return PyErr_NoMemory(); - } - - int old_ngroups = ngroups; - if (getgrouplist(user, basegid, groups, &ngroups) != -1) { - /* Success */ - break; - } - - /* getgrouplist() fails if the group list is too small */ - PyMem_Free(groups); - - if (ngroups > old_ngroups) { - /* If the group list is too small, the glibc implementation of - getgrouplist() sets ngroups to the total number of groups and - returns -1. */ - } - else { - /* Double the group list size */ - if (ngroups > INT_MAX / 2) { - return PyErr_NoMemory(); - } - ngroups *= 2; - } - - /* Retry getgrouplist() with a larger group list */ - } - -#ifdef _Py_MEMORY_SANITIZER - /* Clang memory sanitizer libc intercepts don't know getgrouplist. */ - __msan_unpoison(&ngroups, sizeof(ngroups)); - __msan_unpoison(groups, ngroups*sizeof(*groups)); -#endif - - list = PyList_New(ngroups); - if (list == NULL) { - PyMem_Free(groups); - return NULL; - } - - for (i = 0; i < ngroups; i++) { -#ifdef __APPLE__ - PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]); -#else - PyObject *o = _PyLong_FromGid(groups[i]); -#endif - if (o == NULL) { - Py_DECREF(list); - PyMem_Free(groups); - return NULL; - } - PyList_SET_ITEM(list, i, o); - } - - PyMem_Free(groups); - - return list; -} -#endif /* HAVE_GETGROUPLIST */ - - -#ifdef HAVE_GETGROUPS -/*[clinic input] -os.getgroups - -Return list of supplemental group IDs for the process. -[clinic start generated code]*/ - -static PyObject * -os_getgroups_impl(PyObject *module) -/*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/ -{ - // Call getgroups with length 0 to get the actual number of groups - int n = getgroups(0, NULL); - if (n < 0) { - return posix_error(); - } - - if (n == 0) { - return PyList_New(0); - } - - gid_t *grouplist = PyMem_New(gid_t, n); - if (grouplist == NULL) { - return PyErr_NoMemory(); - } - - n = getgroups(n, grouplist); - if (n == -1) { - PyMem_Free(grouplist); - return posix_error(); - } - - PyObject *result = PyList_New(n); - if (result == NULL) { - goto error; - } - - for (int i = 0; i < n; ++i) { - PyObject *group = _PyLong_FromGid(grouplist[i]); - if (group == NULL) { - goto error; - } - PyList_SET_ITEM(result, i, group); - } - PyMem_Free(grouplist); - - return result; - -error: - PyMem_Free(grouplist); - Py_XDECREF(result); - return NULL; -} -#endif /* HAVE_GETGROUPS */ - -#ifdef HAVE_INITGROUPS -#ifdef __APPLE__ -/*[clinic input] -os.initgroups - - username as oname: FSConverter - gid: int - / - -Initialize the group access list. - -Call the system initgroups() to initialize the group access list with all of -the groups of which the specified username is a member, plus the specified -group id. -[clinic start generated code]*/ - -static PyObject * -os_initgroups_impl(PyObject *module, PyObject *oname, int gid) -/*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/ -#else -/*[clinic input] -os.initgroups - - username as oname: FSConverter - gid: gid_t - / - -Initialize the group access list. - -Call the system initgroups() to initialize the group access list with all of -the groups of which the specified username is a member, plus the specified -group id. -[clinic start generated code]*/ - -static PyObject * -os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid) -/*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/ -#endif -{ - const char *username = PyBytes_AS_STRING(oname); - - if (initgroups(username, gid) == -1) - return PyErr_SetFromErrno(PyExc_OSError); - - Py_RETURN_NONE; -} -#endif /* HAVE_INITGROUPS */ - - -#ifdef HAVE_GETPGID -/*[clinic input] -os.getpgid - - pid: pid_t - -Call the system call getpgid(), and return the result. -[clinic start generated code]*/ - -static PyObject * -os_getpgid_impl(PyObject *module, pid_t pid) -/*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/ -{ - pid_t pgid = getpgid(pid); - if (pgid < 0) - return posix_error(); - return PyLong_FromPid(pgid); -} -#endif /* HAVE_GETPGID */ - - -#ifdef HAVE_GETPGRP -/*[clinic input] -os.getpgrp - -Return the current process group id. -[clinic start generated code]*/ - -static PyObject * -os_getpgrp_impl(PyObject *module) -/*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/ -{ -#ifdef GETPGRP_HAVE_ARG - return PyLong_FromPid(getpgrp(0)); -#else /* GETPGRP_HAVE_ARG */ - return PyLong_FromPid(getpgrp()); -#endif /* GETPGRP_HAVE_ARG */ -} -#endif /* HAVE_GETPGRP */ - - -#ifdef HAVE_SETPGRP -/*[clinic input] -os.setpgrp - -Make the current process the leader of its process group. -[clinic start generated code]*/ - -static PyObject * -os_setpgrp_impl(PyObject *module) -/*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/ -{ -#ifdef SETPGRP_HAVE_ARG - if (setpgrp(0, 0) < 0) -#else /* SETPGRP_HAVE_ARG */ - if (setpgrp() < 0) -#endif /* SETPGRP_HAVE_ARG */ - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETPGRP */ - -#ifdef HAVE_GETPPID - -#ifdef MS_WINDOWS -#include - -static PyObject* -win32_getppid() -{ - HANDLE snapshot; - pid_t mypid; - PyObject* result = NULL; - BOOL have_record; - PROCESSENTRY32 pe; - - mypid = getpid(); /* This function never fails */ - - snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (snapshot == INVALID_HANDLE_VALUE) - return PyErr_SetFromWindowsErr(GetLastError()); - - pe.dwSize = sizeof(pe); - have_record = Process32First(snapshot, &pe); - while (have_record) { - if (mypid == (pid_t)pe.th32ProcessID) { - /* We could cache the ulong value in a static variable. */ - result = PyLong_FromPid((pid_t)pe.th32ParentProcessID); - break; - } - - have_record = Process32Next(snapshot, &pe); - } - - /* If our loop exits and our pid was not found (result will be NULL) - * then GetLastError will return ERROR_NO_MORE_FILES. This is an - * error anyway, so let's raise it. */ - if (!result) - result = PyErr_SetFromWindowsErr(GetLastError()); - - CloseHandle(snapshot); - - return result; -} -#endif /*MS_WINDOWS*/ - - -/*[clinic input] -os.getppid - -Return the parent's process id. - -If the parent process has already exited, Windows machines will still -return its id; others systems will return the id of the 'init' process (1). -[clinic start generated code]*/ - -static PyObject * -os_getppid_impl(PyObject *module) -/*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/ -{ -#ifdef MS_WINDOWS - return win32_getppid(); -#else - return PyLong_FromPid(getppid()); -#endif -} -#endif /* HAVE_GETPPID */ - - -#ifdef HAVE_GETLOGIN -/*[clinic input] -os.getlogin - -Return the actual login name. -[clinic start generated code]*/ - -static PyObject * -os_getlogin_impl(PyObject *module) -/*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/ -{ - PyObject *result = NULL; -#ifdef MS_WINDOWS - wchar_t user_name[UNLEN + 1]; - DWORD num_chars = Py_ARRAY_LENGTH(user_name); - - if (GetUserNameW(user_name, &num_chars)) { - /* num_chars is the number of unicode chars plus null terminator */ - result = PyUnicode_FromWideChar(user_name, num_chars - 1); - } - else - result = PyErr_SetFromWindowsErr(GetLastError()); -#else - char *name; - int old_errno = errno; - - errno = 0; - name = getlogin(); - if (name == NULL) { - if (errno) - posix_error(); - else - PyErr_SetString(PyExc_OSError, "unable to determine login name"); - } - else - result = PyUnicode_DecodeFSDefault(name); - errno = old_errno; -#endif - return result; -} -#endif /* HAVE_GETLOGIN */ - - -#ifdef HAVE_GETUID -/*[clinic input] -os.getuid - -Return the current process's user id. -[clinic start generated code]*/ - -static PyObject * -os_getuid_impl(PyObject *module) -/*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/ -{ - return _PyLong_FromUid(getuid()); -} -#endif /* HAVE_GETUID */ - - -#ifdef MS_WINDOWS -#define HAVE_KILL -#endif /* MS_WINDOWS */ - -#ifdef HAVE_KILL -/*[clinic input] -os.kill - - pid: pid_t - signal: Py_ssize_t - / - -Kill a process with a signal. -[clinic start generated code]*/ - -static PyObject * -os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal) -/*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/ -{ - if (PySys_Audit("os.kill", "in", pid, signal) < 0) { - return NULL; - } -#ifndef MS_WINDOWS - if (kill(pid, (int)signal) == -1) { - return posix_error(); - } - - // Check immediately if the signal was sent to the current process. - // Don't micro-optimize pid == getpid(), since PyErr_SetString() check - // is cheap. - if (PyErr_CheckSignals()) { - return NULL; - } - - Py_RETURN_NONE; -#else /* !MS_WINDOWS */ - PyObject *result; - DWORD sig = (DWORD)signal; - DWORD err; - HANDLE handle; - - /* Console processes which share a common console can be sent CTRL+C or - CTRL+BREAK events, provided they handle said events. */ - if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) { - if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) { - err = GetLastError(); - PyErr_SetFromWindowsErr(err); - } - else - Py_RETURN_NONE; - } - - /* If the signal is outside of what GenerateConsoleCtrlEvent can use, - attempt to open and terminate the process. */ - handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid); - if (handle == NULL) { - err = GetLastError(); - return PyErr_SetFromWindowsErr(err); - } - - if (TerminateProcess(handle, sig) == 0) { - err = GetLastError(); - result = PyErr_SetFromWindowsErr(err); - } else { - result = Py_NewRef(Py_None); - } - - CloseHandle(handle); - return result; -#endif /* !MS_WINDOWS */ -} -#endif /* HAVE_KILL */ - - -#ifdef HAVE_KILLPG -/*[clinic input] -os.killpg - - pgid: pid_t - signal: int - / - -Kill a process group with a signal. -[clinic start generated code]*/ - -static PyObject * -os_killpg_impl(PyObject *module, pid_t pgid, int signal) -/*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/ -{ - if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) { - return NULL; - } - /* XXX some man pages make the `pgid` parameter an int, others - a pid_t. Since getpgrp() returns a pid_t, we assume killpg should - take the same type. Moreover, pid_t is always at least as wide as - int (else compilation of this module fails), which is safe. */ - if (killpg(pgid, signal) == -1) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_KILLPG */ - - -#ifdef HAVE_PLOCK -#ifdef HAVE_SYS_LOCK_H -#include -#endif - -/*[clinic input] -os.plock - op: int - / - -Lock program segments into memory."); -[clinic start generated code]*/ - -static PyObject * -os_plock_impl(PyObject *module, int op) -/*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/ -{ - if (plock(op) == -1) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_PLOCK */ - - -#ifdef HAVE_SETUID -/*[clinic input] -os.setuid - - uid: uid_t - / - -Set the current process's user id. -[clinic start generated code]*/ - -static PyObject * -os_setuid_impl(PyObject *module, uid_t uid) -/*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/ -{ - if (setuid(uid) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETUID */ - - -#ifdef HAVE_SETEUID -/*[clinic input] -os.seteuid - - euid: uid_t - / - -Set the current process's effective user id. -[clinic start generated code]*/ - -static PyObject * -os_seteuid_impl(PyObject *module, uid_t euid) -/*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/ -{ - if (seteuid(euid) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETEUID */ - - -#ifdef HAVE_SETEGID -/*[clinic input] -os.setegid - - egid: gid_t - / - -Set the current process's effective group id. -[clinic start generated code]*/ - -static PyObject * -os_setegid_impl(PyObject *module, gid_t egid) -/*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/ -{ - if (setegid(egid) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETEGID */ - - -#ifdef HAVE_SETREUID -/*[clinic input] -os.setreuid - - ruid: uid_t - euid: uid_t - / - -Set the current process's real and effective user ids. -[clinic start generated code]*/ - -static PyObject * -os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid) -/*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/ -{ - if (setreuid(ruid, euid) < 0) { - return posix_error(); - } else { - Py_RETURN_NONE; - } -} -#endif /* HAVE_SETREUID */ - - -#ifdef HAVE_SETREGID -/*[clinic input] -os.setregid - - rgid: gid_t - egid: gid_t - / - -Set the current process's real and effective group ids. -[clinic start generated code]*/ - -static PyObject * -os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid) -/*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/ -{ - if (setregid(rgid, egid) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETREGID */ - - -#ifdef HAVE_SETGID -/*[clinic input] -os.setgid - gid: gid_t - / - -Set the current process's group id. -[clinic start generated code]*/ - -static PyObject * -os_setgid_impl(PyObject *module, gid_t gid) -/*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/ -{ - if (setgid(gid) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETGID */ - - -#ifdef HAVE_SETGROUPS -/*[clinic input] -os.setgroups - - groups: object - / - -Set the groups of the current process to list. -[clinic start generated code]*/ - -static PyObject * -os_setgroups(PyObject *module, PyObject *groups) -/*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/ -{ - if (!PySequence_Check(groups)) { - PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence"); - return NULL; - } - Py_ssize_t len = PySequence_Size(groups); - if (len < 0) { - return NULL; - } - if (len > MAX_GROUPS) { - PyErr_SetString(PyExc_ValueError, "too many groups"); - return NULL; - } - - gid_t *grouplist = PyMem_New(gid_t, len); - for (Py_ssize_t i = 0; i < len; i++) { - PyObject *elem; - elem = PySequence_GetItem(groups, i); - if (!elem) { - PyMem_Free(grouplist); - return NULL; - } - if (!PyLong_Check(elem)) { - PyErr_SetString(PyExc_TypeError, - "groups must be integers"); - Py_DECREF(elem); - PyMem_Free(grouplist); - return NULL; - } else { - if (!_Py_Gid_Converter(elem, &grouplist[i])) { - Py_DECREF(elem); - PyMem_Free(grouplist); - return NULL; - } - } - Py_DECREF(elem); - } - - if (setgroups(len, grouplist) < 0) { - PyMem_Free(grouplist); - return posix_error(); - } - PyMem_Free(grouplist); - Py_RETURN_NONE; -} -#endif /* HAVE_SETGROUPS */ - -#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) -static PyObject * -wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru) -{ - PyObject *result; - PyObject *struct_rusage; - - if (pid == -1) - return posix_error(); - - // If wait succeeded but no child was ready to report status, ru will not - // have been populated. - if (pid == 0) { - memset(ru, 0, sizeof(*ru)); - } - - struct_rusage = _PyImport_GetModuleAttrString("resource", "struct_rusage"); - if (struct_rusage == NULL) - return NULL; - - /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */ - result = PyStructSequence_New((PyTypeObject*) struct_rusage); - Py_DECREF(struct_rusage); - if (!result) - return NULL; - -#ifndef doubletime -#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001) -#endif - - PyStructSequence_SET_ITEM(result, 0, - PyFloat_FromDouble(doubletime(ru->ru_utime))); - PyStructSequence_SET_ITEM(result, 1, - PyFloat_FromDouble(doubletime(ru->ru_stime))); -#define SET_INT(result, index, value)\ - PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value)) - SET_INT(result, 2, ru->ru_maxrss); - SET_INT(result, 3, ru->ru_ixrss); - SET_INT(result, 4, ru->ru_idrss); - SET_INT(result, 5, ru->ru_isrss); - SET_INT(result, 6, ru->ru_minflt); - SET_INT(result, 7, ru->ru_majflt); - SET_INT(result, 8, ru->ru_nswap); - SET_INT(result, 9, ru->ru_inblock); - SET_INT(result, 10, ru->ru_oublock); - SET_INT(result, 11, ru->ru_msgsnd); - SET_INT(result, 12, ru->ru_msgrcv); - SET_INT(result, 13, ru->ru_nsignals); - SET_INT(result, 14, ru->ru_nvcsw); - SET_INT(result, 15, ru->ru_nivcsw); -#undef SET_INT - - if (PyErr_Occurred()) { - Py_DECREF(result); - return NULL; - } - - return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result); -} -#endif /* HAVE_WAIT3 || HAVE_WAIT4 */ - - -#ifdef HAVE_WAIT3 -/*[clinic input] -os.wait3 - - options: int -Wait for completion of a child process. - -Returns a tuple of information about the child process: - (pid, status, rusage) -[clinic start generated code]*/ - -static PyObject * -os_wait3_impl(PyObject *module, int options) -/*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/ -{ - pid_t pid; - struct rusage ru; - int async_err = 0; - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; - - do { - Py_BEGIN_ALLOW_THREADS - pid = wait3(&status, options, &ru); - Py_END_ALLOW_THREADS - } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (pid < 0) - return (!async_err) ? posix_error() : NULL; - - return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru); -} -#endif /* HAVE_WAIT3 */ - - -#ifdef HAVE_WAIT4 -/*[clinic input] - -os.wait4 - - pid: pid_t - options: int - -Wait for completion of a specific child process. - -Returns a tuple of information about the child process: - (pid, status, rusage) -[clinic start generated code]*/ - -static PyObject * -os_wait4_impl(PyObject *module, pid_t pid, int options) -/*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/ -{ - pid_t res; - struct rusage ru; - int async_err = 0; - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; - - do { - Py_BEGIN_ALLOW_THREADS - res = wait4(pid, &status, options, &ru); - Py_END_ALLOW_THREADS - } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (res < 0) - return (!async_err) ? posix_error() : NULL; - - return wait_helper(module, res, WAIT_STATUS_INT(status), &ru); -} -#endif /* HAVE_WAIT4 */ - - -#if defined(HAVE_WAITID) && !defined(__APPLE__) -/*[clinic input] -os.waitid - - idtype: idtype_t - Must be one of be P_PID, P_PGID or P_ALL. - id: id_t - The id to wait on. - options: int - Constructed from the ORing of one or more of WEXITED, WSTOPPED - or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT. - / - -Returns the result of waiting for a process or processes. - -Returns either waitid_result or None if WNOHANG is specified and there are -no children in a waitable state. -[clinic start generated code]*/ - -static PyObject * -os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options) -/*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/ -{ - PyObject *result; - int res; - int async_err = 0; - siginfo_t si; - si.si_pid = 0; - - do { - Py_BEGIN_ALLOW_THREADS - res = waitid(idtype, id, &si, options); - Py_END_ALLOW_THREADS - } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (res < 0) - return (!async_err) ? posix_error() : NULL; - - if (si.si_pid == 0) - Py_RETURN_NONE; - - PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType; - result = PyStructSequence_New((PyTypeObject *)WaitidResultType); - if (!result) - return NULL; - - PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid)); - PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid)); - PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo))); - PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status))); - PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code))); - if (PyErr_Occurred()) { - Py_DECREF(result); - return NULL; - } - - return result; -} -#endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */ - - -#if defined(HAVE_WAITPID) -/*[clinic input] -os.waitpid - pid: pid_t - options: int - / - -Wait for completion of a given child process. - -Returns a tuple of information regarding the child process: - (pid, status) - -The options argument is ignored on Windows. -[clinic start generated code]*/ - -static PyObject * -os_waitpid_impl(PyObject *module, pid_t pid, int options) -/*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/ -{ - pid_t res; - int async_err = 0; - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; - - do { - Py_BEGIN_ALLOW_THREADS - res = waitpid(pid, &status, options); - Py_END_ALLOW_THREADS - } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (res < 0) - return (!async_err) ? posix_error() : NULL; - - return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status)); -} -#elif defined(HAVE_CWAIT) -/* MS C has a variant of waitpid() that's usable for most purposes. */ -/*[clinic input] -os.waitpid - pid: intptr_t - options: int - / - -Wait for completion of a given process. - -Returns a tuple of information regarding the process: - (pid, status << 8) - -The options argument is ignored on Windows. -[clinic start generated code]*/ - -static PyObject * -os_waitpid_impl(PyObject *module, intptr_t pid, int options) -/*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/ -{ - int status; - intptr_t res; - int async_err = 0; - - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - res = _cwait(&status, pid, options); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (res < 0) - return (!async_err) ? posix_error() : NULL; - - unsigned long long ustatus = (unsigned int)status; - - /* shift the status left a byte so this is more like the POSIX waitpid */ - return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8); -} -#endif - - -#ifdef HAVE_WAIT -/*[clinic input] -os.wait - -Wait for completion of a child process. - -Returns a tuple of information about the child process: - (pid, status) -[clinic start generated code]*/ - -static PyObject * -os_wait_impl(PyObject *module) -/*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/ -{ - pid_t pid; - int async_err = 0; - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; - - do { - Py_BEGIN_ALLOW_THREADS - pid = wait(&status); - Py_END_ALLOW_THREADS - } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (pid < 0) - return (!async_err) ? posix_error() : NULL; - - return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status)); -} -#endif /* HAVE_WAIT */ - -#if defined(__linux__) && defined(__NR_pidfd_open) -/*[clinic input] -os.pidfd_open - pid: pid_t - flags: unsigned_int = 0 - -Return a file descriptor referring to the process *pid*. - -The descriptor can be used to perform process management without races and -signals. -[clinic start generated code]*/ - -static PyObject * -os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags) -/*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/ -{ - int fd = syscall(__NR_pidfd_open, pid, flags); - if (fd < 0) { - return posix_error(); - } - return PyLong_FromLong(fd); -} -#endif - - -#ifdef HAVE_SETNS -/*[clinic input] -os.setns - fd: fildes - A file descriptor to a namespace. - nstype: int = 0 - Type of namespace. - -Move the calling thread into different namespaces. -[clinic start generated code]*/ - -static PyObject * -os_setns_impl(PyObject *module, int fd, int nstype) -/*[clinic end generated code: output=5dbd055bfb66ecd0 input=42787871226bf3ee]*/ -{ - int res; - - Py_BEGIN_ALLOW_THREADS - res = setns(fd, nstype); - Py_END_ALLOW_THREADS - - if (res != 0) { - return posix_error(); - } - - Py_RETURN_NONE; -} -#endif - - -#ifdef HAVE_UNSHARE -/*[clinic input] -os.unshare - flags: int - Namespaces to be unshared. - -Disassociate parts of a process (or thread) execution context. -[clinic start generated code]*/ - -static PyObject * -os_unshare_impl(PyObject *module, int flags) -/*[clinic end generated code: output=1b3177906dd237ee input=9e065db3232b8b1b]*/ -{ - int res; - - Py_BEGIN_ALLOW_THREADS - res = unshare(flags); - Py_END_ALLOW_THREADS - - if (res != 0) { - return posix_error(); - } - - Py_RETURN_NONE; -} -#endif - - -#if defined(HAVE_READLINK) || defined(MS_WINDOWS) -/*[clinic input] -os.readlink - - path: path_t - * - dir_fd: dir_fd(requires='readlinkat') = None - -Return a string representing the path to which the symbolic link points. - -If dir_fd is not None, it should be a file descriptor open to a directory, -and path should be relative; path will then be relative to that directory. - -dir_fd may not be implemented on your platform. If it is unavailable, -using it will raise a NotImplementedError. -[clinic start generated code]*/ - -static PyObject * -os_readlink_impl(PyObject *module, path_t *path, int dir_fd) -/*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/ -{ -#if defined(HAVE_READLINK) - char buffer[MAXPATHLEN+1]; - ssize_t length; -#ifdef HAVE_READLINKAT - int readlinkat_unavailable = 0; -#endif - - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_READLINKAT - if (dir_fd != DEFAULT_DIR_FD) { - if (HAVE_READLINKAT_RUNTIME) { - length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN); - } else { - readlinkat_unavailable = 1; - } - } else -#endif - length = readlink(path->narrow, buffer, MAXPATHLEN); - Py_END_ALLOW_THREADS - -#ifdef HAVE_READLINKAT - if (readlinkat_unavailable) { - argument_unavailable_error(NULL, "dir_fd"); - return NULL; - } -#endif - - if (length < 0) { - return path_error(path); - } - buffer[length] = '\0'; - - if (PyUnicode_Check(path->object)) - return PyUnicode_DecodeFSDefaultAndSize(buffer, length); - else - return PyBytes_FromStringAndSize(buffer, length); -#elif defined(MS_WINDOWS) - DWORD n_bytes_returned; - DWORD io_result = 0; - HANDLE reparse_point_handle; - char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; - _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer; - PyObject *result = NULL; - - /* First get a handle to the reparse point */ - Py_BEGIN_ALLOW_THREADS - reparse_point_handle = CreateFileW( - path->wide, - 0, - 0, - 0, - OPEN_EXISTING, - FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, - 0); - if (reparse_point_handle != INVALID_HANDLE_VALUE) { - /* New call DeviceIoControl to read the reparse point */ - io_result = DeviceIoControl( - reparse_point_handle, - FSCTL_GET_REPARSE_POINT, - 0, 0, /* in buffer */ - target_buffer, sizeof(target_buffer), - &n_bytes_returned, - 0 /* we're not using OVERLAPPED_IO */ - ); - CloseHandle(reparse_point_handle); - } - Py_END_ALLOW_THREADS - - if (io_result == 0) { - return path_error(path); - } - - wchar_t *name = NULL; - Py_ssize_t nameLen = 0; - if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK) - { - name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer + - rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset); - nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t); - } - else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) - { - name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer + - rdb->MountPointReparseBuffer.SubstituteNameOffset); - nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t); - } - else - { - PyErr_SetString(PyExc_ValueError, "not a symbolic link"); - } - if (name) { - if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) { - /* Our buffer is mutable, so this is okay */ - name[1] = L'\\'; - } - result = PyUnicode_FromWideChar(name, nameLen); - if (result && path->narrow) { - Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); - } - } - return result; -#endif -} -#endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */ - -#if defined(MS_WINDOWS) - -/* Remove the last portion of the path - return 0 on success */ -static int -_dirnameW(WCHAR *path) -{ - WCHAR *ptr; - size_t length = wcsnlen_s(path, MAX_PATH); - if (length == MAX_PATH) { - return -1; - } - - /* walk the path from the end until a backslash is encountered */ - for(ptr = path + length; ptr != path; ptr--) { - if (*ptr == L'\\' || *ptr == L'/') { - break; - } - } - *ptr = 0; - return 0; -} - -#endif - -#ifdef HAVE_SYMLINK - -#if defined(MS_WINDOWS) - -/* Is this path absolute? */ -static int -_is_absW(const WCHAR *path) -{ - return path[0] == L'\\' || path[0] == L'/' || - (path[0] && path[1] == L':'); -} - -/* join root and rest with a backslash - return 0 on success */ -static int -_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest) -{ - if (_is_absW(rest)) { - return wcscpy_s(dest_path, MAX_PATH, rest); - } - - if (wcscpy_s(dest_path, MAX_PATH, root)) { - return -1; - } - - if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) { - return -1; - } - - return wcscat_s(dest_path, MAX_PATH, rest); -} - -/* Return True if the path at src relative to dest is a directory */ -static int -_check_dirW(LPCWSTR src, LPCWSTR dest) -{ - WIN32_FILE_ATTRIBUTE_DATA src_info; - WCHAR dest_parent[MAX_PATH]; - WCHAR src_resolved[MAX_PATH] = L""; - - /* dest_parent = os.path.dirname(dest) */ - if (wcscpy_s(dest_parent, MAX_PATH, dest) || - _dirnameW(dest_parent)) { - return 0; - } - /* src_resolved = os.path.join(dest_parent, src) */ - if (_joinW(src_resolved, dest_parent, src)) { - return 0; - } - return ( - GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info) - && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY - ); -} -#endif - - -/*[clinic input] -os.symlink - src: path_t - dst: path_t - target_is_directory: bool = False - * - dir_fd: dir_fd(requires='symlinkat')=None - -# "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\ - -Create a symbolic link pointing to src named dst. - -target_is_directory is required on Windows if the target is to be - interpreted as a directory. (On Windows, symlink requires - Windows 6.0 or greater, and raises a NotImplementedError otherwise.) - target_is_directory is ignored on non-Windows platforms. - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -dir_fd may not be implemented on your platform. - If it is unavailable, using it will raise a NotImplementedError. - -[clinic start generated code]*/ - -static PyObject * -os_symlink_impl(PyObject *module, path_t *src, path_t *dst, - int target_is_directory, int dir_fd) -/*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/ -{ -#ifdef MS_WINDOWS - DWORD result; - DWORD flags = 0; - - /* Assumed true, set to false if detected to not be available. */ - static int windows_has_symlink_unprivileged_flag = TRUE; -#else - int result; -#ifdef HAVE_SYMLINKAT - int symlinkat_unavailable = 0; -#endif -#endif - - if (PySys_Audit("os.symlink", "OOi", src->object, dst->object, - dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { - return NULL; - } - -#ifdef MS_WINDOWS - - if (windows_has_symlink_unprivileged_flag) { - /* Allow non-admin symlinks if system allows it. */ - flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE; - } - - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - /* if src is a directory, ensure flags==1 (target_is_directory bit) */ - if (target_is_directory || _check_dirW(src->wide, dst->wide)) { - flags |= SYMBOLIC_LINK_FLAG_DIRECTORY; - } - - result = CreateSymbolicLinkW(dst->wide, src->wide, flags); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - - if (windows_has_symlink_unprivileged_flag && !result && - ERROR_INVALID_PARAMETER == GetLastError()) { - - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - /* This error might be caused by - SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported. - Try again, and update windows_has_symlink_unprivileged_flag if we - are successful this time. - - NOTE: There is a risk of a race condition here if there are other - conditions than the flag causing ERROR_INVALID_PARAMETER, and - another process (or thread) changes that condition in between our - calls to CreateSymbolicLink. - */ - flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE); - result = CreateSymbolicLinkW(dst->wide, src->wide, flags); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - - if (result || ERROR_INVALID_PARAMETER != GetLastError()) { - windows_has_symlink_unprivileged_flag = FALSE; - } - } - - if (!result) - return path_error2(src, dst); - -#else - - if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { - PyErr_SetString(PyExc_ValueError, - "symlink: src and dst must be the same type"); - return NULL; - } - - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_SYMLINKAT - if (dir_fd != DEFAULT_DIR_FD) { - if (HAVE_SYMLINKAT_RUNTIME) { - result = symlinkat(src->narrow, dir_fd, dst->narrow); - } else { - symlinkat_unavailable = 1; - } - } else -#endif - result = symlink(src->narrow, dst->narrow); - Py_END_ALLOW_THREADS - -#ifdef HAVE_SYMLINKAT - if (symlinkat_unavailable) { - argument_unavailable_error(NULL, "dir_fd"); - return NULL; - } -#endif - - if (result) - return path_error2(src, dst); -#endif - - Py_RETURN_NONE; -} -#endif /* HAVE_SYMLINK */ - - - - -static PyStructSequence_Field times_result_fields[] = { - {"user", "user time"}, - {"system", "system time"}, - {"children_user", "user time of children"}, - {"children_system", "system time of children"}, - {"elapsed", "elapsed time since an arbitrary point in the past"}, - {NULL} -}; - -PyDoc_STRVAR(times_result__doc__, -"times_result: Result from os.times().\n\n\ -This object may be accessed either as a tuple of\n\ - (user, system, children_user, children_system, elapsed),\n\ -or via the attributes user, system, children_user, children_system,\n\ -and elapsed.\n\ -\n\ -See os.times for more information."); - -static PyStructSequence_Desc times_result_desc = { - "times_result", /* name */ - times_result__doc__, /* doc */ - times_result_fields, - 5 -}; - -#ifdef MS_WINDOWS -#define HAVE_TIMES /* mandatory, for the method table */ -#endif - -#ifdef HAVE_TIMES - -static PyObject * -build_times_result(PyObject *module, double user, double system, - double children_user, double children_system, - double elapsed) -{ - PyObject *TimesResultType = get_posix_state(module)->TimesResultType; - PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType); - if (value == NULL) - return NULL; - -#define SET(i, field) \ - { \ - PyObject *o = PyFloat_FromDouble(field); \ - if (!o) { \ - Py_DECREF(value); \ - return NULL; \ - } \ - PyStructSequence_SET_ITEM(value, i, o); \ - } \ - - SET(0, user); - SET(1, system); - SET(2, children_user); - SET(3, children_system); - SET(4, elapsed); - -#undef SET - - return value; -} - - -#ifndef MS_WINDOWS -#define NEED_TICKS_PER_SECOND -static long ticks_per_second = -1; -#endif /* MS_WINDOWS */ - -/*[clinic input] -os.times - -Return a collection containing process timing information. - -The object returned behaves like a named tuple with these fields: - (utime, stime, cutime, cstime, elapsed_time) -All fields are floating point numbers. -[clinic start generated code]*/ - -static PyObject * -os_times_impl(PyObject *module) -/*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/ -#ifdef MS_WINDOWS -{ - FILETIME create, exit, kernel, user; - HANDLE hProc; - hProc = GetCurrentProcess(); - GetProcessTimes(hProc, &create, &exit, &kernel, &user); - /* The fields of a FILETIME structure are the hi and lo part - of a 64-bit value expressed in 100 nanosecond units. - 1e7 is one second in such units; 1e-7 the inverse. - 429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7. - */ - return build_times_result(module, - (double)(user.dwHighDateTime*429.4967296 + - user.dwLowDateTime*1e-7), - (double)(kernel.dwHighDateTime*429.4967296 + - kernel.dwLowDateTime*1e-7), - (double)0, - (double)0, - (double)0); -} -#else /* MS_WINDOWS */ -{ - - - struct tms t; - clock_t c; - errno = 0; - c = times(&t); - if (c == (clock_t) -1) - return posix_error(); - return build_times_result(module, - (double)t.tms_utime / ticks_per_second, - (double)t.tms_stime / ticks_per_second, - (double)t.tms_cutime / ticks_per_second, - (double)t.tms_cstime / ticks_per_second, - (double)c / ticks_per_second); -} -#endif /* MS_WINDOWS */ -#endif /* HAVE_TIMES */ - - -#ifdef HAVE_GETSID -/*[clinic input] -os.getsid - - pid: pid_t - / - -Call the system call getsid(pid) and return the result. -[clinic start generated code]*/ - -static PyObject * -os_getsid_impl(PyObject *module, pid_t pid) -/*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/ -{ - int sid; - sid = getsid(pid); - if (sid < 0) - return posix_error(); - return PyLong_FromLong((long)sid); -} -#endif /* HAVE_GETSID */ - - -#ifdef HAVE_SETSID -/*[clinic input] -os.setsid - -Call the system call setsid(). -[clinic start generated code]*/ - -static PyObject * -os_setsid_impl(PyObject *module) -/*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/ -{ - if (setsid() < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETSID */ - - -#ifdef HAVE_SETPGID -/*[clinic input] -os.setpgid - - pid: pid_t - pgrp: pid_t - / - -Call the system call setpgid(pid, pgrp). -[clinic start generated code]*/ - -static PyObject * -os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp) -/*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/ -{ - if (setpgid(pid, pgrp) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETPGID */ - - -#ifdef HAVE_TCGETPGRP -/*[clinic input] -os.tcgetpgrp - - fd: int - / - -Return the process group associated with the terminal specified by fd. -[clinic start generated code]*/ - -static PyObject * -os_tcgetpgrp_impl(PyObject *module, int fd) -/*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/ -{ - pid_t pgid = tcgetpgrp(fd); - if (pgid < 0) - return posix_error(); - return PyLong_FromPid(pgid); -} -#endif /* HAVE_TCGETPGRP */ - - -#ifdef HAVE_TCSETPGRP -/*[clinic input] -os.tcsetpgrp - - fd: int - pgid: pid_t - / - -Set the process group associated with the terminal specified by fd. -[clinic start generated code]*/ - -static PyObject * -os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid) -/*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/ -{ - if (tcsetpgrp(fd, pgid) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_TCSETPGRP */ - -/* Functions acting on file descriptors */ - -#ifdef O_CLOEXEC -extern int _Py_open_cloexec_works; -#endif - - -/*[clinic input] -os.open -> int - path: path_t - flags: int - mode: int = 0o777 - * - dir_fd: dir_fd(requires='openat') = None - -# "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\ - -Open a file for low level IO. Returns a file descriptor (integer). - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -dir_fd may not be implemented on your platform. - If it is unavailable, using it will raise a NotImplementedError. -[clinic start generated code]*/ - -static int -os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd) -/*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/ -{ - int fd; - int async_err = 0; -#ifdef HAVE_OPENAT - int openat_unavailable = 0; -#endif - -#ifdef O_CLOEXEC - int *atomic_flag_works = &_Py_open_cloexec_works; -#elif !defined(MS_WINDOWS) - int *atomic_flag_works = NULL; -#endif - -#ifdef MS_WINDOWS - flags |= O_NOINHERIT; -#elif defined(O_CLOEXEC) - flags |= O_CLOEXEC; -#endif - - if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) { - return -1; - } - - _Py_BEGIN_SUPPRESS_IPH - do { - Py_BEGIN_ALLOW_THREADS -#ifdef MS_WINDOWS - fd = _wopen(path->wide, flags, mode); -#else -#ifdef HAVE_OPENAT - if (dir_fd != DEFAULT_DIR_FD) { - if (HAVE_OPENAT_RUNTIME) { - fd = openat(dir_fd, path->narrow, flags, mode); - - } else { - openat_unavailable = 1; - fd = -1; - } - } else -#endif /* HAVE_OPENAT */ - fd = open(path->narrow, flags, mode); -#endif /* !MS_WINDOWS */ - Py_END_ALLOW_THREADS - } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - _Py_END_SUPPRESS_IPH - -#ifdef HAVE_OPENAT - if (openat_unavailable) { - argument_unavailable_error(NULL, "dir_fd"); - return -1; - } -#endif - - if (fd < 0) { - if (!async_err) - PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object); - return -1; - } - -#ifndef MS_WINDOWS - if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) { - close(fd); - return -1; - } -#endif - - return fd; -} - - -/*[clinic input] -os.close - - fd: int - -Close a file descriptor. -[clinic start generated code]*/ - -static PyObject * -os_close_impl(PyObject *module, int fd) -/*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/ -{ - int res; - /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/ - * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html - * for more details. - */ - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - res = close(fd); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - if (res < 0) - return posix_error(); - Py_RETURN_NONE; -} - -/*[clinic input] -os.closerange - - fd_low: int - fd_high: int - / - -Closes all file descriptors in [fd_low, fd_high), ignoring errors. -[clinic start generated code]*/ - -static PyObject * -os_closerange_impl(PyObject *module, int fd_low, int fd_high) -/*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/ -{ - Py_BEGIN_ALLOW_THREADS - _Py_closerange(fd_low, fd_high - 1); - Py_END_ALLOW_THREADS - Py_RETURN_NONE; -} - - -/*[clinic input] -os.dup -> int - - fd: int - / - -Return a duplicate of a file descriptor. -[clinic start generated code]*/ - -static int -os_dup_impl(PyObject *module, int fd) -/*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/ -{ - return _Py_dup(fd); -} - -// dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS(). -// dup2.c provides working dup2() if and only if F_DUPFD is available. -#if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS)) -/*[clinic input] -os.dup2 -> int - fd: int - fd2: int - inheritable: bool=True - -Duplicate file descriptor. -[clinic start generated code]*/ - -static int -os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable) -/*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/ -{ - int res = 0; -#if defined(HAVE_DUP3) && \ - !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)) - /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */ - static int dup3_works = -1; -#endif - - if (fd < 0 || fd2 < 0) { - posix_error(); - return -1; - } - - /* dup2() can fail with EINTR if the target FD is already open, because it - * then has to be closed. See os_close_impl() for why we don't handle EINTR - * upon close(), and therefore below. - */ -#ifdef MS_WINDOWS - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - res = dup2(fd, fd2); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - if (res < 0) { - posix_error(); - return -1; - } - res = fd2; // msvcrt dup2 returns 0 on success. - - /* Character files like console cannot be make non-inheritable */ - if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) { - close(fd2); - return -1; - } - -#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC) - Py_BEGIN_ALLOW_THREADS - if (!inheritable) - res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2); - else - res = dup2(fd, fd2); - Py_END_ALLOW_THREADS - if (res < 0) { - posix_error(); - return -1; - } - -#else - -#ifdef HAVE_DUP3 - if (!inheritable && dup3_works != 0) { - Py_BEGIN_ALLOW_THREADS - res = dup3(fd, fd2, O_CLOEXEC); - Py_END_ALLOW_THREADS - if (res < 0) { - if (dup3_works == -1) - dup3_works = (errno != ENOSYS); - if (dup3_works) { - posix_error(); - return -1; - } - } - } - - if (inheritable || dup3_works == 0) - { -#endif - Py_BEGIN_ALLOW_THREADS - res = dup2(fd, fd2); - Py_END_ALLOW_THREADS - if (res < 0) { - posix_error(); - return -1; - } - - if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) { - close(fd2); - return -1; - } -#ifdef HAVE_DUP3 - } -#endif - -#endif - - return res; -} -#endif - - -#ifdef HAVE_LOCKF -/*[clinic input] -os.lockf - - fd: int - An open file descriptor. - command: int - One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST. - length: Py_off_t - The number of bytes to lock, starting at the current position. - / - -Apply, test or remove a POSIX lock on an open file descriptor. - -[clinic start generated code]*/ - -static PyObject * -os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length) -/*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/ -{ - int res; - - if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) { - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - res = lockf(fd, command, length); - Py_END_ALLOW_THREADS - - if (res < 0) - return posix_error(); - - Py_RETURN_NONE; -} -#endif /* HAVE_LOCKF */ - - -/*[clinic input] -os.lseek -> Py_off_t - - fd: int - position: Py_off_t - how: int - / - -Set the position of a file descriptor. Return the new position. - -Return the new cursor position in number of bytes -relative to the beginning of the file. -[clinic start generated code]*/ - -static Py_off_t -os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how) -/*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/ -{ - Py_off_t result; - -#ifdef SEEK_SET - /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ - switch (how) { - case 0: how = SEEK_SET; break; - case 1: how = SEEK_CUR; break; - case 2: how = SEEK_END; break; - } -#endif /* SEEK_END */ - - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH -#ifdef MS_WINDOWS - result = _lseeki64(fd, position, how); -#else - result = lseek(fd, position, how); -#endif - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - if (result < 0) - posix_error(); - - return result; -} - - -/*[clinic input] -os.read - fd: int - length: Py_ssize_t - / - -Read from a file descriptor. Returns a bytes object. -[clinic start generated code]*/ - -static PyObject * -os_read_impl(PyObject *module, int fd, Py_ssize_t length) -/*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/ -{ - Py_ssize_t n; - PyObject *buffer; - - if (length < 0) { - errno = EINVAL; - return posix_error(); - } - - length = Py_MIN(length, _PY_READ_MAX); - - buffer = PyBytes_FromStringAndSize((char *)NULL, length); - if (buffer == NULL) - return NULL; - - n = _Py_read(fd, PyBytes_AS_STRING(buffer), length); - if (n == -1) { - Py_DECREF(buffer); - return NULL; - } - - if (n != length) - _PyBytes_Resize(&buffer, n); - - return buffer; -} - -#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \ - || defined(__APPLE__))) \ - || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \ - || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2) -static int -iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type) -{ - Py_ssize_t i, j; - - *iov = PyMem_New(struct iovec, cnt); - if (*iov == NULL) { - PyErr_NoMemory(); - return -1; - } - - *buf = PyMem_New(Py_buffer, cnt); - if (*buf == NULL) { - PyMem_Free(*iov); - PyErr_NoMemory(); - return -1; - } - - for (i = 0; i < cnt; i++) { - PyObject *item = PySequence_GetItem(seq, i); - if (item == NULL) - goto fail; - if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) { - Py_DECREF(item); - goto fail; - } - Py_DECREF(item); - (*iov)[i].iov_base = (*buf)[i].buf; - (*iov)[i].iov_len = (*buf)[i].len; - } - return 0; - -fail: - PyMem_Free(*iov); - for (j = 0; j < i; j++) { - PyBuffer_Release(&(*buf)[j]); - } - PyMem_Free(*buf); - return -1; -} - -static void -iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt) -{ - int i; - PyMem_Free(iov); - for (i = 0; i < cnt; i++) { - PyBuffer_Release(&buf[i]); - } - PyMem_Free(buf); -} -#endif - - -#ifdef HAVE_READV -/*[clinic input] -os.readv -> Py_ssize_t - - fd: int - buffers: object - / - -Read from a file descriptor fd into an iterable of buffers. - -The buffers should be mutable buffers accepting bytes. -readv will transfer data into each buffer until it is full -and then move on to the next buffer in the sequence to hold -the rest of the data. - -readv returns the total number of bytes read, -which may be less than the total capacity of all the buffers. -[clinic start generated code]*/ - -static Py_ssize_t -os_readv_impl(PyObject *module, int fd, PyObject *buffers) -/*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/ -{ - Py_ssize_t cnt, n; - int async_err = 0; - struct iovec *iov; - Py_buffer *buf; - - if (!PySequence_Check(buffers)) { - PyErr_SetString(PyExc_TypeError, - "readv() arg 2 must be a sequence"); - return -1; - } - - cnt = PySequence_Size(buffers); - if (cnt < 0) - return -1; - - if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) - return -1; - - do { - Py_BEGIN_ALLOW_THREADS - n = readv(fd, iov, cnt); - Py_END_ALLOW_THREADS - } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - - iov_cleanup(iov, buf, cnt); - if (n < 0) { - if (!async_err) - posix_error(); - return -1; - } - - return n; -} -#endif /* HAVE_READV */ - - -#ifdef HAVE_PREAD -/*[clinic input] -os.pread - - fd: int - length: Py_ssize_t - offset: Py_off_t - / - -Read a number of bytes from a file descriptor starting at a particular offset. - -Read length bytes from file descriptor fd, starting at offset bytes from -the beginning of the file. The file offset remains unchanged. -[clinic start generated code]*/ - -static PyObject * -os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset) -/*[clinic end generated code: output=3f875c1eef82e32f input=85cb4a5589627144]*/ -{ - Py_ssize_t n; - int async_err = 0; - PyObject *buffer; - - if (length < 0) { - errno = EINVAL; - return posix_error(); - } - buffer = PyBytes_FromStringAndSize((char *)NULL, length); - if (buffer == NULL) - return NULL; - - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - n = pread(fd, PyBytes_AS_STRING(buffer), length, offset); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - - if (n < 0) { - Py_DECREF(buffer); - return (!async_err) ? posix_error() : NULL; - } - if (n != length) - _PyBytes_Resize(&buffer, n); - return buffer; -} -#endif /* HAVE_PREAD */ - -#if defined(HAVE_PREADV) || defined (HAVE_PREADV2) -/*[clinic input] -os.preadv -> Py_ssize_t - - fd: int - buffers: object - offset: Py_off_t - flags: int = 0 - / - -Reads from a file descriptor into a number of mutable bytes-like objects. - -Combines the functionality of readv() and pread(). As readv(), it will -transfer data into each buffer until it is full and then move on to the next -buffer in the sequence to hold the rest of the data. Its fourth argument, -specifies the file offset at which the input operation is to be performed. It -will return the total number of bytes read (which can be less than the total -capacity of all the objects). - -The flags argument contains a bitwise OR of zero or more of the following flags: - -- RWF_HIPRI -- RWF_NOWAIT - -Using non-zero flags requires Linux 4.6 or newer. -[clinic start generated code]*/ - -static Py_ssize_t -os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, - int flags) -/*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/ -{ - Py_ssize_t cnt, n; - int async_err = 0; - struct iovec *iov; - Py_buffer *buf; - - if (!PySequence_Check(buffers)) { - PyErr_SetString(PyExc_TypeError, - "preadv2() arg 2 must be a sequence"); - return -1; - } - - cnt = PySequence_Size(buffers); - if (cnt < 0) { - return -1; - } - -#ifndef HAVE_PREADV2 - if(flags != 0) { - argument_unavailable_error("preadv2", "flags"); - return -1; - } -#endif - - if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) { - return -1; - } -#ifdef HAVE_PREADV2 - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - n = preadv2(fd, iov, cnt, offset, flags); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); -#else - do { -#ifdef __APPLE__ -/* This entire function will be removed from the module dict when the API - * is not available. - */ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability" -#pragma clang diagnostic ignored "-Wunguarded-availability-new" -#endif - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - n = preadv(fd, iov, cnt, offset); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - -#ifdef __APPLE__ -#pragma clang diagnostic pop -#endif - -#endif - - iov_cleanup(iov, buf, cnt); - if (n < 0) { - if (!async_err) { - posix_error(); - } - return -1; - } - - return n; -} -#endif /* HAVE_PREADV */ - - -/*[clinic input] -os.write -> Py_ssize_t - - fd: int - data: Py_buffer - / - -Write a bytes object to a file descriptor. -[clinic start generated code]*/ - -static Py_ssize_t -os_write_impl(PyObject *module, int fd, Py_buffer *data) -/*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/ -{ - return _Py_write(fd, data->buf, data->len); -} - -#ifdef HAVE_SENDFILE -#ifdef __APPLE__ -/*[clinic input] -os.sendfile - - out_fd: int - in_fd: int - offset: Py_off_t - count as sbytes: Py_off_t - headers: object(c_default="NULL") = () - trailers: object(c_default="NULL") = () - flags: int = 0 - -Copy count bytes from file descriptor in_fd to file descriptor out_fd. -[clinic start generated code]*/ - -static PyObject * -os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset, - Py_off_t sbytes, PyObject *headers, PyObject *trailers, - int flags) -/*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/ -#elif defined(__FreeBSD__) || defined(__DragonFly__) -/*[clinic input] -os.sendfile - - out_fd: int - in_fd: int - offset: Py_off_t - count: Py_ssize_t - headers: object(c_default="NULL") = () - trailers: object(c_default="NULL") = () - flags: int = 0 - -Copy count bytes from file descriptor in_fd to file descriptor out_fd. -[clinic start generated code]*/ - -static PyObject * -os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset, - Py_ssize_t count, PyObject *headers, PyObject *trailers, - int flags) -/*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/ -#else -/*[clinic input] -os.sendfile - - out_fd: int - in_fd: int - offset as offobj: object - count: Py_ssize_t - -Copy count bytes from file descriptor in_fd to file descriptor out_fd. -[clinic start generated code]*/ - -static PyObject * -os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj, - Py_ssize_t count) -/*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/ -#endif -{ - Py_ssize_t ret; - int async_err = 0; - -#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) -#ifndef __APPLE__ - off_t sbytes; -#endif - Py_buffer *hbuf, *tbuf; - struct sf_hdtr sf; - - sf.headers = NULL; - sf.trailers = NULL; - - if (headers != NULL) { - if (!PySequence_Check(headers)) { - PyErr_SetString(PyExc_TypeError, - "sendfile() headers must be a sequence"); - return NULL; - } else { - Py_ssize_t i = PySequence_Size(headers); - if (i < 0) - return NULL; - if (i > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "sendfile() header is too large"); - return NULL; - } - if (i > 0) { - sf.hdr_cnt = (int)i; - if (iov_setup(&(sf.headers), &hbuf, - headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0) - return NULL; -#ifdef __APPLE__ - for (i = 0; i < sf.hdr_cnt; i++) { - Py_ssize_t blen = sf.headers[i].iov_len; -# define OFF_T_MAX 0x7fffffffffffffff - if (sbytes >= OFF_T_MAX - blen) { - PyErr_SetString(PyExc_OverflowError, - "sendfile() header is too large"); - return NULL; - } - sbytes += blen; - } -#endif - } - } - } - if (trailers != NULL) { - if (!PySequence_Check(trailers)) { - PyErr_SetString(PyExc_TypeError, - "sendfile() trailers must be a sequence"); - return NULL; - } else { - Py_ssize_t i = PySequence_Size(trailers); - if (i < 0) - return NULL; - if (i > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "sendfile() trailer is too large"); - return NULL; - } - if (i > 0) { - sf.trl_cnt = (int)i; - if (iov_setup(&(sf.trailers), &tbuf, - trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0) - return NULL; - } - } - } - - _Py_BEGIN_SUPPRESS_IPH - do { - Py_BEGIN_ALLOW_THREADS -#ifdef __APPLE__ - ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags); -#else - ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags); -#endif - Py_END_ALLOW_THREADS - } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - _Py_END_SUPPRESS_IPH - - if (sf.headers != NULL) - iov_cleanup(sf.headers, hbuf, sf.hdr_cnt); - if (sf.trailers != NULL) - iov_cleanup(sf.trailers, tbuf, sf.trl_cnt); - - if (ret < 0) { - if ((errno == EAGAIN) || (errno == EBUSY)) { - if (sbytes != 0) { - // some data has been sent - goto done; - } - else { - // no data has been sent; upper application is supposed - // to retry on EAGAIN or EBUSY - return posix_error(); - } - } - return (!async_err) ? posix_error() : NULL; - } - goto done; - -done: - #if !defined(HAVE_LARGEFILE_SUPPORT) - return Py_BuildValue("l", sbytes); - #else - return Py_BuildValue("L", sbytes); - #endif - -#else -#ifdef __linux__ - if (offobj == Py_None) { - do { - Py_BEGIN_ALLOW_THREADS - ret = sendfile(out_fd, in_fd, NULL, count); - Py_END_ALLOW_THREADS - } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (ret < 0) - return (!async_err) ? posix_error() : NULL; - return Py_BuildValue("n", ret); - } -#endif - off_t offset; - if (!Py_off_t_converter(offobj, &offset)) - return NULL; - -#if defined(__sun) && defined(__SVR4) - // On Solaris, sendfile raises EINVAL rather than returning 0 - // when the offset is equal or bigger than the in_fd size. - struct stat st; - - do { - Py_BEGIN_ALLOW_THREADS - ret = fstat(in_fd, &st); - Py_END_ALLOW_THREADS - } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (ret < 0) - return (!async_err) ? posix_error() : NULL; - - if (offset >= st.st_size) { - return Py_BuildValue("i", 0); - } - - // On illumos specifically sendfile() may perform a partial write but - // return -1/an error (in one confirmed case the destination socket - // had a 5 second timeout set and errno was EAGAIN) and it's on the client - // code to check if the offset parameter was modified by sendfile(). - // - // We need this variable to track said change. - off_t original_offset = offset; -#endif - - do { - Py_BEGIN_ALLOW_THREADS - ret = sendfile(out_fd, in_fd, &offset, count); -#if defined(__sun) && defined(__SVR4) - // This handles illumos-specific sendfile() partial write behavior, - // see a comment above for more details. - if (ret < 0 && offset != original_offset) { - ret = offset - original_offset; - } -#endif - Py_END_ALLOW_THREADS - } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (ret < 0) - return (!async_err) ? posix_error() : NULL; - return Py_BuildValue("n", ret); -#endif -} -#endif /* HAVE_SENDFILE */ - - -#if defined(__APPLE__) -/*[clinic input] -os._fcopyfile - - in_fd: int - out_fd: int - flags: int - / - -Efficiently copy content or metadata of 2 regular file descriptors (macOS). -[clinic start generated code]*/ - -static PyObject * -os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags) -/*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/ -{ - int ret; - - Py_BEGIN_ALLOW_THREADS - ret = fcopyfile(in_fd, out_fd, NULL, flags); - Py_END_ALLOW_THREADS - if (ret < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif - - -/*[clinic input] -os.fstat - - fd : int - -Perform a stat system call on the given file descriptor. - -Like stat(), but for an open file descriptor. -Equivalent to os.stat(fd). -[clinic start generated code]*/ - -static PyObject * -os_fstat_impl(PyObject *module, int fd) -/*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/ -{ - STRUCT_STAT st; - int res; - int async_err = 0; - - do { - Py_BEGIN_ALLOW_THREADS - res = FSTAT(fd, &st); - Py_END_ALLOW_THREADS - } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (res != 0) { -#ifdef MS_WINDOWS - return PyErr_SetFromWindowsErr(0); -#else - return (!async_err) ? posix_error() : NULL; -#endif - } - - return _pystat_fromstructstat(module, &st); -} - - -/*[clinic input] -os.isatty -> bool - fd: int - / - -Return True if the fd is connected to a terminal. - -Return True if the file descriptor is an open file descriptor -connected to the slave end of a terminal. -[clinic start generated code]*/ - -static int -os_isatty_impl(PyObject *module, int fd) -/*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/ -{ - int return_value; - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - return_value = isatty(fd); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - return return_value; -} - - -#ifdef HAVE_PIPE -/*[clinic input] -os.pipe - -Create a pipe. - -Returns a tuple of two file descriptors: - (read_fd, write_fd) -[clinic start generated code]*/ - -static PyObject * -os_pipe_impl(PyObject *module) -/*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/ -{ - int fds[2]; -#ifdef MS_WINDOWS - HANDLE read, write; - SECURITY_ATTRIBUTES attr; - BOOL ok; -#else - int res; -#endif - -#ifdef MS_WINDOWS - attr.nLength = sizeof(attr); - attr.lpSecurityDescriptor = NULL; - attr.bInheritHandle = FALSE; - - Py_BEGIN_ALLOW_THREADS - ok = CreatePipe(&read, &write, &attr, 0); - if (ok) { - fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY); - fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY); - if (fds[0] == -1 || fds[1] == -1) { - CloseHandle(read); - CloseHandle(write); - ok = 0; - } - } - Py_END_ALLOW_THREADS - - if (!ok) - return PyErr_SetFromWindowsErr(0); -#else - -#ifdef HAVE_PIPE2 - Py_BEGIN_ALLOW_THREADS - res = pipe2(fds, O_CLOEXEC); - Py_END_ALLOW_THREADS - - if (res != 0 && errno == ENOSYS) - { -#endif - Py_BEGIN_ALLOW_THREADS - res = pipe(fds); - Py_END_ALLOW_THREADS - - if (res == 0) { - if (_Py_set_inheritable(fds[0], 0, NULL) < 0) { - close(fds[0]); - close(fds[1]); - return NULL; - } - if (_Py_set_inheritable(fds[1], 0, NULL) < 0) { - close(fds[0]); - close(fds[1]); - return NULL; - } - } -#ifdef HAVE_PIPE2 - } -#endif - - if (res != 0) - return PyErr_SetFromErrno(PyExc_OSError); -#endif /* !MS_WINDOWS */ - return Py_BuildValue("(ii)", fds[0], fds[1]); -} -#endif /* HAVE_PIPE */ - - -#ifdef HAVE_PIPE2 -/*[clinic input] -os.pipe2 - - flags: int - / - -Create a pipe with flags set atomically. - -Returns a tuple of two file descriptors: - (read_fd, write_fd) - -flags can be constructed by ORing together one or more of these values: -O_NONBLOCK, O_CLOEXEC. -[clinic start generated code]*/ - -static PyObject * -os_pipe2_impl(PyObject *module, int flags) -/*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/ -{ - int fds[2]; - int res; - - res = pipe2(fds, flags); - if (res != 0) - return posix_error(); - return Py_BuildValue("(ii)", fds[0], fds[1]); -} -#endif /* HAVE_PIPE2 */ - - -#ifdef HAVE_WRITEV -/*[clinic input] -os.writev -> Py_ssize_t - fd: int - buffers: object - / - -Iterate over buffers, and write the contents of each to a file descriptor. - -Returns the total number of bytes written. -buffers must be a sequence of bytes-like objects. -[clinic start generated code]*/ - -static Py_ssize_t -os_writev_impl(PyObject *module, int fd, PyObject *buffers) -/*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/ -{ - Py_ssize_t cnt; - Py_ssize_t result; - int async_err = 0; - struct iovec *iov; - Py_buffer *buf; - - if (!PySequence_Check(buffers)) { - PyErr_SetString(PyExc_TypeError, - "writev() arg 2 must be a sequence"); - return -1; - } - cnt = PySequence_Size(buffers); - if (cnt < 0) - return -1; - - if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { - return -1; - } - - do { - Py_BEGIN_ALLOW_THREADS - result = writev(fd, iov, cnt); - Py_END_ALLOW_THREADS - } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - - iov_cleanup(iov, buf, cnt); - if (result < 0 && !async_err) - posix_error(); - - return result; -} -#endif /* HAVE_WRITEV */ - - -#ifdef HAVE_PWRITE -/*[clinic input] -os.pwrite -> Py_ssize_t - - fd: int - buffer: Py_buffer - offset: Py_off_t - / - -Write bytes to a file descriptor starting at a particular offset. - -Write buffer to fd, starting at offset bytes from the beginning of -the file. Returns the number of bytes writte. Does not change the -current file offset. -[clinic start generated code]*/ - -static Py_ssize_t -os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset) -/*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/ -{ - Py_ssize_t size; - int async_err = 0; - - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - - if (size < 0 && !async_err) - posix_error(); - return size; -} -#endif /* HAVE_PWRITE */ - -#if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2) -/*[clinic input] -os.pwritev -> Py_ssize_t - - fd: int - buffers: object - offset: Py_off_t - flags: int = 0 - / - -Writes the contents of bytes-like objects to a file descriptor at a given offset. - -Combines the functionality of writev() and pwrite(). All buffers must be a sequence -of bytes-like objects. Buffers are processed in array order. Entire contents of first -buffer is written before proceeding to second, and so on. The operating system may -set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used. -This function writes the contents of each object to the file descriptor and returns -the total number of bytes written. - -The flags argument contains a bitwise OR of zero or more of the following flags: - -- RWF_DSYNC -- RWF_SYNC -- RWF_APPEND - -Using non-zero flags requires Linux 4.7 or newer. -[clinic start generated code]*/ - -static Py_ssize_t -os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, - int flags) -/*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/ -{ - Py_ssize_t cnt; - Py_ssize_t result; - int async_err = 0; - struct iovec *iov; - Py_buffer *buf; - - if (!PySequence_Check(buffers)) { - PyErr_SetString(PyExc_TypeError, - "pwritev() arg 2 must be a sequence"); - return -1; - } - - cnt = PySequence_Size(buffers); - if (cnt < 0) { - return -1; - } - -#ifndef HAVE_PWRITEV2 - if(flags != 0) { - argument_unavailable_error("pwritev2", "flags"); - return -1; - } -#endif - - if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { - return -1; - } -#ifdef HAVE_PWRITEV2 - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - result = pwritev2(fd, iov, cnt, offset, flags); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); -#else - -#ifdef __APPLE__ -/* This entire function will be removed from the module dict when the API - * is not available. - */ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability" -#pragma clang diagnostic ignored "-Wunguarded-availability-new" -#endif - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - result = pwritev(fd, iov, cnt, offset); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - -#ifdef __APPLE__ -#pragma clang diagnostic pop -#endif - -#endif - - iov_cleanup(iov, buf, cnt); - if (result < 0) { - if (!async_err) { - posix_error(); - } - return -1; - } - - return result; -} -#endif /* HAVE_PWRITEV */ - -#ifdef HAVE_COPY_FILE_RANGE -/*[clinic input] - -os.copy_file_range - src: int - Source file descriptor. - dst: int - Destination file descriptor. - count: Py_ssize_t - Number of bytes to copy. - offset_src: object = None - Starting offset in src. - offset_dst: object = None - Starting offset in dst. - -Copy count bytes from one file descriptor to another. - -If offset_src is None, then src is read from the current position; -respectively for offset_dst. -[clinic start generated code]*/ - -static PyObject * -os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count, - PyObject *offset_src, PyObject *offset_dst) -/*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/ -{ - off_t offset_src_val, offset_dst_val; - off_t *p_offset_src = NULL; - off_t *p_offset_dst = NULL; - Py_ssize_t ret; - int async_err = 0; - /* The flags argument is provided to allow - * for future extensions and currently must be to 0. */ - int flags = 0; - - - if (count < 0) { - PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed"); - return NULL; - } - - if (offset_src != Py_None) { - if (!Py_off_t_converter(offset_src, &offset_src_val)) { - return NULL; - } - p_offset_src = &offset_src_val; - } - - if (offset_dst != Py_None) { - if (!Py_off_t_converter(offset_dst, &offset_dst_val)) { - return NULL; - } - p_offset_dst = &offset_dst_val; - } - - do { - Py_BEGIN_ALLOW_THREADS - ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags); - Py_END_ALLOW_THREADS - } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - - if (ret < 0) { - return (!async_err) ? posix_error() : NULL; - } - - return PyLong_FromSsize_t(ret); -} -#endif /* HAVE_COPY_FILE_RANGE*/ - -#if (defined(HAVE_SPLICE) && !defined(_AIX)) -/*[clinic input] - -os.splice - src: int - Source file descriptor. - dst: int - Destination file descriptor. - count: Py_ssize_t - Number of bytes to copy. - offset_src: object = None - Starting offset in src. - offset_dst: object = None - Starting offset in dst. - flags: unsigned_int = 0 - Flags to modify the semantics of the call. - -Transfer count bytes from one pipe to a descriptor or vice versa. - -If offset_src is None, then src is read from the current position; -respectively for offset_dst. The offset associated to the file -descriptor that refers to a pipe must be None. -[clinic start generated code]*/ - -static PyObject * -os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count, - PyObject *offset_src, PyObject *offset_dst, - unsigned int flags) -/*[clinic end generated code: output=d0386f25a8519dc5 input=047527c66c6d2e0a]*/ -{ - off_t offset_src_val, offset_dst_val; - off_t *p_offset_src = NULL; - off_t *p_offset_dst = NULL; - Py_ssize_t ret; - int async_err = 0; - - if (count < 0) { - PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed"); - return NULL; - } - - if (offset_src != Py_None) { - if (!Py_off_t_converter(offset_src, &offset_src_val)) { - return NULL; - } - p_offset_src = &offset_src_val; - } - - if (offset_dst != Py_None) { - if (!Py_off_t_converter(offset_dst, &offset_dst_val)) { - return NULL; - } - p_offset_dst = &offset_dst_val; - } - - do { - Py_BEGIN_ALLOW_THREADS - ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags); - Py_END_ALLOW_THREADS - } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - - if (ret < 0) { - return (!async_err) ? posix_error() : NULL; - } - - return PyLong_FromSsize_t(ret); -} -#endif /* HAVE_SPLICE*/ - -#ifdef HAVE_MKFIFO -/*[clinic input] -os.mkfifo - - path: path_t - mode: int=0o666 - * - dir_fd: dir_fd(requires='mkfifoat')=None - -Create a "fifo" (a POSIX named pipe). - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -dir_fd may not be implemented on your platform. - If it is unavailable, using it will raise a NotImplementedError. -[clinic start generated code]*/ - -static PyObject * -os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd) -/*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/ -{ - int result; - int async_err = 0; -#ifdef HAVE_MKFIFOAT - int mkfifoat_unavailable = 0; -#endif - - do { - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_MKFIFOAT - if (dir_fd != DEFAULT_DIR_FD) { - if (HAVE_MKFIFOAT_RUNTIME) { - result = mkfifoat(dir_fd, path->narrow, mode); - - } else { - mkfifoat_unavailable = 1; - result = 0; - } - } else -#endif - result = mkfifo(path->narrow, mode); - Py_END_ALLOW_THREADS - } while (result != 0 && errno == EINTR && - !(async_err = PyErr_CheckSignals())); - -#ifdef HAVE_MKFIFOAT - if (mkfifoat_unavailable) { - argument_unavailable_error(NULL, "dir_fd"); - return NULL; - } -#endif - - if (result != 0) - return (!async_err) ? posix_error() : NULL; - - Py_RETURN_NONE; -} -#endif /* HAVE_MKFIFO */ - - -#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) -/*[clinic input] -os.mknod - - path: path_t - mode: int=0o600 - device: dev_t=0 - * - dir_fd: dir_fd(requires='mknodat')=None - -Create a node in the file system. - -Create a node in the file system (file, device special file or named pipe) -at path. mode specifies both the permissions to use and the -type of node to be created, being combined (bitwise OR) with one of -S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode, -device defines the newly created device special file (probably using -os.makedev()). Otherwise device is ignored. - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -dir_fd may not be implemented on your platform. - If it is unavailable, using it will raise a NotImplementedError. -[clinic start generated code]*/ - -static PyObject * -os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device, - int dir_fd) -/*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/ -{ - int result; - int async_err = 0; -#ifdef HAVE_MKNODAT - int mknodat_unavailable = 0; -#endif - - do { - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_MKNODAT - if (dir_fd != DEFAULT_DIR_FD) { - if (HAVE_MKNODAT_RUNTIME) { - result = mknodat(dir_fd, path->narrow, mode, device); - - } else { - mknodat_unavailable = 1; - result = 0; - } - } else -#endif - result = mknod(path->narrow, mode, device); - Py_END_ALLOW_THREADS - } while (result != 0 && errno == EINTR && - !(async_err = PyErr_CheckSignals())); -#ifdef HAVE_MKNODAT - if (mknodat_unavailable) { - argument_unavailable_error(NULL, "dir_fd"); - return NULL; - } -#endif - if (result != 0) - return (!async_err) ? posix_error() : NULL; - - Py_RETURN_NONE; -} -#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */ - - -#ifdef HAVE_DEVICE_MACROS -/*[clinic input] -os.major -> unsigned_int - - device: dev_t - / - -Extracts a device major number from a raw device number. -[clinic start generated code]*/ - -static unsigned int -os_major_impl(PyObject *module, dev_t device) -/*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/ -{ - return major(device); -} - - -/*[clinic input] -os.minor -> unsigned_int - - device: dev_t - / - -Extracts a device minor number from a raw device number. -[clinic start generated code]*/ - -static unsigned int -os_minor_impl(PyObject *module, dev_t device) -/*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/ -{ - return minor(device); -} - - -/*[clinic input] -os.makedev -> dev_t - - major: int - minor: int - / - -Composes a raw device number from the major and minor device numbers. -[clinic start generated code]*/ - -static dev_t -os_makedev_impl(PyObject *module, int major, int minor) -/*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/ -{ - return makedev(major, minor); -} -#endif /* HAVE_DEVICE_MACROS */ - - -#if defined HAVE_FTRUNCATE || defined MS_WINDOWS -/*[clinic input] -os.ftruncate - - fd: int - length: Py_off_t - / - -Truncate a file, specified by file descriptor, to a specific length. -[clinic start generated code]*/ - -static PyObject * -os_ftruncate_impl(PyObject *module, int fd, Py_off_t length) -/*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/ -{ - int result; - int async_err = 0; - - if (PySys_Audit("os.truncate", "in", fd, length) < 0) { - return NULL; - } - - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH -#ifdef MS_WINDOWS - result = _chsize_s(fd, length); -#else - result = ftruncate(fd, length); -#endif - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (result != 0 && errno == EINTR && - !(async_err = PyErr_CheckSignals())); - if (result != 0) - return (!async_err) ? posix_error() : NULL; - Py_RETURN_NONE; -} -#endif /* HAVE_FTRUNCATE || MS_WINDOWS */ - - -#if defined HAVE_TRUNCATE || defined MS_WINDOWS -/*[clinic input] -os.truncate - path: path_t(allow_fd='PATH_HAVE_FTRUNCATE') - length: Py_off_t - -Truncate a file, specified by path, to a specific length. - -On some platforms, path may also be specified as an open file descriptor. - If this functionality is unavailable, using it raises an exception. -[clinic start generated code]*/ - -static PyObject * -os_truncate_impl(PyObject *module, path_t *path, Py_off_t length) -/*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/ -{ - int result; -#ifdef MS_WINDOWS - int fd; -#endif - - if (path->fd != -1) - return os_ftruncate_impl(module, path->fd, length); - - if (PySys_Audit("os.truncate", "On", path->object, length) < 0) { - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH -#ifdef MS_WINDOWS - fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT); - if (fd < 0) - result = -1; - else { - result = _chsize_s(fd, length); - close(fd); - if (result < 0) - errno = result; - } -#else - result = truncate(path->narrow, length); -#endif - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - if (result < 0) - return posix_path_error(path); - - Py_RETURN_NONE; -} -#endif /* HAVE_TRUNCATE || MS_WINDOWS */ - - -/* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise() - and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is - defined, which is the case in Python on AIX. AIX bug report: - http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */ -#if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__) -# define POSIX_FADVISE_AIX_BUG -#endif - - -#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) -/*[clinic input] -os.posix_fallocate - - fd: int - offset: Py_off_t - length: Py_off_t - / - -Ensure a file has allocated at least a particular number of bytes on disk. - -Ensure that the file specified by fd encompasses a range of bytes -starting at offset bytes from the beginning and continuing for length bytes. -[clinic start generated code]*/ - -static PyObject * -os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset, - Py_off_t length) -/*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/ -{ - int result; - int async_err = 0; - - do { - Py_BEGIN_ALLOW_THREADS - result = posix_fallocate(fd, offset, length); - Py_END_ALLOW_THREADS - } while (result == EINTR && !(async_err = PyErr_CheckSignals())); - - if (result == 0) - Py_RETURN_NONE; - - if (async_err) - return NULL; - - errno = result; - return posix_error(); -} -#endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */ - - -#if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG) -/*[clinic input] -os.posix_fadvise - - fd: int - offset: Py_off_t - length: Py_off_t - advice: int - / - -Announce an intention to access data in a specific pattern. - -Announce an intention to access data in a specific pattern, thus allowing -the kernel to make optimizations. -The advice applies to the region of the file specified by fd starting at -offset and continuing for length bytes. -advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL, -POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or -POSIX_FADV_DONTNEED. -[clinic start generated code]*/ - -static PyObject * -os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset, - Py_off_t length, int advice) -/*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/ -{ - int result; - int async_err = 0; - - do { - Py_BEGIN_ALLOW_THREADS - result = posix_fadvise(fd, offset, length, advice); - Py_END_ALLOW_THREADS - } while (result == EINTR && !(async_err = PyErr_CheckSignals())); - - if (result == 0) - Py_RETURN_NONE; - - if (async_err) - return NULL; - - errno = result; - return posix_error(); -} -#endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */ - - -#ifdef MS_WINDOWS -static PyObject* -win32_putenv(PyObject *name, PyObject *value) -{ - /* Search from index 1 because on Windows starting '=' is allowed for - defining hidden environment variables. */ - if (PyUnicode_GET_LENGTH(name) == 0 || - PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1) - { - PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); - return NULL; - } - PyObject *unicode; - if (value != NULL) { - unicode = PyUnicode_FromFormat("%U=%U", name, value); - } - else { - unicode = PyUnicode_FromFormat("%U=", name); - } - if (unicode == NULL) { - return NULL; - } - - Py_ssize_t size; - /* PyUnicode_AsWideCharString() rejects embedded null characters */ - wchar_t *env = PyUnicode_AsWideCharString(unicode, &size); - Py_DECREF(unicode); - - if (env == NULL) { - return NULL; - } - if (size > _MAX_ENV) { - PyErr_Format(PyExc_ValueError, - "the environment variable is longer than %u characters", - _MAX_ENV); - PyMem_Free(env); - return NULL; - } - - /* _wputenv() and SetEnvironmentVariableW() update the environment in the - Process Environment Block (PEB). _wputenv() also updates CRT 'environ' - and '_wenviron' variables, whereas SetEnvironmentVariableW() does not. - - Prefer _wputenv() to be compatible with C libraries using CRT - variables and CRT functions using these variables (ex: getenv()). */ - int err = _wputenv(env); - PyMem_Free(env); - - if (err) { - posix_error(); - return NULL; - } - - Py_RETURN_NONE; -} -#endif - - -#ifdef MS_WINDOWS -/*[clinic input] -os.putenv - - name: unicode - value: unicode - / - -Change or add an environment variable. -[clinic start generated code]*/ - -static PyObject * -os_putenv_impl(PyObject *module, PyObject *name, PyObject *value) -/*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/ -{ - if (PySys_Audit("os.putenv", "OO", name, value) < 0) { - return NULL; - } - return win32_putenv(name, value); -} -#else -/*[clinic input] -os.putenv - - name: FSConverter - value: FSConverter - / - -Change or add an environment variable. -[clinic start generated code]*/ - -static PyObject * -os_putenv_impl(PyObject *module, PyObject *name, PyObject *value) -/*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/ -{ - const char *name_string = PyBytes_AS_STRING(name); - const char *value_string = PyBytes_AS_STRING(value); - - if (strchr(name_string, '=') != NULL) { - PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); - return NULL; - } - - if (PySys_Audit("os.putenv", "OO", name, value) < 0) { - return NULL; - } - - if (setenv(name_string, value_string, 1)) { - return posix_error(); - } - Py_RETURN_NONE; -} -#endif /* !defined(MS_WINDOWS) */ - - -#ifdef MS_WINDOWS -/*[clinic input] -os.unsetenv - name: unicode - / - -Delete an environment variable. -[clinic start generated code]*/ - -static PyObject * -os_unsetenv_impl(PyObject *module, PyObject *name) -/*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/ -{ - if (PySys_Audit("os.unsetenv", "(O)", name) < 0) { - return NULL; - } - return win32_putenv(name, NULL); -} -#else -/*[clinic input] -os.unsetenv - name: FSConverter - / - -Delete an environment variable. -[clinic start generated code]*/ - -static PyObject * -os_unsetenv_impl(PyObject *module, PyObject *name) -/*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/ -{ - if (PySys_Audit("os.unsetenv", "(O)", name) < 0) { - return NULL; - } -#ifdef HAVE_BROKEN_UNSETENV - unsetenv(PyBytes_AS_STRING(name)); -#else - int err = unsetenv(PyBytes_AS_STRING(name)); - if (err) { - return posix_error(); - } -#endif - - Py_RETURN_NONE; -} -#endif /* !MS_WINDOWS */ - - -/*[clinic input] -os.strerror - - code: int - / - -Translate an error code to a message string. -[clinic start generated code]*/ - -static PyObject * -os_strerror_impl(PyObject *module, int code) -/*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/ -{ - char *message = strerror(code); - if (message == NULL) { - PyErr_SetString(PyExc_ValueError, - "strerror() argument out of range"); - return NULL; - } - return PyUnicode_DecodeLocale(message, "surrogateescape"); -} - - -#ifdef HAVE_SYS_WAIT_H -#ifdef WCOREDUMP -/*[clinic input] -os.WCOREDUMP -> bool - - status: int - / - -Return True if the process returning status was dumped to a core file. -[clinic start generated code]*/ - -static int -os_WCOREDUMP_impl(PyObject *module, int status) -/*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/ -{ - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - return WCOREDUMP(wait_status); -} -#endif /* WCOREDUMP */ - - -#ifdef WIFCONTINUED -/*[clinic input] -os.WIFCONTINUED -> bool - - status: int - -Return True if a particular process was continued from a job control stop. - -Return True if the process returning status was continued from a -job control stop. -[clinic start generated code]*/ - -static int -os_WIFCONTINUED_impl(PyObject *module, int status) -/*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/ -{ - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - return WIFCONTINUED(wait_status); -} -#endif /* WIFCONTINUED */ - - -#ifdef WIFSTOPPED -/*[clinic input] -os.WIFSTOPPED -> bool - - status: int - -Return True if the process returning status was stopped. -[clinic start generated code]*/ - -static int -os_WIFSTOPPED_impl(PyObject *module, int status) -/*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/ -{ - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - return WIFSTOPPED(wait_status); -} -#endif /* WIFSTOPPED */ - - -#ifdef WIFSIGNALED -/*[clinic input] -os.WIFSIGNALED -> bool - - status: int - -Return True if the process returning status was terminated by a signal. -[clinic start generated code]*/ - -static int -os_WIFSIGNALED_impl(PyObject *module, int status) -/*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/ -{ - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - return WIFSIGNALED(wait_status); -} -#endif /* WIFSIGNALED */ - - -#ifdef WIFEXITED -/*[clinic input] -os.WIFEXITED -> bool - - status: int - -Return True if the process returning status exited via the exit() system call. -[clinic start generated code]*/ - -static int -os_WIFEXITED_impl(PyObject *module, int status) -/*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/ -{ - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - return WIFEXITED(wait_status); -} -#endif /* WIFEXITED */ - - -#ifdef WEXITSTATUS -/*[clinic input] -os.WEXITSTATUS -> int - - status: int - -Return the process return code from status. -[clinic start generated code]*/ - -static int -os_WEXITSTATUS_impl(PyObject *module, int status) -/*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/ -{ - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - return WEXITSTATUS(wait_status); -} -#endif /* WEXITSTATUS */ - - -#ifdef WTERMSIG -/*[clinic input] -os.WTERMSIG -> int - - status: int - -Return the signal that terminated the process that provided the status value. -[clinic start generated code]*/ - -static int -os_WTERMSIG_impl(PyObject *module, int status) -/*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/ -{ - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - return WTERMSIG(wait_status); -} -#endif /* WTERMSIG */ - - -#ifdef WSTOPSIG -/*[clinic input] -os.WSTOPSIG -> int - - status: int - -Return the signal that stopped the process that provided the status value. -[clinic start generated code]*/ - -static int -os_WSTOPSIG_impl(PyObject *module, int status) -/*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/ -{ - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - return WSTOPSIG(wait_status); -} -#endif /* WSTOPSIG */ -#endif /* HAVE_SYS_WAIT_H */ - - -#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) -#ifdef _SCO_DS -/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the - needed definitions in sys/statvfs.h */ -#define _SVID3 -#endif -#include - -static PyObject* -_pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) { - PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType; - PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType); - if (v == NULL) - return NULL; - -#if !defined(HAVE_LARGEFILE_SUPPORT) - PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize)); - PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize)); - PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks)); - PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree)); - PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail)); - PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files)); - PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree)); - PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail)); - PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag)); - PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax)); -#else - PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize)); - PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize)); - PyStructSequence_SET_ITEM(v, 2, - PyLong_FromLongLong((long long) st.f_blocks)); - PyStructSequence_SET_ITEM(v, 3, - PyLong_FromLongLong((long long) st.f_bfree)); - PyStructSequence_SET_ITEM(v, 4, - PyLong_FromLongLong((long long) st.f_bavail)); - PyStructSequence_SET_ITEM(v, 5, - PyLong_FromLongLong((long long) st.f_files)); - PyStructSequence_SET_ITEM(v, 6, - PyLong_FromLongLong((long long) st.f_ffree)); - PyStructSequence_SET_ITEM(v, 7, - PyLong_FromLongLong((long long) st.f_favail)); - PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag)); - PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax)); -#endif -/* The _ALL_SOURCE feature test macro defines f_fsid as a structure - * (issue #32390). */ -#if defined(_AIX) && defined(_ALL_SOURCE) - PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0])); -#else - PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid)); -#endif - if (PyErr_Occurred()) { - Py_DECREF(v); - return NULL; - } - - return v; -} - - -/*[clinic input] -os.fstatvfs - fd: int - / - -Perform an fstatvfs system call on the given fd. - -Equivalent to statvfs(fd). -[clinic start generated code]*/ - -static PyObject * -os_fstatvfs_impl(PyObject *module, int fd) -/*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/ -{ - int result; - int async_err = 0; - struct statvfs st; - - do { - Py_BEGIN_ALLOW_THREADS - result = fstatvfs(fd, &st); - Py_END_ALLOW_THREADS - } while (result != 0 && errno == EINTR && - !(async_err = PyErr_CheckSignals())); - if (result != 0) - return (!async_err) ? posix_error() : NULL; - - return _pystatvfs_fromstructstatvfs(module, st); -} -#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */ - - -#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) -#include -/*[clinic input] -os.statvfs - - path: path_t(allow_fd='PATH_HAVE_FSTATVFS') - -Perform a statvfs system call on the given path. - -path may always be specified as a string. -On some platforms, path may also be specified as an open file descriptor. - If this functionality is unavailable, using it raises an exception. -[clinic start generated code]*/ - -static PyObject * -os_statvfs_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/ -{ - int result; - struct statvfs st; - - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_FSTATVFS - if (path->fd != -1) { - result = fstatvfs(path->fd, &st); - } - else -#endif - result = statvfs(path->narrow, &st); - Py_END_ALLOW_THREADS - - if (result) { - return path_error(path); - } - - return _pystatvfs_fromstructstatvfs(module, st); -} -#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */ - - -#ifdef MS_WINDOWS -/*[clinic input] -os._getdiskusage - - path: path_t - -Return disk usage statistics about the given path as a (total, free) tuple. -[clinic start generated code]*/ - -static PyObject * -os__getdiskusage_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/ -{ - BOOL retval; - ULARGE_INTEGER _, total, free; - DWORD err = 0; - - Py_BEGIN_ALLOW_THREADS - retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free); - Py_END_ALLOW_THREADS - if (retval == 0) { - if (GetLastError() == ERROR_DIRECTORY) { - wchar_t *dir_path = NULL; - - dir_path = PyMem_New(wchar_t, path->length + 1); - if (dir_path == NULL) { - return PyErr_NoMemory(); - } - - wcscpy_s(dir_path, path->length + 1, path->wide); - - if (_dirnameW(dir_path) != -1) { - Py_BEGIN_ALLOW_THREADS - retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free); - Py_END_ALLOW_THREADS - } - /* Record the last error in case it's modified by PyMem_Free. */ - err = GetLastError(); - PyMem_Free(dir_path); - if (retval) { - goto success; - } - } - return PyErr_SetFromWindowsErr(err); - } - -success: - return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart); -} -#endif /* MS_WINDOWS */ - - -/* This is used for fpathconf(), pathconf(), confstr() and sysconf(). - * It maps strings representing configuration variable names to - * integer values, allowing those functions to be called with the - * magic names instead of polluting the module's namespace with tons of - * rarely-used constants. There are three separate tables that use - * these definitions. - * - * This code is always included, even if none of the interfaces that - * need it are included. The #if hackery needed to avoid it would be - * sufficiently pervasive that it's not worth the loss of readability. - */ -struct constdef { - const char *name; - int value; -}; - -static int -conv_confname(PyObject *arg, int *valuep, struct constdef *table, - size_t tablesize) -{ - if (PyLong_Check(arg)) { - int value = _PyLong_AsInt(arg); - if (value == -1 && PyErr_Occurred()) - return 0; - *valuep = value; - return 1; - } - else { - /* look up the value in the table using a binary search */ - size_t lo = 0; - size_t mid; - size_t hi = tablesize; - int cmp; - const char *confname; - if (!PyUnicode_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "configuration names must be strings or integers"); - return 0; - } - confname = PyUnicode_AsUTF8(arg); - if (confname == NULL) - return 0; - while (lo < hi) { - mid = (lo + hi) / 2; - cmp = strcmp(confname, table[mid].name); - if (cmp < 0) - hi = mid; - else if (cmp > 0) - lo = mid + 1; - else { - *valuep = table[mid].value; - return 1; - } - } - PyErr_SetString(PyExc_ValueError, "unrecognized configuration name"); - return 0; - } -} - - -#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF) -static struct constdef posix_constants_pathconf[] = { -#ifdef _PC_ABI_AIO_XFER_MAX - {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX}, -#endif -#ifdef _PC_ABI_ASYNC_IO - {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO}, -#endif -#ifdef _PC_ASYNC_IO - {"PC_ASYNC_IO", _PC_ASYNC_IO}, -#endif -#ifdef _PC_CHOWN_RESTRICTED - {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED}, -#endif -#ifdef _PC_FILESIZEBITS - {"PC_FILESIZEBITS", _PC_FILESIZEBITS}, -#endif -#ifdef _PC_LAST - {"PC_LAST", _PC_LAST}, -#endif -#ifdef _PC_LINK_MAX - {"PC_LINK_MAX", _PC_LINK_MAX}, -#endif -#ifdef _PC_MAX_CANON - {"PC_MAX_CANON", _PC_MAX_CANON}, -#endif -#ifdef _PC_MAX_INPUT - {"PC_MAX_INPUT", _PC_MAX_INPUT}, -#endif -#ifdef _PC_NAME_MAX - {"PC_NAME_MAX", _PC_NAME_MAX}, -#endif -#ifdef _PC_NO_TRUNC - {"PC_NO_TRUNC", _PC_NO_TRUNC}, -#endif -#ifdef _PC_PATH_MAX - {"PC_PATH_MAX", _PC_PATH_MAX}, -#endif -#ifdef _PC_PIPE_BUF - {"PC_PIPE_BUF", _PC_PIPE_BUF}, -#endif -#ifdef _PC_PRIO_IO - {"PC_PRIO_IO", _PC_PRIO_IO}, -#endif -#ifdef _PC_SOCK_MAXBUF - {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF}, -#endif -#ifdef _PC_SYNC_IO - {"PC_SYNC_IO", _PC_SYNC_IO}, -#endif -#ifdef _PC_VDISABLE - {"PC_VDISABLE", _PC_VDISABLE}, -#endif -#ifdef _PC_ACL_ENABLED - {"PC_ACL_ENABLED", _PC_ACL_ENABLED}, -#endif -#ifdef _PC_MIN_HOLE_SIZE - {"PC_MIN_HOLE_SIZE", _PC_MIN_HOLE_SIZE}, -#endif -#ifdef _PC_ALLOC_SIZE_MIN - {"PC_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN}, -#endif -#ifdef _PC_REC_INCR_XFER_SIZE - {"PC_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE}, -#endif -#ifdef _PC_REC_MAX_XFER_SIZE - {"PC_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE}, -#endif -#ifdef _PC_REC_MIN_XFER_SIZE - {"PC_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE}, -#endif -#ifdef _PC_REC_XFER_ALIGN - {"PC_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN}, -#endif -#ifdef _PC_SYMLINK_MAX - {"PC_SYMLINK_MAX", _PC_SYMLINK_MAX}, -#endif -#ifdef _PC_XATTR_ENABLED - {"PC_XATTR_ENABLED", _PC_XATTR_ENABLED}, -#endif -#ifdef _PC_XATTR_EXISTS - {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS}, -#endif -#ifdef _PC_TIMESTAMP_RESOLUTION - {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION}, -#endif -}; - -static int -conv_path_confname(PyObject *arg, int *valuep) -{ - return conv_confname(arg, valuep, posix_constants_pathconf, - sizeof(posix_constants_pathconf) - / sizeof(struct constdef)); -} -#endif - - -#ifdef HAVE_FPATHCONF -/*[clinic input] -os.fpathconf -> long - - fd: fildes - name: path_confname - / - -Return the configuration limit name for the file descriptor fd. - -If there is no limit, return -1. -[clinic start generated code]*/ - -static long -os_fpathconf_impl(PyObject *module, int fd, int name) -/*[clinic end generated code: output=d5b7042425fc3e21 input=5b8d2471cfaae186]*/ -{ - long limit; - - errno = 0; - limit = fpathconf(fd, name); - if (limit == -1 && errno != 0) - posix_error(); - - return limit; -} -#endif /* HAVE_FPATHCONF */ - - -#ifdef HAVE_PATHCONF -/*[clinic input] -os.pathconf -> long - path: path_t(allow_fd='PATH_HAVE_FPATHCONF') - name: path_confname - -Return the configuration limit name for the file or directory path. - -If there is no limit, return -1. -On some platforms, path may also be specified as an open file descriptor. - If this functionality is unavailable, using it raises an exception. -[clinic start generated code]*/ - -static long -os_pathconf_impl(PyObject *module, path_t *path, int name) -/*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/ -{ - long limit; - - errno = 0; -#ifdef HAVE_FPATHCONF - if (path->fd != -1) - limit = fpathconf(path->fd, name); - else -#endif - limit = pathconf(path->narrow, name); - if (limit == -1 && errno != 0) { - if (errno == EINVAL) - /* could be a path or name problem */ - posix_error(); - else - path_error(path); - } - - return limit; -} -#endif /* HAVE_PATHCONF */ - -#ifdef HAVE_CONFSTR -static struct constdef posix_constants_confstr[] = { -#ifdef _CS_ARCHITECTURE - {"CS_ARCHITECTURE", _CS_ARCHITECTURE}, -#endif -#ifdef _CS_GNU_LIBC_VERSION - {"CS_GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION}, -#endif -#ifdef _CS_GNU_LIBPTHREAD_VERSION - {"CS_GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION}, -#endif -#ifdef _CS_HOSTNAME - {"CS_HOSTNAME", _CS_HOSTNAME}, -#endif -#ifdef _CS_HW_PROVIDER - {"CS_HW_PROVIDER", _CS_HW_PROVIDER}, -#endif -#ifdef _CS_HW_SERIAL - {"CS_HW_SERIAL", _CS_HW_SERIAL}, -#endif -#ifdef _CS_INITTAB_NAME - {"CS_INITTAB_NAME", _CS_INITTAB_NAME}, -#endif -#ifdef _CS_LFS64_CFLAGS - {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS}, -#endif -#ifdef _CS_LFS64_LDFLAGS - {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS}, -#endif -#ifdef _CS_LFS64_LIBS - {"CS_LFS64_LIBS", _CS_LFS64_LIBS}, -#endif -#ifdef _CS_LFS64_LINTFLAGS - {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS}, -#endif -#ifdef _CS_LFS_CFLAGS - {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS}, -#endif -#ifdef _CS_LFS_LDFLAGS - {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS}, -#endif -#ifdef _CS_LFS_LIBS - {"CS_LFS_LIBS", _CS_LFS_LIBS}, -#endif -#ifdef _CS_LFS_LINTFLAGS - {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS}, -#endif -#ifdef _CS_MACHINE - {"CS_MACHINE", _CS_MACHINE}, -#endif -#ifdef _CS_PATH - {"CS_PATH", _CS_PATH}, -#endif -#ifdef _CS_RELEASE - {"CS_RELEASE", _CS_RELEASE}, -#endif -#ifdef _CS_SRPC_DOMAIN - {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN}, -#endif -#ifdef _CS_SYSNAME - {"CS_SYSNAME", _CS_SYSNAME}, -#endif -#ifdef _CS_VERSION - {"CS_VERSION", _CS_VERSION}, -#endif -#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS - {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS}, -#endif -#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS - {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS}, -#endif -#ifdef _CS_XBS5_ILP32_OFF32_LIBS - {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS}, -#endif -#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS - {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS}, -#endif -#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS - {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS}, -#endif -#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS - {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS}, -#endif -#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS - {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS}, -#endif -#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS - {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS}, -#endif -#ifdef _CS_XBS5_LP64_OFF64_CFLAGS - {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS}, -#endif -#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS - {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS}, -#endif -#ifdef _CS_XBS5_LP64_OFF64_LIBS - {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS}, -#endif -#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS - {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS}, -#endif -#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS - {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS}, -#endif -#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS - {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS}, -#endif -#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS - {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS}, -#endif -#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS - {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS}, -#endif -#ifdef _MIPS_CS_AVAIL_PROCESSORS - {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS}, -#endif -#ifdef _MIPS_CS_BASE - {"MIPS_CS_BASE", _MIPS_CS_BASE}, -#endif -#ifdef _MIPS_CS_HOSTID - {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID}, -#endif -#ifdef _MIPS_CS_HW_NAME - {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME}, -#endif -#ifdef _MIPS_CS_NUM_PROCESSORS - {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS}, -#endif -#ifdef _MIPS_CS_OSREL_MAJ - {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ}, -#endif -#ifdef _MIPS_CS_OSREL_MIN - {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN}, -#endif -#ifdef _MIPS_CS_OSREL_PATCH - {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH}, -#endif -#ifdef _MIPS_CS_OS_NAME - {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME}, -#endif -#ifdef _MIPS_CS_OS_PROVIDER - {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER}, -#endif -#ifdef _MIPS_CS_PROCESSORS - {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS}, -#endif -#ifdef _MIPS_CS_SERIAL - {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL}, -#endif -#ifdef _MIPS_CS_VENDOR - {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR}, -#endif -}; - -static int -conv_confstr_confname(PyObject *arg, int *valuep) -{ - return conv_confname(arg, valuep, posix_constants_confstr, - sizeof(posix_constants_confstr) - / sizeof(struct constdef)); -} - - -/*[clinic input] -os.confstr - - name: confstr_confname - / - -Return a string-valued system configuration variable. -[clinic start generated code]*/ - -static PyObject * -os_confstr_impl(PyObject *module, int name) -/*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/ -{ - PyObject *result = NULL; - char buffer[255]; - size_t len; - - errno = 0; - len = confstr(name, buffer, sizeof(buffer)); - if (len == 0) { - if (errno) { - posix_error(); - return NULL; - } - else { - Py_RETURN_NONE; - } - } - - if (len >= sizeof(buffer)) { - size_t len2; - char *buf = PyMem_Malloc(len); - if (buf == NULL) - return PyErr_NoMemory(); - len2 = confstr(name, buf, len); - assert(len == len2); - result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1); - PyMem_Free(buf); - } - else - result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1); - return result; -} -#endif /* HAVE_CONFSTR */ - - -#ifdef HAVE_SYSCONF -static struct constdef posix_constants_sysconf[] = { -#ifdef _SC_2_CHAR_TERM - {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM}, -#endif -#ifdef _SC_2_C_BIND - {"SC_2_C_BIND", _SC_2_C_BIND}, -#endif -#ifdef _SC_2_C_DEV - {"SC_2_C_DEV", _SC_2_C_DEV}, -#endif -#ifdef _SC_2_C_VERSION - {"SC_2_C_VERSION", _SC_2_C_VERSION}, -#endif -#ifdef _SC_2_FORT_DEV - {"SC_2_FORT_DEV", _SC_2_FORT_DEV}, -#endif -#ifdef _SC_2_FORT_RUN - {"SC_2_FORT_RUN", _SC_2_FORT_RUN}, -#endif -#ifdef _SC_2_LOCALEDEF - {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF}, -#endif -#ifdef _SC_2_SW_DEV - {"SC_2_SW_DEV", _SC_2_SW_DEV}, -#endif -#ifdef _SC_2_UPE - {"SC_2_UPE", _SC_2_UPE}, -#endif -#ifdef _SC_2_VERSION - {"SC_2_VERSION", _SC_2_VERSION}, -#endif -#ifdef _SC_ABI_ASYNCHRONOUS_IO - {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO}, -#endif -#ifdef _SC_ACL - {"SC_ACL", _SC_ACL}, -#endif -#ifdef _SC_AIO_LISTIO_MAX - {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX}, -#endif -#ifdef _SC_AIO_MAX - {"SC_AIO_MAX", _SC_AIO_MAX}, -#endif -#ifdef _SC_AIO_PRIO_DELTA_MAX - {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX}, -#endif -#ifdef _SC_ARG_MAX - {"SC_ARG_MAX", _SC_ARG_MAX}, -#endif -#ifdef _SC_ASYNCHRONOUS_IO - {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO}, -#endif -#ifdef _SC_ATEXIT_MAX - {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX}, -#endif -#ifdef _SC_AUDIT - {"SC_AUDIT", _SC_AUDIT}, -#endif -#ifdef _SC_AVPHYS_PAGES - {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES}, -#endif -#ifdef _SC_BC_BASE_MAX - {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX}, -#endif -#ifdef _SC_BC_DIM_MAX - {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX}, -#endif -#ifdef _SC_BC_SCALE_MAX - {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX}, -#endif -#ifdef _SC_BC_STRING_MAX - {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX}, -#endif -#ifdef _SC_CAP - {"SC_CAP", _SC_CAP}, -#endif -#ifdef _SC_CHARCLASS_NAME_MAX - {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX}, -#endif -#ifdef _SC_CHAR_BIT - {"SC_CHAR_BIT", _SC_CHAR_BIT}, -#endif -#ifdef _SC_CHAR_MAX - {"SC_CHAR_MAX", _SC_CHAR_MAX}, -#endif -#ifdef _SC_CHAR_MIN - {"SC_CHAR_MIN", _SC_CHAR_MIN}, -#endif -#ifdef _SC_CHILD_MAX - {"SC_CHILD_MAX", _SC_CHILD_MAX}, -#endif -#ifdef _SC_CLK_TCK - {"SC_CLK_TCK", _SC_CLK_TCK}, -#endif -#ifdef _SC_COHER_BLKSZ - {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ}, -#endif -#ifdef _SC_COLL_WEIGHTS_MAX - {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX}, -#endif -#ifdef _SC_DCACHE_ASSOC - {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC}, -#endif -#ifdef _SC_DCACHE_BLKSZ - {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ}, -#endif -#ifdef _SC_DCACHE_LINESZ - {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ}, -#endif -#ifdef _SC_DCACHE_SZ - {"SC_DCACHE_SZ", _SC_DCACHE_SZ}, -#endif -#ifdef _SC_DCACHE_TBLKSZ - {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ}, -#endif -#ifdef _SC_DELAYTIMER_MAX - {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX}, -#endif -#ifdef _SC_EQUIV_CLASS_MAX - {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX}, -#endif -#ifdef _SC_EXPR_NEST_MAX - {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX}, -#endif -#ifdef _SC_FSYNC - {"SC_FSYNC", _SC_FSYNC}, -#endif -#ifdef _SC_GETGR_R_SIZE_MAX - {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX}, -#endif -#ifdef _SC_GETPW_R_SIZE_MAX - {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX}, -#endif -#ifdef _SC_ICACHE_ASSOC - {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC}, -#endif -#ifdef _SC_ICACHE_BLKSZ - {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ}, -#endif -#ifdef _SC_ICACHE_LINESZ - {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ}, -#endif -#ifdef _SC_ICACHE_SZ - {"SC_ICACHE_SZ", _SC_ICACHE_SZ}, -#endif -#ifdef _SC_INF - {"SC_INF", _SC_INF}, -#endif -#ifdef _SC_INT_MAX - {"SC_INT_MAX", _SC_INT_MAX}, -#endif -#ifdef _SC_INT_MIN - {"SC_INT_MIN", _SC_INT_MIN}, -#endif -#ifdef _SC_IOV_MAX - {"SC_IOV_MAX", _SC_IOV_MAX}, -#endif -#ifdef _SC_IP_SECOPTS - {"SC_IP_SECOPTS", _SC_IP_SECOPTS}, -#endif -#ifdef _SC_JOB_CONTROL - {"SC_JOB_CONTROL", _SC_JOB_CONTROL}, -#endif -#ifdef _SC_KERN_POINTERS - {"SC_KERN_POINTERS", _SC_KERN_POINTERS}, -#endif -#ifdef _SC_KERN_SIM - {"SC_KERN_SIM", _SC_KERN_SIM}, -#endif -#ifdef _SC_LINE_MAX - {"SC_LINE_MAX", _SC_LINE_MAX}, -#endif -#ifdef _SC_LOGIN_NAME_MAX - {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX}, -#endif -#ifdef _SC_LOGNAME_MAX - {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX}, -#endif -#ifdef _SC_LONG_BIT - {"SC_LONG_BIT", _SC_LONG_BIT}, -#endif -#ifdef _SC_MAC - {"SC_MAC", _SC_MAC}, -#endif -#ifdef _SC_MAPPED_FILES - {"SC_MAPPED_FILES", _SC_MAPPED_FILES}, -#endif -#ifdef _SC_MAXPID - {"SC_MAXPID", _SC_MAXPID}, -#endif -#ifdef _SC_MB_LEN_MAX - {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX}, -#endif -#ifdef _SC_MEMLOCK - {"SC_MEMLOCK", _SC_MEMLOCK}, -#endif -#ifdef _SC_MEMLOCK_RANGE - {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE}, -#endif -#ifdef _SC_MEMORY_PROTECTION - {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION}, -#endif -#ifdef _SC_MESSAGE_PASSING - {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING}, -#endif -#ifdef _SC_MMAP_FIXED_ALIGNMENT - {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT}, -#endif -#ifdef _SC_MQ_OPEN_MAX - {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX}, -#endif -#ifdef _SC_MQ_PRIO_MAX - {"SC_MQ_PRIO_MAX", _SC_MQ_PRIO_MAX}, -#endif -#ifdef _SC_NACLS_MAX - {"SC_NACLS_MAX", _SC_NACLS_MAX}, -#endif -#ifdef _SC_NGROUPS_MAX - {"SC_NGROUPS_MAX", _SC_NGROUPS_MAX}, -#endif -#ifdef _SC_NL_ARGMAX - {"SC_NL_ARGMAX", _SC_NL_ARGMAX}, -#endif -#ifdef _SC_NL_LANGMAX - {"SC_NL_LANGMAX", _SC_NL_LANGMAX}, -#endif -#ifdef _SC_NL_MSGMAX - {"SC_NL_MSGMAX", _SC_NL_MSGMAX}, -#endif -#ifdef _SC_NL_NMAX - {"SC_NL_NMAX", _SC_NL_NMAX}, -#endif -#ifdef _SC_NL_SETMAX - {"SC_NL_SETMAX", _SC_NL_SETMAX}, -#endif -#ifdef _SC_NL_TEXTMAX - {"SC_NL_TEXTMAX", _SC_NL_TEXTMAX}, -#endif -#ifdef _SC_NPROCESSORS_CONF - {"SC_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF}, -#endif -#ifdef _SC_NPROCESSORS_ONLN - {"SC_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN}, -#endif -#ifdef _SC_NPROC_CONF - {"SC_NPROC_CONF", _SC_NPROC_CONF}, -#endif -#ifdef _SC_NPROC_ONLN - {"SC_NPROC_ONLN", _SC_NPROC_ONLN}, -#endif -#ifdef _SC_NZERO - {"SC_NZERO", _SC_NZERO}, -#endif -#ifdef _SC_OPEN_MAX - {"SC_OPEN_MAX", _SC_OPEN_MAX}, -#endif -#ifdef _SC_PAGESIZE - {"SC_PAGESIZE", _SC_PAGESIZE}, -#endif -#ifdef _SC_PAGE_SIZE - {"SC_PAGE_SIZE", _SC_PAGE_SIZE}, -#endif -#ifdef _SC_AIX_REALMEM - {"SC_AIX_REALMEM", _SC_AIX_REALMEM}, -#endif -#ifdef _SC_PASS_MAX - {"SC_PASS_MAX", _SC_PASS_MAX}, -#endif -#ifdef _SC_PHYS_PAGES - {"SC_PHYS_PAGES", _SC_PHYS_PAGES}, -#endif -#ifdef _SC_PII - {"SC_PII", _SC_PII}, -#endif -#ifdef _SC_PII_INTERNET - {"SC_PII_INTERNET", _SC_PII_INTERNET}, -#endif -#ifdef _SC_PII_INTERNET_DGRAM - {"SC_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM}, -#endif -#ifdef _SC_PII_INTERNET_STREAM - {"SC_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM}, -#endif -#ifdef _SC_PII_OSI - {"SC_PII_OSI", _SC_PII_OSI}, -#endif -#ifdef _SC_PII_OSI_CLTS - {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS}, -#endif -#ifdef _SC_PII_OSI_COTS - {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS}, -#endif -#ifdef _SC_PII_OSI_M - {"SC_PII_OSI_M", _SC_PII_OSI_M}, -#endif -#ifdef _SC_PII_SOCKET - {"SC_PII_SOCKET", _SC_PII_SOCKET}, -#endif -#ifdef _SC_PII_XTI - {"SC_PII_XTI", _SC_PII_XTI}, -#endif -#ifdef _SC_POLL - {"SC_POLL", _SC_POLL}, -#endif -#ifdef _SC_PRIORITIZED_IO - {"SC_PRIORITIZED_IO", _SC_PRIORITIZED_IO}, -#endif -#ifdef _SC_PRIORITY_SCHEDULING - {"SC_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING}, -#endif -#ifdef _SC_REALTIME_SIGNALS - {"SC_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS}, -#endif -#ifdef _SC_RE_DUP_MAX - {"SC_RE_DUP_MAX", _SC_RE_DUP_MAX}, -#endif -#ifdef _SC_RTSIG_MAX - {"SC_RTSIG_MAX", _SC_RTSIG_MAX}, -#endif -#ifdef _SC_SAVED_IDS - {"SC_SAVED_IDS", _SC_SAVED_IDS}, -#endif -#ifdef _SC_SCHAR_MAX - {"SC_SCHAR_MAX", _SC_SCHAR_MAX}, -#endif -#ifdef _SC_SCHAR_MIN - {"SC_SCHAR_MIN", _SC_SCHAR_MIN}, -#endif -#ifdef _SC_SELECT - {"SC_SELECT", _SC_SELECT}, -#endif -#ifdef _SC_SEMAPHORES - {"SC_SEMAPHORES", _SC_SEMAPHORES}, -#endif -#ifdef _SC_SEM_NSEMS_MAX - {"SC_SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX}, -#endif -#ifdef _SC_SEM_VALUE_MAX - {"SC_SEM_VALUE_MAX", _SC_SEM_VALUE_MAX}, -#endif -#ifdef _SC_SHARED_MEMORY_OBJECTS - {"SC_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS}, -#endif -#ifdef _SC_SHRT_MAX - {"SC_SHRT_MAX", _SC_SHRT_MAX}, -#endif -#ifdef _SC_SHRT_MIN - {"SC_SHRT_MIN", _SC_SHRT_MIN}, -#endif -#ifdef _SC_SIGQUEUE_MAX - {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX}, -#endif -#ifdef _SC_SIGRT_MAX - {"SC_SIGRT_MAX", _SC_SIGRT_MAX}, -#endif -#ifdef _SC_SIGRT_MIN - {"SC_SIGRT_MIN", _SC_SIGRT_MIN}, -#endif -#ifdef _SC_SOFTPOWER - {"SC_SOFTPOWER", _SC_SOFTPOWER}, -#endif -#ifdef _SC_SPLIT_CACHE - {"SC_SPLIT_CACHE", _SC_SPLIT_CACHE}, -#endif -#ifdef _SC_SSIZE_MAX - {"SC_SSIZE_MAX", _SC_SSIZE_MAX}, -#endif -#ifdef _SC_STACK_PROT - {"SC_STACK_PROT", _SC_STACK_PROT}, -#endif -#ifdef _SC_STREAM_MAX - {"SC_STREAM_MAX", _SC_STREAM_MAX}, -#endif -#ifdef _SC_SYNCHRONIZED_IO - {"SC_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO}, -#endif -#ifdef _SC_THREADS - {"SC_THREADS", _SC_THREADS}, -#endif -#ifdef _SC_THREAD_ATTR_STACKADDR - {"SC_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR}, -#endif -#ifdef _SC_THREAD_ATTR_STACKSIZE - {"SC_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE}, -#endif -#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS - {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS}, -#endif -#ifdef _SC_THREAD_KEYS_MAX - {"SC_THREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX}, -#endif -#ifdef _SC_THREAD_PRIORITY_SCHEDULING - {"SC_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING}, -#endif -#ifdef _SC_THREAD_PRIO_INHERIT - {"SC_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT}, -#endif -#ifdef _SC_THREAD_PRIO_PROTECT - {"SC_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT}, -#endif -#ifdef _SC_THREAD_PROCESS_SHARED - {"SC_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED}, -#endif -#ifdef _SC_THREAD_SAFE_FUNCTIONS - {"SC_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS}, -#endif -#ifdef _SC_THREAD_STACK_MIN - {"SC_THREAD_STACK_MIN", _SC_THREAD_STACK_MIN}, -#endif -#ifdef _SC_THREAD_THREADS_MAX - {"SC_THREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX}, -#endif -#ifdef _SC_TIMERS - {"SC_TIMERS", _SC_TIMERS}, -#endif -#ifdef _SC_TIMER_MAX - {"SC_TIMER_MAX", _SC_TIMER_MAX}, -#endif -#ifdef _SC_TTY_NAME_MAX - {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX}, -#endif -#ifdef _SC_TZNAME_MAX - {"SC_TZNAME_MAX", _SC_TZNAME_MAX}, -#endif -#ifdef _SC_T_IOV_MAX - {"SC_T_IOV_MAX", _SC_T_IOV_MAX}, -#endif -#ifdef _SC_UCHAR_MAX - {"SC_UCHAR_MAX", _SC_UCHAR_MAX}, -#endif -#ifdef _SC_UINT_MAX - {"SC_UINT_MAX", _SC_UINT_MAX}, -#endif -#ifdef _SC_UIO_MAXIOV - {"SC_UIO_MAXIOV", _SC_UIO_MAXIOV}, -#endif -#ifdef _SC_ULONG_MAX - {"SC_ULONG_MAX", _SC_ULONG_MAX}, -#endif -#ifdef _SC_USHRT_MAX - {"SC_USHRT_MAX", _SC_USHRT_MAX}, -#endif -#ifdef _SC_VERSION - {"SC_VERSION", _SC_VERSION}, -#endif -#ifdef _SC_WORD_BIT - {"SC_WORD_BIT", _SC_WORD_BIT}, -#endif -#ifdef _SC_XBS5_ILP32_OFF32 - {"SC_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32}, -#endif -#ifdef _SC_XBS5_ILP32_OFFBIG - {"SC_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG}, -#endif -#ifdef _SC_XBS5_LP64_OFF64 - {"SC_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64}, -#endif -#ifdef _SC_XBS5_LPBIG_OFFBIG - {"SC_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG}, -#endif -#ifdef _SC_XOPEN_CRYPT - {"SC_XOPEN_CRYPT", _SC_XOPEN_CRYPT}, -#endif -#ifdef _SC_XOPEN_ENH_I18N - {"SC_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N}, -#endif -#ifdef _SC_XOPEN_LEGACY - {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY}, -#endif -#ifdef _SC_XOPEN_REALTIME - {"SC_XOPEN_REALTIME", _SC_XOPEN_REALTIME}, -#endif -#ifdef _SC_XOPEN_REALTIME_THREADS - {"SC_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS}, -#endif -#ifdef _SC_XOPEN_SHM - {"SC_XOPEN_SHM", _SC_XOPEN_SHM}, -#endif -#ifdef _SC_XOPEN_UNIX - {"SC_XOPEN_UNIX", _SC_XOPEN_UNIX}, -#endif -#ifdef _SC_XOPEN_VERSION - {"SC_XOPEN_VERSION", _SC_XOPEN_VERSION}, -#endif -#ifdef _SC_XOPEN_XCU_VERSION - {"SC_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION}, -#endif -#ifdef _SC_XOPEN_XPG2 - {"SC_XOPEN_XPG2", _SC_XOPEN_XPG2}, -#endif -#ifdef _SC_XOPEN_XPG3 - {"SC_XOPEN_XPG3", _SC_XOPEN_XPG3}, -#endif -#ifdef _SC_XOPEN_XPG4 - {"SC_XOPEN_XPG4", _SC_XOPEN_XPG4}, -#endif -#ifdef _SC_MINSIGSTKSZ - {"SC_MINSIGSTKSZ", _SC_MINSIGSTKSZ}, -#endif -}; - -static int -conv_sysconf_confname(PyObject *arg, int *valuep) -{ - return conv_confname(arg, valuep, posix_constants_sysconf, - sizeof(posix_constants_sysconf) - / sizeof(struct constdef)); -} - - -/*[clinic input] -os.sysconf -> long - name: sysconf_confname - / - -Return an integer-valued system configuration variable. -[clinic start generated code]*/ - -static long -os_sysconf_impl(PyObject *module, int name) -/*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/ -{ - long value; - - errno = 0; - value = sysconf(name); - if (value == -1 && errno != 0) - posix_error(); - return value; -} -#endif /* HAVE_SYSCONF */ - - -/* This code is used to ensure that the tables of configuration value names - * are in sorted order as required by conv_confname(), and also to build - * the exported dictionaries that are used to publish information about the - * names available on the host platform. - * - * Sorting the table at runtime ensures that the table is properly ordered - * when used, even for platforms we're not able to test on. It also makes - * it easier to add additional entries to the tables. - */ - -static int -cmp_constdefs(const void *v1, const void *v2) -{ - const struct constdef *c1 = - (const struct constdef *) v1; - const struct constdef *c2 = - (const struct constdef *) v2; - - return strcmp(c1->name, c2->name); -} - -static int -setup_confname_table(struct constdef *table, size_t tablesize, - const char *tablename, PyObject *module) -{ - PyObject *d = NULL; - size_t i; - - qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs); - d = PyDict_New(); - if (d == NULL) - return -1; - - for (i=0; i < tablesize; ++i) { - PyObject *o = PyLong_FromLong(table[i].value); - if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) { - Py_XDECREF(o); - Py_DECREF(d); - return -1; - } - Py_DECREF(o); - } - return PyModule_AddObject(module, tablename, d); -} - -/* Return -1 on failure, 0 on success. */ -static int -setup_confname_tables(PyObject *module) -{ -#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF) - if (setup_confname_table(posix_constants_pathconf, - sizeof(posix_constants_pathconf) - / sizeof(struct constdef), - "pathconf_names", module)) - return -1; -#endif -#ifdef HAVE_CONFSTR - if (setup_confname_table(posix_constants_confstr, - sizeof(posix_constants_confstr) - / sizeof(struct constdef), - "confstr_names", module)) - return -1; -#endif -#ifdef HAVE_SYSCONF - if (setup_confname_table(posix_constants_sysconf, - sizeof(posix_constants_sysconf) - / sizeof(struct constdef), - "sysconf_names", module)) - return -1; -#endif - return 0; -} - - -/*[clinic input] -os.abort - -Abort the interpreter immediately. - -This function 'dumps core' or otherwise fails in the hardest way possible -on the hosting operating system. This function never returns. -[clinic start generated code]*/ - -static PyObject * -os_abort_impl(PyObject *module) -/*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/ -{ - abort(); - /*NOTREACHED*/ -#ifndef __clang__ - /* Issue #28152: abort() is declared with __attribute__((__noreturn__)). - GCC emits a warning without "return NULL;" (compiler bug?), but Clang - is smarter and emits a warning on the return. */ - Py_FatalError("abort() called from Python code didn't abort!"); - return NULL; -#endif -} - -#ifdef MS_WINDOWS -/* Grab ShellExecute dynamically from shell32 */ -static int has_ShellExecute = -1; -static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR, - LPCWSTR, INT); -static int -check_ShellExecute() -{ - HINSTANCE hShell32; - - /* only recheck */ - if (-1 == has_ShellExecute) { - Py_BEGIN_ALLOW_THREADS - /* Security note: this call is not vulnerable to "DLL hijacking". - SHELL32 is part of "KnownDLLs" and so Windows always load - the system SHELL32.DLL, even if there is another SHELL32.DLL - in the DLL search path. */ - hShell32 = LoadLibraryW(L"SHELL32"); - if (hShell32) { - *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32, - "ShellExecuteW"); - has_ShellExecute = Py_ShellExecuteW != NULL; - } else { - has_ShellExecute = 0; - } - Py_END_ALLOW_THREADS - } - return has_ShellExecute; -} - - -/*[clinic input] -os.startfile - filepath: path_t - operation: Py_UNICODE = NULL - arguments: Py_UNICODE = NULL - cwd: path_t(nullable=True) = None - show_cmd: int = 1 - -Start a file with its associated application. - -When "operation" is not specified or "open", this acts like -double-clicking the file in Explorer, or giving the file name as an -argument to the DOS "start" command: the file is opened with whatever -application (if any) its extension is associated. -When another "operation" is given, it specifies what should be done with -the file. A typical operation is "print". - -"arguments" is passed to the application, but should be omitted if the -file is a document. - -"cwd" is the working directory for the operation. If "filepath" is -relative, it will be resolved against this directory. This argument -should usually be an absolute path. - -"show_cmd" can be used to override the recommended visibility option. -See the Windows ShellExecute documentation for values. - -startfile returns as soon as the associated application is launched. -There is no option to wait for the application to close, and no way -to retrieve the application's exit status. - -The filepath is relative to the current directory. If you want to use -an absolute path, make sure the first character is not a slash ("/"); -the underlying Win32 ShellExecute function doesn't work if it is. -[clinic start generated code]*/ - -static PyObject * -os_startfile_impl(PyObject *module, path_t *filepath, - const Py_UNICODE *operation, const Py_UNICODE *arguments, - path_t *cwd, int show_cmd) -/*[clinic end generated code: output=3baa4f9795841880 input=8248997b80669622]*/ -{ - HINSTANCE rc; - - if(!check_ShellExecute()) { - /* If the OS doesn't have ShellExecute, return a - NotImplementedError. */ - return PyErr_Format(PyExc_NotImplementedError, - "startfile not available on this platform"); - } - - if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) { - return NULL; - } - if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation, - arguments, cwd->object ? cwd->object : Py_None, - show_cmd) < 0) { - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide, - arguments, cwd->wide, show_cmd); - Py_END_ALLOW_THREADS - - if (rc <= (HINSTANCE)32) { - win32_error_object("startfile", filepath->object); - return NULL; - } - Py_RETURN_NONE; -} -#endif /* MS_WINDOWS */ - - -#ifdef HAVE_GETLOADAVG -/*[clinic input] -os.getloadavg - -Return average recent system load information. - -Return the number of processes in the system run queue averaged over -the last 1, 5, and 15 minutes as a tuple of three floats. -Raises OSError if the load average was unobtainable. -[clinic start generated code]*/ - -static PyObject * -os_getloadavg_impl(PyObject *module) -/*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/ -{ - double loadavg[3]; - if (getloadavg(loadavg, 3)!=3) { - PyErr_SetString(PyExc_OSError, "Load averages are unobtainable"); - return NULL; - } else - return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]); -} -#endif /* HAVE_GETLOADAVG */ - - -/*[clinic input] -os.device_encoding - fd: int - -Return a string describing the encoding of a terminal's file descriptor. - -The file descriptor must be attached to a terminal. -If the device is not a terminal, return None. -[clinic start generated code]*/ - -static PyObject * -os_device_encoding_impl(PyObject *module, int fd) -/*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/ -{ - return _Py_device_encoding(fd); -} - - -#ifdef HAVE_SETRESUID -/*[clinic input] -os.setresuid - - ruid: uid_t - euid: uid_t - suid: uid_t - / - -Set the current process's real, effective, and saved user ids. -[clinic start generated code]*/ - -static PyObject * -os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid) -/*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/ -{ - if (setresuid(ruid, euid, suid) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETRESUID */ - - -#ifdef HAVE_SETRESGID -/*[clinic input] -os.setresgid - - rgid: gid_t - egid: gid_t - sgid: gid_t - / - -Set the current process's real, effective, and saved group ids. -[clinic start generated code]*/ - -static PyObject * -os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid) -/*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/ -{ - if (setresgid(rgid, egid, sgid) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETRESGID */ - - -#ifdef HAVE_GETRESUID -/*[clinic input] -os.getresuid - -Return a tuple of the current process's real, effective, and saved user ids. -[clinic start generated code]*/ - -static PyObject * -os_getresuid_impl(PyObject *module) -/*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/ -{ - uid_t ruid, euid, suid; - if (getresuid(&ruid, &euid, &suid) < 0) - return posix_error(); - return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid), - _PyLong_FromUid(euid), - _PyLong_FromUid(suid)); -} -#endif /* HAVE_GETRESUID */ - - -#ifdef HAVE_GETRESGID -/*[clinic input] -os.getresgid - -Return a tuple of the current process's real, effective, and saved group ids. -[clinic start generated code]*/ - -static PyObject * -os_getresgid_impl(PyObject *module) -/*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/ -{ - gid_t rgid, egid, sgid; - if (getresgid(&rgid, &egid, &sgid) < 0) - return posix_error(); - return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid), - _PyLong_FromGid(egid), - _PyLong_FromGid(sgid)); -} -#endif /* HAVE_GETRESGID */ - - -#ifdef USE_XATTRS -/*[clinic input] -os.getxattr - - path: path_t(allow_fd=True) - attribute: path_t - * - follow_symlinks: bool = True - -Return the value of extended attribute attribute on path. - -path may be either a string, a path-like object, or an open file descriptor. -If follow_symlinks is False, and the last element of the path is a symbolic - link, getxattr will examine the symbolic link itself instead of the file - the link points to. - -[clinic start generated code]*/ - -static PyObject * -os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute, - int follow_symlinks) -/*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/ -{ - Py_ssize_t i; - PyObject *buffer = NULL; - - if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks)) - return NULL; - - if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) { - return NULL; - } - - for (i = 0; ; i++) { - void *ptr; - ssize_t result; - static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0}; - Py_ssize_t buffer_size = buffer_sizes[i]; - if (!buffer_size) { - path_error(path); - return NULL; - } - buffer = PyBytes_FromStringAndSize(NULL, buffer_size); - if (!buffer) - return NULL; - ptr = PyBytes_AS_STRING(buffer); - - Py_BEGIN_ALLOW_THREADS; - if (path->fd >= 0) - result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size); - else if (follow_symlinks) - result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size); - else - result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size); - Py_END_ALLOW_THREADS; - - if (result < 0) { - Py_DECREF(buffer); - if (errno == ERANGE) - continue; - path_error(path); - return NULL; - } - - if (result != buffer_size) { - /* Can only shrink. */ - _PyBytes_Resize(&buffer, result); - } - break; - } - - return buffer; -} - - -/*[clinic input] -os.setxattr - - path: path_t(allow_fd=True) - attribute: path_t - value: Py_buffer - flags: int = 0 - * - follow_symlinks: bool = True - -Set extended attribute attribute on path to value. - -path may be either a string, a path-like object, or an open file descriptor. -If follow_symlinks is False, and the last element of the path is a symbolic - link, setxattr will modify the symbolic link itself instead of the file - the link points to. - -[clinic start generated code]*/ - -static PyObject * -os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute, - Py_buffer *value, int flags, int follow_symlinks) -/*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/ -{ - ssize_t result; - - if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks)) - return NULL; - - if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object, - value->buf, value->len, flags) < 0) { - return NULL; - } - - Py_BEGIN_ALLOW_THREADS; - if (path->fd > -1) - result = fsetxattr(path->fd, attribute->narrow, - value->buf, value->len, flags); - else if (follow_symlinks) - result = setxattr(path->narrow, attribute->narrow, - value->buf, value->len, flags); - else - result = lsetxattr(path->narrow, attribute->narrow, - value->buf, value->len, flags); - Py_END_ALLOW_THREADS; - - if (result) { - path_error(path); - return NULL; - } - - Py_RETURN_NONE; -} - - -/*[clinic input] -os.removexattr - - path: path_t(allow_fd=True) - attribute: path_t - * - follow_symlinks: bool = True - -Remove extended attribute attribute on path. - -path may be either a string, a path-like object, or an open file descriptor. -If follow_symlinks is False, and the last element of the path is a symbolic - link, removexattr will modify the symbolic link itself instead of the file - the link points to. - -[clinic start generated code]*/ - -static PyObject * -os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute, - int follow_symlinks) -/*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/ -{ - ssize_t result; - - if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks)) - return NULL; - - if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) { - return NULL; - } - - Py_BEGIN_ALLOW_THREADS; - if (path->fd > -1) - result = fremovexattr(path->fd, attribute->narrow); - else if (follow_symlinks) - result = removexattr(path->narrow, attribute->narrow); - else - result = lremovexattr(path->narrow, attribute->narrow); - Py_END_ALLOW_THREADS; - - if (result) { - return path_error(path); - } - - Py_RETURN_NONE; -} - - -/*[clinic input] -os.listxattr - - path: path_t(allow_fd=True, nullable=True) = None - * - follow_symlinks: bool = True - -Return a list of extended attributes on path. - -path may be either None, a string, a path-like object, or an open file descriptor. -if path is None, listxattr will examine the current directory. -If follow_symlinks is False, and the last element of the path is a symbolic - link, listxattr will examine the symbolic link itself instead of the file - the link points to. -[clinic start generated code]*/ - -static PyObject * -os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks) -/*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/ -{ - Py_ssize_t i; - PyObject *result = NULL; - const char *name; - char *buffer = NULL; - - if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks)) - goto exit; - - if (PySys_Audit("os.listxattr", "(O)", - path->object ? path->object : Py_None) < 0) { - return NULL; - } - - name = path->narrow ? path->narrow : "."; - - for (i = 0; ; i++) { - const char *start, *trace, *end; - ssize_t length; - static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 }; - Py_ssize_t buffer_size = buffer_sizes[i]; - if (!buffer_size) { - /* ERANGE */ - path_error(path); - break; - } - buffer = PyMem_Malloc(buffer_size); - if (!buffer) { - PyErr_NoMemory(); - break; - } - - Py_BEGIN_ALLOW_THREADS; - if (path->fd > -1) - length = flistxattr(path->fd, buffer, buffer_size); - else if (follow_symlinks) - length = listxattr(name, buffer, buffer_size); - else - length = llistxattr(name, buffer, buffer_size); - Py_END_ALLOW_THREADS; - - if (length < 0) { - if (errno == ERANGE) { - PyMem_Free(buffer); - buffer = NULL; - continue; - } - path_error(path); - break; - } - - result = PyList_New(0); - if (!result) { - goto exit; - } - - end = buffer + length; - for (trace = start = buffer; trace != end; trace++) { - if (!*trace) { - int error; - PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start, - trace - start); - if (!attribute) { - Py_DECREF(result); - result = NULL; - goto exit; - } - error = PyList_Append(result, attribute); - Py_DECREF(attribute); - if (error) { - Py_DECREF(result); - result = NULL; - goto exit; - } - start = trace + 1; - } - } - break; - } -exit: - if (buffer) - PyMem_Free(buffer); - return result; -} -#endif /* USE_XATTRS */ - - -/*[clinic input] -os.urandom - - size: Py_ssize_t - / - -Return a bytes object containing random bytes suitable for cryptographic use. -[clinic start generated code]*/ - -static PyObject * -os_urandom_impl(PyObject *module, Py_ssize_t size) -/*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/ -{ - PyObject *bytes; - int result; - - if (size < 0) - return PyErr_Format(PyExc_ValueError, - "negative argument not allowed"); - bytes = PyBytes_FromStringAndSize(NULL, size); - if (bytes == NULL) - return NULL; - - result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes)); - if (result == -1) { - Py_DECREF(bytes); - return NULL; - } - return bytes; -} - -#ifdef HAVE_MEMFD_CREATE -/*[clinic input] -os.memfd_create - - name: FSConverter - flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC - -[clinic start generated code]*/ - -static PyObject * -os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags) -/*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/ -{ - int fd; - const char *bytes = PyBytes_AS_STRING(name); - Py_BEGIN_ALLOW_THREADS - fd = memfd_create(bytes, flags); - Py_END_ALLOW_THREADS - if (fd == -1) { - return PyErr_SetFromErrno(PyExc_OSError); - } - return PyLong_FromLong(fd); -} -#endif - -#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC) -/*[clinic input] -os.eventfd - - initval: unsigned_int - flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC - -Creates and returns an event notification file descriptor. -[clinic start generated code]*/ - -static PyObject * -os_eventfd_impl(PyObject *module, unsigned int initval, int flags) -/*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/ - -{ - /* initval is limited to uint32_t, internal counter is uint64_t */ - int fd; - Py_BEGIN_ALLOW_THREADS - fd = eventfd(initval, flags); - Py_END_ALLOW_THREADS - if (fd == -1) { - return PyErr_SetFromErrno(PyExc_OSError); - } - return PyLong_FromLong(fd); -} - -/*[clinic input] -os.eventfd_read - - fd: fildes - -Read eventfd value -[clinic start generated code]*/ - -static PyObject * -os_eventfd_read_impl(PyObject *module, int fd) -/*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/ -{ - eventfd_t value; - int result; - Py_BEGIN_ALLOW_THREADS - result = eventfd_read(fd, &value); - Py_END_ALLOW_THREADS - if (result == -1) { - return PyErr_SetFromErrno(PyExc_OSError); - } - return PyLong_FromUnsignedLongLong(value); -} - -/*[clinic input] -os.eventfd_write - - fd: fildes - value: unsigned_long_long - -Write eventfd value. -[clinic start generated code]*/ - -static PyObject * -os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value) -/*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/ -{ - int result; - Py_BEGIN_ALLOW_THREADS - result = eventfd_write(fd, value); - Py_END_ALLOW_THREADS - if (result == -1) { - return PyErr_SetFromErrno(PyExc_OSError); - } - Py_RETURN_NONE; -} -#endif /* HAVE_EVENTFD && EFD_CLOEXEC */ - -/* Terminal size querying */ - -PyDoc_STRVAR(TerminalSize_docstring, - "A tuple of (columns, lines) for holding terminal window size"); - -static PyStructSequence_Field TerminalSize_fields[] = { - {"columns", "width of the terminal window in characters"}, - {"lines", "height of the terminal window in characters"}, - {NULL, NULL} -}; - -static PyStructSequence_Desc TerminalSize_desc = { - "os.terminal_size", - TerminalSize_docstring, - TerminalSize_fields, - 2, -}; - -#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) -/*[clinic input] -os.get_terminal_size - - fd: int(c_default="fileno(stdout)", py_default="") = -1 - / - -Return the size of the terminal window as (columns, lines). - -The optional argument fd (default standard output) specifies -which file descriptor should be queried. - -If the file descriptor is not connected to a terminal, an OSError -is thrown. - -This function will only be defined if an implementation is -available for this system. - -shutil.get_terminal_size is the high-level function which should -normally be used, os.get_terminal_size is the low-level implementation. -[clinic start generated code]*/ - -static PyObject * -os_get_terminal_size_impl(PyObject *module, int fd) -/*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/ -{ - int columns, lines; - PyObject *termsize; - - /* Under some conditions stdout may not be connected and - * fileno(stdout) may point to an invalid file descriptor. For example - * GUI apps don't have valid standard streams by default. - * - * If this happens, and the optional fd argument is not present, - * the ioctl below will fail returning EBADF. This is what we want. - */ - -#ifdef TERMSIZE_USE_IOCTL - { - struct winsize w; - if (ioctl(fd, TIOCGWINSZ, &w)) - return PyErr_SetFromErrno(PyExc_OSError); - columns = w.ws_col; - lines = w.ws_row; - } -#endif /* TERMSIZE_USE_IOCTL */ - -#ifdef TERMSIZE_USE_CONIO - { - HANDLE handle; - CONSOLE_SCREEN_BUFFER_INFO csbi; - handle = _Py_get_osfhandle(fd); - if (handle == INVALID_HANDLE_VALUE) - return NULL; - - if (!GetConsoleScreenBufferInfo(handle, &csbi)) - return PyErr_SetFromWindowsErr(0); - - columns = csbi.srWindow.Right - csbi.srWindow.Left + 1; - lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; - } -#endif /* TERMSIZE_USE_CONIO */ - - PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType; - termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType); - if (termsize == NULL) - return NULL; - PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns)); - PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines)); - if (PyErr_Occurred()) { - Py_DECREF(termsize); - return NULL; - } - return termsize; -} -#endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */ - - -/*[clinic input] -os.cpu_count - -Return the number of CPUs in the system; return None if indeterminable. - -This number is not equivalent to the number of CPUs the current process can -use. The number of usable CPUs can be obtained with -``len(os.sched_getaffinity(0))`` -[clinic start generated code]*/ - -static PyObject * -os_cpu_count_impl(PyObject *module) -/*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/ -{ - int ncpu = 0; -#ifdef MS_WINDOWS - ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS); -#elif defined(__hpux) - ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL); -#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) - ncpu = sysconf(_SC_NPROCESSORS_ONLN); -#elif defined(__VXWORKS__) - ncpu = _Py_popcount32(vxCpuEnabledGet()); -#elif defined(__DragonFly__) || \ - defined(__OpenBSD__) || \ - defined(__FreeBSD__) || \ - defined(__NetBSD__) || \ - defined(__APPLE__) - int mib[2]; - size_t len = sizeof(ncpu); - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) - ncpu = 0; -#endif - if (ncpu >= 1) - return PyLong_FromLong(ncpu); - else - Py_RETURN_NONE; -} - - -/*[clinic input] -os.get_inheritable -> bool - - fd: int - / - -Get the close-on-exe flag of the specified file descriptor. -[clinic start generated code]*/ - -static int -os_get_inheritable_impl(PyObject *module, int fd) -/*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/ -{ - int return_value; - _Py_BEGIN_SUPPRESS_IPH - return_value = _Py_get_inheritable(fd); - _Py_END_SUPPRESS_IPH - return return_value; -} - - -/*[clinic input] -os.set_inheritable - fd: int - inheritable: int - / - -Set the inheritable flag of the specified file descriptor. -[clinic start generated code]*/ - -static PyObject * -os_set_inheritable_impl(PyObject *module, int fd, int inheritable) -/*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/ -{ - int result; - - _Py_BEGIN_SUPPRESS_IPH - result = _Py_set_inheritable(fd, inheritable, NULL); - _Py_END_SUPPRESS_IPH - if (result < 0) - return NULL; - Py_RETURN_NONE; -} - - -#ifdef MS_WINDOWS -/*[clinic input] -os.get_handle_inheritable -> bool - handle: intptr_t - / - -Get the close-on-exe flag of the specified file descriptor. -[clinic start generated code]*/ - -static int -os_get_handle_inheritable_impl(PyObject *module, intptr_t handle) -/*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/ -{ - DWORD flags; - - if (!GetHandleInformation((HANDLE)handle, &flags)) { - PyErr_SetFromWindowsErr(0); - return -1; - } - - return flags & HANDLE_FLAG_INHERIT; -} - - -/*[clinic input] -os.set_handle_inheritable - handle: intptr_t - inheritable: bool - / - -Set the inheritable flag of the specified handle. -[clinic start generated code]*/ - -static PyObject * -os_set_handle_inheritable_impl(PyObject *module, intptr_t handle, - int inheritable) -/*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/ -{ - DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0; - if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) { - PyErr_SetFromWindowsErr(0); - return NULL; - } - Py_RETURN_NONE; -} -#endif /* MS_WINDOWS */ - -#ifndef MS_WINDOWS -/*[clinic input] -os.get_blocking -> bool - fd: int - / - -Get the blocking mode of the file descriptor. - -Return False if the O_NONBLOCK flag is set, True if the flag is cleared. -[clinic start generated code]*/ - -static int -os_get_blocking_impl(PyObject *module, int fd) -/*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/ -{ - int blocking; - - _Py_BEGIN_SUPPRESS_IPH - blocking = _Py_get_blocking(fd); - _Py_END_SUPPRESS_IPH - return blocking; -} - -/*[clinic input] -os.set_blocking - fd: int - blocking: bool(accept={int}) - / - -Set the blocking mode of the specified file descriptor. - -Set the O_NONBLOCK flag if blocking is False, -clear the O_NONBLOCK flag otherwise. -[clinic start generated code]*/ - -static PyObject * -os_set_blocking_impl(PyObject *module, int fd, int blocking) -/*[clinic end generated code: output=384eb43aa0762a9d input=bf5c8efdc5860ff3]*/ -{ - int result; - - _Py_BEGIN_SUPPRESS_IPH - result = _Py_set_blocking(fd, blocking); - _Py_END_SUPPRESS_IPH - if (result < 0) - return NULL; - Py_RETURN_NONE; -} -#endif /* !MS_WINDOWS */ - - -/*[clinic input] -class os.DirEntry "DirEntry *" "DirEntryType" -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/ - -typedef struct { - PyObject_HEAD - PyObject *name; - PyObject *path; - PyObject *stat; - PyObject *lstat; -#ifdef MS_WINDOWS - struct _Py_stat_struct win32_lstat; - uint64_t win32_file_index; - int got_file_index; -#else /* POSIX */ -#ifdef HAVE_DIRENT_D_TYPE - unsigned char d_type; -#endif - ino_t d_ino; - int dir_fd; -#endif -} DirEntry; - -static void -DirEntry_dealloc(DirEntry *entry) -{ - PyTypeObject *tp = Py_TYPE(entry); - Py_XDECREF(entry->name); - Py_XDECREF(entry->path); - Py_XDECREF(entry->stat); - Py_XDECREF(entry->lstat); - freefunc free_func = PyType_GetSlot(tp, Py_tp_free); - free_func(entry); - Py_DECREF(tp); -} - -/* Forward reference */ -static int -DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self, - int follow_symlinks, unsigned short mode_bits); - -/*[clinic input] -os.DirEntry.is_symlink -> bool - defining_class: defining_class - / - -Return True if the entry is a symbolic link; cached per entry. -[clinic start generated code]*/ - -static int -os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class) -/*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/ -{ -#ifdef MS_WINDOWS - return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK; -#elif defined(HAVE_DIRENT_D_TYPE) - /* POSIX */ - if (self->d_type != DT_UNKNOWN) - return self->d_type == DT_LNK; - else - return DirEntry_test_mode(defining_class, self, 0, S_IFLNK); -#else - /* POSIX without d_type */ - return DirEntry_test_mode(defining_class, self, 0, S_IFLNK); -#endif -} - -static PyObject * -DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks) -{ - int result; - STRUCT_STAT st; - PyObject *ub; - -#ifdef MS_WINDOWS - if (!PyUnicode_FSDecoder(self->path, &ub)) - return NULL; - wchar_t *path = PyUnicode_AsWideCharString(ub, NULL); - Py_DECREF(ub); -#else /* POSIX */ - if (!PyUnicode_FSConverter(self->path, &ub)) - return NULL; - const char *path = PyBytes_AS_STRING(ub); - if (self->dir_fd != DEFAULT_DIR_FD) { -#ifdef HAVE_FSTATAT - if (HAVE_FSTATAT_RUNTIME) { - Py_BEGIN_ALLOW_THREADS - result = fstatat(self->dir_fd, path, &st, - follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); - Py_END_ALLOW_THREADS - } else - -#endif /* HAVE_FSTATAT */ - { - Py_DECREF(ub); - PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat"); - return NULL; - } - } - else -#endif - { - Py_BEGIN_ALLOW_THREADS - if (follow_symlinks) { - result = STAT(path, &st); - } - else { - result = LSTAT(path, &st); - } - Py_END_ALLOW_THREADS - } -#if defined(MS_WINDOWS) - PyMem_Free(path); -#else - Py_DECREF(ub); -#endif - - if (result != 0) - return path_object_error(self->path); - - return _pystat_fromstructstat(module, &st); -} - -static PyObject * -DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self) -{ - if (!self->lstat) { - PyObject *module = PyType_GetModule(defining_class); -#ifdef MS_WINDOWS - self->lstat = _pystat_fromstructstat(module, &self->win32_lstat); -#else /* POSIX */ - self->lstat = DirEntry_fetch_stat(module, self, 0); -#endif - } - return Py_XNewRef(self->lstat); -} - -/*[clinic input] -os.DirEntry.stat - defining_class: defining_class - / - * - follow_symlinks: bool = True - -Return stat_result object for the entry; cached per entry. -[clinic start generated code]*/ - -static PyObject * -os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class, - int follow_symlinks) -/*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/ -{ - if (!follow_symlinks) { - return DirEntry_get_lstat(defining_class, self); - } - - if (!self->stat) { - int result = os_DirEntry_is_symlink_impl(self, defining_class); - if (result == -1) { - return NULL; - } - if (result) { - PyObject *module = PyType_GetModule(defining_class); - self->stat = DirEntry_fetch_stat(module, self, 1); - } - else { - self->stat = DirEntry_get_lstat(defining_class, self); - } - } - - return Py_XNewRef(self->stat); -} - -/* Set exception and return -1 on error, 0 for False, 1 for True */ -static int -DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self, - int follow_symlinks, unsigned short mode_bits) -{ - PyObject *stat = NULL; - PyObject *st_mode = NULL; - long mode; - int result; -#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE) - int is_symlink; - int need_stat; -#endif -#ifdef MS_WINDOWS - unsigned long dir_bits; -#endif - -#ifdef MS_WINDOWS - is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK; - need_stat = follow_symlinks && is_symlink; -#elif defined(HAVE_DIRENT_D_TYPE) - is_symlink = self->d_type == DT_LNK; - need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink); -#endif - -#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE) - if (need_stat) { -#endif - stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks); - if (!stat) { - if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) { - /* If file doesn't exist (anymore), then return False - (i.e., say it's not a file/directory) */ - PyErr_Clear(); - return 0; - } - goto error; - } - _posixstate* state = get_posix_state(PyType_GetModule(defining_class)); - st_mode = PyObject_GetAttr(stat, state->st_mode); - if (!st_mode) - goto error; - - mode = PyLong_AsLong(st_mode); - if (mode == -1 && PyErr_Occurred()) - goto error; - Py_CLEAR(st_mode); - Py_CLEAR(stat); - result = (mode & S_IFMT) == mode_bits; -#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE) - } - else if (is_symlink) { - assert(mode_bits != S_IFLNK); - result = 0; - } - else { - assert(mode_bits == S_IFDIR || mode_bits == S_IFREG); -#ifdef MS_WINDOWS - dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY; - if (mode_bits == S_IFDIR) - result = dir_bits != 0; - else - result = dir_bits == 0; -#else /* POSIX */ - if (mode_bits == S_IFDIR) - result = self->d_type == DT_DIR; - else - result = self->d_type == DT_REG; -#endif - } -#endif - - return result; - -error: - Py_XDECREF(st_mode); - Py_XDECREF(stat); - return -1; -} - -/*[clinic input] -os.DirEntry.is_dir -> bool - defining_class: defining_class - / - * - follow_symlinks: bool = True - -Return True if the entry is a directory; cached per entry. -[clinic start generated code]*/ - -static int -os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class, - int follow_symlinks) -/*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/ -{ - return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR); -} - -/*[clinic input] -os.DirEntry.is_file -> bool - defining_class: defining_class - / - * - follow_symlinks: bool = True - -Return True if the entry is a file; cached per entry. -[clinic start generated code]*/ - -static int -os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class, - int follow_symlinks) -/*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/ -{ - return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG); -} - -/*[clinic input] -os.DirEntry.inode - -Return inode of the entry; cached per entry. -[clinic start generated code]*/ - -static PyObject * -os_DirEntry_inode_impl(DirEntry *self) -/*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/ -{ -#ifdef MS_WINDOWS - if (!self->got_file_index) { - PyObject *unicode; - STRUCT_STAT stat; - int result; - - if (!PyUnicode_FSDecoder(self->path, &unicode)) - return NULL; - wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL); - Py_DECREF(unicode); - result = LSTAT(path, &stat); - PyMem_Free(path); - - if (result != 0) - return path_object_error(self->path); - - self->win32_file_index = stat.st_ino; - self->got_file_index = 1; - } - static_assert(sizeof(unsigned long long) >= sizeof(self->win32_file_index), - "DirEntry.win32_file_index is larger than unsigned long long"); - return PyLong_FromUnsignedLongLong(self->win32_file_index); -#else /* POSIX */ - static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino), - "DirEntry.d_ino is larger than unsigned long long"); - return PyLong_FromUnsignedLongLong(self->d_ino); -#endif -} - -static PyObject * -DirEntry_repr(DirEntry *self) -{ - return PyUnicode_FromFormat("", self->name); -} - -/*[clinic input] -os.DirEntry.__fspath__ - -Returns the path for the entry. -[clinic start generated code]*/ - -static PyObject * -os_DirEntry___fspath___impl(DirEntry *self) -/*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/ -{ - return Py_NewRef(self->path); -} - -static PyMemberDef DirEntry_members[] = { - {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY, - "the entry's base filename, relative to scandir() \"path\" argument"}, - {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY, - "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"}, - {NULL} -}; - -#include "clinic/posixmodule.c.h" - -static PyMethodDef DirEntry_methods[] = { - OS_DIRENTRY_IS_DIR_METHODDEF - OS_DIRENTRY_IS_FILE_METHODDEF - OS_DIRENTRY_IS_SYMLINK_METHODDEF - OS_DIRENTRY_STAT_METHODDEF - OS_DIRENTRY_INODE_METHODDEF - OS_DIRENTRY___FSPATH___METHODDEF - {"__class_getitem__", Py_GenericAlias, - METH_O|METH_CLASS, PyDoc_STR("See PEP 585")}, - {NULL} -}; - -static PyType_Slot DirEntryType_slots[] = { - {Py_tp_dealloc, DirEntry_dealloc}, - {Py_tp_repr, DirEntry_repr}, - {Py_tp_methods, DirEntry_methods}, - {Py_tp_members, DirEntry_members}, - {0, 0}, -}; - -static PyType_Spec DirEntryType_spec = { - MODNAME ".DirEntry", - sizeof(DirEntry), - 0, - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, - DirEntryType_slots -}; - - -#ifdef MS_WINDOWS - -static wchar_t * -join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename) -{ - Py_ssize_t path_len; - Py_ssize_t size; - wchar_t *result; - wchar_t ch; - - if (!path_wide) { /* Default arg: "." */ - path_wide = L"."; - path_len = 1; - } - else { - path_len = wcslen(path_wide); - } - - /* The +1's are for the path separator and the NUL */ - size = path_len + 1 + wcslen(filename) + 1; - result = PyMem_New(wchar_t, size); - if (!result) { - PyErr_NoMemory(); - return NULL; - } - wcscpy(result, path_wide); - if (path_len > 0) { - ch = result[path_len - 1]; - if (ch != SEP && ch != ALTSEP && ch != L':') - result[path_len++] = SEP; - wcscpy(result + path_len, filename); - } - return result; -} - -static PyObject * -DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW) -{ - DirEntry *entry; - BY_HANDLE_FILE_INFORMATION file_info; - ULONG reparse_tag; - wchar_t *joined_path; - - PyObject *DirEntryType = get_posix_state(module)->DirEntryType; - entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType); - if (!entry) - return NULL; - entry->name = NULL; - entry->path = NULL; - entry->stat = NULL; - entry->lstat = NULL; - entry->got_file_index = 0; - - entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1); - if (!entry->name) - goto error; - if (path->narrow) { - Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name)); - if (!entry->name) - goto error; - } - - joined_path = join_path_filenameW(path->wide, dataW->cFileName); - if (!joined_path) - goto error; - - entry->path = PyUnicode_FromWideChar(joined_path, -1); - PyMem_Free(joined_path); - if (!entry->path) - goto error; - if (path->narrow) { - Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path)); - if (!entry->path) - goto error; - } - - find_data_to_file_info(dataW, &file_info, &reparse_tag); - _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat); - - return (PyObject *)entry; - -error: - Py_DECREF(entry); - return NULL; -} - -#else /* POSIX */ - -static char * -join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len) -{ - Py_ssize_t path_len; - Py_ssize_t size; - char *result; - - if (!path_narrow) { /* Default arg: "." */ - path_narrow = "."; - path_len = 1; - } - else { - path_len = strlen(path_narrow); - } - - if (filename_len == -1) - filename_len = strlen(filename); - - /* The +1's are for the path separator and the NUL */ - size = path_len + 1 + filename_len + 1; - result = PyMem_New(char, size); - if (!result) { - PyErr_NoMemory(); - return NULL; - } - strcpy(result, path_narrow); - if (path_len > 0 && result[path_len - 1] != '/') - result[path_len++] = '/'; - strcpy(result + path_len, filename); - return result; -} - -static PyObject * -DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name, - Py_ssize_t name_len, ino_t d_ino -#ifdef HAVE_DIRENT_D_TYPE - , unsigned char d_type -#endif - ) -{ - DirEntry *entry; - char *joined_path; - - PyObject *DirEntryType = get_posix_state(module)->DirEntryType; - entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType); - if (!entry) - return NULL; - entry->name = NULL; - entry->path = NULL; - entry->stat = NULL; - entry->lstat = NULL; - - if (path->fd != -1) { - entry->dir_fd = path->fd; - joined_path = NULL; - } - else { - entry->dir_fd = DEFAULT_DIR_FD; - joined_path = join_path_filename(path->narrow, name, name_len); - if (!joined_path) - goto error; - } - - if (!path->narrow || !PyBytes_Check(path->object)) { - entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len); - if (joined_path) - entry->path = PyUnicode_DecodeFSDefault(joined_path); - } - else { - entry->name = PyBytes_FromStringAndSize(name, name_len); - if (joined_path) - entry->path = PyBytes_FromString(joined_path); - } - PyMem_Free(joined_path); - if (!entry->name) - goto error; - - if (path->fd != -1) { - entry->path = Py_NewRef(entry->name); - } - else if (!entry->path) - goto error; - -#ifdef HAVE_DIRENT_D_TYPE - entry->d_type = d_type; -#endif - entry->d_ino = d_ino; - - return (PyObject *)entry; - -error: - Py_XDECREF(entry); - return NULL; -} - -#endif - - -typedef struct { - PyObject_HEAD - path_t path; -#ifdef MS_WINDOWS - HANDLE handle; - WIN32_FIND_DATAW file_data; - int first_time; -#else /* POSIX */ - DIR *dirp; -#endif -#ifdef HAVE_FDOPENDIR - int fd; -#endif -} ScandirIterator; - -#ifdef MS_WINDOWS - -static int -ScandirIterator_is_closed(ScandirIterator *iterator) -{ - return iterator->handle == INVALID_HANDLE_VALUE; -} - -static void -ScandirIterator_closedir(ScandirIterator *iterator) -{ - HANDLE handle = iterator->handle; - - if (handle == INVALID_HANDLE_VALUE) - return; - - iterator->handle = INVALID_HANDLE_VALUE; - Py_BEGIN_ALLOW_THREADS - FindClose(handle); - Py_END_ALLOW_THREADS -} - -static PyObject * -ScandirIterator_iternext(ScandirIterator *iterator) -{ - WIN32_FIND_DATAW *file_data = &iterator->file_data; - BOOL success; - PyObject *entry; - - /* Happens if the iterator is iterated twice, or closed explicitly */ - if (iterator->handle == INVALID_HANDLE_VALUE) - return NULL; - - while (1) { - if (!iterator->first_time) { - Py_BEGIN_ALLOW_THREADS - success = FindNextFileW(iterator->handle, file_data); - Py_END_ALLOW_THREADS - if (!success) { - /* Error or no more files */ - if (GetLastError() != ERROR_NO_MORE_FILES) - path_error(&iterator->path); - break; - } - } - iterator->first_time = 0; - - /* Skip over . and .. */ - if (wcscmp(file_data->cFileName, L".") != 0 && - wcscmp(file_data->cFileName, L"..") != 0) - { - PyObject *module = PyType_GetModule(Py_TYPE(iterator)); - entry = DirEntry_from_find_data(module, &iterator->path, file_data); - if (!entry) - break; - return entry; - } - - /* Loop till we get a non-dot directory or finish iterating */ - } - - /* Error or no more files */ - ScandirIterator_closedir(iterator); - return NULL; -} - -#else /* POSIX */ - -static int -ScandirIterator_is_closed(ScandirIterator *iterator) -{ - return !iterator->dirp; -} - -static void -ScandirIterator_closedir(ScandirIterator *iterator) -{ - DIR *dirp = iterator->dirp; - - if (!dirp) - return; - - iterator->dirp = NULL; - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_FDOPENDIR - if (iterator->path.fd != -1) - rewinddir(dirp); -#endif - closedir(dirp); - Py_END_ALLOW_THREADS - return; -} - -static PyObject * -ScandirIterator_iternext(ScandirIterator *iterator) -{ - struct dirent *direntp; - Py_ssize_t name_len; - int is_dot; - PyObject *entry; - - /* Happens if the iterator is iterated twice, or closed explicitly */ - if (!iterator->dirp) - return NULL; - - while (1) { - errno = 0; - Py_BEGIN_ALLOW_THREADS - direntp = readdir(iterator->dirp); - Py_END_ALLOW_THREADS - - if (!direntp) { - /* Error or no more files */ - if (errno != 0) - path_error(&iterator->path); - break; - } - - /* Skip over . and .. */ - name_len = NAMLEN(direntp); - is_dot = direntp->d_name[0] == '.' && - (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2)); - if (!is_dot) { - PyObject *module = PyType_GetModule(Py_TYPE(iterator)); - entry = DirEntry_from_posix_info(module, - &iterator->path, direntp->d_name, - name_len, direntp->d_ino -#ifdef HAVE_DIRENT_D_TYPE - , direntp->d_type -#endif - ); - if (!entry) - break; - return entry; - } - - /* Loop till we get a non-dot directory or finish iterating */ - } - - /* Error or no more files */ - ScandirIterator_closedir(iterator); - return NULL; -} - -#endif - -static PyObject * -ScandirIterator_close(ScandirIterator *self, PyObject *args) -{ - ScandirIterator_closedir(self); - Py_RETURN_NONE; -} - -static PyObject * -ScandirIterator_enter(PyObject *self, PyObject *args) -{ - return Py_NewRef(self); -} - -static PyObject * -ScandirIterator_exit(ScandirIterator *self, PyObject *args) -{ - ScandirIterator_closedir(self); - Py_RETURN_NONE; -} - -static void -ScandirIterator_finalize(ScandirIterator *iterator) -{ - PyObject *error_type, *error_value, *error_traceback; - - /* Save the current exception, if any. */ - PyErr_Fetch(&error_type, &error_value, &error_traceback); - - if (!ScandirIterator_is_closed(iterator)) { - ScandirIterator_closedir(iterator); - - if (PyErr_ResourceWarning((PyObject *)iterator, 1, - "unclosed scandir iterator %R", iterator)) { - /* Spurious errors can appear at shutdown */ - if (PyErr_ExceptionMatches(PyExc_Warning)) { - PyErr_WriteUnraisable((PyObject *) iterator); - } - } - } - - path_cleanup(&iterator->path); - - /* Restore the saved exception. */ - PyErr_Restore(error_type, error_value, error_traceback); -} - -static void -ScandirIterator_dealloc(ScandirIterator *iterator) -{ - PyTypeObject *tp = Py_TYPE(iterator); - if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0) - return; - - freefunc free_func = PyType_GetSlot(tp, Py_tp_free); - free_func(iterator); - Py_DECREF(tp); -} - -static PyMethodDef ScandirIterator_methods[] = { - {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS}, - {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS}, - {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS}, - {NULL} -}; - -static PyType_Slot ScandirIteratorType_slots[] = { - {Py_tp_dealloc, ScandirIterator_dealloc}, - {Py_tp_finalize, ScandirIterator_finalize}, - {Py_tp_iter, PyObject_SelfIter}, - {Py_tp_iternext, ScandirIterator_iternext}, - {Py_tp_methods, ScandirIterator_methods}, - {0, 0}, -}; - -static PyType_Spec ScandirIteratorType_spec = { - MODNAME ".ScandirIterator", - sizeof(ScandirIterator), - 0, - // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since - // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance. - (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE - | Py_TPFLAGS_DISALLOW_INSTANTIATION), - ScandirIteratorType_slots -}; - -/*[clinic input] -os.scandir - - path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None - -Return an iterator of DirEntry objects for given path. - -path can be specified as either str, bytes, or a path-like object. If path -is bytes, the names of yielded DirEntry objects will also be bytes; in -all other circumstances they will be str. - -If path is None, uses the path='.'. -[clinic start generated code]*/ - -static PyObject * -os_scandir_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/ -{ - ScandirIterator *iterator; -#ifdef MS_WINDOWS - wchar_t *path_strW; -#else - const char *path_str; -#ifdef HAVE_FDOPENDIR - int fd = -1; -#endif -#endif - - if (PySys_Audit("os.scandir", "O", - path->object ? path->object : Py_None) < 0) { - return NULL; - } - - PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType; - iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType); - if (!iterator) - return NULL; - -#ifdef MS_WINDOWS - iterator->handle = INVALID_HANDLE_VALUE; -#else - iterator->dirp = NULL; -#endif - - /* Move the ownership to iterator->path */ - memcpy(&iterator->path, path, sizeof(path_t)); - memset(path, 0, sizeof(path_t)); - -#ifdef MS_WINDOWS - iterator->first_time = 1; - - path_strW = join_path_filenameW(iterator->path.wide, L"*.*"); - if (!path_strW) - goto error; - - Py_BEGIN_ALLOW_THREADS - iterator->handle = FindFirstFileW(path_strW, &iterator->file_data); - Py_END_ALLOW_THREADS - - PyMem_Free(path_strW); - - if (iterator->handle == INVALID_HANDLE_VALUE) { - path_error(&iterator->path); - goto error; - } -#else /* POSIX */ - errno = 0; -#ifdef HAVE_FDOPENDIR - if (iterator->path.fd != -1) { - if (HAVE_FDOPENDIR_RUNTIME) { - /* closedir() closes the FD, so we duplicate it */ - fd = _Py_dup(iterator->path.fd); - if (fd == -1) - goto error; - - Py_BEGIN_ALLOW_THREADS - iterator->dirp = fdopendir(fd); - Py_END_ALLOW_THREADS - } else { - PyErr_SetString(PyExc_TypeError, - "scandir: path should be string, bytes, os.PathLike or None, not int"); - return NULL; - } - } - else -#endif - { - if (iterator->path.narrow) - path_str = iterator->path.narrow; - else - path_str = "."; - - Py_BEGIN_ALLOW_THREADS - iterator->dirp = opendir(path_str); - Py_END_ALLOW_THREADS - } - - if (!iterator->dirp) { - path_error(&iterator->path); -#ifdef HAVE_FDOPENDIR - if (fd != -1) { - Py_BEGIN_ALLOW_THREADS - close(fd); - Py_END_ALLOW_THREADS - } -#endif - goto error; - } -#endif - - return (PyObject *)iterator; - -error: - Py_DECREF(iterator); - return NULL; -} - -/* - Return the file system path representation of the object. - - If the object is str or bytes, then allow it to pass through with - an incremented refcount. If the object defines __fspath__(), then - return the result of that method. All other types raise a TypeError. -*/ -PyObject * -PyOS_FSPath(PyObject *path) -{ - /* For error message reasons, this function is manually inlined in - path_converter(). */ - PyObject *func = NULL; - PyObject *path_repr = NULL; - - if (PyUnicode_Check(path) || PyBytes_Check(path)) { - return Py_NewRef(path); - } - - func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__)); - if (NULL == func) { - return PyErr_Format(PyExc_TypeError, - "expected str, bytes or os.PathLike object, " - "not %.200s", - _PyType_Name(Py_TYPE(path))); - } - - path_repr = _PyObject_CallNoArgs(func); - Py_DECREF(func); - if (NULL == path_repr) { - return NULL; - } - - if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) { - PyErr_Format(PyExc_TypeError, - "expected %.200s.__fspath__() to return str or bytes, " - "not %.200s", _PyType_Name(Py_TYPE(path)), - _PyType_Name(Py_TYPE(path_repr))); - Py_DECREF(path_repr); - return NULL; - } - - return path_repr; -} - -/*[clinic input] -os.fspath - - path: object - -Return the file system path representation of the object. - -If the object is str or bytes, then allow it to pass through as-is. If the -object defines __fspath__(), then return the result of that method. All other -types raise a TypeError. -[clinic start generated code]*/ - -static PyObject * -os_fspath_impl(PyObject *module, PyObject *path) -/*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/ -{ - return PyOS_FSPath(path); -} - -#ifdef HAVE_GETRANDOM_SYSCALL -/*[clinic input] -os.getrandom - - size: Py_ssize_t - flags: int=0 - -Obtain a series of random bytes. -[clinic start generated code]*/ - -static PyObject * -os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags) -/*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/ -{ - PyObject *bytes; - Py_ssize_t n; - - if (size < 0) { - errno = EINVAL; - return posix_error(); - } - - bytes = PyBytes_FromStringAndSize(NULL, size); - if (bytes == NULL) { - PyErr_NoMemory(); - return NULL; - } - - while (1) { - n = syscall(SYS_getrandom, - PyBytes_AS_STRING(bytes), - PyBytes_GET_SIZE(bytes), - flags); - if (n < 0 && errno == EINTR) { - if (PyErr_CheckSignals() < 0) { - goto error; - } - - /* getrandom() was interrupted by a signal: retry */ - continue; - } - break; - } - - if (n < 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - if (n != size) { - _PyBytes_Resize(&bytes, n); - } - - return bytes; - -error: - Py_DECREF(bytes); - return NULL; -} -#endif /* HAVE_GETRANDOM_SYSCALL */ - -#ifdef MS_WINDOWS -/* bpo-36085: Helper functions for managing DLL search directories - * on win32 - */ - -typedef DLL_DIRECTORY_COOKIE (WINAPI *PAddDllDirectory)(PCWSTR newDirectory); -typedef BOOL (WINAPI *PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie); - -/*[clinic input] -os._add_dll_directory - - path: path_t - -Add a path to the DLL search path. - -This search path is used when resolving dependencies for imported -extension modules (the module itself is resolved through sys.path), -and also by ctypes. - -Returns an opaque value that may be passed to os.remove_dll_directory -to remove this directory from the search path. -[clinic start generated code]*/ - -static PyObject * -os__add_dll_directory_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/ -{ - HMODULE hKernel32; - PAddDllDirectory AddDllDirectory; - DLL_DIRECTORY_COOKIE cookie = 0; - DWORD err = 0; - - if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) { - return NULL; - } - - /* For Windows 7, we have to load this. As this will be a fairly - infrequent operation, just do it each time. Kernel32 is always - loaded. */ - Py_BEGIN_ALLOW_THREADS - if (!(hKernel32 = GetModuleHandleW(L"kernel32")) || - !(AddDllDirectory = (PAddDllDirectory)GetProcAddress( - hKernel32, "AddDllDirectory")) || - !(cookie = (*AddDllDirectory)(path->wide))) { - err = GetLastError(); - } - Py_END_ALLOW_THREADS - - if (err) { - return win32_error_object_err("add_dll_directory", - path->object, err); - } - - return PyCapsule_New(cookie, "DLL directory cookie", NULL); -} - -/*[clinic input] -os._remove_dll_directory - - cookie: object - -Removes a path from the DLL search path. - -The parameter is an opaque value that was returned from -os.add_dll_directory. You can only remove directories that you added -yourself. -[clinic start generated code]*/ - -static PyObject * -os__remove_dll_directory_impl(PyObject *module, PyObject *cookie) -/*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/ -{ - HMODULE hKernel32; - PRemoveDllDirectory RemoveDllDirectory; - DLL_DIRECTORY_COOKIE cookieValue; - DWORD err = 0; - - if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) { - PyErr_SetString(PyExc_TypeError, - "Provided cookie was not returned from os.add_dll_directory"); - return NULL; - } - - cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer( - cookie, "DLL directory cookie"); - - /* For Windows 7, we have to load this. As this will be a fairly - infrequent operation, just do it each time. Kernel32 is always - loaded. */ - Py_BEGIN_ALLOW_THREADS - if (!(hKernel32 = GetModuleHandleW(L"kernel32")) || - !(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress( - hKernel32, "RemoveDllDirectory")) || - !(*RemoveDllDirectory)(cookieValue)) { - err = GetLastError(); - } - Py_END_ALLOW_THREADS - - if (err) { - return win32_error_object_err("remove_dll_directory", - NULL, err); - } - - if (PyCapsule_SetName(cookie, NULL)) { - return NULL; - } - - Py_RETURN_NONE; -} - -#endif - - -/* Only check if WIFEXITED is available: expect that it comes - with WEXITSTATUS, WIFSIGNALED, etc. - - os.waitstatus_to_exitcode() is implemented in C and not in Python, so - subprocess can safely call it during late Python finalization without - risking that used os attributes were set to None by finalize_modules(). */ -#if defined(WIFEXITED) || defined(MS_WINDOWS) -/*[clinic input] -os.waitstatus_to_exitcode - - status as status_obj: object - -Convert a wait status to an exit code. - -On Unix: - -* If WIFEXITED(status) is true, return WEXITSTATUS(status). -* If WIFSIGNALED(status) is true, return -WTERMSIG(status). -* Otherwise, raise a ValueError. - -On Windows, return status shifted right by 8 bits. - -On Unix, if the process is being traced or if waitpid() was called with -WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true. -This function must not be called if WIFSTOPPED(status) is true. -[clinic start generated code]*/ - -static PyObject * -os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj) -/*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/ -{ -#ifndef MS_WINDOWS - int status = _PyLong_AsInt(status_obj); - if (status == -1 && PyErr_Occurred()) { - return NULL; - } - - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - int exitcode; - if (WIFEXITED(wait_status)) { - exitcode = WEXITSTATUS(wait_status); - /* Sanity check to provide warranty on the function behavior. - It should not occur in practice */ - if (exitcode < 0) { - PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode); - return NULL; - } - } - else if (WIFSIGNALED(wait_status)) { - int signum = WTERMSIG(wait_status); - /* Sanity check to provide warranty on the function behavior. - It should not occurs in practice */ - if (signum <= 0) { - PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum); - return NULL; - } - exitcode = -signum; - } else if (WIFSTOPPED(wait_status)) { - /* Status only received if the process is being traced - or if waitpid() was called with WUNTRACED option. */ - int signum = WSTOPSIG(wait_status); - PyErr_Format(PyExc_ValueError, - "process stopped by delivery of signal %i", - signum); - return NULL; - } - else { - PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status); - return NULL; - } - return PyLong_FromLong(exitcode); -#else - /* Windows implementation: see os.waitpid() implementation - which uses _cwait(). */ - unsigned long long status = PyLong_AsUnsignedLongLong(status_obj); - if (status == (unsigned long long)-1 && PyErr_Occurred()) { - return NULL; - } - - unsigned long long exitcode = (status >> 8); - /* ExitProcess() accepts an UINT type: - reject exit code which doesn't fit in an UINT */ - if (exitcode > UINT_MAX) { - PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode); - return NULL; - } - return PyLong_FromUnsignedLong((unsigned long)exitcode); -#endif -} -#endif - - -static PyMethodDef posix_methods[] = { - - OS_STAT_METHODDEF - OS_ACCESS_METHODDEF - OS_TTYNAME_METHODDEF - OS_CHDIR_METHODDEF - OS_CHFLAGS_METHODDEF - OS_CHMOD_METHODDEF - OS_FCHMOD_METHODDEF - OS_LCHMOD_METHODDEF - OS_CHOWN_METHODDEF - OS_FCHOWN_METHODDEF - OS_LCHOWN_METHODDEF - OS_LCHFLAGS_METHODDEF - OS_CHROOT_METHODDEF - OS_CTERMID_METHODDEF - OS_GETCWD_METHODDEF - OS_GETCWDB_METHODDEF - OS_LINK_METHODDEF - OS_LISTDIR_METHODDEF - OS_LSTAT_METHODDEF - OS_MKDIR_METHODDEF - OS_NICE_METHODDEF - OS_GETPRIORITY_METHODDEF - OS_SETPRIORITY_METHODDEF - OS_POSIX_SPAWN_METHODDEF - OS_POSIX_SPAWNP_METHODDEF - OS_READLINK_METHODDEF - OS_COPY_FILE_RANGE_METHODDEF - OS_SPLICE_METHODDEF - OS_RENAME_METHODDEF - OS_REPLACE_METHODDEF - OS_RMDIR_METHODDEF - OS_SYMLINK_METHODDEF - OS_SYSTEM_METHODDEF - OS_UMASK_METHODDEF - OS_UNAME_METHODDEF - OS_UNLINK_METHODDEF - OS_REMOVE_METHODDEF - OS_UTIME_METHODDEF - OS_TIMES_METHODDEF - OS__EXIT_METHODDEF - OS__FCOPYFILE_METHODDEF - OS_EXECV_METHODDEF - OS_EXECVE_METHODDEF - OS_SPAWNV_METHODDEF - OS_SPAWNVE_METHODDEF - OS_FORK1_METHODDEF - OS_FORK_METHODDEF - OS_REGISTER_AT_FORK_METHODDEF - OS_SCHED_GET_PRIORITY_MAX_METHODDEF - OS_SCHED_GET_PRIORITY_MIN_METHODDEF - OS_SCHED_GETPARAM_METHODDEF - OS_SCHED_GETSCHEDULER_METHODDEF - OS_SCHED_RR_GET_INTERVAL_METHODDEF - OS_SCHED_SETPARAM_METHODDEF - OS_SCHED_SETSCHEDULER_METHODDEF - OS_SCHED_YIELD_METHODDEF - OS_SCHED_SETAFFINITY_METHODDEF - OS_SCHED_GETAFFINITY_METHODDEF - OS_OPENPTY_METHODDEF - OS_LOGIN_TTY_METHODDEF - OS_FORKPTY_METHODDEF - OS_GETEGID_METHODDEF - OS_GETEUID_METHODDEF - OS_GETGID_METHODDEF - OS_GETGROUPLIST_METHODDEF - OS_GETGROUPS_METHODDEF - OS_GETPID_METHODDEF - OS_GETPGRP_METHODDEF - OS_GETPPID_METHODDEF - OS_GETUID_METHODDEF - OS_GETLOGIN_METHODDEF - OS_KILL_METHODDEF - OS_KILLPG_METHODDEF - OS_PLOCK_METHODDEF - OS_STARTFILE_METHODDEF - OS_SETUID_METHODDEF - OS_SETEUID_METHODDEF - OS_SETREUID_METHODDEF - OS_SETGID_METHODDEF - OS_SETEGID_METHODDEF - OS_SETREGID_METHODDEF - OS_SETGROUPS_METHODDEF - OS_INITGROUPS_METHODDEF - OS_GETPGID_METHODDEF - OS_SETPGRP_METHODDEF - OS_WAIT_METHODDEF - OS_WAIT3_METHODDEF - OS_WAIT4_METHODDEF - OS_WAITID_METHODDEF - OS_WAITPID_METHODDEF - OS_PIDFD_OPEN_METHODDEF - OS_GETSID_METHODDEF - OS_SETSID_METHODDEF - OS_SETPGID_METHODDEF - OS_TCGETPGRP_METHODDEF - OS_TCSETPGRP_METHODDEF - OS_OPEN_METHODDEF - OS_CLOSE_METHODDEF - OS_CLOSERANGE_METHODDEF - OS_DEVICE_ENCODING_METHODDEF - OS_DUP_METHODDEF - OS_DUP2_METHODDEF - OS_LOCKF_METHODDEF - OS_LSEEK_METHODDEF - OS_READ_METHODDEF - OS_READV_METHODDEF - OS_PREAD_METHODDEF - OS_PREADV_METHODDEF - OS_WRITE_METHODDEF - OS_WRITEV_METHODDEF - OS_PWRITE_METHODDEF - OS_PWRITEV_METHODDEF - OS_SENDFILE_METHODDEF - OS_FSTAT_METHODDEF - OS_ISATTY_METHODDEF - OS_PIPE_METHODDEF - OS_PIPE2_METHODDEF - OS_MKFIFO_METHODDEF - OS_MKNOD_METHODDEF - OS_MAJOR_METHODDEF - OS_MINOR_METHODDEF - OS_MAKEDEV_METHODDEF - OS_FTRUNCATE_METHODDEF - OS_TRUNCATE_METHODDEF - OS_POSIX_FALLOCATE_METHODDEF - OS_POSIX_FADVISE_METHODDEF - OS_PUTENV_METHODDEF - OS_UNSETENV_METHODDEF - OS_STRERROR_METHODDEF - OS_FCHDIR_METHODDEF - OS_FSYNC_METHODDEF - OS_SYNC_METHODDEF - OS_FDATASYNC_METHODDEF - OS_WCOREDUMP_METHODDEF - OS_WIFCONTINUED_METHODDEF - OS_WIFSTOPPED_METHODDEF - OS_WIFSIGNALED_METHODDEF - OS_WIFEXITED_METHODDEF - OS_WEXITSTATUS_METHODDEF - OS_WTERMSIG_METHODDEF - OS_WSTOPSIG_METHODDEF - OS_FSTATVFS_METHODDEF - OS_STATVFS_METHODDEF - OS_CONFSTR_METHODDEF - OS_SYSCONF_METHODDEF - OS_FPATHCONF_METHODDEF - OS_PATHCONF_METHODDEF - OS_ABORT_METHODDEF - OS__GETFULLPATHNAME_METHODDEF - OS__GETDISKUSAGE_METHODDEF - OS__GETFINALPATHNAME_METHODDEF - OS__GETVOLUMEPATHNAME_METHODDEF - OS__PATH_SPLITROOT_METHODDEF - OS__PATH_NORMPATH_METHODDEF - OS_GETLOADAVG_METHODDEF - OS_URANDOM_METHODDEF - OS_SETRESUID_METHODDEF - OS_SETRESGID_METHODDEF - OS_GETRESUID_METHODDEF - OS_GETRESGID_METHODDEF - - OS_GETXATTR_METHODDEF - OS_SETXATTR_METHODDEF - OS_REMOVEXATTR_METHODDEF - OS_LISTXATTR_METHODDEF - - OS_GET_TERMINAL_SIZE_METHODDEF - OS_CPU_COUNT_METHODDEF - OS_GET_INHERITABLE_METHODDEF - OS_SET_INHERITABLE_METHODDEF - OS_GET_HANDLE_INHERITABLE_METHODDEF - OS_SET_HANDLE_INHERITABLE_METHODDEF - OS_GET_BLOCKING_METHODDEF - OS_SET_BLOCKING_METHODDEF - OS_SCANDIR_METHODDEF - OS_FSPATH_METHODDEF - OS_GETRANDOM_METHODDEF - OS_MEMFD_CREATE_METHODDEF - OS_EVENTFD_METHODDEF - OS_EVENTFD_READ_METHODDEF - OS_EVENTFD_WRITE_METHODDEF - OS__ADD_DLL_DIRECTORY_METHODDEF - OS__REMOVE_DLL_DIRECTORY_METHODDEF - OS_WAITSTATUS_TO_EXITCODE_METHODDEF - OS_SETNS_METHODDEF - OS_UNSHARE_METHODDEF - {NULL, NULL} /* Sentinel */ -}; - -static int -all_ins(PyObject *m) -{ -#ifdef F_OK - if (PyModule_AddIntMacro(m, F_OK)) return -1; -#endif -#ifdef R_OK - if (PyModule_AddIntMacro(m, R_OK)) return -1; -#endif -#ifdef W_OK - if (PyModule_AddIntMacro(m, W_OK)) return -1; -#endif -#ifdef X_OK - if (PyModule_AddIntMacro(m, X_OK)) return -1; -#endif -#ifdef NGROUPS_MAX - if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1; -#endif -#ifdef TMP_MAX - if (PyModule_AddIntMacro(m, TMP_MAX)) return -1; -#endif -#ifdef WCONTINUED - if (PyModule_AddIntMacro(m, WCONTINUED)) return -1; -#endif -#ifdef WNOHANG - if (PyModule_AddIntMacro(m, WNOHANG)) return -1; -#endif -#ifdef WUNTRACED - if (PyModule_AddIntMacro(m, WUNTRACED)) return -1; -#endif -#ifdef O_RDONLY - if (PyModule_AddIntMacro(m, O_RDONLY)) return -1; -#endif -#ifdef O_WRONLY - if (PyModule_AddIntMacro(m, O_WRONLY)) return -1; -#endif -#ifdef O_RDWR - if (PyModule_AddIntMacro(m, O_RDWR)) return -1; -#endif -#ifdef O_NDELAY - if (PyModule_AddIntMacro(m, O_NDELAY)) return -1; -#endif -#ifdef O_NONBLOCK - if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1; -#endif -#ifdef O_APPEND - if (PyModule_AddIntMacro(m, O_APPEND)) return -1; -#endif -#ifdef O_DSYNC - if (PyModule_AddIntMacro(m, O_DSYNC)) return -1; -#endif -#ifdef O_RSYNC - if (PyModule_AddIntMacro(m, O_RSYNC)) return -1; -#endif -#ifdef O_SYNC - if (PyModule_AddIntMacro(m, O_SYNC)) return -1; -#endif -#ifdef O_NOCTTY - if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1; -#endif -#ifdef O_CREAT - if (PyModule_AddIntMacro(m, O_CREAT)) return -1; -#endif -#ifdef O_EXCL - if (PyModule_AddIntMacro(m, O_EXCL)) return -1; -#endif -#ifdef O_TRUNC - if (PyModule_AddIntMacro(m, O_TRUNC)) return -1; -#endif -#ifdef O_BINARY - if (PyModule_AddIntMacro(m, O_BINARY)) return -1; -#endif -#ifdef O_TEXT - if (PyModule_AddIntMacro(m, O_TEXT)) return -1; -#endif -#ifdef O_XATTR - if (PyModule_AddIntMacro(m, O_XATTR)) return -1; -#endif -#ifdef O_LARGEFILE - if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1; -#endif -#ifndef __GNU__ -#ifdef O_SHLOCK - if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1; -#endif -#ifdef O_EXLOCK - if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1; -#endif -#endif -#ifdef O_EXEC - if (PyModule_AddIntMacro(m, O_EXEC)) return -1; -#endif -#ifdef O_SEARCH - if (PyModule_AddIntMacro(m, O_SEARCH)) return -1; -#endif -#ifdef O_PATH - if (PyModule_AddIntMacro(m, O_PATH)) return -1; -#endif -#ifdef O_TTY_INIT - if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1; -#endif -#ifdef O_TMPFILE - if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1; -#endif -#ifdef PRIO_PROCESS - if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1; -#endif -#ifdef PRIO_PGRP - if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1; -#endif -#ifdef PRIO_USER - if (PyModule_AddIntMacro(m, PRIO_USER)) return -1; -#endif -#ifdef O_CLOEXEC - if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1; -#endif -#ifdef O_ACCMODE - if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1; -#endif -#ifdef O_EVTONLY - if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1; -#endif -#ifdef O_FSYNC - if (PyModule_AddIntMacro(m, O_FSYNC)) return -1; -#endif -#ifdef O_SYMLINK - if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1; -#endif - -#ifdef SEEK_HOLE - if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1; -#endif -#ifdef SEEK_DATA - if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1; -#endif - -/* MS Windows */ -#ifdef O_NOINHERIT - /* Don't inherit in child processes. */ - if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1; -#endif -#ifdef _O_SHORT_LIVED - /* Optimize for short life (keep in memory). */ - /* MS forgot to define this one with a non-underscore form too. */ - if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1; -#endif -#ifdef O_TEMPORARY - /* Automatically delete when last handle is closed. */ - if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1; -#endif -#ifdef O_RANDOM - /* Optimize for random access. */ - if (PyModule_AddIntMacro(m, O_RANDOM)) return -1; -#endif -#ifdef O_SEQUENTIAL - /* Optimize for sequential access. */ - if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1; -#endif - -/* GNU extensions. */ -#ifdef O_ASYNC - /* Send a SIGIO signal whenever input or output - becomes available on file descriptor */ - if (PyModule_AddIntMacro(m, O_ASYNC)) return -1; -#endif -#ifdef O_DIRECT - /* Direct disk access. */ - if (PyModule_AddIntMacro(m, O_DIRECT)) return -1; -#endif -#ifdef O_DIRECTORY - /* Must be a directory. */ - if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1; -#endif -#ifdef O_NOFOLLOW - /* Do not follow links. */ - if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1; -#endif -#ifdef O_NOFOLLOW_ANY - if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1; -#endif -#ifdef O_NOLINKS - /* Fails if link count of the named file is greater than 1 */ - if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1; -#endif -#ifdef O_NOATIME - /* Do not update the access time. */ - if (PyModule_AddIntMacro(m, O_NOATIME)) return -1; -#endif - - /* These come from sysexits.h */ -#ifdef EX_OK - if (PyModule_AddIntMacro(m, EX_OK)) return -1; -#endif /* EX_OK */ -#ifdef EX_USAGE - if (PyModule_AddIntMacro(m, EX_USAGE)) return -1; -#endif /* EX_USAGE */ -#ifdef EX_DATAERR - if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1; -#endif /* EX_DATAERR */ -#ifdef EX_NOINPUT - if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1; -#endif /* EX_NOINPUT */ -#ifdef EX_NOUSER - if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1; -#endif /* EX_NOUSER */ -#ifdef EX_NOHOST - if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1; -#endif /* EX_NOHOST */ -#ifdef EX_UNAVAILABLE - if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1; -#endif /* EX_UNAVAILABLE */ -#ifdef EX_SOFTWARE - if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1; -#endif /* EX_SOFTWARE */ -#ifdef EX_OSERR - if (PyModule_AddIntMacro(m, EX_OSERR)) return -1; -#endif /* EX_OSERR */ -#ifdef EX_OSFILE - if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1; -#endif /* EX_OSFILE */ -#ifdef EX_CANTCREAT - if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1; -#endif /* EX_CANTCREAT */ -#ifdef EX_IOERR - if (PyModule_AddIntMacro(m, EX_IOERR)) return -1; -#endif /* EX_IOERR */ -#ifdef EX_TEMPFAIL - if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1; -#endif /* EX_TEMPFAIL */ -#ifdef EX_PROTOCOL - if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1; -#endif /* EX_PROTOCOL */ -#ifdef EX_NOPERM - if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1; -#endif /* EX_NOPERM */ -#ifdef EX_CONFIG - if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1; -#endif /* EX_CONFIG */ -#ifdef EX_NOTFOUND - if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1; -#endif /* EX_NOTFOUND */ - - /* statvfs */ -#ifdef ST_RDONLY - if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1; -#endif /* ST_RDONLY */ -#ifdef ST_NOSUID - if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1; -#endif /* ST_NOSUID */ - - /* GNU extensions */ -#ifdef ST_NODEV - if (PyModule_AddIntMacro(m, ST_NODEV)) return -1; -#endif /* ST_NODEV */ -#ifdef ST_NOEXEC - if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1; -#endif /* ST_NOEXEC */ -#ifdef ST_SYNCHRONOUS - if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1; -#endif /* ST_SYNCHRONOUS */ -#ifdef ST_MANDLOCK - if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1; -#endif /* ST_MANDLOCK */ -#ifdef ST_WRITE - if (PyModule_AddIntMacro(m, ST_WRITE)) return -1; -#endif /* ST_WRITE */ -#ifdef ST_APPEND - if (PyModule_AddIntMacro(m, ST_APPEND)) return -1; -#endif /* ST_APPEND */ -#ifdef ST_NOATIME - if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1; -#endif /* ST_NOATIME */ -#ifdef ST_NODIRATIME - if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1; -#endif /* ST_NODIRATIME */ -#ifdef ST_RELATIME - if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1; -#endif /* ST_RELATIME */ - - /* FreeBSD sendfile() constants */ -#ifdef SF_NODISKIO - if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1; -#endif - /* is obsolete since the 11.x release */ -#ifdef SF_MNOWAIT - if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1; -#endif -#ifdef SF_SYNC - if (PyModule_AddIntMacro(m, SF_SYNC)) return -1; -#endif -#ifdef SF_NOCACHE - if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1; -#endif - - /* constants for posix_fadvise */ -#ifdef POSIX_FADV_NORMAL - if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1; -#endif -#ifdef POSIX_FADV_SEQUENTIAL - if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1; -#endif -#ifdef POSIX_FADV_RANDOM - if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1; -#endif -#ifdef POSIX_FADV_NOREUSE - if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1; -#endif -#ifdef POSIX_FADV_WILLNEED - if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1; -#endif -#ifdef POSIX_FADV_DONTNEED - if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1; -#endif - - /* constants for waitid */ -#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID) - if (PyModule_AddIntMacro(m, P_PID)) return -1; - if (PyModule_AddIntMacro(m, P_PGID)) return -1; - if (PyModule_AddIntMacro(m, P_ALL)) return -1; -#ifdef P_PIDFD - if (PyModule_AddIntMacro(m, P_PIDFD)) return -1; -#endif -#ifdef PIDFD_NONBLOCK - if (PyModule_AddIntMacro(m, PIDFD_NONBLOCK)) return -1; -#endif -#endif -#ifdef WEXITED - if (PyModule_AddIntMacro(m, WEXITED)) return -1; -#endif -#ifdef WNOWAIT - if (PyModule_AddIntMacro(m, WNOWAIT)) return -1; -#endif -#ifdef WSTOPPED - if (PyModule_AddIntMacro(m, WSTOPPED)) return -1; -#endif -#ifdef CLD_EXITED - if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1; -#endif -#ifdef CLD_KILLED - if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1; -#endif -#ifdef CLD_DUMPED - if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1; -#endif -#ifdef CLD_TRAPPED - if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1; -#endif -#ifdef CLD_STOPPED - if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1; -#endif -#ifdef CLD_CONTINUED - if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1; -#endif - - /* constants for lockf */ -#ifdef F_LOCK - if (PyModule_AddIntMacro(m, F_LOCK)) return -1; -#endif -#ifdef F_TLOCK - if (PyModule_AddIntMacro(m, F_TLOCK)) return -1; -#endif -#ifdef F_ULOCK - if (PyModule_AddIntMacro(m, F_ULOCK)) return -1; -#endif -#ifdef F_TEST - if (PyModule_AddIntMacro(m, F_TEST)) return -1; -#endif - -#ifdef RWF_DSYNC - if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1; -#endif -#ifdef RWF_HIPRI - if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1; -#endif -#ifdef RWF_SYNC - if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1; -#endif -#ifdef RWF_NOWAIT - if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1; -#endif -#ifdef RWF_APPEND - if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1; -#endif - -/* constants for splice */ -#if defined(HAVE_SPLICE) && defined(__linux__) - if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1; - if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1; - if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1; -#endif - -/* constants for posix_spawn */ -#ifdef HAVE_POSIX_SPAWN - if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1; - if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1; - if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1; -#endif - -#if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN) - if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1; - if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1; - if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1; -#endif -#ifdef HAVE_SPAWNV - if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1; - if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1; -#endif - -#ifdef HAVE_SCHED_H -#ifdef SCHED_OTHER - if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1; -#endif -#ifdef SCHED_FIFO - if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1; -#endif -#ifdef SCHED_RR - if (PyModule_AddIntMacro(m, SCHED_RR)) return -1; -#endif -#ifdef SCHED_SPORADIC - if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1; -#endif -#ifdef SCHED_BATCH - if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1; -#endif -#ifdef SCHED_IDLE - if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1; -#endif -#ifdef SCHED_RESET_ON_FORK - if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1; -#endif -#ifdef SCHED_SYS - if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1; -#endif -#ifdef SCHED_IA - if (PyModule_AddIntMacro(m, SCHED_IA)) return -1; -#endif -#ifdef SCHED_FSS - if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1; -#endif -#ifdef SCHED_FX - if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1; -#endif - -/* constants for namespaces */ -#if defined(HAVE_SETNS) || defined(HAVE_UNSHARE) -#ifdef CLONE_FS - if (PyModule_AddIntMacro(m, CLONE_FS)) return -1; -#endif -#ifdef CLONE_FILES - if (PyModule_AddIntMacro(m, CLONE_FILES)) return -1; -#endif -#ifdef CLONE_NEWNS - if (PyModule_AddIntMacro(m, CLONE_NEWNS)) return -1; -#endif -#ifdef CLONE_NEWCGROUP - if (PyModule_AddIntMacro(m, CLONE_NEWCGROUP)) return -1; -#endif -#ifdef CLONE_NEWUTS - if (PyModule_AddIntMacro(m, CLONE_NEWUTS)) return -1; -#endif -#ifdef CLONE_NEWIPC - if (PyModule_AddIntMacro(m, CLONE_NEWIPC)) return -1; -#endif -#ifdef CLONE_NEWUSER - if (PyModule_AddIntMacro(m, CLONE_NEWUSER)) return -1; -#endif -#ifdef CLONE_NEWPID - if (PyModule_AddIntMacro(m, CLONE_NEWPID)) return -1; -#endif -#ifdef CLONE_NEWNET - if (PyModule_AddIntMacro(m, CLONE_NEWNET)) return -1; -#endif -#ifdef CLONE_NEWTIME - if (PyModule_AddIntMacro(m, CLONE_NEWTIME)) return -1; -#endif -#ifdef CLONE_SYSVSEM - if (PyModule_AddIntMacro(m, CLONE_SYSVSEM)) return -1; -#endif -#ifdef CLONE_THREAD - if (PyModule_AddIntMacro(m, CLONE_THREAD)) return -1; -#endif -#ifdef CLONE_SIGHAND - if (PyModule_AddIntMacro(m, CLONE_SIGHAND)) return -1; -#endif -#ifdef CLONE_VM - if (PyModule_AddIntMacro(m, CLONE_VM)) return -1; -#endif -#endif - -#endif - -#ifdef USE_XATTRS - if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1; - if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1; - if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1; -#endif - -#if HAVE_DECL_RTLD_LAZY - if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1; -#endif -#if HAVE_DECL_RTLD_NOW - if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1; -#endif -#if HAVE_DECL_RTLD_GLOBAL - if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1; -#endif -#if HAVE_DECL_RTLD_LOCAL - if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1; -#endif -#if HAVE_DECL_RTLD_NODELETE - if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1; -#endif -#if HAVE_DECL_RTLD_NOLOAD - if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1; -#endif -#if HAVE_DECL_RTLD_DEEPBIND - if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1; -#endif -#if HAVE_DECL_RTLD_MEMBER - if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1; -#endif - -#ifdef HAVE_GETRANDOM_SYSCALL - if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1; - if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1; -#endif -#ifdef HAVE_MEMFD_CREATE - if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1; - if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1; -#ifdef MFD_HUGETLB - if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1; -#endif -#ifdef MFD_HUGE_SHIFT - if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1; -#endif -#ifdef MFD_HUGE_MASK - if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1; -#endif -#ifdef MFD_HUGE_64KB - if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1; -#endif -#ifdef MFD_HUGE_512KB - if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1; -#endif -#ifdef MFD_HUGE_1MB - if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1; -#endif -#ifdef MFD_HUGE_2MB - if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1; -#endif -#ifdef MFD_HUGE_8MB - if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1; -#endif -#ifdef MFD_HUGE_16MB - if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1; -#endif -#ifdef MFD_HUGE_32MB - if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1; -#endif -#ifdef MFD_HUGE_256MB - if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1; -#endif -#ifdef MFD_HUGE_512MB - if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1; -#endif -#ifdef MFD_HUGE_1GB - if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1; -#endif -#ifdef MFD_HUGE_2GB - if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1; -#endif -#ifdef MFD_HUGE_16GB - if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1; -#endif -#endif /* HAVE_MEMFD_CREATE */ - -#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC) - if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1; -#ifdef EFD_NONBLOCK - if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1; -#endif -#ifdef EFD_SEMAPHORE - if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1; -#endif -#endif /* HAVE_EVENTFD && EFD_CLOEXEC */ - -#if defined(__APPLE__) - if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1; - if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1; - if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1; - if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1; -#endif - -#ifdef MS_WINDOWS - if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1; - if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1; - if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1; - if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1; - if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1; -#endif - - return 0; -} - - - -#define PROBE(name, test) \ - static int name(void) \ - { \ - if (test) { \ - return 1; \ - } else { \ - return 0; \ - } \ - } - -#ifdef HAVE_FSTATAT -PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME) -#endif - -#ifdef HAVE_FACCESSAT -PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME) -#endif - -#ifdef HAVE_FCHMODAT -PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME) -#endif - -#ifdef HAVE_FCHOWNAT -PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME) -#endif - -#ifdef HAVE_LINKAT -PROBE(probe_linkat, HAVE_LINKAT_RUNTIME) -#endif - -#ifdef HAVE_FDOPENDIR -PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME) -#endif - -#ifdef HAVE_MKDIRAT -PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME) -#endif - -#ifdef HAVE_MKFIFOAT -PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME) -#endif - -#ifdef HAVE_MKNODAT -PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME) -#endif - -#ifdef HAVE_RENAMEAT -PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME) -#endif - -#ifdef HAVE_UNLINKAT -PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME) -#endif - -#ifdef HAVE_OPENAT -PROBE(probe_openat, HAVE_OPENAT_RUNTIME) -#endif - -#ifdef HAVE_READLINKAT -PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME) -#endif - -#ifdef HAVE_SYMLINKAT -PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME) -#endif - -#ifdef HAVE_FUTIMENS -PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME) -#endif - -#ifdef HAVE_UTIMENSAT -PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME) -#endif - - - - -static const struct have_function { - const char * const label; - int (*probe)(void); -} have_functions[] = { - -#ifdef HAVE_EVENTFD - {"HAVE_EVENTFD", NULL}, -#endif - -#ifdef HAVE_FACCESSAT - { "HAVE_FACCESSAT", probe_faccessat }, -#endif - -#ifdef HAVE_FCHDIR - { "HAVE_FCHDIR", NULL }, -#endif - -#ifdef HAVE_FCHMOD - { "HAVE_FCHMOD", NULL }, -#endif - -#ifdef HAVE_FCHMODAT - { "HAVE_FCHMODAT", probe_fchmodat }, -#endif - -#ifdef HAVE_FCHOWN - { "HAVE_FCHOWN", NULL }, -#endif - -#ifdef HAVE_FCHOWNAT - { "HAVE_FCHOWNAT", probe_fchownat }, -#endif - -#ifdef HAVE_FEXECVE - { "HAVE_FEXECVE", NULL }, -#endif - -#ifdef HAVE_FDOPENDIR - { "HAVE_FDOPENDIR", probe_fdopendir }, -#endif - -#ifdef HAVE_FPATHCONF - { "HAVE_FPATHCONF", NULL }, -#endif - -#ifdef HAVE_FSTATAT - { "HAVE_FSTATAT", probe_fstatat }, -#endif - -#ifdef HAVE_FSTATVFS - { "HAVE_FSTATVFS", NULL }, -#endif - -#if defined HAVE_FTRUNCATE || defined MS_WINDOWS - { "HAVE_FTRUNCATE", NULL }, -#endif - -#ifdef HAVE_FUTIMENS - { "HAVE_FUTIMENS", probe_futimens }, -#endif - -#ifdef HAVE_FUTIMES - { "HAVE_FUTIMES", NULL }, -#endif - -#ifdef HAVE_FUTIMESAT - { "HAVE_FUTIMESAT", NULL }, -#endif - -#ifdef HAVE_LINKAT - { "HAVE_LINKAT", probe_linkat }, -#endif - -#ifdef HAVE_LCHFLAGS - { "HAVE_LCHFLAGS", NULL }, -#endif - -#ifdef HAVE_LCHMOD - { "HAVE_LCHMOD", NULL }, -#endif - -#ifdef HAVE_LCHOWN - { "HAVE_LCHOWN", NULL }, -#endif - -#ifdef HAVE_LSTAT - { "HAVE_LSTAT", NULL }, -#endif - -#ifdef HAVE_LUTIMES - { "HAVE_LUTIMES", NULL }, -#endif - -#ifdef HAVE_MEMFD_CREATE - { "HAVE_MEMFD_CREATE", NULL }, -#endif - -#ifdef HAVE_MKDIRAT - { "HAVE_MKDIRAT", probe_mkdirat }, -#endif - -#ifdef HAVE_MKFIFOAT - { "HAVE_MKFIFOAT", probe_mkfifoat }, -#endif - -#ifdef HAVE_MKNODAT - { "HAVE_MKNODAT", probe_mknodat }, -#endif - -#ifdef HAVE_OPENAT - { "HAVE_OPENAT", probe_openat }, -#endif - -#ifdef HAVE_READLINKAT - { "HAVE_READLINKAT", probe_readlinkat }, -#endif - -#ifdef HAVE_RENAMEAT - { "HAVE_RENAMEAT", probe_renameat }, -#endif - -#ifdef HAVE_SYMLINKAT - { "HAVE_SYMLINKAT", probe_symlinkat }, -#endif - -#ifdef HAVE_UNLINKAT - { "HAVE_UNLINKAT", probe_unlinkat }, -#endif - -#ifdef HAVE_UTIMENSAT - { "HAVE_UTIMENSAT", probe_utimensat }, -#endif - -#ifdef MS_WINDOWS - { "MS_WINDOWS", NULL }, -#endif - - { NULL, NULL } -}; - - -static int -posixmodule_exec(PyObject *m) -{ - _posixstate *state = get_posix_state(m); - -#if defined(HAVE_PWRITEV) - if (HAVE_PWRITEV_RUNTIME) {} else { - PyObject* dct = PyModule_GetDict(m); - - if (dct == NULL) { - return -1; - } - - if (PyDict_DelItemString(dct, "pwritev") == -1) { - PyErr_Clear(); - } - if (PyDict_DelItemString(dct, "preadv") == -1) { - PyErr_Clear(); - } - } -#endif - - /* Initialize environ dictionary */ - PyObject *v = convertenviron(); - Py_XINCREF(v); - if (v == NULL || PyModule_AddObject(m, "environ", v) != 0) - return -1; - Py_DECREF(v); - - if (all_ins(m)) - return -1; - - if (setup_confname_tables(m)) - return -1; - - PyModule_AddObject(m, "error", Py_NewRef(PyExc_OSError)); - -#if defined(HAVE_WAITID) && !defined(__APPLE__) - waitid_result_desc.name = MODNAME ".waitid_result"; - PyObject *WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc); - if (WaitidResultType == NULL) { - return -1; - } - PyModule_AddObject(m, "waitid_result", Py_NewRef(WaitidResultType)); - state->WaitidResultType = WaitidResultType; -#endif - - stat_result_desc.name = "os.stat_result"; /* see issue #19209 */ - stat_result_desc.fields[7].name = PyStructSequence_UnnamedField; - stat_result_desc.fields[8].name = PyStructSequence_UnnamedField; - stat_result_desc.fields[9].name = PyStructSequence_UnnamedField; - PyObject *StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc); - if (StatResultType == NULL) { - return -1; - } - PyModule_AddObject(m, "stat_result", Py_NewRef(StatResultType)); - state->StatResultType = StatResultType; - structseq_new = ((PyTypeObject *)StatResultType)->tp_new; - ((PyTypeObject *)StatResultType)->tp_new = statresult_new; - - statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */ - PyObject *StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc); - if (StatVFSResultType == NULL) { - return -1; - } - PyModule_AddObject(m, "statvfs_result", Py_NewRef(StatVFSResultType)); - state->StatVFSResultType = StatVFSResultType; -#ifdef NEED_TICKS_PER_SECOND -# if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK) - ticks_per_second = sysconf(_SC_CLK_TCK); -# elif defined(HZ) - ticks_per_second = HZ; -# else - ticks_per_second = 60; /* magic fallback value; may be bogus */ -# endif -#endif - -#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) - sched_param_desc.name = MODNAME ".sched_param"; - PyObject *SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc); - if (SchedParamType == NULL) { - return -1; - } - PyModule_AddObject(m, "sched_param", Py_NewRef(SchedParamType)); - state->SchedParamType = SchedParamType; - ((PyTypeObject *)SchedParamType)->tp_new = os_sched_param; -#endif - - /* initialize TerminalSize_info */ - PyObject *TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc); - if (TerminalSizeType == NULL) { - return -1; - } - PyModule_AddObject(m, "terminal_size", Py_NewRef(TerminalSizeType)); - state->TerminalSizeType = TerminalSizeType; - - /* initialize scandir types */ - PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL); - if (ScandirIteratorType == NULL) { - return -1; - } - state->ScandirIteratorType = ScandirIteratorType; - - PyObject *DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL); - if (DirEntryType == NULL) { - return -1; - } - PyModule_AddObject(m, "DirEntry", Py_NewRef(DirEntryType)); - state->DirEntryType = DirEntryType; - - times_result_desc.name = MODNAME ".times_result"; - PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(×_result_desc); - if (TimesResultType == NULL) { - return -1; - } - PyModule_AddObject(m, "times_result", Py_NewRef(TimesResultType)); - state->TimesResultType = TimesResultType; - - PyTypeObject *UnameResultType = PyStructSequence_NewType(&uname_result_desc); - if (UnameResultType == NULL) { - return -1; - } - ; - PyModule_AddObject(m, "uname_result", Py_NewRef(UnameResultType)); - state->UnameResultType = (PyObject *)UnameResultType; - - if ((state->billion = PyLong_FromLong(1000000000)) == NULL) - return -1; -#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) - state->struct_rusage = PyUnicode_InternFromString("struct_rusage"); - if (state->struct_rusage == NULL) - return -1; -#endif - state->st_mode = PyUnicode_InternFromString("st_mode"); - if (state->st_mode == NULL) - return -1; - - /* suppress "function not used" warnings */ - { - int ignored; - fd_specified("", -1); - follow_symlinks_specified("", 1); - dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1); - dir_fd_converter(Py_None, &ignored); - dir_fd_unavailable(Py_None, &ignored); - } - - /* - * provide list of locally available functions - * so os.py can populate support_* lists - */ - PyObject *list = PyList_New(0); - if (!list) { - return -1; - } - for (const struct have_function *trace = have_functions; trace->label; trace++) { - PyObject *unicode; - if (trace->probe && !trace->probe()) continue; - unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL); - if (!unicode) - return -1; - if (PyList_Append(list, unicode)) - return -1; - Py_DECREF(unicode); - } - - PyModule_AddObject(m, "_have_functions", list); - - return 0; -} - - -static PyModuleDef_Slot posixmodile_slots[] = { - {Py_mod_exec, posixmodule_exec}, - {0, NULL} -}; - -static struct PyModuleDef posixmodule = { - PyModuleDef_HEAD_INIT, - .m_name = MODNAME, - .m_doc = posix__doc__, - .m_size = sizeof(_posixstate), - .m_methods = posix_methods, - .m_slots = posixmodile_slots, - .m_traverse = _posix_traverse, - .m_clear = _posix_clear, - .m_free = _posix_free, -}; - -PyMODINIT_FUNC -INITFUNC(void) -{ - return PyModuleDef_Init(&posixmodule); -} - -#ifdef __cplusplus -} -#endif +/* POSIX module implementation */ + +/* This file is also used for Windows NT/MS-Win. In that case the + module actually calls itself 'nt', not 'posix', and a few + functions are either unimplemented or implemented differently. The source + assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent + of the compiler used. Different compilers define their own feature + test macro, e.g. '_MSC_VER'. */ + +#define PY_SSIZE_T_CLEAN + +#include "Python.h" +// Include before pycore internal headers. FSCTL_GET_REPARSE_POINT +// is not exported by if the WIN32_LEAN_AND_MEAN macro is defined, +// whereas pycore_condvar.h defines the WIN32_LEAN_AND_MEAN macro. +#ifdef MS_WINDOWS +# include +# include +#endif + +#ifdef __VXWORKS__ +# include "pycore_bitutils.h" // _Py_popcount32() +#endif +#include "pycore_call.h" // _PyObject_CallNoArgs() +#include "pycore_ceval.h" // _PyEval_ReInitThreads() +#include "pycore_fileutils.h" // _Py_closerange() +#include "pycore_import.h" // _PyImport_ReInitLock() +#include "pycore_initconfig.h" // _PyStatus_EXCEPTION() +#include "pycore_moduleobject.h" // _PyModule_GetState() +#include "pycore_object.h" // _PyObject_LookupSpecial() +#include "pycore_pystate.h" // _PyInterpreterState_GET() +#include "pycore_signal.h" // Py_NSIG + +#include "structmember.h" // PyMemberDef +#ifndef MS_WINDOWS +# include "posixmodule.h" +#else +# include "winreparse.h" +#endif + +#if !defined(EX_OK) && defined(EXIT_SUCCESS) +# define EX_OK EXIT_SUCCESS +#endif + +/* On android API level 21, 'AT_EACCESS' is not declared although + * HAVE_FACCESSAT is defined. */ +#ifdef __ANDROID__ +# undef HAVE_FACCESSAT +#endif + +#include // ctermid() +#include // system() + +/* + * A number of APIs are available on macOS from a certain macOS version. + * To support building with a new SDK while deploying to older versions + * the availability test is split into two: + * - HAVE_: The configure check for compile time availability + * - HAVE__RUNTIME: Runtime check for availability + * + * The latter is always true when not on macOS, or when using a compiler + * that does not support __has_builtin (older versions of Xcode). + * + * Due to compiler restrictions there is one valid use of HAVE__RUNTIME: + * if (HAVE__RUNTIME) { ... } + * + * In mixing the test with other tests or using negations will result in compile + * errors. + */ +#if defined(__APPLE__) + +#if defined(__has_builtin) +#if __has_builtin(__builtin_available) +#define HAVE_BUILTIN_AVAILABLE 1 +#endif +#endif + +#ifdef HAVE_BUILTIN_AVAILABLE +# define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) +# define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) +# define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) +# define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) +# define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) +# define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) +# define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) +# define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) +# define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) +# define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) +# define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) +# define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) +# define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *) +# define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *) +# define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *) +# define HAVE_MKFIFOAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *) +# define HAVE_MKNODAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *) + +# define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *) + +#else /* Xcode 8 or earlier */ + + /* __builtin_available is not present in these compilers, but + * some of the symbols might be weak linked (10.10 SDK or later + * deploying on 10.9. + * + * Fall back to the older style of availability checking for + * symbols introduced in macOS 10.10. + */ + +# ifdef HAVE_FSTATAT +# define HAVE_FSTATAT_RUNTIME (fstatat != NULL) +# endif + +# ifdef HAVE_FACCESSAT +# define HAVE_FACCESSAT_RUNTIME (faccessat != NULL) +# endif + +# ifdef HAVE_FCHMODAT +# define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL) +# endif + +# ifdef HAVE_FCHOWNAT +# define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL) +# endif + +# ifdef HAVE_LINKAT +# define HAVE_LINKAT_RUNTIME (linkat != NULL) +# endif + +# ifdef HAVE_FDOPENDIR +# define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL) +# endif + +# ifdef HAVE_MKDIRAT +# define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL) +# endif + +# ifdef HAVE_RENAMEAT +# define HAVE_RENAMEAT_RUNTIME (renameat != NULL) +# endif + +# ifdef HAVE_UNLINKAT +# define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL) +# endif + +# ifdef HAVE_OPENAT +# define HAVE_OPENAT_RUNTIME (openat != NULL) +# endif + +# ifdef HAVE_READLINKAT +# define HAVE_READLINKAT_RUNTIME (readlinkat != NULL) +# endif + +# ifdef HAVE_SYMLINKAT +# define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL) +# endif + +#endif + +#ifdef HAVE_FUTIMESAT +/* Some of the logic for weak linking depends on this assertion */ +# error "HAVE_FUTIMESAT unexpectedly defined" +#endif + +#else +# define HAVE_FSTATAT_RUNTIME 1 +# define HAVE_FACCESSAT_RUNTIME 1 +# define HAVE_FCHMODAT_RUNTIME 1 +# define HAVE_FCHOWNAT_RUNTIME 1 +# define HAVE_LINKAT_RUNTIME 1 +# define HAVE_FDOPENDIR_RUNTIME 1 +# define HAVE_MKDIRAT_RUNTIME 1 +# define HAVE_RENAMEAT_RUNTIME 1 +# define HAVE_UNLINKAT_RUNTIME 1 +# define HAVE_OPENAT_RUNTIME 1 +# define HAVE_READLINKAT_RUNTIME 1 +# define HAVE_SYMLINKAT_RUNTIME 1 +# define HAVE_FUTIMENS_RUNTIME 1 +# define HAVE_UTIMENSAT_RUNTIME 1 +# define HAVE_PWRITEV_RUNTIME 1 +# define HAVE_MKFIFOAT_RUNTIME 1 +# define HAVE_MKNODAT_RUNTIME 1 +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +PyDoc_STRVAR(posix__doc__, +"This module provides access to operating system functionality that is\n\ +standardized by the C Standard and the POSIX standard (a thinly\n\ +disguised Unix interface). Refer to the library manual and\n\ +corresponding Unix manual entries for more information on calls."); + + +#ifdef HAVE_SYS_UIO_H +# include +#endif + +#ifdef HAVE_SYS_SYSMACROS_H +/* GNU C Library: major(), minor(), makedev() */ +# include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif /* HAVE_SYS_TYPES_H */ + +#ifdef HAVE_SYS_STAT_H +# include +#endif /* HAVE_SYS_STAT_H */ + +#ifdef HAVE_SYS_WAIT_H +# include // WNOHANG +#endif +#ifdef HAVE_LINUX_WAIT_H +# include // P_PIDFD +#endif + +#ifdef HAVE_SIGNAL_H +# include +#endif + +#ifdef HAVE_FCNTL_H +# include +#endif + +#ifdef HAVE_GRP_H +# include +#endif + +#ifdef HAVE_SYSEXITS_H +# include +#endif + +#ifdef HAVE_SYS_LOADAVG_H +# include +#endif + +#ifdef HAVE_SYS_SENDFILE_H +# include +#endif + +#if defined(__APPLE__) +# include +#endif + +#ifdef HAVE_SCHED_H +# include +#endif + +#ifdef HAVE_COPY_FILE_RANGE +# include +#endif + +#if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY) +# undef HAVE_SCHED_SETAFFINITY +#endif + +#if defined(HAVE_SYS_XATTR_H) && defined(__GLIBC__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__) +# define USE_XATTRS +#endif + +#ifdef USE_XATTRS +# include +#endif + +#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) +# ifdef HAVE_SYS_SOCKET_H +# include +# endif +#endif + +#ifdef HAVE_DLFCN_H +# include +#endif + +#ifdef __hpux +# include +#endif + +#if defined(__DragonFly__) || \ + defined(__OpenBSD__) || \ + defined(__FreeBSD__) || \ + defined(__NetBSD__) || \ + defined(__APPLE__) +# include +#endif + +#ifdef HAVE_LINUX_RANDOM_H +# include +#endif +#ifdef HAVE_GETRANDOM_SYSCALL +# include +#endif + +#if defined(MS_WINDOWS) +# define TERMSIZE_USE_CONIO +#elif defined(HAVE_SYS_IOCTL_H) +# include +# if defined(HAVE_TERMIOS_H) +# include +# endif +# if defined(TIOCGWINSZ) +# define TERMSIZE_USE_IOCTL +# endif +#endif /* MS_WINDOWS */ + +/* Various compilers have only certain posix functions */ +/* XXX Gosh I wish these were all moved into pyconfig.h */ +#if defined(__WATCOMC__) && !defined(__QNX__) /* Watcom compiler */ +# define HAVE_OPENDIR 1 +# define HAVE_SYSTEM 1 +# include +#else +# ifdef _MSC_VER + /* Microsoft compiler */ +# define HAVE_GETPPID 1 +# define HAVE_GETLOGIN 1 +# define HAVE_SPAWNV 1 +# define HAVE_EXECV 1 +# define HAVE_WSPAWNV 1 +# define HAVE_WEXECV 1 +# define HAVE_PIPE 1 +# define HAVE_SYSTEM 1 +# define HAVE_CWAIT 1 +# define HAVE_FSYNC 1 +# define fsync _commit +# endif /* _MSC_VER */ +#endif /* ! __WATCOMC__ || __QNX__ */ + +/*[clinic input] +# one of the few times we lie about this name! +module os +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/ + +#ifndef _MSC_VER + +#if defined(__sgi)&&_COMPILER_VERSION>=700 +/* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode + (default) */ +extern char *ctermid_r(char *); +#endif + +#endif /* !_MSC_VER */ + +#if defined(__VXWORKS__) +# include +# include +# include +# include +# ifndef _P_WAIT +# define _P_WAIT 0 +# define _P_NOWAIT 1 +# define _P_NOWAITO 1 +# endif +#endif /* __VXWORKS__ */ + +#ifdef HAVE_POSIX_SPAWN +# include +#endif + +#ifdef HAVE_UTIME_H +# include +#endif /* HAVE_UTIME_H */ + +#ifdef HAVE_SYS_UTIME_H +# include +# define HAVE_UTIME_H /* pretend we do for the rest of this file */ +#endif /* HAVE_SYS_UTIME_H */ + +#ifdef HAVE_SYS_TIMES_H +# include +#endif /* HAVE_SYS_TIMES_H */ + +#ifdef HAVE_SYS_PARAM_H +# include +#endif /* HAVE_SYS_PARAM_H */ + +#ifdef HAVE_SYS_UTSNAME_H +# include +#endif /* HAVE_SYS_UTSNAME_H */ + +#ifdef HAVE_DIRENT_H +# include +# define NAMLEN(dirent) strlen((dirent)->d_name) +#else +# if defined(__WATCOMC__) && !defined(__QNX__) +# include +# define NAMLEN(dirent) strlen((dirent)->d_name) +# else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# endif +# ifdef HAVE_SYS_NDIR_H +# include +# endif +# ifdef HAVE_SYS_DIR_H +# include +# endif +# ifdef HAVE_NDIR_H +# include +# endif +#endif + +#ifdef _MSC_VER +# ifdef HAVE_DIRECT_H +# include +# endif +# ifdef HAVE_IO_H +# include +# endif +# ifdef HAVE_PROCESS_H +# include +# endif +# ifndef IO_REPARSE_TAG_SYMLINK +# define IO_REPARSE_TAG_SYMLINK (0xA000000CL) +# endif +# ifndef IO_REPARSE_TAG_MOUNT_POINT +# define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) +# endif +# include "osdefs.h" // SEP +# include +# include +# include // ShellExecute() +# include // UNLEN +# define HAVE_SYMLINK +#endif /* _MSC_VER */ + +#ifndef MAXPATHLEN +# if defined(PATH_MAX) && PATH_MAX > 1024 +# define MAXPATHLEN PATH_MAX +# else +# define MAXPATHLEN 1024 +# endif +#endif /* MAXPATHLEN */ + +#ifdef UNION_WAIT + /* Emulate some macros on systems that have a union instead of macros */ +# ifndef WIFEXITED +# define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump) +# endif +# ifndef WEXITSTATUS +# define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1) +# endif +# ifndef WTERMSIG +# define WTERMSIG(u_wait) ((u_wait).w_termsig) +# endif +# define WAIT_TYPE union wait +# define WAIT_STATUS_INT(s) (s.w_status) +#else + /* !UNION_WAIT */ +# define WAIT_TYPE int +# define WAIT_STATUS_INT(s) (s) +#endif /* UNION_WAIT */ + +/* Don't use the "_r" form if we don't need it (also, won't have a + prototype for it, at least on Solaris -- maybe others as well?). */ +#if defined(HAVE_CTERMID_R) +# define USE_CTERMID_R +#endif + +/* choose the appropriate stat and fstat functions and return structs */ +#undef STAT +#undef FSTAT +#undef STRUCT_STAT +#ifdef MS_WINDOWS +# define STAT win32_stat +# define LSTAT win32_lstat +# define FSTAT _Py_fstat_noraise +# define STRUCT_STAT struct _Py_stat_struct +#else +# define STAT stat +# define LSTAT lstat +# define FSTAT fstat +# define STRUCT_STAT struct stat +#endif + +#if defined(MAJOR_IN_MKDEV) +# include +#else +# if defined(MAJOR_IN_SYSMACROS) +# include +# endif +# if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H) +# include +# endif +#endif + +#ifdef MS_WINDOWS +# define INITFUNC PyInit_nt +# define MODNAME "nt" +#else +# define INITFUNC PyInit_posix +# define MODNAME "posix" +#endif + +#if defined(__sun) +/* Something to implement in autoconf, not present in autoconf 2.69 */ +# define HAVE_STRUCT_STAT_ST_FSTYPE 1 +#endif + +/* memfd_create is either defined in sys/mman.h or sys/memfd.h + * linux/memfd.h defines additional flags + */ +#ifdef HAVE_SYS_MMAN_H +# include +#endif +#ifdef HAVE_SYS_MEMFD_H +# include +#endif +#ifdef HAVE_LINUX_MEMFD_H +# include +#endif + +/* eventfd() */ +#ifdef HAVE_SYS_EVENTFD_H +# include +#endif + +#ifdef _Py_MEMORY_SANITIZER +# include +#endif + +#ifdef HAVE_FORK +static void +run_at_forkers(PyObject *lst, int reverse) +{ + Py_ssize_t i; + PyObject *cpy; + + if (lst != NULL) { + assert(PyList_CheckExact(lst)); + + /* Use a list copy in case register_at_fork() is called from + * one of the callbacks. + */ + cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst)); + if (cpy == NULL) + PyErr_WriteUnraisable(lst); + else { + if (reverse) + PyList_Reverse(cpy); + for (i = 0; i < PyList_GET_SIZE(cpy); i++) { + PyObject *func, *res; + func = PyList_GET_ITEM(cpy, i); + res = _PyObject_CallNoArgs(func); + if (res == NULL) + PyErr_WriteUnraisable(func); + else + Py_DECREF(res); + } + Py_DECREF(cpy); + } + } +} + +void +PyOS_BeforeFork(void) +{ + run_at_forkers(_PyInterpreterState_GET()->before_forkers, 1); + + _PyImport_AcquireLock(); +} + +void +PyOS_AfterFork_Parent(void) +{ + if (_PyImport_ReleaseLock() <= 0) + Py_FatalError("failed releasing import lock after fork"); + + run_at_forkers(_PyInterpreterState_GET()->after_forkers_parent, 0); +} + +void +PyOS_AfterFork_Child(void) +{ + PyStatus status; + _PyRuntimeState *runtime = &_PyRuntime; + + status = _PyGILState_Reinit(runtime); + if (_PyStatus_EXCEPTION(status)) { + goto fatal_error; + } + + PyThreadState *tstate = _PyThreadState_GET(); + _Py_EnsureTstateNotNULL(tstate); + + status = _PyEval_ReInitThreads(tstate); + if (_PyStatus_EXCEPTION(status)) { + goto fatal_error; + } + + status = _PyImport_ReInitLock(); + if (_PyStatus_EXCEPTION(status)) { + goto fatal_error; + } + + _PySignal_AfterFork(); + + status = _PyRuntimeState_ReInitThreads(runtime); + if (_PyStatus_EXCEPTION(status)) { + goto fatal_error; + } + + status = _PyInterpreterState_DeleteExceptMain(runtime); + if (_PyStatus_EXCEPTION(status)) { + goto fatal_error; + } + assert(_PyThreadState_GET() == tstate); + + status = _PyPerfTrampoline_AfterFork_Child(); + if (_PyStatus_EXCEPTION(status)) { + goto fatal_error; + } + + run_at_forkers(tstate->interp->after_forkers_child, 0); + return; + +fatal_error: + Py_ExitStatusException(status); +} + +static int +register_at_forker(PyObject **lst, PyObject *func) +{ + if (func == NULL) /* nothing to register? do nothing. */ + return 0; + if (*lst == NULL) { + *lst = PyList_New(0); + if (*lst == NULL) + return -1; + } + return PyList_Append(*lst, func); +} +#endif /* HAVE_FORK */ + + +/* Legacy wrapper */ +void +PyOS_AfterFork(void) +{ +#ifdef HAVE_FORK + PyOS_AfterFork_Child(); +#endif +} + + +#ifdef MS_WINDOWS +/* defined in fileutils.c */ +void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *); +void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *, + ULONG, struct _Py_stat_struct *); +#endif + + +#ifndef MS_WINDOWS +PyObject * +_PyLong_FromUid(uid_t uid) +{ + if (uid == (uid_t)-1) + return PyLong_FromLong(-1); + return PyLong_FromUnsignedLong(uid); +} + +PyObject * +_PyLong_FromGid(gid_t gid) +{ + if (gid == (gid_t)-1) + return PyLong_FromLong(-1); + return PyLong_FromUnsignedLong(gid); +} + +int +_Py_Uid_Converter(PyObject *obj, uid_t *p) +{ + uid_t uid; + PyObject *index; + int overflow; + long result; + unsigned long uresult; + + index = _PyNumber_Index(obj); + if (index == NULL) { + PyErr_Format(PyExc_TypeError, + "uid should be integer, not %.200s", + _PyType_Name(Py_TYPE(obj))); + return 0; + } + + /* + * Handling uid_t is complicated for two reasons: + * * Although uid_t is (always?) unsigned, it still + * accepts -1. + * * We don't know its size in advance--it may be + * bigger than an int, or it may be smaller than + * a long. + * + * So a bit of defensive programming is in order. + * Start with interpreting the value passed + * in as a signed long and see if it works. + */ + + result = PyLong_AsLongAndOverflow(index, &overflow); + + if (!overflow) { + uid = (uid_t)result; + + if (result == -1) { + if (PyErr_Occurred()) + goto fail; + /* It's a legitimate -1, we're done. */ + goto success; + } + + /* Any other negative number is disallowed. */ + if (result < 0) + goto underflow; + + /* Ensure the value wasn't truncated. */ + if (sizeof(uid_t) < sizeof(long) && + (long)uid != result) + goto underflow; + goto success; + } + + if (overflow < 0) + goto underflow; + + /* + * Okay, the value overflowed a signed long. If it + * fits in an *unsigned* long, it may still be okay, + * as uid_t may be unsigned long on this platform. + */ + uresult = PyLong_AsUnsignedLong(index); + if (PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_OverflowError)) + goto overflow; + goto fail; + } + + uid = (uid_t)uresult; + + /* + * If uid == (uid_t)-1, the user actually passed in ULONG_MAX, + * but this value would get interpreted as (uid_t)-1 by chown + * and its siblings. That's not what the user meant! So we + * throw an overflow exception instead. (We already + * handled a real -1 with PyLong_AsLongAndOverflow() above.) + */ + if (uid == (uid_t)-1) + goto overflow; + + /* Ensure the value wasn't truncated. */ + if (sizeof(uid_t) < sizeof(long) && + (unsigned long)uid != uresult) + goto overflow; + /* fallthrough */ + +success: + Py_DECREF(index); + *p = uid; + return 1; + +underflow: + PyErr_SetString(PyExc_OverflowError, + "uid is less than minimum"); + goto fail; + +overflow: + PyErr_SetString(PyExc_OverflowError, + "uid is greater than maximum"); + /* fallthrough */ + +fail: + Py_DECREF(index); + return 0; +} + +int +_Py_Gid_Converter(PyObject *obj, gid_t *p) +{ + gid_t gid; + PyObject *index; + int overflow; + long result; + unsigned long uresult; + + index = _PyNumber_Index(obj); + if (index == NULL) { + PyErr_Format(PyExc_TypeError, + "gid should be integer, not %.200s", + _PyType_Name(Py_TYPE(obj))); + return 0; + } + + /* + * Handling gid_t is complicated for two reasons: + * * Although gid_t is (always?) unsigned, it still + * accepts -1. + * * We don't know its size in advance--it may be + * bigger than an int, or it may be smaller than + * a long. + * + * So a bit of defensive programming is in order. + * Start with interpreting the value passed + * in as a signed long and see if it works. + */ + + result = PyLong_AsLongAndOverflow(index, &overflow); + + if (!overflow) { + gid = (gid_t)result; + + if (result == -1) { + if (PyErr_Occurred()) + goto fail; + /* It's a legitimate -1, we're done. */ + goto success; + } + + /* Any other negative number is disallowed. */ + if (result < 0) { + goto underflow; + } + + /* Ensure the value wasn't truncated. */ + if (sizeof(gid_t) < sizeof(long) && + (long)gid != result) + goto underflow; + goto success; + } + + if (overflow < 0) + goto underflow; + + /* + * Okay, the value overflowed a signed long. If it + * fits in an *unsigned* long, it may still be okay, + * as gid_t may be unsigned long on this platform. + */ + uresult = PyLong_AsUnsignedLong(index); + if (PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_OverflowError)) + goto overflow; + goto fail; + } + + gid = (gid_t)uresult; + + /* + * If gid == (gid_t)-1, the user actually passed in ULONG_MAX, + * but this value would get interpreted as (gid_t)-1 by chown + * and its siblings. That's not what the user meant! So we + * throw an overflow exception instead. (We already + * handled a real -1 with PyLong_AsLongAndOverflow() above.) + */ + if (gid == (gid_t)-1) + goto overflow; + + /* Ensure the value wasn't truncated. */ + if (sizeof(gid_t) < sizeof(long) && + (unsigned long)gid != uresult) + goto overflow; + /* fallthrough */ + +success: + Py_DECREF(index); + *p = gid; + return 1; + +underflow: + PyErr_SetString(PyExc_OverflowError, + "gid is less than minimum"); + goto fail; + +overflow: + PyErr_SetString(PyExc_OverflowError, + "gid is greater than maximum"); + /* fallthrough */ + +fail: + Py_DECREF(index); + return 0; +} +#endif /* MS_WINDOWS */ + + +#define _PyLong_FromDev PyLong_FromLongLong + + +#if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) || defined(HAVE_DEVICE_MACROS) +static int +_Py_Dev_Converter(PyObject *obj, void *p) +{ + *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj); + if (PyErr_Occurred()) + return 0; + return 1; +} +#endif /* (HAVE_MKNOD && HAVE_MAKEDEV) || HAVE_DEVICE_MACROS */ + + +#ifdef AT_FDCWD +/* + * Why the (int) cast? Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965); + * without the int cast, the value gets interpreted as uint (4291925331), + * which doesn't play nicely with all the initializer lines in this file that + * look like this: + * int dir_fd = DEFAULT_DIR_FD; + */ +#define DEFAULT_DIR_FD (int)AT_FDCWD +#else +#define DEFAULT_DIR_FD (-100) +#endif + +static int +_fd_converter(PyObject *o, int *p) +{ + int overflow; + long long_value; + + PyObject *index = _PyNumber_Index(o); + if (index == NULL) { + return 0; + } + + assert(PyLong_Check(index)); + long_value = PyLong_AsLongAndOverflow(index, &overflow); + Py_DECREF(index); + assert(!PyErr_Occurred()); + if (overflow > 0 || long_value > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "fd is greater than maximum"); + return 0; + } + if (overflow < 0 || long_value < INT_MIN) { + PyErr_SetString(PyExc_OverflowError, + "fd is less than minimum"); + return 0; + } + + *p = (int)long_value; + return 1; +} + +static int +dir_fd_converter(PyObject *o, void *p) +{ + if (o == Py_None) { + *(int *)p = DEFAULT_DIR_FD; + return 1; + } + else if (PyIndex_Check(o)) { + return _fd_converter(o, (int *)p); + } + else { + PyErr_Format(PyExc_TypeError, + "argument should be integer or None, not %.200s", + _PyType_Name(Py_TYPE(o))); + return 0; + } +} + +typedef struct { + PyObject *billion; + PyObject *DirEntryType; + PyObject *ScandirIteratorType; +#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) + PyObject *SchedParamType; +#endif + PyObject *StatResultType; + PyObject *StatVFSResultType; + PyObject *TerminalSizeType; + PyObject *TimesResultType; + PyObject *UnameResultType; +#if defined(HAVE_WAITID) && !defined(__APPLE__) + PyObject *WaitidResultType; +#endif +#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) + PyObject *struct_rusage; +#endif + PyObject *st_mode; +} _posixstate; + + +static inline _posixstate* +get_posix_state(PyObject *module) +{ + void *state = _PyModule_GetState(module); + assert(state != NULL); + return (_posixstate *)state; +} + +/* + * A PyArg_ParseTuple "converter" function + * that handles filesystem paths in the manner + * preferred by the os module. + * + * path_converter accepts (Unicode) strings and their + * subclasses, and bytes and their subclasses. What + * it does with the argument depends on the platform: + * + * * On Windows, if we get a (Unicode) string we + * extract the wchar_t * and return it; if we get + * bytes we decode to wchar_t * and return that. + * + * * On all other platforms, strings are encoded + * to bytes using PyUnicode_FSConverter, then we + * extract the char * from the bytes object and + * return that. + * + * path_converter also optionally accepts signed + * integers (representing open file descriptors) instead + * of path strings. + * + * Input fields: + * path.nullable + * If nonzero, the path is permitted to be None. + * path.allow_fd + * If nonzero, the path is permitted to be a file handle + * (a signed int) instead of a string. + * path.function_name + * If non-NULL, path_converter will use that as the name + * of the function in error messages. + * (If path.function_name is NULL it omits the function name.) + * path.argument_name + * If non-NULL, path_converter will use that as the name + * of the parameter in error messages. + * (If path.argument_name is NULL it uses "path".) + * + * Output fields: + * path.wide + * Points to the path if it was expressed as Unicode + * and was not encoded. (Only used on Windows.) + * path.narrow + * Points to the path if it was expressed as bytes, + * or it was Unicode and was encoded to bytes. (On Windows, + * is a non-zero integer if the path was expressed as bytes. + * The type is deliberately incompatible to prevent misuse.) + * path.fd + * Contains a file descriptor if path.accept_fd was true + * and the caller provided a signed integer instead of any + * sort of string. + * + * WARNING: if your "path" parameter is optional, and is + * unspecified, path_converter will never get called. + * So if you set allow_fd, you *MUST* initialize path.fd = -1 + * yourself! + * path.length + * The length of the path in characters, if specified as + * a string. + * path.object + * The original object passed in (if get a PathLike object, + * the result of PyOS_FSPath() is treated as the original object). + * Own a reference to the object. + * path.cleanup + * For internal use only. May point to a temporary object. + * (Pay no attention to the man behind the curtain.) + * + * At most one of path.wide or path.narrow will be non-NULL. + * If path was None and path.nullable was set, + * or if path was an integer and path.allow_fd was set, + * both path.wide and path.narrow will be NULL + * and path.length will be 0. + * + * path_converter takes care to not write to the path_t + * unless it's successful. However it must reset the + * "cleanup" field each time it's called. + * + * Use as follows: + * path_t path; + * memset(&path, 0, sizeof(path)); + * PyArg_ParseTuple(args, "O&", path_converter, &path); + * // ... use values from path ... + * path_cleanup(&path); + * + * (Note that if PyArg_Parse fails you don't need to call + * path_cleanup(). However it is safe to do so.) + */ +typedef struct { + const char *function_name; + const char *argument_name; + int nullable; + int allow_fd; + const wchar_t *wide; +#ifdef MS_WINDOWS + BOOL narrow; +#else + const char *narrow; +#endif + int fd; + Py_ssize_t length; + PyObject *object; + PyObject *cleanup; +} path_t; + +#ifdef MS_WINDOWS +#define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \ + {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL} +#else +#define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \ + {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL} +#endif + +static void +path_cleanup(path_t *path) +{ + wchar_t *wide = (wchar_t *)path->wide; + path->wide = NULL; + PyMem_Free(wide); + Py_CLEAR(path->object); + Py_CLEAR(path->cleanup); +} + +static int +path_converter(PyObject *o, void *p) +{ + path_t *path = (path_t *)p; + PyObject *bytes = NULL; + Py_ssize_t length = 0; + int is_index, is_bytes, is_unicode; + const char *narrow; +#ifdef MS_WINDOWS + PyObject *wo = NULL; + wchar_t *wide = NULL; +#endif + +#define FORMAT_EXCEPTION(exc, fmt) \ + PyErr_Format(exc, "%s%s" fmt, \ + path->function_name ? path->function_name : "", \ + path->function_name ? ": " : "", \ + path->argument_name ? path->argument_name : "path") + + /* Py_CLEANUP_SUPPORTED support */ + if (o == NULL) { + path_cleanup(path); + return 1; + } + + /* Ensure it's always safe to call path_cleanup(). */ + path->object = path->cleanup = NULL; + /* path->object owns a reference to the original object */ + Py_INCREF(o); + + if ((o == Py_None) && path->nullable) { + path->wide = NULL; +#ifdef MS_WINDOWS + path->narrow = FALSE; +#else + path->narrow = NULL; +#endif + path->fd = -1; + goto success_exit; + } + + /* Only call this here so that we don't treat the return value of + os.fspath() as an fd or buffer. */ + is_index = path->allow_fd && PyIndex_Check(o); + is_bytes = PyBytes_Check(o); + is_unicode = PyUnicode_Check(o); + + if (!is_index && !is_unicode && !is_bytes) { + /* Inline PyOS_FSPath() for better error messages. */ + PyObject *func, *res; + + func = _PyObject_LookupSpecial(o, &_Py_ID(__fspath__)); + if (NULL == func) { + goto error_format; + } + res = _PyObject_CallNoArgs(func); + Py_DECREF(func); + if (NULL == res) { + goto error_exit; + } + else if (PyUnicode_Check(res)) { + is_unicode = 1; + } + else if (PyBytes_Check(res)) { + is_bytes = 1; + } + else { + PyErr_Format(PyExc_TypeError, + "expected %.200s.__fspath__() to return str or bytes, " + "not %.200s", _PyType_Name(Py_TYPE(o)), + _PyType_Name(Py_TYPE(res))); + Py_DECREF(res); + goto error_exit; + } + + /* still owns a reference to the original object */ + Py_DECREF(o); + o = res; + } + + if (is_unicode) { +#ifdef MS_WINDOWS + wide = PyUnicode_AsWideCharString(o, &length); + if (!wide) { + goto error_exit; + } + if (length > 32767) { + FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); + goto error_exit; + } + if (wcslen(wide) != length) { + FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); + goto error_exit; + } + + path->wide = wide; + path->narrow = FALSE; + path->fd = -1; + wide = NULL; + goto success_exit; +#else + if (!PyUnicode_FSConverter(o, &bytes)) { + goto error_exit; + } +#endif + } + else if (is_bytes) { + bytes = Py_NewRef(o); + } + else if (is_index) { + if (!_fd_converter(o, &path->fd)) { + goto error_exit; + } + path->wide = NULL; +#ifdef MS_WINDOWS + path->narrow = FALSE; +#else + path->narrow = NULL; +#endif + goto success_exit; + } + else { + error_format: + PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s", + path->function_name ? path->function_name : "", + path->function_name ? ": " : "", + path->argument_name ? path->argument_name : "path", + path->allow_fd && path->nullable ? "string, bytes, os.PathLike, " + "integer or None" : + path->allow_fd ? "string, bytes, os.PathLike or integer" : + path->nullable ? "string, bytes, os.PathLike or None" : + "string, bytes or os.PathLike", + _PyType_Name(Py_TYPE(o))); + goto error_exit; + } + + length = PyBytes_GET_SIZE(bytes); + narrow = PyBytes_AS_STRING(bytes); + if ((size_t)length != strlen(narrow)) { + FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); + goto error_exit; + } + +#ifdef MS_WINDOWS + wo = PyUnicode_DecodeFSDefaultAndSize( + narrow, + length + ); + if (!wo) { + goto error_exit; + } + + wide = PyUnicode_AsWideCharString(wo, &length); + Py_DECREF(wo); + if (!wide) { + goto error_exit; + } + if (length > 32767) { + FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); + goto error_exit; + } + if (wcslen(wide) != length) { + FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); + goto error_exit; + } + path->wide = wide; + path->narrow = TRUE; + Py_DECREF(bytes); + wide = NULL; +#else + path->wide = NULL; + path->narrow = narrow; + if (bytes == o) { + /* Still a reference owned by path->object, don't have to + worry about path->narrow is used after free. */ + Py_DECREF(bytes); + } + else { + path->cleanup = bytes; + } +#endif + path->fd = -1; + + success_exit: + path->length = length; + path->object = o; + return Py_CLEANUP_SUPPORTED; + + error_exit: + Py_XDECREF(o); + Py_XDECREF(bytes); +#ifdef MS_WINDOWS + PyMem_Free(wide); +#endif + return 0; +} + +static void +argument_unavailable_error(const char *function_name, const char *argument_name) +{ + PyErr_Format(PyExc_NotImplementedError, + "%s%s%s unavailable on this platform", + (function_name != NULL) ? function_name : "", + (function_name != NULL) ? ": ": "", + argument_name); +} + +static int +dir_fd_unavailable(PyObject *o, void *p) +{ + int dir_fd; + if (!dir_fd_converter(o, &dir_fd)) + return 0; + if (dir_fd != DEFAULT_DIR_FD) { + argument_unavailable_error(NULL, "dir_fd"); + return 0; + } + *(int *)p = dir_fd; + return 1; +} + +static int +fd_specified(const char *function_name, int fd) +{ + if (fd == -1) + return 0; + + argument_unavailable_error(function_name, "fd"); + return 1; +} + +static int +follow_symlinks_specified(const char *function_name, int follow_symlinks) +{ + if (follow_symlinks) + return 0; + + argument_unavailable_error(function_name, "follow_symlinks"); + return 1; +} + +static int +path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd) +{ + if (!path->wide && (dir_fd != DEFAULT_DIR_FD) +#ifndef MS_WINDOWS + && !path->narrow +#endif + ) { + PyErr_Format(PyExc_ValueError, + "%s: can't specify dir_fd without matching path", + function_name); + return 1; + } + return 0; +} + +static int +dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd) +{ + if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) { + PyErr_Format(PyExc_ValueError, + "%s: can't specify both dir_fd and fd", + function_name); + return 1; + } + return 0; +} + +static int +fd_and_follow_symlinks_invalid(const char *function_name, int fd, + int follow_symlinks) +{ + if ((fd > 0) && (!follow_symlinks)) { + PyErr_Format(PyExc_ValueError, + "%s: cannot use fd and follow_symlinks together", + function_name); + return 1; + } + return 0; +} + +static int +dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd, + int follow_symlinks) +{ + if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) { + PyErr_Format(PyExc_ValueError, + "%s: cannot use dir_fd and follow_symlinks together", + function_name); + return 1; + } + return 0; +} + +#ifdef MS_WINDOWS + typedef long long Py_off_t; +#else + typedef off_t Py_off_t; +#endif + +static int +Py_off_t_converter(PyObject *arg, void *addr) +{ +#ifdef HAVE_LARGEFILE_SUPPORT + *((Py_off_t *)addr) = PyLong_AsLongLong(arg); +#else + *((Py_off_t *)addr) = PyLong_AsLong(arg); +#endif + if (PyErr_Occurred()) + return 0; + return 1; +} + +static PyObject * +PyLong_FromPy_off_t(Py_off_t offset) +{ +#ifdef HAVE_LARGEFILE_SUPPORT + return PyLong_FromLongLong(offset); +#else + return PyLong_FromLong(offset); +#endif +} + +#ifdef HAVE_SIGSET_T +/* Convert an iterable of integers to a sigset. + Return 1 on success, return 0 and raise an exception on error. */ +int +_Py_Sigset_Converter(PyObject *obj, void *addr) +{ + sigset_t *mask = (sigset_t *)addr; + PyObject *iterator, *item; + long signum; + int overflow; + + // The extra parens suppress the unreachable-code warning with clang on MacOS + if (sigemptyset(mask) < (0)) { + /* Probably only if mask == NULL. */ + PyErr_SetFromErrno(PyExc_OSError); + return 0; + } + + iterator = PyObject_GetIter(obj); + if (iterator == NULL) { + return 0; + } + + while ((item = PyIter_Next(iterator)) != NULL) { + signum = PyLong_AsLongAndOverflow(item, &overflow); + Py_DECREF(item); + if (signum <= 0 || signum >= Py_NSIG) { + if (overflow || signum != -1 || !PyErr_Occurred()) { + PyErr_Format(PyExc_ValueError, + "signal number %ld out of range [1; %i]", + signum, Py_NSIG - 1); + } + goto error; + } + if (sigaddset(mask, (int)signum)) { + if (errno != EINVAL) { + /* Probably impossible */ + PyErr_SetFromErrno(PyExc_OSError); + goto error; + } + /* For backwards compatibility, allow idioms such as + * `range(1, NSIG)` but warn about invalid signal numbers + */ + const char msg[] = + "invalid signal number %ld, please use valid_signals()"; + if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) { + goto error; + } + } + } + if (!PyErr_Occurred()) { + Py_DECREF(iterator); + return 1; + } + +error: + Py_DECREF(iterator); + return 0; +} +#endif /* HAVE_SIGSET_T */ + +#ifdef MS_WINDOWS + +static int +win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag) +{ + char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer; + DWORD n_bytes_returned; + + if (0 == DeviceIoControl( + reparse_point_handle, + FSCTL_GET_REPARSE_POINT, + NULL, 0, /* in buffer */ + target_buffer, sizeof(target_buffer), + &n_bytes_returned, + NULL)) /* we're not using OVERLAPPED_IO */ + return FALSE; + + if (reparse_tag) + *reparse_tag = rdb->ReparseTag; + + return TRUE; +} + +#endif /* MS_WINDOWS */ + +/* Return a dictionary corresponding to the POSIX environment table */ +#if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED)) +/* On Darwin/MacOSX a shared library or framework has no access to +** environ directly, we must obtain it with _NSGetEnviron(). See also +** man environ(7). +*/ +#include +#elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__)) +extern char **environ; +#endif /* !_MSC_VER */ + +static PyObject * +convertenviron(void) +{ + PyObject *d; +#ifdef MS_WINDOWS + wchar_t **e; +#else + char **e; +#endif + + d = PyDict_New(); + if (d == NULL) + return NULL; +#ifdef MS_WINDOWS + /* _wenviron must be initialized in this way if the program is started + through main() instead of wmain(). */ + _wgetenv(L""); + e = _wenviron; +#elif defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED)) + /* environ is not accessible as an extern in a shared object on OSX; use + _NSGetEnviron to resolve it. The value changes if you add environment + variables between calls to Py_Initialize, so don't cache the value. */ + e = *_NSGetEnviron(); +#else + e = environ; +#endif + if (e == NULL) + return d; + for (; *e != NULL; e++) { + PyObject *k; + PyObject *v; +#ifdef MS_WINDOWS + const wchar_t *p = wcschr(*e, L'='); +#else + const char *p = strchr(*e, '='); +#endif + if (p == NULL) + continue; +#ifdef MS_WINDOWS + k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e)); +#else + k = PyBytes_FromStringAndSize(*e, (int)(p-*e)); +#endif + if (k == NULL) { + Py_DECREF(d); + return NULL; + } +#ifdef MS_WINDOWS + v = PyUnicode_FromWideChar(p+1, wcslen(p+1)); +#else + v = PyBytes_FromStringAndSize(p+1, strlen(p+1)); +#endif + if (v == NULL) { + Py_DECREF(k); + Py_DECREF(d); + return NULL; + } + if (PyDict_SetDefault(d, k, v) == NULL) { + Py_DECREF(v); + Py_DECREF(k); + Py_DECREF(d); + return NULL; + } + Py_DECREF(k); + Py_DECREF(v); + } + return d; +} + +/* Set a POSIX-specific error from errno, and return NULL */ + +static PyObject * +posix_error(void) +{ + return PyErr_SetFromErrno(PyExc_OSError); +} + +#ifdef MS_WINDOWS +static PyObject * +win32_error(const char* function, const char* filename) +{ + /* XXX We should pass the function name along in the future. + (winreg.c also wants to pass the function name.) + This would however require an additional param to the + Windows error object, which is non-trivial. + */ + errno = GetLastError(); + if (filename) + return PyErr_SetFromWindowsErrWithFilename(errno, filename); + else + return PyErr_SetFromWindowsErr(errno); +} + +static PyObject * +win32_error_object_err(const char* function, PyObject* filename, DWORD err) +{ + /* XXX - see win32_error for comments on 'function' */ + if (filename) + return PyErr_SetExcFromWindowsErrWithFilenameObject( + PyExc_OSError, + err, + filename); + else + return PyErr_SetFromWindowsErr(err); +} + +static PyObject * +win32_error_object(const char* function, PyObject* filename) +{ + errno = GetLastError(); + return win32_error_object_err(function, filename, errno); +} + +#endif /* MS_WINDOWS */ + +static PyObject * +posix_path_object_error(PyObject *path) +{ + return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path); +} + +static PyObject * +path_object_error(PyObject *path) +{ +#ifdef MS_WINDOWS + return PyErr_SetExcFromWindowsErrWithFilenameObject( + PyExc_OSError, 0, path); +#else + return posix_path_object_error(path); +#endif +} + +static PyObject * +path_object_error2(PyObject *path, PyObject *path2) +{ +#ifdef MS_WINDOWS + return PyErr_SetExcFromWindowsErrWithFilenameObjects( + PyExc_OSError, 0, path, path2); +#else + return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2); +#endif +} + +static PyObject * +path_error(path_t *path) +{ + return path_object_error(path->object); +} + +static PyObject * +posix_path_error(path_t *path) +{ + return posix_path_object_error(path->object); +} + +static PyObject * +path_error2(path_t *path, path_t *path2) +{ + return path_object_error2(path->object, path2->object); +} + + +/* POSIX generic methods */ + +static PyObject * +posix_fildes_fd(int fd, int (*func)(int)) +{ + int res; + int async_err = 0; + + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + res = (*func)(fd); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (res != 0) + return (!async_err) ? posix_error() : NULL; + Py_RETURN_NONE; +} + + +#ifdef MS_WINDOWS +/* This is a reimplementation of the C library's chdir function, + but one that produces Win32 errors instead of DOS error codes. + chdir is essentially a wrapper around SetCurrentDirectory; however, + it also needs to set "magic" environment variables indicating + the per-drive current directory, which are of the form =: */ +static BOOL __stdcall +win32_wchdir(LPCWSTR path) +{ + wchar_t path_buf[MAX_PATH], *new_path = path_buf; + int result; + wchar_t env[4] = L"=x:"; + + if(!SetCurrentDirectoryW(path)) + return FALSE; + result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path); + if (!result) + return FALSE; + if (result > Py_ARRAY_LENGTH(path_buf)) { + new_path = PyMem_RawMalloc(result * sizeof(wchar_t)); + if (!new_path) { + SetLastError(ERROR_OUTOFMEMORY); + return FALSE; + } + result = GetCurrentDirectoryW(result, new_path); + if (!result) { + PyMem_RawFree(new_path); + return FALSE; + } + } + int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 || + wcsncmp(new_path, L"//", 2) == 0); + if (!is_unc_like_path) { + env[1] = new_path[0]; + result = SetEnvironmentVariableW(env, new_path); + } + if (new_path != path_buf) + PyMem_RawFree(new_path); + return result ? TRUE : FALSE; +} +#endif + +#ifdef MS_WINDOWS +/* The CRT of Windows has a number of flaws wrt. its stat() implementation: + - time stamps are restricted to second resolution + - file modification times suffer from forth-and-back conversions between + UTC and local time + Therefore, we implement our own stat, based on the Win32 API directly. +*/ +#define HAVE_STAT_NSEC 1 +#define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1 +#define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1 + +static void +find_data_to_file_info(WIN32_FIND_DATAW *pFileData, + BY_HANDLE_FILE_INFORMATION *info, + ULONG *reparse_tag) +{ + memset(info, 0, sizeof(*info)); + info->dwFileAttributes = pFileData->dwFileAttributes; + info->ftCreationTime = pFileData->ftCreationTime; + info->ftLastAccessTime = pFileData->ftLastAccessTime; + info->ftLastWriteTime = pFileData->ftLastWriteTime; + info->nFileSizeHigh = pFileData->nFileSizeHigh; + info->nFileSizeLow = pFileData->nFileSizeLow; +/* info->nNumberOfLinks = 1; */ + if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) + *reparse_tag = pFileData->dwReserved0; + else + *reparse_tag = 0; +} + +static BOOL +attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag) +{ + HANDLE hFindFile; + WIN32_FIND_DATAW FileData; + LPCWSTR filename = pszFile; + size_t n = wcslen(pszFile); + if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) { + // cannot use PyMem_Malloc here because we do not hold the GIL + filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0])); + wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n); + while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) { + ((LPWSTR)filename)[n] = L'\0'; + } + if (!n || (n == 1 && filename[1] == L':')) { + // Nothing left to query + free((void *)filename); + return FALSE; + } + } + hFindFile = FindFirstFileW(filename, &FileData); + if (pszFile != filename) { + free((void *)filename); + } + if (hFindFile == INVALID_HANDLE_VALUE) { + return FALSE; + } + FindClose(hFindFile); + find_data_to_file_info(&FileData, info, reparse_tag); + return TRUE; +} + +static int +win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result, + BOOL traverse) +{ + HANDLE hFile; + BY_HANDLE_FILE_INFORMATION fileInfo; + FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 }; + DWORD fileType, error; + BOOL isUnhandledTag = FALSE; + int retval = 0; + + DWORD access = FILE_READ_ATTRIBUTES; + DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */ + if (!traverse) { + flags |= FILE_FLAG_OPEN_REPARSE_POINT; + } + + hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + /* Either the path doesn't exist, or the caller lacks access. */ + error = GetLastError(); + switch (error) { + case ERROR_ACCESS_DENIED: /* Cannot sync or read attributes. */ + case ERROR_SHARING_VIOLATION: /* It's a paging file. */ + /* Try reading the parent directory. */ + if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) { + /* Cannot read the parent directory. */ + switch (GetLastError()) { + case ERROR_FILE_NOT_FOUND: /* File cannot be found */ + case ERROR_PATH_NOT_FOUND: /* File parent directory cannot be found */ + case ERROR_NOT_READY: /* Drive exists but unavailable */ + case ERROR_BAD_NET_NAME: /* Remote drive unavailable */ + break; + /* Restore the error from CreateFileW(). */ + default: + SetLastError(error); + } + + return -1; + } + if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { + if (traverse || + !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) { + /* The stat call has to traverse but cannot, so fail. */ + SetLastError(error); + return -1; + } + } + break; + + case ERROR_INVALID_PARAMETER: + /* \\.\con requires read or write access. */ + hFile = CreateFileW(path, access | GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, flags, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + SetLastError(error); + return -1; + } + break; + + case ERROR_CANT_ACCESS_FILE: + /* bpo37834: open unhandled reparse points if traverse fails. */ + if (traverse) { + traverse = FALSE; + isUnhandledTag = TRUE; + hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, + flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL); + } + if (hFile == INVALID_HANDLE_VALUE) { + SetLastError(error); + return -1; + } + break; + + default: + return -1; + } + } + + if (hFile != INVALID_HANDLE_VALUE) { + /* Handle types other than files on disk. */ + fileType = GetFileType(hFile); + if (fileType != FILE_TYPE_DISK) { + if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) { + retval = -1; + goto cleanup; + } + DWORD fileAttributes = GetFileAttributesW(path); + memset(result, 0, sizeof(*result)); + if (fileAttributes != INVALID_FILE_ATTRIBUTES && + fileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + /* \\.\pipe\ or \\.\mailslot\ */ + result->st_mode = _S_IFDIR; + } else if (fileType == FILE_TYPE_CHAR) { + /* \\.\nul */ + result->st_mode = _S_IFCHR; + } else if (fileType == FILE_TYPE_PIPE) { + /* \\.\pipe\spam */ + result->st_mode = _S_IFIFO; + } + /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */ + goto cleanup; + } + + /* Query the reparse tag, and traverse a non-link. */ + if (!traverse) { + if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo, + &tagInfo, sizeof(tagInfo))) { + /* Allow devices that do not support FileAttributeTagInfo. */ + switch (GetLastError()) { + case ERROR_INVALID_PARAMETER: + case ERROR_INVALID_FUNCTION: + case ERROR_NOT_SUPPORTED: + tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL; + tagInfo.ReparseTag = 0; + break; + default: + retval = -1; + goto cleanup; + } + } else if (tagInfo.FileAttributes & + FILE_ATTRIBUTE_REPARSE_POINT) { + if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) { + if (isUnhandledTag) { + /* Traversing previously failed for either this link + or its target. */ + SetLastError(ERROR_CANT_ACCESS_FILE); + retval = -1; + goto cleanup; + } + /* Traverse a non-link, but not if traversing already failed + for an unhandled tag. */ + } else if (!isUnhandledTag) { + CloseHandle(hFile); + return win32_xstat_impl(path, result, TRUE); + } + } + } + + if (!GetFileInformationByHandle(hFile, &fileInfo)) { + switch (GetLastError()) { + case ERROR_INVALID_PARAMETER: + case ERROR_INVALID_FUNCTION: + case ERROR_NOT_SUPPORTED: + /* Volumes and physical disks are block devices, e.g. + \\.\C: and \\.\PhysicalDrive0. */ + memset(result, 0, sizeof(*result)); + result->st_mode = 0x6000; /* S_IFBLK */ + goto cleanup; + } + retval = -1; + goto cleanup; + } + } + + _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, result); + + if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + /* Fix the file execute permissions. This hack sets S_IEXEC if + the filename has an extension that is commonly used by files + that CreateProcessW can execute. A real implementation calls + GetSecurityInfo, OpenThreadToken/OpenProcessToken, and + AccessCheck to check for generic read, write, and execute + access. */ + const wchar_t *fileExtension = wcsrchr(path, '.'); + if (fileExtension) { + if (_wcsicmp(fileExtension, L".exe") == 0 || + _wcsicmp(fileExtension, L".bat") == 0 || + _wcsicmp(fileExtension, L".cmd") == 0 || + _wcsicmp(fileExtension, L".com") == 0) { + result->st_mode |= 0111; + } + } + } + +cleanup: + if (hFile != INVALID_HANDLE_VALUE) { + /* Preserve last error if we are failing */ + error = retval ? GetLastError() : 0; + if (!CloseHandle(hFile)) { + retval = -1; + } else if (retval) { + /* Restore last error */ + SetLastError(error); + } + } + + return retval; +} + +static int +win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse) +{ + /* Protocol violation: we explicitly clear errno, instead of + setting it to a POSIX error. Callers should use GetLastError. */ + int code = win32_xstat_impl(path, result, traverse); + errno = 0; + return code; +} +/* About the following functions: win32_lstat_w, win32_stat, win32_stat_w + + In Posix, stat automatically traverses symlinks and returns the stat + structure for the target. In Windows, the equivalent GetFileAttributes by + default does not traverse symlinks and instead returns attributes for + the symlink. + + Instead, we will open the file (which *does* traverse symlinks by default) + and GetFileInformationByHandle(). */ + +static int +win32_lstat(const wchar_t* path, struct _Py_stat_struct *result) +{ + return win32_xstat(path, result, FALSE); +} + +static int +win32_stat(const wchar_t* path, struct _Py_stat_struct *result) +{ + return win32_xstat(path, result, TRUE); +} + +#endif /* MS_WINDOWS */ + +PyDoc_STRVAR(stat_result__doc__, +"stat_result: Result from stat, fstat, or lstat.\n\n\ +This object may be accessed either as a tuple of\n\ + (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\ +or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\ +\n\ +Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\ +or st_flags, they are available as attributes only.\n\ +\n\ +See os.stat for more information."); + +static PyStructSequence_Field stat_result_fields[] = { + {"st_mode", "protection bits"}, + {"st_ino", "inode"}, + {"st_dev", "device"}, + {"st_nlink", "number of hard links"}, + {"st_uid", "user ID of owner"}, + {"st_gid", "group ID of owner"}, + {"st_size", "total size, in bytes"}, + /* The NULL is replaced with PyStructSequence_UnnamedField later. */ + {NULL, "integer time of last access"}, + {NULL, "integer time of last modification"}, + {NULL, "integer time of last change"}, + {"st_atime", "time of last access"}, + {"st_mtime", "time of last modification"}, + {"st_ctime", "time of last change"}, + {"st_atime_ns", "time of last access in nanoseconds"}, + {"st_mtime_ns", "time of last modification in nanoseconds"}, + {"st_ctime_ns", "time of last change in nanoseconds"}, +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + {"st_blksize", "blocksize for filesystem I/O"}, +#endif +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS + {"st_blocks", "number of blocks allocated"}, +#endif +#ifdef HAVE_STRUCT_STAT_ST_RDEV + {"st_rdev", "device type (if inode device)"}, +#endif +#ifdef HAVE_STRUCT_STAT_ST_FLAGS + {"st_flags", "user defined flags for file"}, +#endif +#ifdef HAVE_STRUCT_STAT_ST_GEN + {"st_gen", "generation number"}, +#endif +#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME + {"st_birthtime", "time of creation"}, +#endif +#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES + {"st_file_attributes", "Windows file attribute bits"}, +#endif +#ifdef HAVE_STRUCT_STAT_ST_FSTYPE + {"st_fstype", "Type of filesystem"}, +#endif +#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG + {"st_reparse_tag", "Windows reparse tag"}, +#endif + {0} +}; + +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE +#define ST_BLKSIZE_IDX 16 +#else +#define ST_BLKSIZE_IDX 15 +#endif + +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS +#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1) +#else +#define ST_BLOCKS_IDX ST_BLKSIZE_IDX +#endif + +#ifdef HAVE_STRUCT_STAT_ST_RDEV +#define ST_RDEV_IDX (ST_BLOCKS_IDX+1) +#else +#define ST_RDEV_IDX ST_BLOCKS_IDX +#endif + +#ifdef HAVE_STRUCT_STAT_ST_FLAGS +#define ST_FLAGS_IDX (ST_RDEV_IDX+1) +#else +#define ST_FLAGS_IDX ST_RDEV_IDX +#endif + +#ifdef HAVE_STRUCT_STAT_ST_GEN +#define ST_GEN_IDX (ST_FLAGS_IDX+1) +#else +#define ST_GEN_IDX ST_FLAGS_IDX +#endif + +#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME +#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1) +#else +#define ST_BIRTHTIME_IDX ST_GEN_IDX +#endif + +#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES +#define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1) +#else +#define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX +#endif + +#ifdef HAVE_STRUCT_STAT_ST_FSTYPE +#define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1) +#else +#define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX +#endif + +#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG +#define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1) +#else +#define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX +#endif + +static PyStructSequence_Desc stat_result_desc = { + "stat_result", /* name */ + stat_result__doc__, /* doc */ + stat_result_fields, + 10 +}; + +PyDoc_STRVAR(statvfs_result__doc__, +"statvfs_result: Result from statvfs or fstatvfs.\n\n\ +This object may be accessed either as a tuple of\n\ + (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\ +or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\ +\n\ +See os.statvfs for more information."); + +static PyStructSequence_Field statvfs_result_fields[] = { + {"f_bsize", }, + {"f_frsize", }, + {"f_blocks", }, + {"f_bfree", }, + {"f_bavail", }, + {"f_files", }, + {"f_ffree", }, + {"f_favail", }, + {"f_flag", }, + {"f_namemax",}, + {"f_fsid", }, + {0} +}; + +static PyStructSequence_Desc statvfs_result_desc = { + "statvfs_result", /* name */ + statvfs_result__doc__, /* doc */ + statvfs_result_fields, + 10 +}; + +#if defined(HAVE_WAITID) && !defined(__APPLE__) +PyDoc_STRVAR(waitid_result__doc__, +"waitid_result: Result from waitid.\n\n\ +This object may be accessed either as a tuple of\n\ + (si_pid, si_uid, si_signo, si_status, si_code),\n\ +or via the attributes si_pid, si_uid, and so on.\n\ +\n\ +See os.waitid for more information."); + +static PyStructSequence_Field waitid_result_fields[] = { + {"si_pid", }, + {"si_uid", }, + {"si_signo", }, + {"si_status", }, + {"si_code", }, + {0} +}; + +static PyStructSequence_Desc waitid_result_desc = { + "waitid_result", /* name */ + waitid_result__doc__, /* doc */ + waitid_result_fields, + 5 +}; +#endif +static newfunc structseq_new; + +static PyObject * +statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyStructSequence *result; + int i; + + result = (PyStructSequence*)structseq_new(type, args, kwds); + if (!result) + return NULL; + /* If we have been initialized from a tuple, + st_?time might be set to None. Initialize it + from the int slots. */ + for (i = 7; i <= 9; i++) { + if (result->ob_item[i+3] == Py_None) { + Py_DECREF(Py_None); + result->ob_item[i+3] = Py_NewRef(result->ob_item[i]); + } + } + return (PyObject*)result; +} + +static int +_posix_clear(PyObject *module) +{ + _posixstate *state = get_posix_state(module); + Py_CLEAR(state->billion); + Py_CLEAR(state->DirEntryType); + Py_CLEAR(state->ScandirIteratorType); +#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) + Py_CLEAR(state->SchedParamType); +#endif + Py_CLEAR(state->StatResultType); + Py_CLEAR(state->StatVFSResultType); + Py_CLEAR(state->TerminalSizeType); + Py_CLEAR(state->TimesResultType); + Py_CLEAR(state->UnameResultType); +#if defined(HAVE_WAITID) && !defined(__APPLE__) + Py_CLEAR(state->WaitidResultType); +#endif +#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) + Py_CLEAR(state->struct_rusage); +#endif + Py_CLEAR(state->st_mode); + return 0; +} + +static int +_posix_traverse(PyObject *module, visitproc visit, void *arg) +{ + _posixstate *state = get_posix_state(module); + Py_VISIT(state->billion); + Py_VISIT(state->DirEntryType); + Py_VISIT(state->ScandirIteratorType); +#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) + Py_VISIT(state->SchedParamType); +#endif + Py_VISIT(state->StatResultType); + Py_VISIT(state->StatVFSResultType); + Py_VISIT(state->TerminalSizeType); + Py_VISIT(state->TimesResultType); + Py_VISIT(state->UnameResultType); +#if defined(HAVE_WAITID) && !defined(__APPLE__) + Py_VISIT(state->WaitidResultType); +#endif +#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) + Py_VISIT(state->struct_rusage); +#endif + Py_VISIT(state->st_mode); + return 0; +} + +static void +_posix_free(void *module) +{ + _posix_clear((PyObject *)module); +} + +static void +fill_time(PyObject *module, PyObject *v, int index, time_t sec, unsigned long nsec) +{ + PyObject *s = _PyLong_FromTime_t(sec); + PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec); + PyObject *s_in_ns = NULL; + PyObject *ns_total = NULL; + PyObject *float_s = NULL; + + if (!(s && ns_fractional)) + goto exit; + + s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion); + if (!s_in_ns) + goto exit; + + ns_total = PyNumber_Add(s_in_ns, ns_fractional); + if (!ns_total) + goto exit; + + float_s = PyFloat_FromDouble(sec + 1e-9*nsec); + if (!float_s) { + goto exit; + } + + PyStructSequence_SET_ITEM(v, index, s); + PyStructSequence_SET_ITEM(v, index+3, float_s); + PyStructSequence_SET_ITEM(v, index+6, ns_total); + s = NULL; + float_s = NULL; + ns_total = NULL; +exit: + Py_XDECREF(s); + Py_XDECREF(ns_fractional); + Py_XDECREF(s_in_ns); + Py_XDECREF(ns_total); + Py_XDECREF(float_s); +} + +/* pack a system stat C structure into the Python stat tuple + (used by posix_stat() and posix_fstat()) */ +static PyObject* +_pystat_fromstructstat(PyObject *module, STRUCT_STAT *st) +{ + unsigned long ansec, mnsec, cnsec; + PyObject *StatResultType = get_posix_state(module)->StatResultType; + PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType); + if (v == NULL) + return NULL; + + PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode)); + static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino), + "stat.st_ino is larger than unsigned long long"); + PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLongLong(st->st_ino)); +#ifdef MS_WINDOWS + PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev)); +#else + PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev)); +#endif + PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink)); +#if defined(MS_WINDOWS) + PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0)); + PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0)); +#else + PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid)); + PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid)); +#endif + static_assert(sizeof(long long) >= sizeof(st->st_size), + "stat.st_size is larger than long long"); + PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size)); + +#if defined(HAVE_STAT_TV_NSEC) + ansec = st->st_atim.tv_nsec; + mnsec = st->st_mtim.tv_nsec; + cnsec = st->st_ctim.tv_nsec; +#elif defined(HAVE_STAT_TV_NSEC2) + ansec = st->st_atimespec.tv_nsec; + mnsec = st->st_mtimespec.tv_nsec; + cnsec = st->st_ctimespec.tv_nsec; +#elif defined(HAVE_STAT_NSEC) + ansec = st->st_atime_nsec; + mnsec = st->st_mtime_nsec; + cnsec = st->st_ctime_nsec; +#else + ansec = mnsec = cnsec = 0; +#endif + fill_time(module, v, 7, st->st_atime, ansec); + fill_time(module, v, 8, st->st_mtime, mnsec); + fill_time(module, v, 9, st->st_ctime, cnsec); + +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX, + PyLong_FromLong((long)st->st_blksize)); +#endif +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS + PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX, + PyLong_FromLong((long)st->st_blocks)); +#endif +#ifdef HAVE_STRUCT_STAT_ST_RDEV + PyStructSequence_SET_ITEM(v, ST_RDEV_IDX, + PyLong_FromLong((long)st->st_rdev)); +#endif +#ifdef HAVE_STRUCT_STAT_ST_GEN + PyStructSequence_SET_ITEM(v, ST_GEN_IDX, + PyLong_FromLong((long)st->st_gen)); +#endif +#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME + { + PyObject *val; + unsigned long bsec,bnsec; + bsec = (long)st->st_birthtime; +#ifdef HAVE_STAT_TV_NSEC2 + bnsec = st->st_birthtimespec.tv_nsec; +#else + bnsec = 0; +#endif + val = PyFloat_FromDouble(bsec + 1e-9*bnsec); + PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX, + val); + } +#endif +#ifdef HAVE_STRUCT_STAT_ST_FLAGS + PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX, + PyLong_FromLong((long)st->st_flags)); +#endif +#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES + PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX, + PyLong_FromUnsignedLong(st->st_file_attributes)); +#endif +#ifdef HAVE_STRUCT_STAT_ST_FSTYPE + PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX, + PyUnicode_FromString(st->st_fstype)); +#endif +#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG + PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX, + PyLong_FromUnsignedLong(st->st_reparse_tag)); +#endif + + if (PyErr_Occurred()) { + Py_DECREF(v); + return NULL; + } + + return v; +} + +/* POSIX methods */ + + +static PyObject * +posix_do_stat(PyObject *module, const char *function_name, path_t *path, + int dir_fd, int follow_symlinks) +{ + STRUCT_STAT st; + int result; + +#ifdef HAVE_FSTATAT + int fstatat_unavailable = 0; +#endif + +#if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT) + if (follow_symlinks_specified(function_name, follow_symlinks)) + return NULL; +#endif + + if (path_and_dir_fd_invalid("stat", path, dir_fd) || + dir_fd_and_fd_invalid("stat", dir_fd, path->fd) || + fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + if (path->fd != -1) + result = FSTAT(path->fd, &st); +#ifdef MS_WINDOWS + else if (follow_symlinks) + result = win32_stat(path->wide, &st); + else + result = win32_lstat(path->wide, &st); +#else + else +#if defined(HAVE_LSTAT) + if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) + result = LSTAT(path->narrow, &st); + else +#endif /* HAVE_LSTAT */ +#ifdef HAVE_FSTATAT + if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) { + if (HAVE_FSTATAT_RUNTIME) { + result = fstatat(dir_fd, path->narrow, &st, + follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); + + } else { + fstatat_unavailable = 1; + } + } else +#endif /* HAVE_FSTATAT */ + result = STAT(path->narrow, &st); +#endif /* MS_WINDOWS */ + Py_END_ALLOW_THREADS + +#ifdef HAVE_FSTATAT + if (fstatat_unavailable) { + argument_unavailable_error("stat", "dir_fd"); + return NULL; + } +#endif + + if (result != 0) { + return path_error(path); + } + + return _pystat_fromstructstat(module, &st); +} + +/*[python input] + +for s in """ + +FACCESSAT +FCHMODAT +FCHOWNAT +FSTATAT +LINKAT +MKDIRAT +MKFIFOAT +MKNODAT +OPENAT +READLINKAT +SYMLINKAT +UNLINKAT + +""".strip().split(): + s = s.strip() + print(""" +#ifdef HAVE_{s} + #define {s}_DIR_FD_CONVERTER dir_fd_converter +#else + #define {s}_DIR_FD_CONVERTER dir_fd_unavailable +#endif +""".rstrip().format(s=s)) + +for s in """ + +FCHDIR +FCHMOD +FCHOWN +FDOPENDIR +FEXECVE +FPATHCONF +FSTATVFS +FTRUNCATE + +""".strip().split(): + s = s.strip() + print(""" +#ifdef HAVE_{s} + #define PATH_HAVE_{s} 1 +#else + #define PATH_HAVE_{s} 0 +#endif + +""".rstrip().format(s=s)) +[python start generated code]*/ + +#ifdef HAVE_FACCESSAT + #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#ifdef HAVE_FCHMODAT + #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#ifdef HAVE_FCHOWNAT + #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#ifdef HAVE_FSTATAT + #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#ifdef HAVE_LINKAT + #define LINKAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#ifdef HAVE_MKDIRAT + #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#ifdef HAVE_MKFIFOAT + #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#ifdef HAVE_MKNODAT + #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#ifdef HAVE_OPENAT + #define OPENAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#ifdef HAVE_READLINKAT + #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#ifdef HAVE_SYMLINKAT + #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#ifdef HAVE_UNLINKAT + #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#ifdef HAVE_FCHDIR + #define PATH_HAVE_FCHDIR 1 +#else + #define PATH_HAVE_FCHDIR 0 +#endif + +#ifdef HAVE_FCHMOD + #define PATH_HAVE_FCHMOD 1 +#else + #define PATH_HAVE_FCHMOD 0 +#endif + +#ifdef HAVE_FCHOWN + #define PATH_HAVE_FCHOWN 1 +#else + #define PATH_HAVE_FCHOWN 0 +#endif + +#ifdef HAVE_FDOPENDIR + #define PATH_HAVE_FDOPENDIR 1 +#else + #define PATH_HAVE_FDOPENDIR 0 +#endif + +#ifdef HAVE_FEXECVE + #define PATH_HAVE_FEXECVE 1 +#else + #define PATH_HAVE_FEXECVE 0 +#endif + +#ifdef HAVE_FPATHCONF + #define PATH_HAVE_FPATHCONF 1 +#else + #define PATH_HAVE_FPATHCONF 0 +#endif + +#ifdef HAVE_FSTATVFS + #define PATH_HAVE_FSTATVFS 1 +#else + #define PATH_HAVE_FSTATVFS 0 +#endif + +#ifdef HAVE_FTRUNCATE + #define PATH_HAVE_FTRUNCATE 1 +#else + #define PATH_HAVE_FTRUNCATE 0 +#endif +/*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/ + +#ifdef MS_WINDOWS + #undef PATH_HAVE_FTRUNCATE + #define PATH_HAVE_FTRUNCATE 1 +#endif + +/*[python input] + +class path_t_converter(CConverter): + + type = "path_t" + impl_by_reference = True + parse_by_reference = True + + converter = 'path_converter' + + def converter_init(self, *, allow_fd=False, nullable=False): + # right now path_t doesn't support default values. + # to support a default value, you'll need to override initialize(). + if self.default not in (unspecified, None): + fail("Can't specify a default to the path_t converter!") + + if self.c_default not in (None, 'Py_None'): + raise RuntimeError("Can't specify a c_default to the path_t converter!") + + self.nullable = nullable + self.allow_fd = allow_fd + + def pre_render(self): + def strify(value): + if isinstance(value, str): + return value + return str(int(bool(value))) + + # add self.py_name here when merging with posixmodule conversion + self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format( + self.function.name, + self.name, + strify(self.nullable), + strify(self.allow_fd), + ) + + def cleanup(self): + return "path_cleanup(&" + self.name + ");\n" + + +class dir_fd_converter(CConverter): + type = 'int' + + def converter_init(self, requires=None): + if self.default in (unspecified, None): + self.c_default = 'DEFAULT_DIR_FD' + if isinstance(requires, str): + self.converter = requires.upper() + '_DIR_FD_CONVERTER' + else: + self.converter = 'dir_fd_converter' + +class uid_t_converter(CConverter): + type = "uid_t" + converter = '_Py_Uid_Converter' + +class gid_t_converter(CConverter): + type = "gid_t" + converter = '_Py_Gid_Converter' + +class dev_t_converter(CConverter): + type = 'dev_t' + converter = '_Py_Dev_Converter' + +class dev_t_return_converter(unsigned_long_return_converter): + type = 'dev_t' + conversion_fn = '_PyLong_FromDev' + unsigned_cast = '(dev_t)' + +class FSConverter_converter(CConverter): + type = 'PyObject *' + converter = 'PyUnicode_FSConverter' + def converter_init(self): + if self.default is not unspecified: + fail("FSConverter_converter does not support default values") + self.c_default = 'NULL' + + def cleanup(self): + return "Py_XDECREF(" + self.name + ");\n" + +class pid_t_converter(CConverter): + type = 'pid_t' + format_unit = '" _Py_PARSE_PID "' + +class idtype_t_converter(int_converter): + type = 'idtype_t' + +class id_t_converter(CConverter): + type = 'id_t' + format_unit = '" _Py_PARSE_PID "' + +class intptr_t_converter(CConverter): + type = 'intptr_t' + format_unit = '" _Py_PARSE_INTPTR "' + +class Py_off_t_converter(CConverter): + type = 'Py_off_t' + converter = 'Py_off_t_converter' + +class Py_off_t_return_converter(long_return_converter): + type = 'Py_off_t' + conversion_fn = 'PyLong_FromPy_off_t' + +class path_confname_converter(CConverter): + type="int" + converter="conv_path_confname" + +class confstr_confname_converter(path_confname_converter): + converter='conv_confstr_confname' + +class sysconf_confname_converter(path_confname_converter): + converter="conv_sysconf_confname" + +[python start generated code]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=3338733161aa7879]*/ + +/*[clinic input] + +os.stat + + path : path_t(allow_fd=True) + Path to be examined; can be string, bytes, a path-like object or + open-file-descriptor int. + + * + + dir_fd : dir_fd(requires='fstatat') = None + If not None, it should be a file descriptor open to a directory, + and path should be a relative string; path will then be relative to + that directory. + + follow_symlinks: bool = True + If False, and the last element of the path is a symbolic link, + stat will examine the symbolic link itself instead of the file + the link points to. + +Perform a stat system call on the given path. + +dir_fd and follow_symlinks may not be implemented + on your platform. If they are unavailable, using them will raise a + NotImplementedError. + +It's an error to use dir_fd or follow_symlinks when specifying path as + an open file descriptor. + +[clinic start generated code]*/ + +static PyObject * +os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks) +/*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/ +{ + return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks); +} + + +/*[clinic input] +os.lstat + + path : path_t + + * + + dir_fd : dir_fd(requires='fstatat') = None + +Perform a stat system call on the given path, without following symbolic links. + +Like stat(), but do not follow symbolic links. +Equivalent to stat(path, follow_symlinks=False). +[clinic start generated code]*/ + +static PyObject * +os_lstat_impl(PyObject *module, path_t *path, int dir_fd) +/*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/ +{ + int follow_symlinks = 0; + return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks); +} + + +/*[clinic input] +os.access -> bool + + path: path_t + Path to be tested; can be string, bytes, or a path-like object. + + mode: int + Operating-system mode bitfield. Can be F_OK to test existence, + or the inclusive-OR of R_OK, W_OK, and X_OK. + + * + + dir_fd : dir_fd(requires='faccessat') = None + If not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that + directory. + + effective_ids: bool = False + If True, access will use the effective uid/gid instead of + the real uid/gid. + + follow_symlinks: bool = True + If False, and the last element of the path is a symbolic link, + access will examine the symbolic link itself instead of the file + the link points to. + +Use the real uid/gid to test for access to a path. + +{parameters} +dir_fd, effective_ids, and follow_symlinks may not be implemented + on your platform. If they are unavailable, using them will raise a + NotImplementedError. + +Note that most operations will use the effective uid/gid, therefore this + routine can be used in a suid/sgid environment to test if the invoking user + has the specified access to the path. + +[clinic start generated code]*/ + +static int +os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd, + int effective_ids, int follow_symlinks) +/*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/ +{ + int return_value; + +#ifdef MS_WINDOWS + DWORD attr; +#else + int result; +#endif + +#ifdef HAVE_FACCESSAT + int faccessat_unavailable = 0; +#endif + +#ifndef HAVE_FACCESSAT + if (follow_symlinks_specified("access", follow_symlinks)) + return -1; + + if (effective_ids) { + argument_unavailable_error("access", "effective_ids"); + return -1; + } +#endif + +#ifdef MS_WINDOWS + Py_BEGIN_ALLOW_THREADS + attr = GetFileAttributesW(path->wide); + Py_END_ALLOW_THREADS + + /* + * Access is possible if + * * we didn't get a -1, and + * * write access wasn't requested, + * * or the file isn't read-only, + * * or it's a directory. + * (Directories cannot be read-only on Windows.) + */ + return_value = (attr != INVALID_FILE_ATTRIBUTES) && + (!(mode & 2) || + !(attr & FILE_ATTRIBUTE_READONLY) || + (attr & FILE_ATTRIBUTE_DIRECTORY)); +#else + + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_FACCESSAT + if ((dir_fd != DEFAULT_DIR_FD) || + effective_ids || + !follow_symlinks) { + + if (HAVE_FACCESSAT_RUNTIME) { + int flags = 0; + if (!follow_symlinks) + flags |= AT_SYMLINK_NOFOLLOW; + if (effective_ids) + flags |= AT_EACCESS; + result = faccessat(dir_fd, path->narrow, mode, flags); + } else { + faccessat_unavailable = 1; + } + } + else +#endif + result = access(path->narrow, mode); + Py_END_ALLOW_THREADS + +#ifdef HAVE_FACCESSAT + if (faccessat_unavailable) { + if (dir_fd != DEFAULT_DIR_FD) { + argument_unavailable_error("access", "dir_fd"); + return -1; + } + if (follow_symlinks_specified("access", follow_symlinks)) + return -1; + + if (effective_ids) { + argument_unavailable_error("access", "effective_ids"); + return -1; + } + /* should be unreachable */ + return -1; + } +#endif + return_value = !result; +#endif + + return return_value; +} + +#ifndef F_OK +#define F_OK 0 +#endif +#ifndef R_OK +#define R_OK 4 +#endif +#ifndef W_OK +#define W_OK 2 +#endif +#ifndef X_OK +#define X_OK 1 +#endif + + +#ifdef HAVE_TTYNAME +/*[clinic input] +os.ttyname + + fd: int + Integer file descriptor handle. + + / + +Return the name of the terminal device connected to 'fd'. +[clinic start generated code]*/ + +static PyObject * +os_ttyname_impl(PyObject *module, int fd) +/*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/ +{ + + long size = sysconf(_SC_TTY_NAME_MAX); + if (size == -1) { + return posix_error(); + } + char *buffer = (char *)PyMem_RawMalloc(size); + if (buffer == NULL) { + return PyErr_NoMemory(); + } + int ret = ttyname_r(fd, buffer, size); + if (ret != 0) { + PyMem_RawFree(buffer); + errno = ret; + return posix_error(); + } + PyObject *res = PyUnicode_DecodeFSDefault(buffer); + PyMem_RawFree(buffer); + return res; +} +#endif + +#ifdef HAVE_CTERMID +/*[clinic input] +os.ctermid + +Return the name of the controlling terminal for this process. +[clinic start generated code]*/ + +static PyObject * +os_ctermid_impl(PyObject *module) +/*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/ +{ + char *ret; + char buffer[L_ctermid]; + +#ifdef USE_CTERMID_R + ret = ctermid_r(buffer); +#else + ret = ctermid(buffer); +#endif + if (ret == NULL) + return posix_error(); + return PyUnicode_DecodeFSDefault(buffer); +} +#endif /* HAVE_CTERMID */ + + +/*[clinic input] +os.chdir + + path: path_t(allow_fd='PATH_HAVE_FCHDIR') + +Change the current working directory to the specified path. + +path may always be specified as a string. +On some platforms, path may also be specified as an open file descriptor. + If this functionality is unavailable, using it raises an exception. +[clinic start generated code]*/ + +static PyObject * +os_chdir_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/ +{ + int result; + + if (PySys_Audit("os.chdir", "(O)", path->object) < 0) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS +#ifdef MS_WINDOWS + /* on unix, success = 0, on windows, success = !0 */ + result = !win32_wchdir(path->wide); +#else +#ifdef HAVE_FCHDIR + if (path->fd != -1) + result = fchdir(path->fd); + else +#endif + result = chdir(path->narrow); +#endif + Py_END_ALLOW_THREADS + + if (result) { + return path_error(path); + } + + Py_RETURN_NONE; +} + + +#ifdef HAVE_FCHDIR +/*[clinic input] +os.fchdir + + fd: fildes + +Change to the directory of the given file descriptor. + +fd must be opened on a directory, not a file. +Equivalent to os.chdir(fd). + +[clinic start generated code]*/ + +static PyObject * +os_fchdir_impl(PyObject *module, int fd) +/*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/ +{ + if (PySys_Audit("os.chdir", "(i)", fd) < 0) { + return NULL; + } + return posix_fildes_fd(fd, fchdir); +} +#endif /* HAVE_FCHDIR */ + + +/*[clinic input] +os.chmod + + path: path_t(allow_fd='PATH_HAVE_FCHMOD') + Path to be modified. May always be specified as a str, bytes, or a path-like object. + On some platforms, path may also be specified as an open file descriptor. + If this functionality is unavailable, using it raises an exception. + + mode: int + Operating-system mode bitfield. + + * + + dir_fd : dir_fd(requires='fchmodat') = None + If not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that + directory. + + follow_symlinks: bool = True + If False, and the last element of the path is a symbolic link, + chmod will modify the symbolic link itself instead of the file + the link points to. + +Change the access permissions of a file. + +It is an error to use dir_fd or follow_symlinks when specifying path as + an open file descriptor. +dir_fd and follow_symlinks may not be implemented on your platform. + If they are unavailable, using them will raise a NotImplementedError. + +[clinic start generated code]*/ + +static PyObject * +os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, + int follow_symlinks) +/*[clinic end generated code: output=5cf6a94915cc7bff input=989081551c00293b]*/ +{ + int result; + +#ifdef MS_WINDOWS + DWORD attr; +#endif + +#ifdef HAVE_FCHMODAT + int fchmodat_nofollow_unsupported = 0; + int fchmodat_unsupported = 0; +#endif + +#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD)) + if (follow_symlinks_specified("chmod", follow_symlinks)) + return NULL; +#endif + + if (PySys_Audit("os.chmod", "Oii", path->object, mode, + dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { + return NULL; + } + +#ifdef MS_WINDOWS + Py_BEGIN_ALLOW_THREADS + attr = GetFileAttributesW(path->wide); + if (attr == INVALID_FILE_ATTRIBUTES) + result = 0; + else { + if (mode & _S_IWRITE) + attr &= ~FILE_ATTRIBUTE_READONLY; + else + attr |= FILE_ATTRIBUTE_READONLY; + result = SetFileAttributesW(path->wide, attr); + } + Py_END_ALLOW_THREADS + + if (!result) { + return path_error(path); + } +#else /* MS_WINDOWS */ + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_FCHMOD + if (path->fd != -1) + result = fchmod(path->fd, mode); + else +#endif /* HAVE_CHMOD */ +#ifdef HAVE_LCHMOD + if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) + result = lchmod(path->narrow, mode); + else +#endif /* HAVE_LCHMOD */ +#ifdef HAVE_FCHMODAT + if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) { + if (HAVE_FCHMODAT_RUNTIME) { + /* + * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW! + * The documentation specifically shows how to use it, + * and then says it isn't implemented yet. + * (true on linux with glibc 2.15, and openindiana 3.x) + * + * Once it is supported, os.chmod will automatically + * support dir_fd and follow_symlinks=False. (Hopefully.) + * Until then, we need to be careful what exception we raise. + */ + result = fchmodat(dir_fd, path->narrow, mode, + follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); + /* + * But wait! We can't throw the exception without allowing threads, + * and we can't do that in this nested scope. (Macro trickery, sigh.) + */ + fchmodat_nofollow_unsupported = + result && + ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) && + !follow_symlinks; + } else { + fchmodat_unsupported = 1; + fchmodat_nofollow_unsupported = 1; + + result = -1; + } + } + else +#endif /* HAVE_FHCMODAT */ + { +#ifdef HAVE_CHMOD + result = chmod(path->narrow, mode); +#elif defined(__wasi__) + // WASI SDK 15.0 does not support chmod. + // Ignore missing syscall for now. + result = 0; +#else + result = -1; + errno = ENOSYS; +#endif + } + Py_END_ALLOW_THREADS + + if (result) { +#ifdef HAVE_FCHMODAT + if (fchmodat_unsupported) { + if (dir_fd != DEFAULT_DIR_FD) { + argument_unavailable_error("chmod", "dir_fd"); + return NULL; + } + } + + if (fchmodat_nofollow_unsupported) { + if (dir_fd != DEFAULT_DIR_FD) + dir_fd_and_follow_symlinks_invalid("chmod", + dir_fd, follow_symlinks); + else + follow_symlinks_specified("chmod", follow_symlinks); + return NULL; + } + else +#endif /* HAVE_FCHMODAT */ + return path_error(path); + } +#endif /* MS_WINDOWS */ + + Py_RETURN_NONE; +} + + +#ifdef HAVE_FCHMOD +/*[clinic input] +os.fchmod + + fd: int + mode: int + +Change the access permissions of the file given by file descriptor fd. + +Equivalent to os.chmod(fd, mode). +[clinic start generated code]*/ + +static PyObject * +os_fchmod_impl(PyObject *module, int fd, int mode) +/*[clinic end generated code: output=afd9bc05b4e426b3 input=8ab11975ca01ee5b]*/ +{ + int res; + int async_err = 0; + + if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) { + return NULL; + } + + do { + Py_BEGIN_ALLOW_THREADS + res = fchmod(fd, mode); + Py_END_ALLOW_THREADS + } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (res != 0) + return (!async_err) ? posix_error() : NULL; + + Py_RETURN_NONE; +} +#endif /* HAVE_FCHMOD */ + + +#ifdef HAVE_LCHMOD +/*[clinic input] +os.lchmod + + path: path_t + mode: int + +Change the access permissions of a file, without following symbolic links. + +If path is a symlink, this affects the link itself rather than the target. +Equivalent to chmod(path, mode, follow_symlinks=False)." +[clinic start generated code]*/ + +static PyObject * +os_lchmod_impl(PyObject *module, path_t *path, int mode) +/*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/ +{ + int res; + if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) { + return NULL; + } + Py_BEGIN_ALLOW_THREADS + res = lchmod(path->narrow, mode); + Py_END_ALLOW_THREADS + if (res < 0) { + path_error(path); + return NULL; + } + Py_RETURN_NONE; +} +#endif /* HAVE_LCHMOD */ + + +#ifdef HAVE_CHFLAGS +/*[clinic input] +os.chflags + + path: path_t + flags: unsigned_long(bitwise=True) + follow_symlinks: bool=True + +Set file flags. + +If follow_symlinks is False, and the last element of the path is a symbolic + link, chflags will change flags on the symbolic link itself instead of the + file the link points to. +follow_symlinks may not be implemented on your platform. If it is +unavailable, using it will raise a NotImplementedError. + +[clinic start generated code]*/ + +static PyObject * +os_chflags_impl(PyObject *module, path_t *path, unsigned long flags, + int follow_symlinks) +/*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/ +{ + int result; + +#ifndef HAVE_LCHFLAGS + if (follow_symlinks_specified("chflags", follow_symlinks)) + return NULL; +#endif + + if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_LCHFLAGS + if (!follow_symlinks) + result = lchflags(path->narrow, flags); + else +#endif + result = chflags(path->narrow, flags); + Py_END_ALLOW_THREADS + + if (result) + return path_error(path); + + Py_RETURN_NONE; +} +#endif /* HAVE_CHFLAGS */ + + +#ifdef HAVE_LCHFLAGS +/*[clinic input] +os.lchflags + + path: path_t + flags: unsigned_long(bitwise=True) + +Set file flags. + +This function will not follow symbolic links. +Equivalent to chflags(path, flags, follow_symlinks=False). +[clinic start generated code]*/ + +static PyObject * +os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags) +/*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/ +{ + int res; + if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) { + return NULL; + } + Py_BEGIN_ALLOW_THREADS + res = lchflags(path->narrow, flags); + Py_END_ALLOW_THREADS + if (res < 0) { + return path_error(path); + } + Py_RETURN_NONE; +} +#endif /* HAVE_LCHFLAGS */ + + +#ifdef HAVE_CHROOT +/*[clinic input] +os.chroot + path: path_t + +Change root directory to path. + +[clinic start generated code]*/ + +static PyObject * +os_chroot_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/ +{ + int res; + Py_BEGIN_ALLOW_THREADS + res = chroot(path->narrow); + Py_END_ALLOW_THREADS + if (res < 0) + return path_error(path); + Py_RETURN_NONE; +} +#endif /* HAVE_CHROOT */ + + +#ifdef HAVE_FSYNC +/*[clinic input] +os.fsync + + fd: fildes + +Force write of fd to disk. +[clinic start generated code]*/ + +static PyObject * +os_fsync_impl(PyObject *module, int fd) +/*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/ +{ + return posix_fildes_fd(fd, fsync); +} +#endif /* HAVE_FSYNC */ + + +#ifdef HAVE_SYNC +/*[clinic input] +os.sync + +Force write of everything to disk. +[clinic start generated code]*/ + +static PyObject * +os_sync_impl(PyObject *module) +/*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/ +{ + Py_BEGIN_ALLOW_THREADS + sync(); + Py_END_ALLOW_THREADS + Py_RETURN_NONE; +} +#endif /* HAVE_SYNC */ + + +#ifdef HAVE_FDATASYNC +#ifdef __hpux +extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */ +#endif + +/*[clinic input] +os.fdatasync + + fd: fildes + +Force write of fd to disk without forcing update of metadata. +[clinic start generated code]*/ + +static PyObject * +os_fdatasync_impl(PyObject *module, int fd) +/*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/ +{ + return posix_fildes_fd(fd, fdatasync); +} +#endif /* HAVE_FDATASYNC */ + + +#ifdef HAVE_CHOWN +/*[clinic input] +os.chown + + path : path_t(allow_fd='PATH_HAVE_FCHOWN') + Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int. + + uid: uid_t + + gid: gid_t + + * + + dir_fd : dir_fd(requires='fchownat') = None + If not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that + directory. + + follow_symlinks: bool = True + If False, and the last element of the path is a symbolic link, + stat will examine the symbolic link itself instead of the file + the link points to. + +Change the owner and group id of path to the numeric uid and gid.\ + +path may always be specified as a string. +On some platforms, path may also be specified as an open file descriptor. + If this functionality is unavailable, using it raises an exception. +If dir_fd is not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that directory. +If follow_symlinks is False, and the last element of the path is a symbolic + link, chown will modify the symbolic link itself instead of the file the + link points to. +It is an error to use dir_fd or follow_symlinks when specifying path as + an open file descriptor. +dir_fd and follow_symlinks may not be implemented on your platform. + If they are unavailable, using them will raise a NotImplementedError. + +[clinic start generated code]*/ + +static PyObject * +os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid, + int dir_fd, int follow_symlinks) +/*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/ +{ + int result; + +#if defined(HAVE_FCHOWNAT) + int fchownat_unsupported = 0; +#endif + +#if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT)) + if (follow_symlinks_specified("chown", follow_symlinks)) + return NULL; +#endif + if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) || + fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks)) + return NULL; + + if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, + dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_FCHOWN + if (path->fd != -1) + result = fchown(path->fd, uid, gid); + else +#endif +#ifdef HAVE_LCHOWN + if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) + result = lchown(path->narrow, uid, gid); + else +#endif +#ifdef HAVE_FCHOWNAT + if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) { + if (HAVE_FCHOWNAT_RUNTIME) { + result = fchownat(dir_fd, path->narrow, uid, gid, + follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); + } else { + fchownat_unsupported = 1; + } + } else +#endif + result = chown(path->narrow, uid, gid); + Py_END_ALLOW_THREADS + +#ifdef HAVE_FCHOWNAT + if (fchownat_unsupported) { + /* This would be incorrect if the current platform + * doesn't support lchown. + */ + argument_unavailable_error(NULL, "dir_fd"); + return NULL; + } +#endif + + if (result) + return path_error(path); + + Py_RETURN_NONE; +} +#endif /* HAVE_CHOWN */ + + +#ifdef HAVE_FCHOWN +/*[clinic input] +os.fchown + + fd: int + uid: uid_t + gid: gid_t + +Change the owner and group id of the file specified by file descriptor. + +Equivalent to os.chown(fd, uid, gid). + +[clinic start generated code]*/ + +static PyObject * +os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid) +/*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/ +{ + int res; + int async_err = 0; + + if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) { + return NULL; + } + + do { + Py_BEGIN_ALLOW_THREADS + res = fchown(fd, uid, gid); + Py_END_ALLOW_THREADS + } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (res != 0) + return (!async_err) ? posix_error() : NULL; + + Py_RETURN_NONE; +} +#endif /* HAVE_FCHOWN */ + + +#ifdef HAVE_LCHOWN +/*[clinic input] +os.lchown + + path : path_t + uid: uid_t + gid: gid_t + +Change the owner and group id of path to the numeric uid and gid. + +This function will not follow symbolic links. +Equivalent to os.chown(path, uid, gid, follow_symlinks=False). +[clinic start generated code]*/ + +static PyObject * +os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid) +/*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/ +{ + int res; + if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) { + return NULL; + } + Py_BEGIN_ALLOW_THREADS + res = lchown(path->narrow, uid, gid); + Py_END_ALLOW_THREADS + if (res < 0) { + return path_error(path); + } + Py_RETURN_NONE; +} +#endif /* HAVE_LCHOWN */ + + +static PyObject * +posix_getcwd(int use_bytes) +{ +#ifdef MS_WINDOWS + wchar_t wbuf[MAXPATHLEN]; + wchar_t *wbuf2 = wbuf; + DWORD len; + + Py_BEGIN_ALLOW_THREADS + len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf); + /* If the buffer is large enough, len does not include the + terminating \0. If the buffer is too small, len includes + the space needed for the terminator. */ + if (len >= Py_ARRAY_LENGTH(wbuf)) { + if (len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) { + wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t)); + } + else { + wbuf2 = NULL; + } + if (wbuf2) { + len = GetCurrentDirectoryW(len, wbuf2); + } + } + Py_END_ALLOW_THREADS + + if (!wbuf2) { + PyErr_NoMemory(); + return NULL; + } + if (!len) { + if (wbuf2 != wbuf) + PyMem_RawFree(wbuf2); + return PyErr_SetFromWindowsErr(0); + } + + PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len); + if (wbuf2 != wbuf) { + PyMem_RawFree(wbuf2); + } + + if (use_bytes) { + if (resobj == NULL) { + return NULL; + } + Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj)); + } + + return resobj; +#else + const size_t chunk = 1024; + + char *buf = NULL; + char *cwd = NULL; + size_t buflen = 0; + + Py_BEGIN_ALLOW_THREADS + do { + char *newbuf; + if (buflen <= PY_SSIZE_T_MAX - chunk) { + buflen += chunk; + newbuf = PyMem_RawRealloc(buf, buflen); + } + else { + newbuf = NULL; + } + if (newbuf == NULL) { + PyMem_RawFree(buf); + buf = NULL; + break; + } + buf = newbuf; + + cwd = getcwd(buf, buflen); + } while (cwd == NULL && errno == ERANGE); + Py_END_ALLOW_THREADS + + if (buf == NULL) { + return PyErr_NoMemory(); + } + if (cwd == NULL) { + PyMem_RawFree(buf); + return posix_error(); + } + + PyObject *obj; + if (use_bytes) { + obj = PyBytes_FromStringAndSize(buf, strlen(buf)); + } + else { + obj = PyUnicode_DecodeFSDefault(buf); + } + PyMem_RawFree(buf); + + return obj; +#endif /* !MS_WINDOWS */ +} + + +/*[clinic input] +os.getcwd + +Return a unicode string representing the current working directory. +[clinic start generated code]*/ + +static PyObject * +os_getcwd_impl(PyObject *module) +/*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/ +{ + return posix_getcwd(0); +} + + +/*[clinic input] +os.getcwdb + +Return a bytes string representing the current working directory. +[clinic start generated code]*/ + +static PyObject * +os_getcwdb_impl(PyObject *module) +/*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/ +{ + return posix_getcwd(1); +} + + +#if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS)) +#define HAVE_LINK 1 +#endif + +#ifdef HAVE_LINK +/*[clinic input] + +os.link + + src : path_t + dst : path_t + * + src_dir_fd : dir_fd = None + dst_dir_fd : dir_fd = None + follow_symlinks: bool = True + +Create a hard link to a file. + +If either src_dir_fd or dst_dir_fd is not None, it should be a file + descriptor open to a directory, and the respective path string (src or dst) + should be relative; the path will then be relative to that directory. +If follow_symlinks is False, and the last element of src is a symbolic + link, link will create a link to the symbolic link itself instead of the + file the link points to. +src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your + platform. If they are unavailable, using them will raise a + NotImplementedError. +[clinic start generated code]*/ + +static PyObject * +os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, + int dst_dir_fd, int follow_symlinks) +/*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/ +{ +#ifdef MS_WINDOWS + BOOL result = FALSE; +#else + int result; +#endif +#if defined(HAVE_LINKAT) + int linkat_unavailable = 0; +#endif + +#ifndef HAVE_LINKAT + if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) { + argument_unavailable_error("link", "src_dir_fd and dst_dir_fd"); + return NULL; + } +#endif + +#ifndef MS_WINDOWS + if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { + PyErr_SetString(PyExc_NotImplementedError, + "link: src and dst must be the same type"); + return NULL; + } +#endif + + if (PySys_Audit("os.link", "OOii", src->object, dst->object, + src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd, + dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) { + return NULL; + } + +#ifdef MS_WINDOWS + Py_BEGIN_ALLOW_THREADS + result = CreateHardLinkW(dst->wide, src->wide, NULL); + Py_END_ALLOW_THREADS + + if (!result) + return path_error2(src, dst); +#else + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_LINKAT + if ((src_dir_fd != DEFAULT_DIR_FD) || + (dst_dir_fd != DEFAULT_DIR_FD) || + (!follow_symlinks)) { + + if (HAVE_LINKAT_RUNTIME) { + + result = linkat(src_dir_fd, src->narrow, + dst_dir_fd, dst->narrow, + follow_symlinks ? AT_SYMLINK_FOLLOW : 0); + + } +#ifdef __APPLE__ + else { + if (src_dir_fd == DEFAULT_DIR_FD && dst_dir_fd == DEFAULT_DIR_FD) { + /* See issue 41355: This matches the behaviour of !HAVE_LINKAT */ + result = link(src->narrow, dst->narrow); + } else { + linkat_unavailable = 1; + } + } +#endif + } + else +#endif /* HAVE_LINKAT */ + result = link(src->narrow, dst->narrow); + Py_END_ALLOW_THREADS + +#ifdef HAVE_LINKAT + if (linkat_unavailable) { + /* Either or both dir_fd arguments were specified */ + if (src_dir_fd != DEFAULT_DIR_FD) { + argument_unavailable_error("link", "src_dir_fd"); + } else { + argument_unavailable_error("link", "dst_dir_fd"); + } + return NULL; + } +#endif + + if (result) + return path_error2(src, dst); +#endif /* MS_WINDOWS */ + + Py_RETURN_NONE; +} +#endif + + +#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR) +static PyObject * +_listdir_windows_no_opendir(path_t *path, PyObject *list) +{ + PyObject *v; + HANDLE hFindFile = INVALID_HANDLE_VALUE; + BOOL result; + wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */ + /* only claim to have space for MAX_PATH */ + Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4; + wchar_t *wnamebuf = NULL; + + WIN32_FIND_DATAW wFileData; + const wchar_t *po_wchars; + + if (!path->wide) { /* Default arg: "." */ + po_wchars = L"."; + len = 1; + } else { + po_wchars = path->wide; + len = wcslen(path->wide); + } + /* The +5 is so we can append "\\*.*\0" */ + wnamebuf = PyMem_New(wchar_t, len + 5); + if (!wnamebuf) { + PyErr_NoMemory(); + goto exit; + } + wcscpy(wnamebuf, po_wchars); + if (len > 0) { + wchar_t wch = wnamebuf[len-1]; + if (wch != SEP && wch != ALTSEP && wch != L':') + wnamebuf[len++] = SEP; + wcscpy(wnamebuf + len, L"*.*"); + } + if ((list = PyList_New(0)) == NULL) { + goto exit; + } + Py_BEGIN_ALLOW_THREADS + hFindFile = FindFirstFileW(wnamebuf, &wFileData); + Py_END_ALLOW_THREADS + if (hFindFile == INVALID_HANDLE_VALUE) { + int error = GetLastError(); + if (error == ERROR_FILE_NOT_FOUND) + goto exit; + Py_DECREF(list); + list = path_error(path); + goto exit; + } + do { + /* Skip over . and .. */ + if (wcscmp(wFileData.cFileName, L".") != 0 && + wcscmp(wFileData.cFileName, L"..") != 0) { + v = PyUnicode_FromWideChar(wFileData.cFileName, + wcslen(wFileData.cFileName)); + if (path->narrow && v) { + Py_SETREF(v, PyUnicode_EncodeFSDefault(v)); + } + if (v == NULL) { + Py_DECREF(list); + list = NULL; + break; + } + if (PyList_Append(list, v) != 0) { + Py_DECREF(v); + Py_DECREF(list); + list = NULL; + break; + } + Py_DECREF(v); + } + Py_BEGIN_ALLOW_THREADS + result = FindNextFileW(hFindFile, &wFileData); + Py_END_ALLOW_THREADS + /* FindNextFile sets error to ERROR_NO_MORE_FILES if + it got to the end of the directory. */ + if (!result && GetLastError() != ERROR_NO_MORE_FILES) { + Py_DECREF(list); + list = path_error(path); + goto exit; + } + } while (result == TRUE); + +exit: + if (hFindFile != INVALID_HANDLE_VALUE) { + if (FindClose(hFindFile) == FALSE) { + if (list != NULL) { + Py_DECREF(list); + list = path_error(path); + } + } + } + PyMem_Free(wnamebuf); + + return list; +} /* end of _listdir_windows_no_opendir */ + +#else /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */ + +static PyObject * +_posix_listdir(path_t *path, PyObject *list) +{ + PyObject *v; + DIR *dirp = NULL; + struct dirent *ep; + int return_str; /* if false, return bytes */ +#ifdef HAVE_FDOPENDIR + int fd = -1; +#endif + + errno = 0; +#ifdef HAVE_FDOPENDIR + if (path->fd != -1) { + if (HAVE_FDOPENDIR_RUNTIME) { + /* closedir() closes the FD, so we duplicate it */ + fd = _Py_dup(path->fd); + if (fd == -1) + return NULL; + + return_str = 1; + + Py_BEGIN_ALLOW_THREADS + dirp = fdopendir(fd); + Py_END_ALLOW_THREADS + } else { + PyErr_SetString(PyExc_TypeError, + "listdir: path should be string, bytes, os.PathLike or None, not int"); + return NULL; + } + } + else +#endif + { + const char *name; + if (path->narrow) { + name = path->narrow; + /* only return bytes if they specified a bytes object */ + return_str = !PyBytes_Check(path->object); + } + else { + name = "."; + return_str = 1; + } + + Py_BEGIN_ALLOW_THREADS + dirp = opendir(name); + Py_END_ALLOW_THREADS + } + + if (dirp == NULL) { + list = path_error(path); +#ifdef HAVE_FDOPENDIR + if (fd != -1) { + Py_BEGIN_ALLOW_THREADS + close(fd); + Py_END_ALLOW_THREADS + } +#endif + goto exit; + } + if ((list = PyList_New(0)) == NULL) { + goto exit; + } + for (;;) { + errno = 0; + Py_BEGIN_ALLOW_THREADS + ep = readdir(dirp); + Py_END_ALLOW_THREADS + if (ep == NULL) { + if (errno == 0) { + break; + } else { + Py_DECREF(list); + list = path_error(path); + goto exit; + } + } + if (ep->d_name[0] == '.' && + (NAMLEN(ep) == 1 || + (ep->d_name[1] == '.' && NAMLEN(ep) == 2))) + continue; + if (return_str) + v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep)); + else + v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep)); + if (v == NULL) { + Py_CLEAR(list); + break; + } + if (PyList_Append(list, v) != 0) { + Py_DECREF(v); + Py_CLEAR(list); + break; + } + Py_DECREF(v); + } + +exit: + if (dirp != NULL) { + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_FDOPENDIR + if (fd > -1) + rewinddir(dirp); +#endif + closedir(dirp); + Py_END_ALLOW_THREADS + } + + return list; +} /* end of _posix_listdir */ +#endif /* which OS */ + + +/*[clinic input] +os.listdir + + path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None + +Return a list containing the names of the files in the directory. + +path can be specified as either str, bytes, or a path-like object. If path is bytes, + the filenames returned will also be bytes; in all other circumstances + the filenames returned will be str. +If path is None, uses the path='.'. +On some platforms, path may also be specified as an open file descriptor;\ + the file descriptor must refer to a directory. + If this functionality is unavailable, using it raises NotImplementedError. + +The list is in arbitrary order. It does not include the special +entries '.' and '..' even if they are present in the directory. + + +[clinic start generated code]*/ + +static PyObject * +os_listdir_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/ +{ + if (PySys_Audit("os.listdir", "O", + path->object ? path->object : Py_None) < 0) { + return NULL; + } +#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR) + return _listdir_windows_no_opendir(path, NULL); +#else + return _posix_listdir(path, NULL); +#endif +} + +#ifdef MS_WINDOWS +int +_PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p) +{ + wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf; + DWORD result; + + result = GetFullPathNameW(path, + Py_ARRAY_LENGTH(woutbuf), woutbuf, + NULL); + if (!result) { + return -1; + } + + if (result >= Py_ARRAY_LENGTH(woutbuf)) { + if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) { + woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t)); + } + else { + woutbufp = NULL; + } + if (!woutbufp) { + *abspath_p = NULL; + return 0; + } + + result = GetFullPathNameW(path, result, woutbufp, NULL); + if (!result) { + PyMem_RawFree(woutbufp); + return -1; + } + } + + if (woutbufp != woutbuf) { + *abspath_p = woutbufp; + return 0; + } + + *abspath_p = _PyMem_RawWcsdup(woutbufp); + return 0; +} + + +/* A helper function for abspath on win32 */ +/*[clinic input] +os._getfullpathname + + path: path_t + / + +[clinic start generated code]*/ + +static PyObject * +os__getfullpathname_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/ +{ + wchar_t *abspath; + + if (_PyOS_getfullpathname(path->wide, &abspath) < 0) { + return win32_error_object("GetFullPathNameW", path->object); + } + if (abspath == NULL) { + return PyErr_NoMemory(); + } + + PyObject *str = PyUnicode_FromWideChar(abspath, wcslen(abspath)); + PyMem_RawFree(abspath); + if (str == NULL) { + return NULL; + } + if (path->narrow) { + Py_SETREF(str, PyUnicode_EncodeFSDefault(str)); + } + return str; +} + + +/*[clinic input] +os._getfinalpathname + + path: path_t + / + +A helper function for samepath on windows. +[clinic start generated code]*/ + +static PyObject * +os__getfinalpathname_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/ +{ + HANDLE hFile; + wchar_t buf[MAXPATHLEN], *target_path = buf; + int buf_size = Py_ARRAY_LENGTH(buf); + int result_length; + PyObject *result; + + Py_BEGIN_ALLOW_THREADS + hFile = CreateFileW( + path->wide, + 0, /* desired access */ + 0, /* share mode */ + NULL, /* security attributes */ + OPEN_EXISTING, + /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ + FILE_FLAG_BACKUP_SEMANTICS, + NULL); + Py_END_ALLOW_THREADS + + if (hFile == INVALID_HANDLE_VALUE) { + return win32_error_object("CreateFileW", path->object); + } + + /* We have a good handle to the target, use it to determine the + target path name. */ + while (1) { + Py_BEGIN_ALLOW_THREADS + result_length = GetFinalPathNameByHandleW(hFile, target_path, + buf_size, VOLUME_NAME_DOS); + Py_END_ALLOW_THREADS + + if (!result_length) { + result = win32_error_object("GetFinalPathNameByHandleW", + path->object); + goto cleanup; + } + + if (result_length < buf_size) { + break; + } + + wchar_t *tmp; + tmp = PyMem_Realloc(target_path != buf ? target_path : NULL, + result_length * sizeof(*tmp)); + if (!tmp) { + result = PyErr_NoMemory(); + goto cleanup; + } + + buf_size = result_length; + target_path = tmp; + } + + result = PyUnicode_FromWideChar(target_path, result_length); + if (result && path->narrow) { + Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); + } + +cleanup: + if (target_path != buf) { + PyMem_Free(target_path); + } + CloseHandle(hFile); + return result; +} + + +/*[clinic input] +os._getvolumepathname + + path: path_t + +A helper function for ismount on Win32. +[clinic start generated code]*/ + +static PyObject * +os__getvolumepathname_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/ +{ + PyObject *result; + wchar_t *mountpath=NULL; + size_t buflen; + BOOL ret; + + /* Volume path should be shorter than entire path */ + buflen = Py_MAX(path->length, MAX_PATH); + + if (buflen > PY_DWORD_MAX) { + PyErr_SetString(PyExc_OverflowError, "path too long"); + return NULL; + } + + mountpath = PyMem_New(wchar_t, buflen); + if (mountpath == NULL) + return PyErr_NoMemory(); + + Py_BEGIN_ALLOW_THREADS + ret = GetVolumePathNameW(path->wide, mountpath, + Py_SAFE_DOWNCAST(buflen, size_t, DWORD)); + Py_END_ALLOW_THREADS + + if (!ret) { + result = win32_error_object("_getvolumepathname", path->object); + goto exit; + } + result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath)); + if (path->narrow) + Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); + +exit: + PyMem_Free(mountpath); + return result; +} + + +/*[clinic input] +os._path_splitroot + + path: path_t + +Removes everything after the root on Win32. +[clinic start generated code]*/ + +static PyObject * +os__path_splitroot_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=ab7f1a88b654581c input=dc93b1d3984cffb6]*/ +{ + wchar_t *buffer; + wchar_t *end; + PyObject *result = NULL; + HRESULT ret; + + buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1)); + if (!buffer) { + return NULL; + } + wcscpy(buffer, path->wide); + for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) { + *p = L'\\'; + } + + Py_BEGIN_ALLOW_THREADS + ret = PathCchSkipRoot(buffer, &end); + Py_END_ALLOW_THREADS + if (FAILED(ret)) { + result = Py_BuildValue("sO", "", path->object); + } else if (end != buffer) { + size_t rootLen = (size_t)(end - buffer); + result = Py_BuildValue("NN", + PyUnicode_FromWideChar(path->wide, rootLen), + PyUnicode_FromWideChar(path->wide + rootLen, -1) + ); + } else { + result = Py_BuildValue("Os", path->object, ""); + } + PyMem_Free(buffer); + + return result; +} + + +#endif /* MS_WINDOWS */ + + +/*[clinic input] +os._path_normpath + + path: object + +Basic path normalization. +[clinic start generated code]*/ + +static PyObject * +os__path_normpath_impl(PyObject *module, PyObject *path) +/*[clinic end generated code: output=b94d696d828019da input=5e90c39e12549dc0]*/ +{ + if (!PyUnicode_Check(path)) { + PyErr_Format(PyExc_TypeError, "expected 'str', not '%.200s'", + Py_TYPE(path)->tp_name); + return NULL; + } + Py_ssize_t len; + wchar_t *buffer = PyUnicode_AsWideCharString(path, &len); + if (!buffer) { + return NULL; + } + PyObject *result = PyUnicode_FromWideChar(_Py_normpath(buffer, len), -1); + PyMem_Free(buffer); + return result; +} + +/*[clinic input] +os.mkdir + + path : path_t + + mode: int = 0o777 + + * + + dir_fd : dir_fd(requires='mkdirat') = None + +# "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\ + +Create a directory. + +If dir_fd is not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that directory. +dir_fd may not be implemented on your platform. + If it is unavailable, using it will raise a NotImplementedError. + +The mode argument is ignored on Windows. Where it is used, the current umask +value is first masked out. +[clinic start generated code]*/ + +static PyObject * +os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd) +/*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/ +{ + int result; +#ifdef HAVE_MKDIRAT + int mkdirat_unavailable = 0; +#endif + + if (PySys_Audit("os.mkdir", "Oii", path->object, mode, + dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { + return NULL; + } + +#ifdef MS_WINDOWS + Py_BEGIN_ALLOW_THREADS + result = CreateDirectoryW(path->wide, NULL); + Py_END_ALLOW_THREADS + + if (!result) + return path_error(path); +#else + Py_BEGIN_ALLOW_THREADS +#if HAVE_MKDIRAT + if (dir_fd != DEFAULT_DIR_FD) { + if (HAVE_MKDIRAT_RUNTIME) { + result = mkdirat(dir_fd, path->narrow, mode); + + } else { + mkdirat_unavailable = 1; + } + } else +#endif +#if defined(__WATCOMC__) && !defined(__QNX__) + result = mkdir(path->narrow); +#else + result = mkdir(path->narrow, mode); +#endif + Py_END_ALLOW_THREADS + +#if HAVE_MKDIRAT + if (mkdirat_unavailable) { + argument_unavailable_error(NULL, "dir_fd"); + return NULL; + } +#endif + + if (result < 0) + return path_error(path); +#endif /* MS_WINDOWS */ + Py_RETURN_NONE; +} + + +/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */ +#if defined(HAVE_SYS_RESOURCE_H) +#include +#endif + + +#ifdef HAVE_NICE +/*[clinic input] +os.nice + + increment: int + / + +Add increment to the priority of process and return the new priority. +[clinic start generated code]*/ + +static PyObject * +os_nice_impl(PyObject *module, int increment) +/*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/ +{ + int value; + + /* There are two flavours of 'nice': one that returns the new + priority (as required by almost all standards out there) and the + Linux/FreeBSD one, which returns '0' on success and advices + the use of getpriority() to get the new priority. + + If we are of the nice family that returns the new priority, we + need to clear errno before the call, and check if errno is filled + before calling posix_error() on a returnvalue of -1, because the + -1 may be the actual new priority! */ + + errno = 0; + value = nice(increment); +#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY) + if (value == 0) + value = getpriority(PRIO_PROCESS, 0); +#endif + if (value == -1 && errno != 0) + /* either nice() or getpriority() returned an error */ + return posix_error(); + return PyLong_FromLong((long) value); +} +#endif /* HAVE_NICE */ + + +#ifdef HAVE_GETPRIORITY +/*[clinic input] +os.getpriority + + which: int + who: int + +Return program scheduling priority. +[clinic start generated code]*/ + +static PyObject * +os_getpriority_impl(PyObject *module, int which, int who) +/*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/ +{ + int retval; + + errno = 0; + retval = getpriority(which, who); + if (errno != 0) + return posix_error(); + return PyLong_FromLong((long)retval); +} +#endif /* HAVE_GETPRIORITY */ + + +#ifdef HAVE_SETPRIORITY +/*[clinic input] +os.setpriority + + which: int + who: int + priority: int + +Set program scheduling priority. +[clinic start generated code]*/ + +static PyObject * +os_setpriority_impl(PyObject *module, int which, int who, int priority) +/*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/ +{ + int retval; + + retval = setpriority(which, who, priority); + if (retval == -1) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETPRIORITY */ + + +static PyObject * +internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace) +{ + const char *function_name = is_replace ? "replace" : "rename"; + int dir_fd_specified; + +#ifdef HAVE_RENAMEAT + int renameat_unavailable = 0; +#endif + +#ifdef MS_WINDOWS + BOOL result; + int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0; +#else + int result; +#endif + + dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) || + (dst_dir_fd != DEFAULT_DIR_FD); +#ifndef HAVE_RENAMEAT + if (dir_fd_specified) { + argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd"); + return NULL; + } +#endif + + if (PySys_Audit("os.rename", "OOii", src->object, dst->object, + src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd, + dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) { + return NULL; + } + +#ifdef MS_WINDOWS + Py_BEGIN_ALLOW_THREADS + result = MoveFileExW(src->wide, dst->wide, flags); + Py_END_ALLOW_THREADS + + if (!result) + return path_error2(src, dst); + +#else + if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { + PyErr_Format(PyExc_ValueError, + "%s: src and dst must be the same type", function_name); + return NULL; + } + + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_RENAMEAT + if (dir_fd_specified) { + if (HAVE_RENAMEAT_RUNTIME) { + result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow); + } else { + renameat_unavailable = 1; + } + } else +#endif + result = rename(src->narrow, dst->narrow); + Py_END_ALLOW_THREADS + + +#ifdef HAVE_RENAMEAT + if (renameat_unavailable) { + argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd"); + return NULL; + } +#endif + + if (result) + return path_error2(src, dst); +#endif + Py_RETURN_NONE; +} + + +/*[clinic input] +os.rename + + src : path_t + dst : path_t + * + src_dir_fd : dir_fd = None + dst_dir_fd : dir_fd = None + +Rename a file or directory. + +If either src_dir_fd or dst_dir_fd is not None, it should be a file + descriptor open to a directory, and the respective path string (src or dst) + should be relative; the path will then be relative to that directory. +src_dir_fd and dst_dir_fd, may not be implemented on your platform. + If they are unavailable, using them will raise a NotImplementedError. +[clinic start generated code]*/ + +static PyObject * +os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, + int dst_dir_fd) +/*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/ +{ + return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0); +} + + +/*[clinic input] +os.replace = os.rename + +Rename a file or directory, overwriting the destination. + +If either src_dir_fd or dst_dir_fd is not None, it should be a file + descriptor open to a directory, and the respective path string (src or dst) + should be relative; the path will then be relative to that directory. +src_dir_fd and dst_dir_fd, may not be implemented on your platform. + If they are unavailable, using them will raise a NotImplementedError. +[clinic start generated code]*/ + +static PyObject * +os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, + int dst_dir_fd) +/*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/ +{ + return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1); +} + + +/*[clinic input] +os.rmdir + + path: path_t + * + dir_fd: dir_fd(requires='unlinkat') = None + +Remove a directory. + +If dir_fd is not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that directory. +dir_fd may not be implemented on your platform. + If it is unavailable, using it will raise a NotImplementedError. +[clinic start generated code]*/ + +static PyObject * +os_rmdir_impl(PyObject *module, path_t *path, int dir_fd) +/*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/ +{ + int result; +#ifdef HAVE_UNLINKAT + int unlinkat_unavailable = 0; +#endif + + if (PySys_Audit("os.rmdir", "Oi", path->object, + dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS +#ifdef MS_WINDOWS + /* Windows, success=1, UNIX, success=0 */ + result = !RemoveDirectoryW(path->wide); +#else +#ifdef HAVE_UNLINKAT + if (dir_fd != DEFAULT_DIR_FD) { + if (HAVE_UNLINKAT_RUNTIME) { + result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR); + } else { + unlinkat_unavailable = 1; + result = -1; + } + } else +#endif + result = rmdir(path->narrow); +#endif + Py_END_ALLOW_THREADS + +#ifdef HAVE_UNLINKAT + if (unlinkat_unavailable) { + argument_unavailable_error("rmdir", "dir_fd"); + return NULL; + } +#endif + + if (result) + return path_error(path); + + Py_RETURN_NONE; +} + + +#ifdef HAVE_SYSTEM +#ifdef MS_WINDOWS +/*[clinic input] +os.system -> long + + command: Py_UNICODE + +Execute the command in a subshell. +[clinic start generated code]*/ + +static long +os_system_impl(PyObject *module, const Py_UNICODE *command) +/*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/ +{ + long result; + + if (PySys_Audit("os.system", "(u)", command) < 0) { + return -1; + } + + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + result = _wsystem(command); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + return result; +} +#else /* MS_WINDOWS */ +/*[clinic input] +os.system -> long + + command: FSConverter + +Execute the command in a subshell. +[clinic start generated code]*/ + +static long +os_system_impl(PyObject *module, PyObject *command) +/*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/ +{ + long result; + const char *bytes = PyBytes_AsString(command); + + if (PySys_Audit("os.system", "(O)", command) < 0) { + return -1; + } + + Py_BEGIN_ALLOW_THREADS + result = system(bytes); + Py_END_ALLOW_THREADS + return result; +} +#endif +#endif /* HAVE_SYSTEM */ + + +#ifdef HAVE_UMASK +/*[clinic input] +os.umask + + mask: int + / + +Set the current numeric umask and return the previous umask. +[clinic start generated code]*/ + +static PyObject * +os_umask_impl(PyObject *module, int mask) +/*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/ +{ + int i = (int)umask(mask); + if (i < 0) + return posix_error(); + return PyLong_FromLong((long)i); +} +#endif + +#ifdef MS_WINDOWS + +/* override the default DeleteFileW behavior so that directory +symlinks can be removed with this function, the same as with +Unix symlinks */ +BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName) +{ + WIN32_FILE_ATTRIBUTE_DATA info; + WIN32_FIND_DATAW find_data; + HANDLE find_data_handle; + int is_directory = 0; + int is_link = 0; + + if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) { + is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; + + /* Get WIN32_FIND_DATA structure for the path to determine if + it is a symlink */ + if(is_directory && + info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { + find_data_handle = FindFirstFileW(lpFileName, &find_data); + + if(find_data_handle != INVALID_HANDLE_VALUE) { + /* IO_REPARSE_TAG_SYMLINK if it is a symlink and + IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */ + is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK || + find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT; + FindClose(find_data_handle); + } + } + } + + if (is_directory && is_link) + return RemoveDirectoryW(lpFileName); + + return DeleteFileW(lpFileName); +} +#endif /* MS_WINDOWS */ + + +/*[clinic input] +os.unlink + + path: path_t + * + dir_fd: dir_fd(requires='unlinkat')=None + +Remove a file (same as remove()). + +If dir_fd is not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that directory. +dir_fd may not be implemented on your platform. + If it is unavailable, using it will raise a NotImplementedError. + +[clinic start generated code]*/ + +static PyObject * +os_unlink_impl(PyObject *module, path_t *path, int dir_fd) +/*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/ +{ + int result; +#ifdef HAVE_UNLINKAT + int unlinkat_unavailable = 0; +#endif + + if (PySys_Audit("os.remove", "Oi", path->object, + dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH +#ifdef MS_WINDOWS + /* Windows, success=1, UNIX, success=0 */ + result = !Py_DeleteFileW(path->wide); +#else +#ifdef HAVE_UNLINKAT + if (dir_fd != DEFAULT_DIR_FD) { + if (HAVE_UNLINKAT_RUNTIME) { + + result = unlinkat(dir_fd, path->narrow, 0); + } else { + unlinkat_unavailable = 1; + } + } else +#endif /* HAVE_UNLINKAT */ + result = unlink(path->narrow); +#endif + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + +#ifdef HAVE_UNLINKAT + if (unlinkat_unavailable) { + argument_unavailable_error(NULL, "dir_fd"); + return NULL; + } +#endif + + if (result) + return path_error(path); + + Py_RETURN_NONE; +} + + +/*[clinic input] +os.remove = os.unlink + +Remove a file (same as unlink()). + +If dir_fd is not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that directory. +dir_fd may not be implemented on your platform. + If it is unavailable, using it will raise a NotImplementedError. +[clinic start generated code]*/ + +static PyObject * +os_remove_impl(PyObject *module, path_t *path, int dir_fd) +/*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/ +{ + return os_unlink_impl(module, path, dir_fd); +} + + +static PyStructSequence_Field uname_result_fields[] = { + {"sysname", "operating system name"}, + {"nodename", "name of machine on network (implementation-defined)"}, + {"release", "operating system release"}, + {"version", "operating system version"}, + {"machine", "hardware identifier"}, + {NULL} +}; + +PyDoc_STRVAR(uname_result__doc__, +"uname_result: Result from os.uname().\n\n\ +This object may be accessed either as a tuple of\n\ + (sysname, nodename, release, version, machine),\n\ +or via the attributes sysname, nodename, release, version, and machine.\n\ +\n\ +See os.uname for more information."); + +static PyStructSequence_Desc uname_result_desc = { + MODNAME ".uname_result", /* name */ + uname_result__doc__, /* doc */ + uname_result_fields, + 5 +}; + +#ifdef HAVE_UNAME +/*[clinic input] +os.uname + +Return an object identifying the current operating system. + +The object behaves like a named tuple with the following fields: + (sysname, nodename, release, version, machine) + +[clinic start generated code]*/ + +static PyObject * +os_uname_impl(PyObject *module) +/*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/ +{ + struct utsname u; + int res; + PyObject *value; + + Py_BEGIN_ALLOW_THREADS + res = uname(&u); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error(); + + PyObject *UnameResultType = get_posix_state(module)->UnameResultType; + value = PyStructSequence_New((PyTypeObject *)UnameResultType); + if (value == NULL) + return NULL; + +#define SET(i, field) \ + { \ + PyObject *o = PyUnicode_DecodeFSDefault(field); \ + if (!o) { \ + Py_DECREF(value); \ + return NULL; \ + } \ + PyStructSequence_SET_ITEM(value, i, o); \ + } \ + + SET(0, u.sysname); + SET(1, u.nodename); + SET(2, u.release); + SET(3, u.version); + SET(4, u.machine); + +#undef SET + + return value; +} +#endif /* HAVE_UNAME */ + + + +typedef struct { + int now; + time_t atime_s; + long atime_ns; + time_t mtime_s; + long mtime_ns; +} utime_t; + +/* + * these macros assume that "ut" is a pointer to a utime_t + * they also intentionally leak the declaration of a pointer named "time" + */ +#define UTIME_TO_TIMESPEC \ + struct timespec ts[2]; \ + struct timespec *time; \ + if (ut->now) \ + time = NULL; \ + else { \ + ts[0].tv_sec = ut->atime_s; \ + ts[0].tv_nsec = ut->atime_ns; \ + ts[1].tv_sec = ut->mtime_s; \ + ts[1].tv_nsec = ut->mtime_ns; \ + time = ts; \ + } \ + +#define UTIME_TO_TIMEVAL \ + struct timeval tv[2]; \ + struct timeval *time; \ + if (ut->now) \ + time = NULL; \ + else { \ + tv[0].tv_sec = ut->atime_s; \ + tv[0].tv_usec = ut->atime_ns / 1000; \ + tv[1].tv_sec = ut->mtime_s; \ + tv[1].tv_usec = ut->mtime_ns / 1000; \ + time = tv; \ + } \ + +#define UTIME_TO_UTIMBUF \ + struct utimbuf u; \ + struct utimbuf *time; \ + if (ut->now) \ + time = NULL; \ + else { \ + u.actime = ut->atime_s; \ + u.modtime = ut->mtime_s; \ + time = &u; \ + } + +#define UTIME_TO_TIME_T \ + time_t timet[2]; \ + time_t *time; \ + if (ut->now) \ + time = NULL; \ + else { \ + timet[0] = ut->atime_s; \ + timet[1] = ut->mtime_s; \ + time = timet; \ + } \ + + +#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT) + +static int +utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks) +{ +#if defined(__APPLE__) && defined(HAVE_UTIMENSAT) + if (HAVE_UTIMENSAT_RUNTIME) { + int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW; + UTIME_TO_TIMESPEC; + return utimensat(dir_fd, path, time, flags); + } else { + errno = ENOSYS; + return -1; + } +#elif defined(HAVE_UTIMENSAT) + int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW; + UTIME_TO_TIMESPEC; + return utimensat(dir_fd, path, time, flags); +#elif defined(HAVE_FUTIMESAT) + UTIME_TO_TIMEVAL; + /* + * follow_symlinks will never be false here; + * we only allow !follow_symlinks and dir_fd together + * if we have utimensat() + */ + assert(follow_symlinks); + return futimesat(dir_fd, path, time); +#endif +} + + #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS) + +static int +utime_fd(utime_t *ut, int fd) +{ +#ifdef HAVE_FUTIMENS + + if (HAVE_FUTIMENS_RUNTIME) { + + UTIME_TO_TIMESPEC; + return futimens(fd, time); + + } else +#ifndef HAVE_FUTIMES + { + /* Not sure if this can happen */ + PyErr_SetString( + PyExc_RuntimeError, + "neither futimens nor futimes are supported" + " on this system"); + return -1; + } +#endif + +#endif +#ifdef HAVE_FUTIMES + { + UTIME_TO_TIMEVAL; + return futimes(fd, time); + } +#endif +} + + #define PATH_UTIME_HAVE_FD 1 +#else + #define PATH_UTIME_HAVE_FD 0 +#endif + +#if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES) +# define UTIME_HAVE_NOFOLLOW_SYMLINKS +#endif + +#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS + +static int +utime_nofollow_symlinks(utime_t *ut, const char *path) +{ +#ifdef HAVE_UTIMENSAT + if (HAVE_UTIMENSAT_RUNTIME) { + UTIME_TO_TIMESPEC; + return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW); + } else +#ifndef HAVE_LUTIMES + { + /* Not sure if this can happen */ + PyErr_SetString( + PyExc_RuntimeError, + "neither utimensat nor lutimes are supported" + " on this system"); + return -1; + } +#endif +#endif + +#ifdef HAVE_LUTIMES + { + UTIME_TO_TIMEVAL; + return lutimes(path, time); + } +#endif +} + +#endif + +#ifndef MS_WINDOWS + +static int +utime_default(utime_t *ut, const char *path) +{ +#if defined(__APPLE__) && defined(HAVE_UTIMENSAT) + if (HAVE_UTIMENSAT_RUNTIME) { + UTIME_TO_TIMESPEC; + return utimensat(DEFAULT_DIR_FD, path, time, 0); + } else { + UTIME_TO_TIMEVAL; + return utimes(path, time); + } +#elif defined(HAVE_UTIMENSAT) + UTIME_TO_TIMESPEC; + return utimensat(DEFAULT_DIR_FD, path, time, 0); +#elif defined(HAVE_UTIMES) + UTIME_TO_TIMEVAL; + return utimes(path, time); +#elif defined(HAVE_UTIME_H) + UTIME_TO_UTIMBUF; + return utime(path, time); +#else + UTIME_TO_TIME_T; + return utime(path, time); +#endif +} + +#endif + +static int +split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns) +{ + int result = 0; + PyObject *divmod; + divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion); + if (!divmod) + goto exit; + if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) { + PyErr_Format(PyExc_TypeError, + "%.200s.__divmod__() must return a 2-tuple, not %.200s", + _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod))); + goto exit; + } + *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0)); + if ((*s == -1) && PyErr_Occurred()) + goto exit; + *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1)); + if ((*ns == -1) && PyErr_Occurred()) + goto exit; + + result = 1; +exit: + Py_XDECREF(divmod); + return result; +} + + +/*[clinic input] +os.utime + + path: path_t(allow_fd='PATH_UTIME_HAVE_FD') + times: object = None + * + ns: object = NULL + dir_fd: dir_fd(requires='futimensat') = None + follow_symlinks: bool=True + +# "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\ + +Set the access and modified time of path. + +path may always be specified as a string. +On some platforms, path may also be specified as an open file descriptor. + If this functionality is unavailable, using it raises an exception. + +If times is not None, it must be a tuple (atime, mtime); + atime and mtime should be expressed as float seconds since the epoch. +If ns is specified, it must be a tuple (atime_ns, mtime_ns); + atime_ns and mtime_ns should be expressed as integer nanoseconds + since the epoch. +If times is None and ns is unspecified, utime uses the current time. +Specifying tuples for both times and ns is an error. + +If dir_fd is not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that directory. +If follow_symlinks is False, and the last element of the path is a symbolic + link, utime will modify the symbolic link itself instead of the file the + link points to. +It is an error to use dir_fd or follow_symlinks when specifying path + as an open file descriptor. +dir_fd and follow_symlinks may not be available on your platform. + If they are unavailable, using them will raise a NotImplementedError. + +[clinic start generated code]*/ + +static PyObject * +os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, + int dir_fd, int follow_symlinks) +/*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/ +{ +#ifdef MS_WINDOWS + HANDLE hFile; + FILETIME atime, mtime; +#else + int result; +#endif + + utime_t utime; + + memset(&utime, 0, sizeof(utime_t)); + + if (times != Py_None && ns) { + PyErr_SetString(PyExc_ValueError, + "utime: you may specify either 'times'" + " or 'ns' but not both"); + return NULL; + } + + if (times != Py_None) { + time_t a_sec, m_sec; + long a_nsec, m_nsec; + if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) { + PyErr_SetString(PyExc_TypeError, + "utime: 'times' must be either" + " a tuple of two ints or None"); + return NULL; + } + utime.now = 0; + if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0), + &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 || + _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1), + &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) { + return NULL; + } + utime.atime_s = a_sec; + utime.atime_ns = a_nsec; + utime.mtime_s = m_sec; + utime.mtime_ns = m_nsec; + } + else if (ns) { + if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) { + PyErr_SetString(PyExc_TypeError, + "utime: 'ns' must be a tuple of two ints"); + return NULL; + } + utime.now = 0; + if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0), + &utime.atime_s, &utime.atime_ns) || + !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1), + &utime.mtime_s, &utime.mtime_ns)) { + return NULL; + } + } + else { + /* times and ns are both None/unspecified. use "now". */ + utime.now = 1; + } + +#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS) + if (follow_symlinks_specified("utime", follow_symlinks)) + return NULL; +#endif + + if (path_and_dir_fd_invalid("utime", path, dir_fd) || + dir_fd_and_fd_invalid("utime", dir_fd, path->fd) || + fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks)) + return NULL; + +#if !defined(HAVE_UTIMENSAT) + if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) { + PyErr_SetString(PyExc_ValueError, + "utime: cannot use dir_fd and follow_symlinks " + "together on this platform"); + return NULL; + } +#endif + + if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None, + dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { + return NULL; + } + +#ifdef MS_WINDOWS + Py_BEGIN_ALLOW_THREADS + hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0, + NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, NULL); + Py_END_ALLOW_THREADS + if (hFile == INVALID_HANDLE_VALUE) { + path_error(path); + return NULL; + } + + if (utime.now) { + GetSystemTimeAsFileTime(&mtime); + atime = mtime; + } + else { + _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime); + _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime); + } + if (!SetFileTime(hFile, NULL, &atime, &mtime)) { + /* Avoid putting the file name into the error here, + as that may confuse the user into believing that + something is wrong with the file, when it also + could be the time stamp that gives a problem. */ + PyErr_SetFromWindowsErr(0); + CloseHandle(hFile); + return NULL; + } + CloseHandle(hFile); +#else /* MS_WINDOWS */ + Py_BEGIN_ALLOW_THREADS + +#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS + if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) + result = utime_nofollow_symlinks(&utime, path->narrow); + else +#endif + +#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT) + if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) { + result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks); + + } else +#endif + +#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS) + if (path->fd != -1) + result = utime_fd(&utime, path->fd); + else +#endif + + result = utime_default(&utime, path->narrow); + + Py_END_ALLOW_THREADS + +#if defined(__APPLE__) && defined(HAVE_UTIMENSAT) + /* See utime_dir_fd implementation */ + if (result == -1 && errno == ENOSYS) { + argument_unavailable_error(NULL, "dir_fd"); + return NULL; + } +#endif + + if (result < 0) { + /* see previous comment about not putting filename in error here */ + posix_error(); + return NULL; + } + +#endif /* MS_WINDOWS */ + + Py_RETURN_NONE; +} + +/* Process operations */ + + +/*[clinic input] +os._exit + + status: int + +Exit to the system with specified status, without normal exit processing. +[clinic start generated code]*/ + +static PyObject * +os__exit_impl(PyObject *module, int status) +/*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/ +{ + _exit(status); + return NULL; /* Make gcc -Wall happy */ +} + +#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV) +#define EXECV_CHAR wchar_t +#else +#define EXECV_CHAR char +#endif + +#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN) +static void +free_string_array(EXECV_CHAR **array, Py_ssize_t count) +{ + Py_ssize_t i; + for (i = 0; i < count; i++) + PyMem_Free(array[i]); + PyMem_Free(array); +} + +static int +fsconvert_strdup(PyObject *o, EXECV_CHAR **out) +{ + Py_ssize_t size; + PyObject *ub; + int result = 0; +#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV) + if (!PyUnicode_FSDecoder(o, &ub)) + return 0; + *out = PyUnicode_AsWideCharString(ub, &size); + if (*out) + result = 1; +#else + if (!PyUnicode_FSConverter(o, &ub)) + return 0; + size = PyBytes_GET_SIZE(ub); + *out = PyMem_Malloc(size + 1); + if (*out) { + memcpy(*out, PyBytes_AS_STRING(ub), size + 1); + result = 1; + } else + PyErr_NoMemory(); +#endif + Py_DECREF(ub); + return result; +} +#endif + +#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN) +static EXECV_CHAR** +parse_envlist(PyObject* env, Py_ssize_t *envc_ptr) +{ + Py_ssize_t i, pos, envc; + PyObject *keys=NULL, *vals=NULL; + PyObject *key, *val, *key2, *val2, *keyval; + EXECV_CHAR **envlist; + + i = PyMapping_Size(env); + if (i < 0) + return NULL; + envlist = PyMem_NEW(EXECV_CHAR *, i + 1); + if (envlist == NULL) { + PyErr_NoMemory(); + return NULL; + } + envc = 0; + keys = PyMapping_Keys(env); + if (!keys) + goto error; + vals = PyMapping_Values(env); + if (!vals) + goto error; + if (!PyList_Check(keys) || !PyList_Check(vals)) { + PyErr_Format(PyExc_TypeError, + "env.keys() or env.values() is not a list"); + goto error; + } + + for (pos = 0; pos < i; pos++) { + key = PyList_GetItem(keys, pos); + val = PyList_GetItem(vals, pos); + if (!key || !val) + goto error; + +#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV) + if (!PyUnicode_FSDecoder(key, &key2)) + goto error; + if (!PyUnicode_FSDecoder(val, &val2)) { + Py_DECREF(key2); + goto error; + } + /* Search from index 1 because on Windows starting '=' is allowed for + defining hidden environment variables. */ + if (PyUnicode_GET_LENGTH(key2) == 0 || + PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1) + { + PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); + Py_DECREF(key2); + Py_DECREF(val2); + goto error; + } + keyval = PyUnicode_FromFormat("%U=%U", key2, val2); +#else + if (!PyUnicode_FSConverter(key, &key2)) + goto error; + if (!PyUnicode_FSConverter(val, &val2)) { + Py_DECREF(key2); + goto error; + } + if (PyBytes_GET_SIZE(key2) == 0 || + strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL) + { + PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); + Py_DECREF(key2); + Py_DECREF(val2); + goto error; + } + keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2), + PyBytes_AS_STRING(val2)); +#endif + Py_DECREF(key2); + Py_DECREF(val2); + if (!keyval) + goto error; + + if (!fsconvert_strdup(keyval, &envlist[envc++])) { + Py_DECREF(keyval); + goto error; + } + + Py_DECREF(keyval); + } + Py_DECREF(vals); + Py_DECREF(keys); + + envlist[envc] = 0; + *envc_ptr = envc; + return envlist; + +error: + Py_XDECREF(keys); + Py_XDECREF(vals); + free_string_array(envlist, envc); + return NULL; +} + +static EXECV_CHAR** +parse_arglist(PyObject* argv, Py_ssize_t *argc) +{ + int i; + EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1); + if (argvlist == NULL) { + PyErr_NoMemory(); + return NULL; + } + for (i = 0; i < *argc; i++) { + PyObject* item = PySequence_ITEM(argv, i); + if (item == NULL) + goto fail; + if (!fsconvert_strdup(item, &argvlist[i])) { + Py_DECREF(item); + goto fail; + } + Py_DECREF(item); + } + argvlist[*argc] = NULL; + return argvlist; +fail: + *argc = i; + free_string_array(argvlist, *argc); + return NULL; +} + +#endif + + +#ifdef HAVE_EXECV +/*[clinic input] +os.execv + + path: path_t + Path of executable file. + argv: object + Tuple or list of strings. + / + +Execute an executable path with arguments, replacing current process. +[clinic start generated code]*/ + +static PyObject * +os_execv_impl(PyObject *module, path_t *path, PyObject *argv) +/*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/ +{ + EXECV_CHAR **argvlist; + Py_ssize_t argc; + + PyInterpreterState *interp = _PyInterpreterState_GET(); + if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) { + PyErr_SetString(PyExc_RuntimeError, + "exec not supported for isolated subinterpreters"); + return NULL; + } + + /* execv has two arguments: (path, argv), where + argv is a list or tuple of strings. */ + + if (!PyList_Check(argv) && !PyTuple_Check(argv)) { + PyErr_SetString(PyExc_TypeError, + "execv() arg 2 must be a tuple or list"); + return NULL; + } + argc = PySequence_Size(argv); + if (argc < 1) { + PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty"); + return NULL; + } + + argvlist = parse_arglist(argv, &argc); + if (argvlist == NULL) { + return NULL; + } + if (!argvlist[0][0]) { + PyErr_SetString(PyExc_ValueError, + "execv() arg 2 first element cannot be empty"); + free_string_array(argvlist, argc); + return NULL; + } + + if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) { + free_string_array(argvlist, argc); + return NULL; + } + + _Py_BEGIN_SUPPRESS_IPH +#ifdef HAVE_WEXECV + _wexecv(path->wide, argvlist); +#else + execv(path->narrow, argvlist); +#endif + _Py_END_SUPPRESS_IPH + + /* If we get here it's definitely an error */ + + free_string_array(argvlist, argc); + return posix_error(); +} + + +/*[clinic input] +os.execve + + path: path_t(allow_fd='PATH_HAVE_FEXECVE') + Path of executable file. + argv: object + Tuple or list of strings. + env: object + Dictionary of strings mapping to strings. + +Execute an executable path with arguments, replacing current process. +[clinic start generated code]*/ + +static PyObject * +os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env) +/*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/ +{ + EXECV_CHAR **argvlist = NULL; + EXECV_CHAR **envlist; + Py_ssize_t argc, envc; + + PyInterpreterState *interp = _PyInterpreterState_GET(); + if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) { + PyErr_SetString(PyExc_RuntimeError, + "exec not supported for isolated subinterpreters"); + return NULL; + } + + /* execve has three arguments: (path, argv, env), where + argv is a list or tuple of strings and env is a dictionary + like posix.environ. */ + + if (!PyList_Check(argv) && !PyTuple_Check(argv)) { + PyErr_SetString(PyExc_TypeError, + "execve: argv must be a tuple or list"); + goto fail_0; + } + argc = PySequence_Size(argv); + if (argc < 1) { + PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty"); + return NULL; + } + + if (!PyMapping_Check(env)) { + PyErr_SetString(PyExc_TypeError, + "execve: environment must be a mapping object"); + goto fail_0; + } + + argvlist = parse_arglist(argv, &argc); + if (argvlist == NULL) { + goto fail_0; + } + if (!argvlist[0][0]) { + PyErr_SetString(PyExc_ValueError, + "execve: argv first element cannot be empty"); + goto fail_0; + } + + envlist = parse_envlist(env, &envc); + if (envlist == NULL) + goto fail_0; + + if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) { + goto fail_1; + } + + _Py_BEGIN_SUPPRESS_IPH +#ifdef HAVE_FEXECVE + if (path->fd > -1) + fexecve(path->fd, argvlist, envlist); + else +#endif +#ifdef HAVE_WEXECV + _wexecve(path->wide, argvlist, envlist); +#else + execve(path->narrow, argvlist, envlist); +#endif + _Py_END_SUPPRESS_IPH + + /* If we get here it's definitely an error */ + + posix_path_error(path); + fail_1: + free_string_array(envlist, envc); + fail_0: + if (argvlist) + free_string_array(argvlist, argc); + return NULL; +} + +#endif /* HAVE_EXECV */ + +#ifdef HAVE_POSIX_SPAWN + +enum posix_spawn_file_actions_identifier { + POSIX_SPAWN_OPEN, + POSIX_SPAWN_CLOSE, + POSIX_SPAWN_DUP2 +}; + +#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) +static int +convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res); +#endif + +static int +parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup, + int resetids, int setsid, PyObject *setsigmask, + PyObject *setsigdef, PyObject *scheduler, + posix_spawnattr_t *attrp) +{ + long all_flags = 0; + + errno = posix_spawnattr_init(attrp); + if (errno) { + posix_error(); + return -1; + } + + if (setpgroup) { + pid_t pgid = PyLong_AsPid(setpgroup); + if (pgid == (pid_t)-1 && PyErr_Occurred()) { + goto fail; + } + errno = posix_spawnattr_setpgroup(attrp, pgid); + if (errno) { + posix_error(); + goto fail; + } + all_flags |= POSIX_SPAWN_SETPGROUP; + } + + if (resetids) { + all_flags |= POSIX_SPAWN_RESETIDS; + } + + if (setsid) { +#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME + if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) { +#endif +#ifdef POSIX_SPAWN_SETSID + all_flags |= POSIX_SPAWN_SETSID; +#elif defined(POSIX_SPAWN_SETSID_NP) + all_flags |= POSIX_SPAWN_SETSID_NP; +#else + argument_unavailable_error(func_name, "setsid"); + return -1; +#endif + +#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME + } else { + argument_unavailable_error(func_name, "setsid"); + return -1; + } +#endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */ + + } + +#ifdef HAVE_SIGSET_T + if (setsigmask) { + sigset_t set; + if (!_Py_Sigset_Converter(setsigmask, &set)) { + goto fail; + } + errno = posix_spawnattr_setsigmask(attrp, &set); + if (errno) { + posix_error(); + goto fail; + } + all_flags |= POSIX_SPAWN_SETSIGMASK; + } + + if (setsigdef) { + sigset_t set; + if (!_Py_Sigset_Converter(setsigdef, &set)) { + goto fail; + } + errno = posix_spawnattr_setsigdefault(attrp, &set); + if (errno) { + posix_error(); + goto fail; + } + all_flags |= POSIX_SPAWN_SETSIGDEF; + } +#else + if (setsigmask || setsigdef) { + PyErr_SetString(PyExc_NotImplementedError, + "sigset is not supported on this platform"); + goto fail; + } +#endif + + if (scheduler) { +#ifdef POSIX_SPAWN_SETSCHEDULER + PyObject *py_schedpolicy; + PyObject *schedparam_obj; + struct sched_param schedparam; + + if (!PyArg_ParseTuple(scheduler, "OO" + ";A scheduler tuple must have two elements", + &py_schedpolicy, &schedparam_obj)) { + goto fail; + } + if (!convert_sched_param(module, schedparam_obj, &schedparam)) { + goto fail; + } + if (py_schedpolicy != Py_None) { + int schedpolicy = _PyLong_AsInt(py_schedpolicy); + + if (schedpolicy == -1 && PyErr_Occurred()) { + goto fail; + } + errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy); + if (errno) { + posix_error(); + goto fail; + } + all_flags |= POSIX_SPAWN_SETSCHEDULER; + } + errno = posix_spawnattr_setschedparam(attrp, &schedparam); + if (errno) { + posix_error(); + goto fail; + } + all_flags |= POSIX_SPAWN_SETSCHEDPARAM; +#else + PyErr_SetString(PyExc_NotImplementedError, + "The scheduler option is not supported in this system."); + goto fail; +#endif + } + + errno = posix_spawnattr_setflags(attrp, all_flags); + if (errno) { + posix_error(); + goto fail; + } + + return 0; + +fail: + (void)posix_spawnattr_destroy(attrp); + return -1; +} + +static int +parse_file_actions(PyObject *file_actions, + posix_spawn_file_actions_t *file_actionsp, + PyObject *temp_buffer) +{ + PyObject *seq; + PyObject *file_action = NULL; + PyObject *tag_obj; + + seq = PySequence_Fast(file_actions, + "file_actions must be a sequence or None"); + if (seq == NULL) { + return -1; + } + + errno = posix_spawn_file_actions_init(file_actionsp); + if (errno) { + posix_error(); + Py_DECREF(seq); + return -1; + } + + for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) { + file_action = PySequence_Fast_GET_ITEM(seq, i); + Py_INCREF(file_action); + if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) { + PyErr_SetString(PyExc_TypeError, + "Each file_actions element must be a non-empty tuple"); + goto fail; + } + long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0)); + if (tag == -1 && PyErr_Occurred()) { + goto fail; + } + + /* Populate the file_actions object */ + switch (tag) { + case POSIX_SPAWN_OPEN: { + int fd, oflag; + PyObject *path; + unsigned long mode; + if (!PyArg_ParseTuple(file_action, "OiO&ik" + ";A open file_action tuple must have 5 elements", + &tag_obj, &fd, PyUnicode_FSConverter, &path, + &oflag, &mode)) + { + goto fail; + } + if (PyList_Append(temp_buffer, path)) { + Py_DECREF(path); + goto fail; + } + errno = posix_spawn_file_actions_addopen(file_actionsp, + fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode); + Py_DECREF(path); + if (errno) { + posix_error(); + goto fail; + } + break; + } + case POSIX_SPAWN_CLOSE: { + int fd; + if (!PyArg_ParseTuple(file_action, "Oi" + ";A close file_action tuple must have 2 elements", + &tag_obj, &fd)) + { + goto fail; + } + errno = posix_spawn_file_actions_addclose(file_actionsp, fd); + if (errno) { + posix_error(); + goto fail; + } + break; + } + case POSIX_SPAWN_DUP2: { + int fd1, fd2; + if (!PyArg_ParseTuple(file_action, "Oii" + ";A dup2 file_action tuple must have 3 elements", + &tag_obj, &fd1, &fd2)) + { + goto fail; + } + errno = posix_spawn_file_actions_adddup2(file_actionsp, + fd1, fd2); + if (errno) { + posix_error(); + goto fail; + } + break; + } + default: { + PyErr_SetString(PyExc_TypeError, + "Unknown file_actions identifier"); + goto fail; + } + } + Py_DECREF(file_action); + } + + Py_DECREF(seq); + return 0; + +fail: + Py_DECREF(seq); + Py_DECREF(file_action); + (void)posix_spawn_file_actions_destroy(file_actionsp); + return -1; +} + + +static PyObject * +py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv, + PyObject *env, PyObject *file_actions, + PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask, + PyObject *setsigdef, PyObject *scheduler) +{ + const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn"; + EXECV_CHAR **argvlist = NULL; + EXECV_CHAR **envlist = NULL; + posix_spawn_file_actions_t file_actions_buf; + posix_spawn_file_actions_t *file_actionsp = NULL; + posix_spawnattr_t attr; + posix_spawnattr_t *attrp = NULL; + Py_ssize_t argc, envc; + PyObject *result = NULL; + PyObject *temp_buffer = NULL; + pid_t pid; + int err_code; + + /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where + argv is a list or tuple of strings and env is a dictionary + like posix.environ. */ + + if (!PyList_Check(argv) && !PyTuple_Check(argv)) { + PyErr_Format(PyExc_TypeError, + "%s: argv must be a tuple or list", func_name); + goto exit; + } + argc = PySequence_Size(argv); + if (argc < 1) { + PyErr_Format(PyExc_ValueError, + "%s: argv must not be empty", func_name); + return NULL; + } + + if (!PyMapping_Check(env)) { + PyErr_Format(PyExc_TypeError, + "%s: environment must be a mapping object", func_name); + goto exit; + } + + argvlist = parse_arglist(argv, &argc); + if (argvlist == NULL) { + goto exit; + } + if (!argvlist[0][0]) { + PyErr_Format(PyExc_ValueError, + "%s: argv first element cannot be empty", func_name); + goto exit; + } + + envlist = parse_envlist(env, &envc); + if (envlist == NULL) { + goto exit; + } + + if (file_actions != NULL && file_actions != Py_None) { + /* There is a bug in old versions of glibc that makes some of the + * helper functions for manipulating file actions not copy the provided + * buffers. The problem is that posix_spawn_file_actions_addopen does not + * copy the value of path for some old versions of glibc (<2.20). + * The use of temp_buffer here is a workaround that keeps the + * python objects that own the buffers alive until posix_spawn gets called. + * Check https://bugs.python.org/issue33630 and + * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/ + temp_buffer = PyList_New(0); + if (!temp_buffer) { + goto exit; + } + if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) { + goto exit; + } + file_actionsp = &file_actions_buf; + } + + if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid, + setsigmask, setsigdef, scheduler, &attr)) { + goto exit; + } + attrp = &attr; + + if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) { + goto exit; + } + + _Py_BEGIN_SUPPRESS_IPH +#ifdef HAVE_POSIX_SPAWNP + if (use_posix_spawnp) { + err_code = posix_spawnp(&pid, path->narrow, + file_actionsp, attrp, argvlist, envlist); + } + else +#endif /* HAVE_POSIX_SPAWNP */ + { + err_code = posix_spawn(&pid, path->narrow, + file_actionsp, attrp, argvlist, envlist); + } + _Py_END_SUPPRESS_IPH + + if (err_code) { + errno = err_code; + PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object); + goto exit; + } +#ifdef _Py_MEMORY_SANITIZER + __msan_unpoison(&pid, sizeof(pid)); +#endif + result = PyLong_FromPid(pid); + +exit: + if (file_actionsp) { + (void)posix_spawn_file_actions_destroy(file_actionsp); + } + if (attrp) { + (void)posix_spawnattr_destroy(attrp); + } + if (envlist) { + free_string_array(envlist, envc); + } + if (argvlist) { + free_string_array(argvlist, argc); + } + Py_XDECREF(temp_buffer); + return result; +} + + +/*[clinic input] + +os.posix_spawn + path: path_t + Path of executable file. + argv: object + Tuple or list of strings. + env: object + Dictionary of strings mapping to strings. + / + * + file_actions: object(c_default='NULL') = () + A sequence of file action tuples. + setpgroup: object = NULL + The pgroup to use with the POSIX_SPAWN_SETPGROUP flag. + resetids: bool(accept={int}) = False + If the value is `true` the POSIX_SPAWN_RESETIDS will be activated. + setsid: bool(accept={int}) = False + If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated. + setsigmask: object(c_default='NULL') = () + The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag. + setsigdef: object(c_default='NULL') = () + The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag. + scheduler: object = NULL + A tuple with the scheduler policy (optional) and parameters. + +Execute the program specified by path in a new process. +[clinic start generated code]*/ + +static PyObject * +os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, + PyObject *env, PyObject *file_actions, + PyObject *setpgroup, int resetids, int setsid, + PyObject *setsigmask, PyObject *setsigdef, + PyObject *scheduler) +/*[clinic end generated code: output=14a1098c566bc675 input=8c6305619a00ad04]*/ +{ + return py_posix_spawn(0, module, path, argv, env, file_actions, + setpgroup, resetids, setsid, setsigmask, setsigdef, + scheduler); +} + #endif /* HAVE_POSIX_SPAWN */ + + + +#ifdef HAVE_POSIX_SPAWNP +/*[clinic input] + +os.posix_spawnp + path: path_t + Path of executable file. + argv: object + Tuple or list of strings. + env: object + Dictionary of strings mapping to strings. + / + * + file_actions: object(c_default='NULL') = () + A sequence of file action tuples. + setpgroup: object = NULL + The pgroup to use with the POSIX_SPAWN_SETPGROUP flag. + resetids: bool(accept={int}) = False + If the value is `True` the POSIX_SPAWN_RESETIDS will be activated. + setsid: bool(accept={int}) = False + If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated. + setsigmask: object(c_default='NULL') = () + The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag. + setsigdef: object(c_default='NULL') = () + The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag. + scheduler: object = NULL + A tuple with the scheduler policy (optional) and parameters. + +Execute the program specified by path in a new process. +[clinic start generated code]*/ + +static PyObject * +os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv, + PyObject *env, PyObject *file_actions, + PyObject *setpgroup, int resetids, int setsid, + PyObject *setsigmask, PyObject *setsigdef, + PyObject *scheduler) +/*[clinic end generated code: output=7b9aaefe3031238d input=c1911043a22028da]*/ +{ + return py_posix_spawn(1, module, path, argv, env, file_actions, + setpgroup, resetids, setsid, setsigmask, setsigdef, + scheduler); +} +#endif /* HAVE_POSIX_SPAWNP */ + +#ifdef HAVE_RTPSPAWN +static intptr_t +_rtp_spawn(int mode, const char *rtpFileName, const char *argv[], + const char *envp[]) +{ + RTP_ID rtpid; + int status; + pid_t res; + int async_err = 0; + + /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes. + uStackSize=0 cannot be used, the default stack size is too small for + Python. */ + if (envp) { + rtpid = rtpSpawn(rtpFileName, argv, envp, + 100, 0x1000000, 0, VX_FP_TASK); + } + else { + rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ, + 100, 0x1000000, 0, VX_FP_TASK); + } + if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) { + do { + res = waitpid((pid_t)rtpid, &status, 0); + } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + + if (res < 0) + return RTP_ID_ERROR; + return ((intptr_t)status); + } + return ((intptr_t)rtpid); +} +#endif + +#if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN) +/*[clinic input] +os.spawnv + + mode: int + Mode of process creation. + path: path_t + Path of executable file. + argv: object + Tuple or list of strings. + / + +Execute the program specified by path in a new process. +[clinic start generated code]*/ + +static PyObject * +os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv) +/*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/ +{ + EXECV_CHAR **argvlist; + int i; + Py_ssize_t argc; + intptr_t spawnval; + PyObject *(*getitem)(PyObject *, Py_ssize_t); + + /* spawnv has three arguments: (mode, path, argv), where + argv is a list or tuple of strings. */ + + if (PyList_Check(argv)) { + argc = PyList_Size(argv); + getitem = PyList_GetItem; + } + else if (PyTuple_Check(argv)) { + argc = PyTuple_Size(argv); + getitem = PyTuple_GetItem; + } + else { + PyErr_SetString(PyExc_TypeError, + "spawnv() arg 2 must be a tuple or list"); + return NULL; + } + if (argc == 0) { + PyErr_SetString(PyExc_ValueError, + "spawnv() arg 2 cannot be empty"); + return NULL; + } + + argvlist = PyMem_NEW(EXECV_CHAR *, argc+1); + if (argvlist == NULL) { + return PyErr_NoMemory(); + } + for (i = 0; i < argc; i++) { + if (!fsconvert_strdup((*getitem)(argv, i), + &argvlist[i])) { + free_string_array(argvlist, i); + PyErr_SetString( + PyExc_TypeError, + "spawnv() arg 2 must contain only strings"); + return NULL; + } + if (i == 0 && !argvlist[0][0]) { + free_string_array(argvlist, i + 1); + PyErr_SetString( + PyExc_ValueError, + "spawnv() arg 2 first element cannot be empty"); + return NULL; + } + } + argvlist[argc] = NULL; + +#if !defined(HAVE_RTPSPAWN) + if (mode == _OLD_P_OVERLAY) + mode = _P_OVERLAY; +#endif + + if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, + Py_None) < 0) { + free_string_array(argvlist, argc); + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH +#ifdef HAVE_WSPAWNV + spawnval = _wspawnv(mode, path->wide, argvlist); +#elif defined(HAVE_RTPSPAWN) + spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL); +#else + spawnval = _spawnv(mode, path->narrow, argvlist); +#endif + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + + free_string_array(argvlist, argc); + + if (spawnval == -1) + return posix_error(); + else + return Py_BuildValue(_Py_PARSE_INTPTR, spawnval); +} + +/*[clinic input] +os.spawnve + + mode: int + Mode of process creation. + path: path_t + Path of executable file. + argv: object + Tuple or list of strings. + env: object + Dictionary of strings mapping to strings. + / + +Execute the program specified by path in a new process. +[clinic start generated code]*/ + +static PyObject * +os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv, + PyObject *env) +/*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/ +{ + EXECV_CHAR **argvlist; + EXECV_CHAR **envlist; + PyObject *res = NULL; + Py_ssize_t argc, i, envc; + intptr_t spawnval; + PyObject *(*getitem)(PyObject *, Py_ssize_t); + Py_ssize_t lastarg = 0; + + /* spawnve has four arguments: (mode, path, argv, env), where + argv is a list or tuple of strings and env is a dictionary + like posix.environ. */ + + if (PyList_Check(argv)) { + argc = PyList_Size(argv); + getitem = PyList_GetItem; + } + else if (PyTuple_Check(argv)) { + argc = PyTuple_Size(argv); + getitem = PyTuple_GetItem; + } + else { + PyErr_SetString(PyExc_TypeError, + "spawnve() arg 2 must be a tuple or list"); + goto fail_0; + } + if (argc == 0) { + PyErr_SetString(PyExc_ValueError, + "spawnve() arg 2 cannot be empty"); + goto fail_0; + } + if (!PyMapping_Check(env)) { + PyErr_SetString(PyExc_TypeError, + "spawnve() arg 3 must be a mapping object"); + goto fail_0; + } + + argvlist = PyMem_NEW(EXECV_CHAR *, argc+1); + if (argvlist == NULL) { + PyErr_NoMemory(); + goto fail_0; + } + for (i = 0; i < argc; i++) { + if (!fsconvert_strdup((*getitem)(argv, i), + &argvlist[i])) + { + lastarg = i; + goto fail_1; + } + if (i == 0 && !argvlist[0][0]) { + lastarg = i + 1; + PyErr_SetString( + PyExc_ValueError, + "spawnv() arg 2 first element cannot be empty"); + goto fail_1; + } + } + lastarg = argc; + argvlist[argc] = NULL; + + envlist = parse_envlist(env, &envc); + if (envlist == NULL) + goto fail_1; + +#if !defined(HAVE_RTPSPAWN) + if (mode == _OLD_P_OVERLAY) + mode = _P_OVERLAY; +#endif + + if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) { + goto fail_2; + } + + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH +#ifdef HAVE_WSPAWNV + spawnval = _wspawnve(mode, path->wide, argvlist, envlist); +#elif defined(HAVE_RTPSPAWN) + spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, + (const char **)envlist); +#else + spawnval = _spawnve(mode, path->narrow, argvlist, envlist); +#endif + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + + if (spawnval == -1) + (void) posix_error(); + else + res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval); + + fail_2: + while (--envc >= 0) { + PyMem_Free(envlist[envc]); + } + PyMem_Free(envlist); + fail_1: + free_string_array(argvlist, lastarg); + fail_0: + return res; +} + +#endif /* HAVE_SPAWNV */ + +#ifdef HAVE_FORK + +/* Helper function to validate arguments. + Returns 0 on success. non-zero on failure with a TypeError raised. + If obj is non-NULL it must be callable. */ +static int +check_null_or_callable(PyObject *obj, const char* obj_name) +{ + if (obj && !PyCallable_Check(obj)) { + PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s", + obj_name, _PyType_Name(Py_TYPE(obj))); + return -1; + } + return 0; +} + +/*[clinic input] +os.register_at_fork + + * + before: object=NULL + A callable to be called in the parent before the fork() syscall. + after_in_child: object=NULL + A callable to be called in the child after fork(). + after_in_parent: object=NULL + A callable to be called in the parent after fork(). + +Register callables to be called when forking a new process. + +'before' callbacks are called in reverse order. +'after_in_child' and 'after_in_parent' callbacks are called in order. + +[clinic start generated code]*/ + +static PyObject * +os_register_at_fork_impl(PyObject *module, PyObject *before, + PyObject *after_in_child, PyObject *after_in_parent) +/*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/ +{ + PyInterpreterState *interp; + + if (!before && !after_in_child && !after_in_parent) { + PyErr_SetString(PyExc_TypeError, "At least one argument is required."); + return NULL; + } + if (check_null_or_callable(before, "before") || + check_null_or_callable(after_in_child, "after_in_child") || + check_null_or_callable(after_in_parent, "after_in_parent")) { + return NULL; + } + interp = _PyInterpreterState_GET(); + + if (register_at_forker(&interp->before_forkers, before)) { + return NULL; + } + if (register_at_forker(&interp->after_forkers_child, after_in_child)) { + return NULL; + } + if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) { + return NULL; + } + Py_RETURN_NONE; +} +#endif /* HAVE_FORK */ + + +#ifdef HAVE_FORK1 +/*[clinic input] +os.fork1 + +Fork a child process with a single multiplexed (i.e., not bound) thread. + +Return 0 to child process and PID of child to parent process. +[clinic start generated code]*/ + +static PyObject * +os_fork1_impl(PyObject *module) +/*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/ +{ + pid_t pid; + + if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) { + PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters"); + return NULL; + } + PyOS_BeforeFork(); + pid = fork1(); + if (pid == 0) { + /* child: this clobbers and resets the import lock. */ + PyOS_AfterFork_Child(); + } else { + /* parent: release the import lock. */ + PyOS_AfterFork_Parent(); + } + if (pid == -1) + return posix_error(); + return PyLong_FromPid(pid); +} +#endif /* HAVE_FORK1 */ + + +#ifdef HAVE_FORK +/*[clinic input] +os.fork + +Fork a child process. + +Return 0 to child process and PID of child to parent process. +[clinic start generated code]*/ + +static PyObject * +os_fork_impl(PyObject *module) +/*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/ +{ + pid_t pid; + PyInterpreterState *interp = _PyInterpreterState_GET(); + if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_FORK)) { + PyErr_SetString(PyExc_RuntimeError, + "fork not supported for isolated subinterpreters"); + return NULL; + } + if (PySys_Audit("os.fork", NULL) < 0) { + return NULL; + } + PyOS_BeforeFork(); + pid = fork(); + if (pid == 0) { + /* child: this clobbers and resets the import lock. */ + PyOS_AfterFork_Child(); + } else { + /* parent: release the import lock. */ + PyOS_AfterFork_Parent(); + } + if (pid == -1) + return posix_error(); + return PyLong_FromPid(pid); +} +#endif /* HAVE_FORK */ + + +#ifdef HAVE_SCHED_H +#ifdef HAVE_SCHED_GET_PRIORITY_MAX +/*[clinic input] +os.sched_get_priority_max + + policy: int + +Get the maximum scheduling priority for policy. +[clinic start generated code]*/ + +static PyObject * +os_sched_get_priority_max_impl(PyObject *module, int policy) +/*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/ +{ + int max; + + max = sched_get_priority_max(policy); + if (max < 0) + return posix_error(); + return PyLong_FromLong(max); +} + + +/*[clinic input] +os.sched_get_priority_min + + policy: int + +Get the minimum scheduling priority for policy. +[clinic start generated code]*/ + +static PyObject * +os_sched_get_priority_min_impl(PyObject *module, int policy) +/*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/ +{ + int min = sched_get_priority_min(policy); + if (min < 0) + return posix_error(); + return PyLong_FromLong(min); +} +#endif /* HAVE_SCHED_GET_PRIORITY_MAX */ + + +#ifdef HAVE_SCHED_SETSCHEDULER +/*[clinic input] +os.sched_getscheduler + pid: pid_t + / + +Get the scheduling policy for the process identified by pid. + +Passing 0 for pid returns the scheduling policy for the calling process. +[clinic start generated code]*/ + +static PyObject * +os_sched_getscheduler_impl(PyObject *module, pid_t pid) +/*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/ +{ + int policy; + + policy = sched_getscheduler(pid); + if (policy < 0) + return posix_error(); + return PyLong_FromLong(policy); +} +#endif /* HAVE_SCHED_SETSCHEDULER */ + + +#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) +/*[clinic input] +class os.sched_param "PyObject *" "SchedParamType" + +@classmethod +os.sched_param.__new__ + + sched_priority: object + A scheduling parameter. + +Currently has only one field: sched_priority +[clinic start generated code]*/ + +static PyObject * +os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority) +/*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/ +{ + PyObject *res; + + res = PyStructSequence_New(type); + if (!res) + return NULL; + PyStructSequence_SET_ITEM(res, 0, Py_NewRef(sched_priority)); + return res; +} + +PyDoc_VAR(os_sched_param__doc__); + +static PyStructSequence_Field sched_param_fields[] = { + {"sched_priority", "the scheduling priority"}, + {0} +}; + +static PyStructSequence_Desc sched_param_desc = { + "sched_param", /* name */ + os_sched_param__doc__, /* doc */ + sched_param_fields, + 1 +}; + +static int +convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res) +{ + long priority; + + if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) { + PyErr_SetString(PyExc_TypeError, "must have a sched_param object"); + return 0; + } + priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0)); + if (priority == -1 && PyErr_Occurred()) + return 0; + if (priority > INT_MAX || priority < INT_MIN) { + PyErr_SetString(PyExc_OverflowError, "sched_priority out of range"); + return 0; + } + res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int); + return 1; +} +#endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */ + + +#ifdef HAVE_SCHED_SETSCHEDULER +/*[clinic input] +os.sched_setscheduler + + pid: pid_t + policy: int + param as param_obj: object + / + +Set the scheduling policy for the process identified by pid. + +If pid is 0, the calling process is changed. +param is an instance of sched_param. +[clinic start generated code]*/ + +static PyObject * +os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy, + PyObject *param_obj) +/*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/ +{ + struct sched_param param; + if (!convert_sched_param(module, param_obj, ¶m)) { + return NULL; + } + + /* + ** sched_setscheduler() returns 0 in Linux, but the previous + ** scheduling policy under Solaris/Illumos, and others. + ** On error, -1 is returned in all Operating Systems. + */ + if (sched_setscheduler(pid, policy, ¶m) == -1) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SCHED_SETSCHEDULER*/ + + +#ifdef HAVE_SCHED_SETPARAM +/*[clinic input] +os.sched_getparam + pid: pid_t + / + +Returns scheduling parameters for the process identified by pid. + +If pid is 0, returns parameters for the calling process. +Return value is an instance of sched_param. +[clinic start generated code]*/ + +static PyObject * +os_sched_getparam_impl(PyObject *module, pid_t pid) +/*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/ +{ + struct sched_param param; + PyObject *result; + PyObject *priority; + + if (sched_getparam(pid, ¶m)) + return posix_error(); + PyObject *SchedParamType = get_posix_state(module)->SchedParamType; + result = PyStructSequence_New((PyTypeObject *)SchedParamType); + if (!result) + return NULL; + priority = PyLong_FromLong(param.sched_priority); + if (!priority) { + Py_DECREF(result); + return NULL; + } + PyStructSequence_SET_ITEM(result, 0, priority); + return result; +} + + +/*[clinic input] +os.sched_setparam + pid: pid_t + param as param_obj: object + / + +Set scheduling parameters for the process identified by pid. + +If pid is 0, sets parameters for the calling process. +param should be an instance of sched_param. +[clinic start generated code]*/ + +static PyObject * +os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj) +/*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/ +{ + struct sched_param param; + if (!convert_sched_param(module, param_obj, ¶m)) { + return NULL; + } + + if (sched_setparam(pid, ¶m)) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SCHED_SETPARAM */ + + +#ifdef HAVE_SCHED_RR_GET_INTERVAL +/*[clinic input] +os.sched_rr_get_interval -> double + pid: pid_t + / + +Return the round-robin quantum for the process identified by pid, in seconds. + +Value returned is a float. +[clinic start generated code]*/ + +static double +os_sched_rr_get_interval_impl(PyObject *module, pid_t pid) +/*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/ +{ + struct timespec interval; + if (sched_rr_get_interval(pid, &interval)) { + posix_error(); + return -1.0; + } +#ifdef _Py_MEMORY_SANITIZER + __msan_unpoison(&interval, sizeof(interval)); +#endif + return (double)interval.tv_sec + 1e-9*interval.tv_nsec; +} +#endif /* HAVE_SCHED_RR_GET_INTERVAL */ + + +/*[clinic input] +os.sched_yield + +Voluntarily relinquish the CPU. +[clinic start generated code]*/ + +static PyObject * +os_sched_yield_impl(PyObject *module) +/*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/ +{ + int result; + Py_BEGIN_ALLOW_THREADS + result = sched_yield(); + Py_END_ALLOW_THREADS + if (result < 0) { + return posix_error(); + } + Py_RETURN_NONE; +} + +#ifdef HAVE_SCHED_SETAFFINITY +/* The minimum number of CPUs allocated in a cpu_set_t */ +static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT; + +/*[clinic input] +os.sched_setaffinity + pid: pid_t + mask : object + / + +Set the CPU affinity of the process identified by pid to mask. + +mask should be an iterable of integers identifying CPUs. +[clinic start generated code]*/ + +static PyObject * +os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask) +/*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/ +{ + int ncpus; + size_t setsize; + cpu_set_t *cpu_set = NULL; + PyObject *iterator = NULL, *item; + + iterator = PyObject_GetIter(mask); + if (iterator == NULL) + return NULL; + + ncpus = NCPUS_START; + setsize = CPU_ALLOC_SIZE(ncpus); + cpu_set = CPU_ALLOC(ncpus); + if (cpu_set == NULL) { + PyErr_NoMemory(); + goto error; + } + CPU_ZERO_S(setsize, cpu_set); + + while ((item = PyIter_Next(iterator))) { + long cpu; + if (!PyLong_Check(item)) { + PyErr_Format(PyExc_TypeError, + "expected an iterator of ints, " + "but iterator yielded %R", + Py_TYPE(item)); + Py_DECREF(item); + goto error; + } + cpu = PyLong_AsLong(item); + Py_DECREF(item); + if (cpu < 0) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_ValueError, "negative CPU number"); + goto error; + } + if (cpu > INT_MAX - 1) { + PyErr_SetString(PyExc_OverflowError, "CPU number too large"); + goto error; + } + if (cpu >= ncpus) { + /* Grow CPU mask to fit the CPU number */ + int newncpus = ncpus; + cpu_set_t *newmask; + size_t newsetsize; + while (newncpus <= cpu) { + if (newncpus > INT_MAX / 2) + newncpus = cpu + 1; + else + newncpus = newncpus * 2; + } + newmask = CPU_ALLOC(newncpus); + if (newmask == NULL) { + PyErr_NoMemory(); + goto error; + } + newsetsize = CPU_ALLOC_SIZE(newncpus); + CPU_ZERO_S(newsetsize, newmask); + memcpy(newmask, cpu_set, setsize); + CPU_FREE(cpu_set); + setsize = newsetsize; + cpu_set = newmask; + ncpus = newncpus; + } + CPU_SET_S(cpu, setsize, cpu_set); + } + if (PyErr_Occurred()) { + goto error; + } + Py_CLEAR(iterator); + + if (sched_setaffinity(pid, setsize, cpu_set)) { + posix_error(); + goto error; + } + CPU_FREE(cpu_set); + Py_RETURN_NONE; + +error: + if (cpu_set) + CPU_FREE(cpu_set); + Py_XDECREF(iterator); + return NULL; +} + + +/*[clinic input] +os.sched_getaffinity + pid: pid_t + / + +Return the affinity of the process identified by pid (or the current process if zero). + +The affinity is returned as a set of CPU identifiers. +[clinic start generated code]*/ + +static PyObject * +os_sched_getaffinity_impl(PyObject *module, pid_t pid) +/*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/ +{ + int cpu, ncpus, count; + size_t setsize; + cpu_set_t *mask = NULL; + PyObject *res = NULL; + + ncpus = NCPUS_START; + while (1) { + setsize = CPU_ALLOC_SIZE(ncpus); + mask = CPU_ALLOC(ncpus); + if (mask == NULL) + return PyErr_NoMemory(); + if (sched_getaffinity(pid, setsize, mask) == 0) + break; + CPU_FREE(mask); + if (errno != EINVAL) + return posix_error(); + if (ncpus > INT_MAX / 2) { + PyErr_SetString(PyExc_OverflowError, "could not allocate " + "a large enough CPU set"); + return NULL; + } + ncpus = ncpus * 2; + } + + res = PySet_New(NULL); + if (res == NULL) + goto error; + for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) { + if (CPU_ISSET_S(cpu, setsize, mask)) { + PyObject *cpu_num = PyLong_FromLong(cpu); + --count; + if (cpu_num == NULL) + goto error; + if (PySet_Add(res, cpu_num)) { + Py_DECREF(cpu_num); + goto error; + } + Py_DECREF(cpu_num); + } + } + CPU_FREE(mask); + return res; + +error: + if (mask) + CPU_FREE(mask); + Py_XDECREF(res); + return NULL; +} + +#endif /* HAVE_SCHED_SETAFFINITY */ + +#endif /* HAVE_SCHED_H */ + + +/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */ +#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX) +# define DEV_PTY_FILE "/dev/ptc" +# define HAVE_DEV_PTMX +#else +# define DEV_PTY_FILE "/dev/ptmx" +#endif + +#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) +#ifdef HAVE_PTY_H +#include +#ifdef HAVE_UTMP_H +#include +#endif /* HAVE_UTMP_H */ +#elif defined(HAVE_LIBUTIL_H) +#include +#elif defined(HAVE_UTIL_H) +#include +#endif /* HAVE_PTY_H */ +#ifdef HAVE_STROPTS_H +#include +#endif +#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */ + + +#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) +/*[clinic input] +os.openpty + +Open a pseudo-terminal. + +Return a tuple of (master_fd, slave_fd) containing open file descriptors +for both the master and slave ends. +[clinic start generated code]*/ + +static PyObject * +os_openpty_impl(PyObject *module) +/*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/ +{ + int master_fd = -1, slave_fd = -1; +#ifndef HAVE_OPENPTY + char * slave_name; +#endif +#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY) + PyOS_sighandler_t sig_saved; +#if defined(__sun) && defined(__SVR4) + extern char *ptsname(int fildes); +#endif +#endif + +#ifdef HAVE_OPENPTY + if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0) + goto posix_error; + + if (_Py_set_inheritable(master_fd, 0, NULL) < 0) + goto error; + if (_Py_set_inheritable(slave_fd, 0, NULL) < 0) + goto error; + +#elif defined(HAVE__GETPTY) + slave_name = _getpty(&master_fd, O_RDWR, 0666, 0); + if (slave_name == NULL) + goto posix_error; + if (_Py_set_inheritable(master_fd, 0, NULL) < 0) + goto error; + + slave_fd = _Py_open(slave_name, O_RDWR); + if (slave_fd < 0) + goto error; + +#else + master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */ + if (master_fd < 0) + goto posix_error; + + sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL); + + /* change permission of slave */ + if (grantpt(master_fd) < 0) { + PyOS_setsig(SIGCHLD, sig_saved); + goto posix_error; + } + + /* unlock slave */ + if (unlockpt(master_fd) < 0) { + PyOS_setsig(SIGCHLD, sig_saved); + goto posix_error; + } + + PyOS_setsig(SIGCHLD, sig_saved); + + slave_name = ptsname(master_fd); /* get name of slave */ + if (slave_name == NULL) + goto posix_error; + + slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */ + if (slave_fd == -1) + goto error; + + if (_Py_set_inheritable(master_fd, 0, NULL) < 0) + goto posix_error; + +#if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC) + ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */ + ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */ +#ifndef __hpux + ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */ +#endif /* __hpux */ +#endif /* HAVE_CYGWIN */ +#endif /* HAVE_OPENPTY */ + + return Py_BuildValue("(ii)", master_fd, slave_fd); + +posix_error: + posix_error(); +error: + if (master_fd != -1) + close(master_fd); + if (slave_fd != -1) + close(slave_fd); + return NULL; +} +#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */ + + +#if defined(HAVE_SETSID) && defined(TIOCSCTTY) +#define HAVE_FALLBACK_LOGIN_TTY 1 +#endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */ + +#if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) +/*[clinic input] +os.login_tty + + fd: fildes + / + +Prepare the tty of which fd is a file descriptor for a new login session. + +Make the calling process a session leader; make the tty the +controlling tty, the stdin, the stdout, and the stderr of the +calling process; close fd. +[clinic start generated code]*/ + +static PyObject * +os_login_tty_impl(PyObject *module, int fd) +/*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/ +{ +#ifdef HAVE_LOGIN_TTY + if (login_tty(fd) == -1) { + return posix_error(); + } +#else /* defined(HAVE_FALLBACK_LOGIN_TTY) */ + /* Establish a new session. */ + if (setsid() == -1) { + return posix_error(); + } + + /* The tty becomes the controlling terminal. */ + if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) { + return posix_error(); + } + + /* The tty becomes stdin/stdout/stderr */ + if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) { + return posix_error(); + } + if (fd > 2) { + close(fd); + } +#endif /* HAVE_LOGIN_TTY */ + Py_RETURN_NONE; +} +#endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */ + + +#ifdef HAVE_FORKPTY +/*[clinic input] +os.forkpty + +Fork a new process with a new pseudo-terminal as controlling tty. + +Returns a tuple of (pid, master_fd). +Like fork(), return pid of 0 to the child process, +and pid of child to the parent process. +To both, return fd of newly opened pseudo-terminal. +[clinic start generated code]*/ + +static PyObject * +os_forkpty_impl(PyObject *module) +/*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/ +{ + int master_fd = -1; + pid_t pid; + + if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) { + PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters"); + return NULL; + } + if (PySys_Audit("os.forkpty", NULL) < 0) { + return NULL; + } + PyOS_BeforeFork(); + pid = forkpty(&master_fd, NULL, NULL, NULL); + if (pid == 0) { + /* child: this clobbers and resets the import lock. */ + PyOS_AfterFork_Child(); + } else { + /* parent: release the import lock. */ + PyOS_AfterFork_Parent(); + } + if (pid == -1) { + return posix_error(); + } + return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd); +} +#endif /* HAVE_FORKPTY */ + + +#ifdef HAVE_GETEGID +/*[clinic input] +os.getegid + +Return the current process's effective group id. +[clinic start generated code]*/ + +static PyObject * +os_getegid_impl(PyObject *module) +/*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/ +{ + return _PyLong_FromGid(getegid()); +} +#endif /* HAVE_GETEGID */ + + +#ifdef HAVE_GETEUID +/*[clinic input] +os.geteuid + +Return the current process's effective user id. +[clinic start generated code]*/ + +static PyObject * +os_geteuid_impl(PyObject *module) +/*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/ +{ + return _PyLong_FromUid(geteuid()); +} +#endif /* HAVE_GETEUID */ + + +#ifdef HAVE_GETGID +/*[clinic input] +os.getgid + +Return the current process's group id. +[clinic start generated code]*/ + +static PyObject * +os_getgid_impl(PyObject *module) +/*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/ +{ + return _PyLong_FromGid(getgid()); +} +#endif /* HAVE_GETGID */ + + +#ifdef HAVE_GETPID +/*[clinic input] +os.getpid + +Return the current process id. +[clinic start generated code]*/ + +static PyObject * +os_getpid_impl(PyObject *module) +/*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/ +{ + return PyLong_FromPid(getpid()); +} +#endif /* HAVE_GETPID */ + +#ifdef NGROUPS_MAX +#define MAX_GROUPS NGROUPS_MAX +#else + /* defined to be 16 on Solaris7, so this should be a small number */ +#define MAX_GROUPS 64 +#endif + +#ifdef HAVE_GETGROUPLIST + +#ifdef __APPLE__ +/*[clinic input] +os.getgrouplist + + user: str + username to lookup + group as basegid: int + base group id of the user + / + +Returns a list of groups to which a user belongs. +[clinic start generated code]*/ + +static PyObject * +os_getgrouplist_impl(PyObject *module, const char *user, int basegid) +/*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/ +#else +/*[clinic input] +os.getgrouplist + + user: str + username to lookup + group as basegid: gid_t + base group id of the user + / + +Returns a list of groups to which a user belongs. +[clinic start generated code]*/ + +static PyObject * +os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid) +/*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/ +#endif +{ + int i, ngroups; + PyObject *list; +#ifdef __APPLE__ + int *groups; +#else + gid_t *groups; +#endif + + /* + * NGROUPS_MAX is defined by POSIX.1 as the maximum + * number of supplimental groups a users can belong to. + * We have to increment it by one because + * getgrouplist() returns both the supplemental groups + * and the primary group, i.e. all of the groups the + * user belongs to. + */ + ngroups = 1 + MAX_GROUPS; + + while (1) { +#ifdef __APPLE__ + groups = PyMem_New(int, ngroups); +#else + groups = PyMem_New(gid_t, ngroups); +#endif + if (groups == NULL) { + return PyErr_NoMemory(); + } + + int old_ngroups = ngroups; + if (getgrouplist(user, basegid, groups, &ngroups) != -1) { + /* Success */ + break; + } + + /* getgrouplist() fails if the group list is too small */ + PyMem_Free(groups); + + if (ngroups > old_ngroups) { + /* If the group list is too small, the glibc implementation of + getgrouplist() sets ngroups to the total number of groups and + returns -1. */ + } + else { + /* Double the group list size */ + if (ngroups > INT_MAX / 2) { + return PyErr_NoMemory(); + } + ngroups *= 2; + } + + /* Retry getgrouplist() with a larger group list */ + } + +#ifdef _Py_MEMORY_SANITIZER + /* Clang memory sanitizer libc intercepts don't know getgrouplist. */ + __msan_unpoison(&ngroups, sizeof(ngroups)); + __msan_unpoison(groups, ngroups*sizeof(*groups)); +#endif + + list = PyList_New(ngroups); + if (list == NULL) { + PyMem_Free(groups); + return NULL; + } + + for (i = 0; i < ngroups; i++) { +#ifdef __APPLE__ + PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]); +#else + PyObject *o = _PyLong_FromGid(groups[i]); +#endif + if (o == NULL) { + Py_DECREF(list); + PyMem_Free(groups); + return NULL; + } + PyList_SET_ITEM(list, i, o); + } + + PyMem_Free(groups); + + return list; +} +#endif /* HAVE_GETGROUPLIST */ + + +#ifdef HAVE_GETGROUPS +/*[clinic input] +os.getgroups + +Return list of supplemental group IDs for the process. +[clinic start generated code]*/ + +static PyObject * +os_getgroups_impl(PyObject *module) +/*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/ +{ + // Call getgroups with length 0 to get the actual number of groups + int n = getgroups(0, NULL); + if (n < 0) { + return posix_error(); + } + + if (n == 0) { + return PyList_New(0); + } + + gid_t *grouplist = PyMem_New(gid_t, n); + if (grouplist == NULL) { + return PyErr_NoMemory(); + } + + n = getgroups(n, grouplist); + if (n == -1) { + PyMem_Free(grouplist); + return posix_error(); + } + + PyObject *result = PyList_New(n); + if (result == NULL) { + goto error; + } + + for (int i = 0; i < n; ++i) { + PyObject *group = _PyLong_FromGid(grouplist[i]); + if (group == NULL) { + goto error; + } + PyList_SET_ITEM(result, i, group); + } + PyMem_Free(grouplist); + + return result; + +error: + PyMem_Free(grouplist); + Py_XDECREF(result); + return NULL; +} +#endif /* HAVE_GETGROUPS */ + +#ifdef HAVE_INITGROUPS +#ifdef __APPLE__ +/*[clinic input] +os.initgroups + + username as oname: FSConverter + gid: int + / + +Initialize the group access list. + +Call the system initgroups() to initialize the group access list with all of +the groups of which the specified username is a member, plus the specified +group id. +[clinic start generated code]*/ + +static PyObject * +os_initgroups_impl(PyObject *module, PyObject *oname, int gid) +/*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/ +#else +/*[clinic input] +os.initgroups + + username as oname: FSConverter + gid: gid_t + / + +Initialize the group access list. + +Call the system initgroups() to initialize the group access list with all of +the groups of which the specified username is a member, plus the specified +group id. +[clinic start generated code]*/ + +static PyObject * +os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid) +/*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/ +#endif +{ + const char *username = PyBytes_AS_STRING(oname); + + if (initgroups(username, gid) == -1) + return PyErr_SetFromErrno(PyExc_OSError); + + Py_RETURN_NONE; +} +#endif /* HAVE_INITGROUPS */ + + +#ifdef HAVE_GETPGID +/*[clinic input] +os.getpgid + + pid: pid_t + +Call the system call getpgid(), and return the result. +[clinic start generated code]*/ + +static PyObject * +os_getpgid_impl(PyObject *module, pid_t pid) +/*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/ +{ + pid_t pgid = getpgid(pid); + if (pgid < 0) + return posix_error(); + return PyLong_FromPid(pgid); +} +#endif /* HAVE_GETPGID */ + + +#ifdef HAVE_GETPGRP +/*[clinic input] +os.getpgrp + +Return the current process group id. +[clinic start generated code]*/ + +static PyObject * +os_getpgrp_impl(PyObject *module) +/*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/ +{ +#ifdef GETPGRP_HAVE_ARG + return PyLong_FromPid(getpgrp(0)); +#else /* GETPGRP_HAVE_ARG */ + return PyLong_FromPid(getpgrp()); +#endif /* GETPGRP_HAVE_ARG */ +} +#endif /* HAVE_GETPGRP */ + + +#ifdef HAVE_SETPGRP +/*[clinic input] +os.setpgrp + +Make the current process the leader of its process group. +[clinic start generated code]*/ + +static PyObject * +os_setpgrp_impl(PyObject *module) +/*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/ +{ +#ifdef SETPGRP_HAVE_ARG + if (setpgrp(0, 0) < 0) +#else /* SETPGRP_HAVE_ARG */ + if (setpgrp() < 0) +#endif /* SETPGRP_HAVE_ARG */ + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETPGRP */ + +#ifdef HAVE_GETPPID + +#ifdef MS_WINDOWS +#include + +static PyObject* +win32_getppid() +{ + HANDLE snapshot; + pid_t mypid; + PyObject* result = NULL; + BOOL have_record; + PROCESSENTRY32 pe; + + mypid = getpid(); /* This function never fails */ + + snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (snapshot == INVALID_HANDLE_VALUE) + return PyErr_SetFromWindowsErr(GetLastError()); + + pe.dwSize = sizeof(pe); + have_record = Process32First(snapshot, &pe); + while (have_record) { + if (mypid == (pid_t)pe.th32ProcessID) { + /* We could cache the ulong value in a static variable. */ + result = PyLong_FromPid((pid_t)pe.th32ParentProcessID); + break; + } + + have_record = Process32Next(snapshot, &pe); + } + + /* If our loop exits and our pid was not found (result will be NULL) + * then GetLastError will return ERROR_NO_MORE_FILES. This is an + * error anyway, so let's raise it. */ + if (!result) + result = PyErr_SetFromWindowsErr(GetLastError()); + + CloseHandle(snapshot); + + return result; +} +#endif /*MS_WINDOWS*/ + + +/*[clinic input] +os.getppid + +Return the parent's process id. + +If the parent process has already exited, Windows machines will still +return its id; others systems will return the id of the 'init' process (1). +[clinic start generated code]*/ + +static PyObject * +os_getppid_impl(PyObject *module) +/*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/ +{ +#ifdef MS_WINDOWS + return win32_getppid(); +#else + return PyLong_FromPid(getppid()); +#endif +} +#endif /* HAVE_GETPPID */ + + +#ifdef HAVE_GETLOGIN +/*[clinic input] +os.getlogin + +Return the actual login name. +[clinic start generated code]*/ + +static PyObject * +os_getlogin_impl(PyObject *module) +/*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/ +{ + PyObject *result = NULL; +#ifdef MS_WINDOWS + wchar_t user_name[UNLEN + 1]; + DWORD num_chars = Py_ARRAY_LENGTH(user_name); + + if (GetUserNameW(user_name, &num_chars)) { + /* num_chars is the number of unicode chars plus null terminator */ + result = PyUnicode_FromWideChar(user_name, num_chars - 1); + } + else + result = PyErr_SetFromWindowsErr(GetLastError()); +#else + char *name; + int old_errno = errno; + + errno = 0; + name = getlogin(); + if (name == NULL) { + if (errno) + posix_error(); + else + PyErr_SetString(PyExc_OSError, "unable to determine login name"); + } + else + result = PyUnicode_DecodeFSDefault(name); + errno = old_errno; +#endif + return result; +} +#endif /* HAVE_GETLOGIN */ + + +#ifdef HAVE_GETUID +/*[clinic input] +os.getuid + +Return the current process's user id. +[clinic start generated code]*/ + +static PyObject * +os_getuid_impl(PyObject *module) +/*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/ +{ + return _PyLong_FromUid(getuid()); +} +#endif /* HAVE_GETUID */ + + +#ifdef MS_WINDOWS +#define HAVE_KILL +#endif /* MS_WINDOWS */ + +#ifdef HAVE_KILL +/*[clinic input] +os.kill + + pid: pid_t + signal: Py_ssize_t + / + +Kill a process with a signal. +[clinic start generated code]*/ + +static PyObject * +os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal) +/*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/ +{ + if (PySys_Audit("os.kill", "in", pid, signal) < 0) { + return NULL; + } +#ifndef MS_WINDOWS + if (kill(pid, (int)signal) == -1) { + return posix_error(); + } + + // Check immediately if the signal was sent to the current process. + // Don't micro-optimize pid == getpid(), since PyErr_SetString() check + // is cheap. + if (PyErr_CheckSignals()) { + return NULL; + } + + Py_RETURN_NONE; +#else /* !MS_WINDOWS */ + PyObject *result; + DWORD sig = (DWORD)signal; + DWORD err; + HANDLE handle; + + /* Console processes which share a common console can be sent CTRL+C or + CTRL+BREAK events, provided they handle said events. */ + if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) { + if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) { + err = GetLastError(); + PyErr_SetFromWindowsErr(err); + } + else + Py_RETURN_NONE; + } + + /* If the signal is outside of what GenerateConsoleCtrlEvent can use, + attempt to open and terminate the process. */ + handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid); + if (handle == NULL) { + err = GetLastError(); + return PyErr_SetFromWindowsErr(err); + } + + if (TerminateProcess(handle, sig) == 0) { + err = GetLastError(); + result = PyErr_SetFromWindowsErr(err); + } else { + result = Py_NewRef(Py_None); + } + + CloseHandle(handle); + return result; +#endif /* !MS_WINDOWS */ +} +#endif /* HAVE_KILL */ + + +#ifdef HAVE_KILLPG +/*[clinic input] +os.killpg + + pgid: pid_t + signal: int + / + +Kill a process group with a signal. +[clinic start generated code]*/ + +static PyObject * +os_killpg_impl(PyObject *module, pid_t pgid, int signal) +/*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/ +{ + if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) { + return NULL; + } + /* XXX some man pages make the `pgid` parameter an int, others + a pid_t. Since getpgrp() returns a pid_t, we assume killpg should + take the same type. Moreover, pid_t is always at least as wide as + int (else compilation of this module fails), which is safe. */ + if (killpg(pgid, signal) == -1) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_KILLPG */ + + +#ifdef HAVE_PLOCK +#ifdef HAVE_SYS_LOCK_H +#include +#endif + +/*[clinic input] +os.plock + op: int + / + +Lock program segments into memory."); +[clinic start generated code]*/ + +static PyObject * +os_plock_impl(PyObject *module, int op) +/*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/ +{ + if (plock(op) == -1) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_PLOCK */ + + +#ifdef HAVE_SETUID +/*[clinic input] +os.setuid + + uid: uid_t + / + +Set the current process's user id. +[clinic start generated code]*/ + +static PyObject * +os_setuid_impl(PyObject *module, uid_t uid) +/*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/ +{ + if (setuid(uid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETUID */ + + +#ifdef HAVE_SETEUID +/*[clinic input] +os.seteuid + + euid: uid_t + / + +Set the current process's effective user id. +[clinic start generated code]*/ + +static PyObject * +os_seteuid_impl(PyObject *module, uid_t euid) +/*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/ +{ + if (seteuid(euid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETEUID */ + + +#ifdef HAVE_SETEGID +/*[clinic input] +os.setegid + + egid: gid_t + / + +Set the current process's effective group id. +[clinic start generated code]*/ + +static PyObject * +os_setegid_impl(PyObject *module, gid_t egid) +/*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/ +{ + if (setegid(egid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETEGID */ + + +#ifdef HAVE_SETREUID +/*[clinic input] +os.setreuid + + ruid: uid_t + euid: uid_t + / + +Set the current process's real and effective user ids. +[clinic start generated code]*/ + +static PyObject * +os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid) +/*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/ +{ + if (setreuid(ruid, euid) < 0) { + return posix_error(); + } else { + Py_RETURN_NONE; + } +} +#endif /* HAVE_SETREUID */ + + +#ifdef HAVE_SETREGID +/*[clinic input] +os.setregid + + rgid: gid_t + egid: gid_t + / + +Set the current process's real and effective group ids. +[clinic start generated code]*/ + +static PyObject * +os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid) +/*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/ +{ + if (setregid(rgid, egid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETREGID */ + + +#ifdef HAVE_SETGID +/*[clinic input] +os.setgid + gid: gid_t + / + +Set the current process's group id. +[clinic start generated code]*/ + +static PyObject * +os_setgid_impl(PyObject *module, gid_t gid) +/*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/ +{ + if (setgid(gid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETGID */ + + +#ifdef HAVE_SETGROUPS +/*[clinic input] +os.setgroups + + groups: object + / + +Set the groups of the current process to list. +[clinic start generated code]*/ + +static PyObject * +os_setgroups(PyObject *module, PyObject *groups) +/*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/ +{ + if (!PySequence_Check(groups)) { + PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence"); + return NULL; + } + Py_ssize_t len = PySequence_Size(groups); + if (len < 0) { + return NULL; + } + if (len > MAX_GROUPS) { + PyErr_SetString(PyExc_ValueError, "too many groups"); + return NULL; + } + + gid_t *grouplist = PyMem_New(gid_t, len); + for (Py_ssize_t i = 0; i < len; i++) { + PyObject *elem; + elem = PySequence_GetItem(groups, i); + if (!elem) { + PyMem_Free(grouplist); + return NULL; + } + if (!PyLong_Check(elem)) { + PyErr_SetString(PyExc_TypeError, + "groups must be integers"); + Py_DECREF(elem); + PyMem_Free(grouplist); + return NULL; + } else { + if (!_Py_Gid_Converter(elem, &grouplist[i])) { + Py_DECREF(elem); + PyMem_Free(grouplist); + return NULL; + } + } + Py_DECREF(elem); + } + + if (setgroups(len, grouplist) < 0) { + PyMem_Free(grouplist); + return posix_error(); + } + PyMem_Free(grouplist); + Py_RETURN_NONE; +} +#endif /* HAVE_SETGROUPS */ + +#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) +static PyObject * +wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru) +{ + PyObject *result; + PyObject *struct_rusage; + + if (pid == -1) + return posix_error(); + + // If wait succeeded but no child was ready to report status, ru will not + // have been populated. + if (pid == 0) { + memset(ru, 0, sizeof(*ru)); + } + + struct_rusage = _PyImport_GetModuleAttrString("resource", "struct_rusage"); + if (struct_rusage == NULL) + return NULL; + + /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */ + result = PyStructSequence_New((PyTypeObject*) struct_rusage); + Py_DECREF(struct_rusage); + if (!result) + return NULL; + +#ifndef doubletime +#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001) +#endif + + PyStructSequence_SET_ITEM(result, 0, + PyFloat_FromDouble(doubletime(ru->ru_utime))); + PyStructSequence_SET_ITEM(result, 1, + PyFloat_FromDouble(doubletime(ru->ru_stime))); +#define SET_INT(result, index, value)\ + PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value)) + SET_INT(result, 2, ru->ru_maxrss); + SET_INT(result, 3, ru->ru_ixrss); + SET_INT(result, 4, ru->ru_idrss); + SET_INT(result, 5, ru->ru_isrss); + SET_INT(result, 6, ru->ru_minflt); + SET_INT(result, 7, ru->ru_majflt); + SET_INT(result, 8, ru->ru_nswap); + SET_INT(result, 9, ru->ru_inblock); + SET_INT(result, 10, ru->ru_oublock); + SET_INT(result, 11, ru->ru_msgsnd); + SET_INT(result, 12, ru->ru_msgrcv); + SET_INT(result, 13, ru->ru_nsignals); + SET_INT(result, 14, ru->ru_nvcsw); + SET_INT(result, 15, ru->ru_nivcsw); +#undef SET_INT + + if (PyErr_Occurred()) { + Py_DECREF(result); + return NULL; + } + + return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result); +} +#endif /* HAVE_WAIT3 || HAVE_WAIT4 */ + + +#ifdef HAVE_WAIT3 +/*[clinic input] +os.wait3 + + options: int +Wait for completion of a child process. + +Returns a tuple of information about the child process: + (pid, status, rusage) +[clinic start generated code]*/ + +static PyObject * +os_wait3_impl(PyObject *module, int options) +/*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/ +{ + pid_t pid; + struct rusage ru; + int async_err = 0; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + do { + Py_BEGIN_ALLOW_THREADS + pid = wait3(&status, options, &ru); + Py_END_ALLOW_THREADS + } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (pid < 0) + return (!async_err) ? posix_error() : NULL; + + return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru); +} +#endif /* HAVE_WAIT3 */ + + +#ifdef HAVE_WAIT4 +/*[clinic input] + +os.wait4 + + pid: pid_t + options: int + +Wait for completion of a specific child process. + +Returns a tuple of information about the child process: + (pid, status, rusage) +[clinic start generated code]*/ + +static PyObject * +os_wait4_impl(PyObject *module, pid_t pid, int options) +/*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/ +{ + pid_t res; + struct rusage ru; + int async_err = 0; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + do { + Py_BEGIN_ALLOW_THREADS + res = wait4(pid, &status, options, &ru); + Py_END_ALLOW_THREADS + } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (res < 0) + return (!async_err) ? posix_error() : NULL; + + return wait_helper(module, res, WAIT_STATUS_INT(status), &ru); +} +#endif /* HAVE_WAIT4 */ + + +#if defined(HAVE_WAITID) && !defined(__APPLE__) +/*[clinic input] +os.waitid + + idtype: idtype_t + Must be one of be P_PID, P_PGID or P_ALL. + id: id_t + The id to wait on. + options: int + Constructed from the ORing of one or more of WEXITED, WSTOPPED + or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT. + / + +Returns the result of waiting for a process or processes. + +Returns either waitid_result or None if WNOHANG is specified and there are +no children in a waitable state. +[clinic start generated code]*/ + +static PyObject * +os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options) +/*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/ +{ + PyObject *result; + int res; + int async_err = 0; + siginfo_t si; + si.si_pid = 0; + + do { + Py_BEGIN_ALLOW_THREADS + res = waitid(idtype, id, &si, options); + Py_END_ALLOW_THREADS + } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (res < 0) + return (!async_err) ? posix_error() : NULL; + + if (si.si_pid == 0) + Py_RETURN_NONE; + + PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType; + result = PyStructSequence_New((PyTypeObject *)WaitidResultType); + if (!result) + return NULL; + + PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid)); + PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid)); + PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo))); + PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status))); + PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code))); + if (PyErr_Occurred()) { + Py_DECREF(result); + return NULL; + } + + return result; +} +#endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */ + + +#if defined(HAVE_WAITPID) +/*[clinic input] +os.waitpid + pid: pid_t + options: int + / + +Wait for completion of a given child process. + +Returns a tuple of information regarding the child process: + (pid, status) + +The options argument is ignored on Windows. +[clinic start generated code]*/ + +static PyObject * +os_waitpid_impl(PyObject *module, pid_t pid, int options) +/*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/ +{ + pid_t res; + int async_err = 0; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + do { + Py_BEGIN_ALLOW_THREADS + res = waitpid(pid, &status, options); + Py_END_ALLOW_THREADS + } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (res < 0) + return (!async_err) ? posix_error() : NULL; + + return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status)); +} +#elif defined(HAVE_CWAIT) +/* MS C has a variant of waitpid() that's usable for most purposes. */ +/*[clinic input] +os.waitpid + pid: intptr_t + options: int + / + +Wait for completion of a given process. + +Returns a tuple of information regarding the process: + (pid, status << 8) + +The options argument is ignored on Windows. +[clinic start generated code]*/ + +static PyObject * +os_waitpid_impl(PyObject *module, intptr_t pid, int options) +/*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/ +{ + int status; + intptr_t res; + int async_err = 0; + + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + res = _cwait(&status, pid, options); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (res < 0) + return (!async_err) ? posix_error() : NULL; + + unsigned long long ustatus = (unsigned int)status; + + /* shift the status left a byte so this is more like the POSIX waitpid */ + return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8); +} +#endif + + +#ifdef HAVE_WAIT +/*[clinic input] +os.wait + +Wait for completion of a child process. + +Returns a tuple of information about the child process: + (pid, status) +[clinic start generated code]*/ + +static PyObject * +os_wait_impl(PyObject *module) +/*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/ +{ + pid_t pid; + int async_err = 0; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + do { + Py_BEGIN_ALLOW_THREADS + pid = wait(&status); + Py_END_ALLOW_THREADS + } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (pid < 0) + return (!async_err) ? posix_error() : NULL; + + return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status)); +} +#endif /* HAVE_WAIT */ + +#if defined(__linux__) && defined(__NR_pidfd_open) +/*[clinic input] +os.pidfd_open + pid: pid_t + flags: unsigned_int = 0 + +Return a file descriptor referring to the process *pid*. + +The descriptor can be used to perform process management without races and +signals. +[clinic start generated code]*/ + +static PyObject * +os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags) +/*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/ +{ + int fd = syscall(__NR_pidfd_open, pid, flags); + if (fd < 0) { + return posix_error(); + } + return PyLong_FromLong(fd); +} +#endif + + +#ifdef HAVE_SETNS +/*[clinic input] +os.setns + fd: fildes + A file descriptor to a namespace. + nstype: int = 0 + Type of namespace. + +Move the calling thread into different namespaces. +[clinic start generated code]*/ + +static PyObject * +os_setns_impl(PyObject *module, int fd, int nstype) +/*[clinic end generated code: output=5dbd055bfb66ecd0 input=42787871226bf3ee]*/ +{ + int res; + + Py_BEGIN_ALLOW_THREADS + res = setns(fd, nstype); + Py_END_ALLOW_THREADS + + if (res != 0) { + return posix_error(); + } + + Py_RETURN_NONE; +} +#endif + + +#ifdef HAVE_UNSHARE +/*[clinic input] +os.unshare + flags: int + Namespaces to be unshared. + +Disassociate parts of a process (or thread) execution context. +[clinic start generated code]*/ + +static PyObject * +os_unshare_impl(PyObject *module, int flags) +/*[clinic end generated code: output=1b3177906dd237ee input=9e065db3232b8b1b]*/ +{ + int res; + + Py_BEGIN_ALLOW_THREADS + res = unshare(flags); + Py_END_ALLOW_THREADS + + if (res != 0) { + return posix_error(); + } + + Py_RETURN_NONE; +} +#endif + + +#if defined(HAVE_READLINK) || defined(MS_WINDOWS) +/*[clinic input] +os.readlink + + path: path_t + * + dir_fd: dir_fd(requires='readlinkat') = None + +Return a string representing the path to which the symbolic link points. + +If dir_fd is not None, it should be a file descriptor open to a directory, +and path should be relative; path will then be relative to that directory. + +dir_fd may not be implemented on your platform. If it is unavailable, +using it will raise a NotImplementedError. +[clinic start generated code]*/ + +static PyObject * +os_readlink_impl(PyObject *module, path_t *path, int dir_fd) +/*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/ +{ +#if defined(HAVE_READLINK) + char buffer[MAXPATHLEN+1]; + ssize_t length; +#ifdef HAVE_READLINKAT + int readlinkat_unavailable = 0; +#endif + + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_READLINKAT + if (dir_fd != DEFAULT_DIR_FD) { + if (HAVE_READLINKAT_RUNTIME) { + length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN); + } else { + readlinkat_unavailable = 1; + } + } else +#endif + length = readlink(path->narrow, buffer, MAXPATHLEN); + Py_END_ALLOW_THREADS + +#ifdef HAVE_READLINKAT + if (readlinkat_unavailable) { + argument_unavailable_error(NULL, "dir_fd"); + return NULL; + } +#endif + + if (length < 0) { + return path_error(path); + } + buffer[length] = '\0'; + + if (PyUnicode_Check(path->object)) + return PyUnicode_DecodeFSDefaultAndSize(buffer, length); + else + return PyBytes_FromStringAndSize(buffer, length); +#elif defined(MS_WINDOWS) + DWORD n_bytes_returned; + DWORD io_result = 0; + HANDLE reparse_point_handle; + char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer; + PyObject *result = NULL; + + /* First get a handle to the reparse point */ + Py_BEGIN_ALLOW_THREADS + reparse_point_handle = CreateFileW( + path->wide, + 0, + 0, + 0, + OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, + 0); + if (reparse_point_handle != INVALID_HANDLE_VALUE) { + /* New call DeviceIoControl to read the reparse point */ + io_result = DeviceIoControl( + reparse_point_handle, + FSCTL_GET_REPARSE_POINT, + 0, 0, /* in buffer */ + target_buffer, sizeof(target_buffer), + &n_bytes_returned, + 0 /* we're not using OVERLAPPED_IO */ + ); + CloseHandle(reparse_point_handle); + } + Py_END_ALLOW_THREADS + + if (io_result == 0) { + return path_error(path); + } + + wchar_t *name = NULL; + Py_ssize_t nameLen = 0; + if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK) + { + name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer + + rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset); + nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t); + } + else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) + { + name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer + + rdb->MountPointReparseBuffer.SubstituteNameOffset); + nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t); + } + else + { + PyErr_SetString(PyExc_ValueError, "not a symbolic link"); + } + if (name) { + if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) { + /* Our buffer is mutable, so this is okay */ + name[1] = L'\\'; + } + result = PyUnicode_FromWideChar(name, nameLen); + if (result && path->narrow) { + Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); + } + } + return result; +#endif +} +#endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */ + +#if defined(MS_WINDOWS) + +/* Remove the last portion of the path - return 0 on success */ +static int +_dirnameW(WCHAR *path) +{ + WCHAR *ptr; + size_t length = wcsnlen_s(path, MAX_PATH); + if (length == MAX_PATH) { + return -1; + } + + /* walk the path from the end until a backslash is encountered */ + for(ptr = path + length; ptr != path; ptr--) { + if (*ptr == L'\\' || *ptr == L'/') { + break; + } + } + *ptr = 0; + return 0; +} + +#endif + +#ifdef HAVE_SYMLINK + +#if defined(MS_WINDOWS) + +/* Is this path absolute? */ +static int +_is_absW(const WCHAR *path) +{ + return path[0] == L'\\' || path[0] == L'/' || + (path[0] && path[1] == L':'); +} + +/* join root and rest with a backslash - return 0 on success */ +static int +_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest) +{ + if (_is_absW(rest)) { + return wcscpy_s(dest_path, MAX_PATH, rest); + } + + if (wcscpy_s(dest_path, MAX_PATH, root)) { + return -1; + } + + if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) { + return -1; + } + + return wcscat_s(dest_path, MAX_PATH, rest); +} + +/* Return True if the path at src relative to dest is a directory */ +static int +_check_dirW(LPCWSTR src, LPCWSTR dest) +{ + WIN32_FILE_ATTRIBUTE_DATA src_info; + WCHAR dest_parent[MAX_PATH]; + WCHAR src_resolved[MAX_PATH] = L""; + + /* dest_parent = os.path.dirname(dest) */ + if (wcscpy_s(dest_parent, MAX_PATH, dest) || + _dirnameW(dest_parent)) { + return 0; + } + /* src_resolved = os.path.join(dest_parent, src) */ + if (_joinW(src_resolved, dest_parent, src)) { + return 0; + } + return ( + GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info) + && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY + ); +} +#endif + + +/*[clinic input] +os.symlink + src: path_t + dst: path_t + target_is_directory: bool = False + * + dir_fd: dir_fd(requires='symlinkat')=None + +# "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\ + +Create a symbolic link pointing to src named dst. + +target_is_directory is required on Windows if the target is to be + interpreted as a directory. (On Windows, symlink requires + Windows 6.0 or greater, and raises a NotImplementedError otherwise.) + target_is_directory is ignored on non-Windows platforms. + +If dir_fd is not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that directory. +dir_fd may not be implemented on your platform. + If it is unavailable, using it will raise a NotImplementedError. + +[clinic start generated code]*/ + +static PyObject * +os_symlink_impl(PyObject *module, path_t *src, path_t *dst, + int target_is_directory, int dir_fd) +/*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/ +{ +#ifdef MS_WINDOWS + DWORD result; + DWORD flags = 0; + + /* Assumed true, set to false if detected to not be available. */ + static int windows_has_symlink_unprivileged_flag = TRUE; +#else + int result; +#ifdef HAVE_SYMLINKAT + int symlinkat_unavailable = 0; +#endif +#endif + + if (PySys_Audit("os.symlink", "OOi", src->object, dst->object, + dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { + return NULL; + } + +#ifdef MS_WINDOWS + + if (windows_has_symlink_unprivileged_flag) { + /* Allow non-admin symlinks if system allows it. */ + flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE; + } + + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + /* if src is a directory, ensure flags==1 (target_is_directory bit) */ + if (target_is_directory || _check_dirW(src->wide, dst->wide)) { + flags |= SYMBOLIC_LINK_FLAG_DIRECTORY; + } + + result = CreateSymbolicLinkW(dst->wide, src->wide, flags); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + + if (windows_has_symlink_unprivileged_flag && !result && + ERROR_INVALID_PARAMETER == GetLastError()) { + + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + /* This error might be caused by + SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported. + Try again, and update windows_has_symlink_unprivileged_flag if we + are successful this time. + + NOTE: There is a risk of a race condition here if there are other + conditions than the flag causing ERROR_INVALID_PARAMETER, and + another process (or thread) changes that condition in between our + calls to CreateSymbolicLink. + */ + flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE); + result = CreateSymbolicLinkW(dst->wide, src->wide, flags); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + + if (result || ERROR_INVALID_PARAMETER != GetLastError()) { + windows_has_symlink_unprivileged_flag = FALSE; + } + } + + if (!result) + return path_error2(src, dst); + +#else + + if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { + PyErr_SetString(PyExc_ValueError, + "symlink: src and dst must be the same type"); + return NULL; + } + + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_SYMLINKAT + if (dir_fd != DEFAULT_DIR_FD) { + if (HAVE_SYMLINKAT_RUNTIME) { + result = symlinkat(src->narrow, dir_fd, dst->narrow); + } else { + symlinkat_unavailable = 1; + } + } else +#endif + result = symlink(src->narrow, dst->narrow); + Py_END_ALLOW_THREADS + +#ifdef HAVE_SYMLINKAT + if (symlinkat_unavailable) { + argument_unavailable_error(NULL, "dir_fd"); + return NULL; + } +#endif + + if (result) + return path_error2(src, dst); +#endif + + Py_RETURN_NONE; +} +#endif /* HAVE_SYMLINK */ + + + + +static PyStructSequence_Field times_result_fields[] = { + {"user", "user time"}, + {"system", "system time"}, + {"children_user", "user time of children"}, + {"children_system", "system time of children"}, + {"elapsed", "elapsed time since an arbitrary point in the past"}, + {NULL} +}; + +PyDoc_STRVAR(times_result__doc__, +"times_result: Result from os.times().\n\n\ +This object may be accessed either as a tuple of\n\ + (user, system, children_user, children_system, elapsed),\n\ +or via the attributes user, system, children_user, children_system,\n\ +and elapsed.\n\ +\n\ +See os.times for more information."); + +static PyStructSequence_Desc times_result_desc = { + "times_result", /* name */ + times_result__doc__, /* doc */ + times_result_fields, + 5 +}; + +#ifdef MS_WINDOWS +#define HAVE_TIMES /* mandatory, for the method table */ +#endif + +#ifdef HAVE_TIMES + +static PyObject * +build_times_result(PyObject *module, double user, double system, + double children_user, double children_system, + double elapsed) +{ + PyObject *TimesResultType = get_posix_state(module)->TimesResultType; + PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType); + if (value == NULL) + return NULL; + +#define SET(i, field) \ + { \ + PyObject *o = PyFloat_FromDouble(field); \ + if (!o) { \ + Py_DECREF(value); \ + return NULL; \ + } \ + PyStructSequence_SET_ITEM(value, i, o); \ + } \ + + SET(0, user); + SET(1, system); + SET(2, children_user); + SET(3, children_system); + SET(4, elapsed); + +#undef SET + + return value; +} + + +#ifndef MS_WINDOWS +#define NEED_TICKS_PER_SECOND +static long ticks_per_second = -1; +#endif /* MS_WINDOWS */ + +/*[clinic input] +os.times + +Return a collection containing process timing information. + +The object returned behaves like a named tuple with these fields: + (utime, stime, cutime, cstime, elapsed_time) +All fields are floating point numbers. +[clinic start generated code]*/ + +static PyObject * +os_times_impl(PyObject *module) +/*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/ +#ifdef MS_WINDOWS +{ + FILETIME create, exit, kernel, user; + HANDLE hProc; + hProc = GetCurrentProcess(); + GetProcessTimes(hProc, &create, &exit, &kernel, &user); + /* The fields of a FILETIME structure are the hi and lo part + of a 64-bit value expressed in 100 nanosecond units. + 1e7 is one second in such units; 1e-7 the inverse. + 429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7. + */ + return build_times_result(module, + (double)(user.dwHighDateTime*429.4967296 + + user.dwLowDateTime*1e-7), + (double)(kernel.dwHighDateTime*429.4967296 + + kernel.dwLowDateTime*1e-7), + (double)0, + (double)0, + (double)0); +} +#else /* MS_WINDOWS */ +{ + + + struct tms t; + clock_t c; + errno = 0; + c = times(&t); + if (c == (clock_t) -1) + return posix_error(); + return build_times_result(module, + (double)t.tms_utime / ticks_per_second, + (double)t.tms_stime / ticks_per_second, + (double)t.tms_cutime / ticks_per_second, + (double)t.tms_cstime / ticks_per_second, + (double)c / ticks_per_second); +} +#endif /* MS_WINDOWS */ +#endif /* HAVE_TIMES */ + + +#ifdef HAVE_GETSID +/*[clinic input] +os.getsid + + pid: pid_t + / + +Call the system call getsid(pid) and return the result. +[clinic start generated code]*/ + +static PyObject * +os_getsid_impl(PyObject *module, pid_t pid) +/*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/ +{ + int sid; + sid = getsid(pid); + if (sid < 0) + return posix_error(); + return PyLong_FromLong((long)sid); +} +#endif /* HAVE_GETSID */ + + +#ifdef HAVE_SETSID +/*[clinic input] +os.setsid + +Call the system call setsid(). +[clinic start generated code]*/ + +static PyObject * +os_setsid_impl(PyObject *module) +/*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/ +{ + if (setsid() < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETSID */ + + +#ifdef HAVE_SETPGID +/*[clinic input] +os.setpgid + + pid: pid_t + pgrp: pid_t + / + +Call the system call setpgid(pid, pgrp). +[clinic start generated code]*/ + +static PyObject * +os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp) +/*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/ +{ + if (setpgid(pid, pgrp) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETPGID */ + + +#ifdef HAVE_TCGETPGRP +/*[clinic input] +os.tcgetpgrp + + fd: int + / + +Return the process group associated with the terminal specified by fd. +[clinic start generated code]*/ + +static PyObject * +os_tcgetpgrp_impl(PyObject *module, int fd) +/*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/ +{ + pid_t pgid = tcgetpgrp(fd); + if (pgid < 0) + return posix_error(); + return PyLong_FromPid(pgid); +} +#endif /* HAVE_TCGETPGRP */ + + +#ifdef HAVE_TCSETPGRP +/*[clinic input] +os.tcsetpgrp + + fd: int + pgid: pid_t + / + +Set the process group associated with the terminal specified by fd. +[clinic start generated code]*/ + +static PyObject * +os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid) +/*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/ +{ + if (tcsetpgrp(fd, pgid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_TCSETPGRP */ + +/* Functions acting on file descriptors */ + +#ifdef O_CLOEXEC +extern int _Py_open_cloexec_works; +#endif + + +/*[clinic input] +os.open -> int + path: path_t + flags: int + mode: int = 0o777 + * + dir_fd: dir_fd(requires='openat') = None + +# "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\ + +Open a file for low level IO. Returns a file descriptor (integer). + +If dir_fd is not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that directory. +dir_fd may not be implemented on your platform. + If it is unavailable, using it will raise a NotImplementedError. +[clinic start generated code]*/ + +static int +os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd) +/*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/ +{ + int fd; + int async_err = 0; +#ifdef HAVE_OPENAT + int openat_unavailable = 0; +#endif + +#ifdef O_CLOEXEC + int *atomic_flag_works = &_Py_open_cloexec_works; +#elif !defined(MS_WINDOWS) + int *atomic_flag_works = NULL; +#endif + +#ifdef MS_WINDOWS + flags |= O_NOINHERIT; +#elif defined(O_CLOEXEC) + flags |= O_CLOEXEC; +#endif + + if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) { + return -1; + } + + _Py_BEGIN_SUPPRESS_IPH + do { + Py_BEGIN_ALLOW_THREADS +#ifdef MS_WINDOWS + fd = _wopen(path->wide, flags, mode); +#else +#ifdef HAVE_OPENAT + if (dir_fd != DEFAULT_DIR_FD) { + if (HAVE_OPENAT_RUNTIME) { + fd = openat(dir_fd, path->narrow, flags, mode); + + } else { + openat_unavailable = 1; + fd = -1; + } + } else +#endif /* HAVE_OPENAT */ + fd = open(path->narrow, flags, mode); +#endif /* !MS_WINDOWS */ + Py_END_ALLOW_THREADS + } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + _Py_END_SUPPRESS_IPH + +#ifdef HAVE_OPENAT + if (openat_unavailable) { + argument_unavailable_error(NULL, "dir_fd"); + return -1; + } +#endif + + if (fd < 0) { + if (!async_err) + PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object); + return -1; + } + +#ifndef MS_WINDOWS + if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) { + close(fd); + return -1; + } +#endif + + return fd; +} + + +/*[clinic input] +os.close + + fd: int + +Close a file descriptor. +[clinic start generated code]*/ + +static PyObject * +os_close_impl(PyObject *module, int fd) +/*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/ +{ + int res; + /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/ + * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html + * for more details. + */ + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + res = close(fd); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error(); + Py_RETURN_NONE; +} + +/*[clinic input] +os.closerange + + fd_low: int + fd_high: int + / + +Closes all file descriptors in [fd_low, fd_high), ignoring errors. +[clinic start generated code]*/ + +static PyObject * +os_closerange_impl(PyObject *module, int fd_low, int fd_high) +/*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/ +{ + Py_BEGIN_ALLOW_THREADS + _Py_closerange(fd_low, fd_high - 1); + Py_END_ALLOW_THREADS + Py_RETURN_NONE; +} + + +/*[clinic input] +os.dup -> int + + fd: int + / + +Return a duplicate of a file descriptor. +[clinic start generated code]*/ + +static int +os_dup_impl(PyObject *module, int fd) +/*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/ +{ + return _Py_dup(fd); +} + +// dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS(). +// dup2.c provides working dup2() if and only if F_DUPFD is available. +#if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS)) +/*[clinic input] +os.dup2 -> int + fd: int + fd2: int + inheritable: bool=True + +Duplicate file descriptor. +[clinic start generated code]*/ + +static int +os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable) +/*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/ +{ + int res = 0; +#if defined(HAVE_DUP3) && \ + !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)) + /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */ + static int dup3_works = -1; +#endif + + if (fd < 0 || fd2 < 0) { + posix_error(); + return -1; + } + + /* dup2() can fail with EINTR if the target FD is already open, because it + * then has to be closed. See os_close_impl() for why we don't handle EINTR + * upon close(), and therefore below. + */ +#ifdef MS_WINDOWS + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + res = dup2(fd, fd2); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + if (res < 0) { + posix_error(); + return -1; + } + res = fd2; // msvcrt dup2 returns 0 on success. + + /* Character files like console cannot be make non-inheritable */ + if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) { + close(fd2); + return -1; + } + +#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC) + Py_BEGIN_ALLOW_THREADS + if (!inheritable) + res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2); + else + res = dup2(fd, fd2); + Py_END_ALLOW_THREADS + if (res < 0) { + posix_error(); + return -1; + } + +#else + +#ifdef HAVE_DUP3 + if (!inheritable && dup3_works != 0) { + Py_BEGIN_ALLOW_THREADS + res = dup3(fd, fd2, O_CLOEXEC); + Py_END_ALLOW_THREADS + if (res < 0) { + if (dup3_works == -1) + dup3_works = (errno != ENOSYS); + if (dup3_works) { + posix_error(); + return -1; + } + } + } + + if (inheritable || dup3_works == 0) + { +#endif + Py_BEGIN_ALLOW_THREADS + res = dup2(fd, fd2); + Py_END_ALLOW_THREADS + if (res < 0) { + posix_error(); + return -1; + } + + if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) { + close(fd2); + return -1; + } +#ifdef HAVE_DUP3 + } +#endif + +#endif + + return res; +} +#endif + + +#ifdef HAVE_LOCKF +/*[clinic input] +os.lockf + + fd: int + An open file descriptor. + command: int + One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST. + length: Py_off_t + The number of bytes to lock, starting at the current position. + / + +Apply, test or remove a POSIX lock on an open file descriptor. + +[clinic start generated code]*/ + +static PyObject * +os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length) +/*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/ +{ + int res; + + if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + res = lockf(fd, command, length); + Py_END_ALLOW_THREADS + + if (res < 0) + return posix_error(); + + Py_RETURN_NONE; +} +#endif /* HAVE_LOCKF */ + + +/*[clinic input] +os.lseek -> Py_off_t + + fd: int + position: Py_off_t + how: int + / + +Set the position of a file descriptor. Return the new position. + +Return the new cursor position in number of bytes +relative to the beginning of the file. +[clinic start generated code]*/ + +static Py_off_t +os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how) +/*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/ +{ + Py_off_t result; + +#ifdef SEEK_SET + /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ + switch (how) { + case 0: how = SEEK_SET; break; + case 1: how = SEEK_CUR; break; + case 2: how = SEEK_END; break; + } +#endif /* SEEK_END */ + + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH +#ifdef MS_WINDOWS + result = _lseeki64(fd, position, how); +#else + result = lseek(fd, position, how); +#endif + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + if (result < 0) + posix_error(); + + return result; +} + + +/*[clinic input] +os.read + fd: int + length: Py_ssize_t + / + +Read from a file descriptor. Returns a bytes object. +[clinic start generated code]*/ + +static PyObject * +os_read_impl(PyObject *module, int fd, Py_ssize_t length) +/*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/ +{ + Py_ssize_t n; + PyObject *buffer; + + if (length < 0) { + errno = EINVAL; + return posix_error(); + } + + length = Py_MIN(length, _PY_READ_MAX); + + buffer = PyBytes_FromStringAndSize((char *)NULL, length); + if (buffer == NULL) + return NULL; + + n = _Py_read(fd, PyBytes_AS_STRING(buffer), length); + if (n == -1) { + Py_DECREF(buffer); + return NULL; + } + + if (n != length) + _PyBytes_Resize(&buffer, n); + + return buffer; +} + +#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \ + || defined(__APPLE__))) \ + || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \ + || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2) +static int +iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type) +{ + Py_ssize_t i, j; + + *iov = PyMem_New(struct iovec, cnt); + if (*iov == NULL) { + PyErr_NoMemory(); + return -1; + } + + *buf = PyMem_New(Py_buffer, cnt); + if (*buf == NULL) { + PyMem_Free(*iov); + PyErr_NoMemory(); + return -1; + } + + for (i = 0; i < cnt; i++) { + PyObject *item = PySequence_GetItem(seq, i); + if (item == NULL) + goto fail; + if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) { + Py_DECREF(item); + goto fail; + } + Py_DECREF(item); + (*iov)[i].iov_base = (*buf)[i].buf; + (*iov)[i].iov_len = (*buf)[i].len; + } + return 0; + +fail: + PyMem_Free(*iov); + for (j = 0; j < i; j++) { + PyBuffer_Release(&(*buf)[j]); + } + PyMem_Free(*buf); + return -1; +} + +static void +iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt) +{ + int i; + PyMem_Free(iov); + for (i = 0; i < cnt; i++) { + PyBuffer_Release(&buf[i]); + } + PyMem_Free(buf); +} +#endif + + +#ifdef HAVE_READV +/*[clinic input] +os.readv -> Py_ssize_t + + fd: int + buffers: object + / + +Read from a file descriptor fd into an iterable of buffers. + +The buffers should be mutable buffers accepting bytes. +readv will transfer data into each buffer until it is full +and then move on to the next buffer in the sequence to hold +the rest of the data. + +readv returns the total number of bytes read, +which may be less than the total capacity of all the buffers. +[clinic start generated code]*/ + +static Py_ssize_t +os_readv_impl(PyObject *module, int fd, PyObject *buffers) +/*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/ +{ + Py_ssize_t cnt, n; + int async_err = 0; + struct iovec *iov; + Py_buffer *buf; + + if (!PySequence_Check(buffers)) { + PyErr_SetString(PyExc_TypeError, + "readv() arg 2 must be a sequence"); + return -1; + } + + cnt = PySequence_Size(buffers); + if (cnt < 0) + return -1; + + if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) + return -1; + + do { + Py_BEGIN_ALLOW_THREADS + n = readv(fd, iov, cnt); + Py_END_ALLOW_THREADS + } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + + iov_cleanup(iov, buf, cnt); + if (n < 0) { + if (!async_err) + posix_error(); + return -1; + } + + return n; +} +#endif /* HAVE_READV */ + + +#ifdef HAVE_PREAD +/*[clinic input] +os.pread + + fd: int + length: Py_ssize_t + offset: Py_off_t + / + +Read a number of bytes from a file descriptor starting at a particular offset. + +Read length bytes from file descriptor fd, starting at offset bytes from +the beginning of the file. The file offset remains unchanged. +[clinic start generated code]*/ + +static PyObject * +os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset) +/*[clinic end generated code: output=3f875c1eef82e32f input=85cb4a5589627144]*/ +{ + Py_ssize_t n; + int async_err = 0; + PyObject *buffer; + + if (length < 0) { + errno = EINVAL; + return posix_error(); + } + buffer = PyBytes_FromStringAndSize((char *)NULL, length); + if (buffer == NULL) + return NULL; + + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + n = pread(fd, PyBytes_AS_STRING(buffer), length, offset); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + + if (n < 0) { + Py_DECREF(buffer); + return (!async_err) ? posix_error() : NULL; + } + if (n != length) + _PyBytes_Resize(&buffer, n); + return buffer; +} +#endif /* HAVE_PREAD */ + +#if defined(HAVE_PREADV) || defined (HAVE_PREADV2) +/*[clinic input] +os.preadv -> Py_ssize_t + + fd: int + buffers: object + offset: Py_off_t + flags: int = 0 + / + +Reads from a file descriptor into a number of mutable bytes-like objects. + +Combines the functionality of readv() and pread(). As readv(), it will +transfer data into each buffer until it is full and then move on to the next +buffer in the sequence to hold the rest of the data. Its fourth argument, +specifies the file offset at which the input operation is to be performed. It +will return the total number of bytes read (which can be less than the total +capacity of all the objects). + +The flags argument contains a bitwise OR of zero or more of the following flags: + +- RWF_HIPRI +- RWF_NOWAIT + +Using non-zero flags requires Linux 4.6 or newer. +[clinic start generated code]*/ + +static Py_ssize_t +os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, + int flags) +/*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/ +{ + Py_ssize_t cnt, n; + int async_err = 0; + struct iovec *iov; + Py_buffer *buf; + + if (!PySequence_Check(buffers)) { + PyErr_SetString(PyExc_TypeError, + "preadv2() arg 2 must be a sequence"); + return -1; + } + + cnt = PySequence_Size(buffers); + if (cnt < 0) { + return -1; + } + +#ifndef HAVE_PREADV2 + if(flags != 0) { + argument_unavailable_error("preadv2", "flags"); + return -1; + } +#endif + + if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) { + return -1; + } +#ifdef HAVE_PREADV2 + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + n = preadv2(fd, iov, cnt, offset, flags); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); +#else + do { +#ifdef __APPLE__ +/* This entire function will be removed from the module dict when the API + * is not available. + */ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +#pragma clang diagnostic ignored "-Wunguarded-availability-new" +#endif + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + n = preadv(fd, iov, cnt, offset); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + +#ifdef __APPLE__ +#pragma clang diagnostic pop +#endif + +#endif + + iov_cleanup(iov, buf, cnt); + if (n < 0) { + if (!async_err) { + posix_error(); + } + return -1; + } + + return n; +} +#endif /* HAVE_PREADV */ + + +/*[clinic input] +os.write -> Py_ssize_t + + fd: int + data: Py_buffer + / + +Write a bytes object to a file descriptor. +[clinic start generated code]*/ + +static Py_ssize_t +os_write_impl(PyObject *module, int fd, Py_buffer *data) +/*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/ +{ + return _Py_write(fd, data->buf, data->len); +} + +#ifdef HAVE_SENDFILE +#ifdef __APPLE__ +/*[clinic input] +os.sendfile + + out_fd: int + in_fd: int + offset: Py_off_t + count as sbytes: Py_off_t + headers: object(c_default="NULL") = () + trailers: object(c_default="NULL") = () + flags: int = 0 + +Copy count bytes from file descriptor in_fd to file descriptor out_fd. +[clinic start generated code]*/ + +static PyObject * +os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset, + Py_off_t sbytes, PyObject *headers, PyObject *trailers, + int flags) +/*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/ +#elif defined(__FreeBSD__) || defined(__DragonFly__) +/*[clinic input] +os.sendfile + + out_fd: int + in_fd: int + offset: Py_off_t + count: Py_ssize_t + headers: object(c_default="NULL") = () + trailers: object(c_default="NULL") = () + flags: int = 0 + +Copy count bytes from file descriptor in_fd to file descriptor out_fd. +[clinic start generated code]*/ + +static PyObject * +os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset, + Py_ssize_t count, PyObject *headers, PyObject *trailers, + int flags) +/*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/ +#else +/*[clinic input] +os.sendfile + + out_fd: int + in_fd: int + offset as offobj: object + count: Py_ssize_t + +Copy count bytes from file descriptor in_fd to file descriptor out_fd. +[clinic start generated code]*/ + +static PyObject * +os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj, + Py_ssize_t count) +/*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/ +#endif +{ + Py_ssize_t ret; + int async_err = 0; + +#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) +#ifndef __APPLE__ + off_t sbytes; +#endif + Py_buffer *hbuf, *tbuf; + struct sf_hdtr sf; + + sf.headers = NULL; + sf.trailers = NULL; + + if (headers != NULL) { + if (!PySequence_Check(headers)) { + PyErr_SetString(PyExc_TypeError, + "sendfile() headers must be a sequence"); + return NULL; + } else { + Py_ssize_t i = PySequence_Size(headers); + if (i < 0) + return NULL; + if (i > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "sendfile() header is too large"); + return NULL; + } + if (i > 0) { + sf.hdr_cnt = (int)i; + if (iov_setup(&(sf.headers), &hbuf, + headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0) + return NULL; +#ifdef __APPLE__ + for (i = 0; i < sf.hdr_cnt; i++) { + Py_ssize_t blen = sf.headers[i].iov_len; +# define OFF_T_MAX 0x7fffffffffffffff + if (sbytes >= OFF_T_MAX - blen) { + PyErr_SetString(PyExc_OverflowError, + "sendfile() header is too large"); + return NULL; + } + sbytes += blen; + } +#endif + } + } + } + if (trailers != NULL) { + if (!PySequence_Check(trailers)) { + PyErr_SetString(PyExc_TypeError, + "sendfile() trailers must be a sequence"); + return NULL; + } else { + Py_ssize_t i = PySequence_Size(trailers); + if (i < 0) + return NULL; + if (i > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "sendfile() trailer is too large"); + return NULL; + } + if (i > 0) { + sf.trl_cnt = (int)i; + if (iov_setup(&(sf.trailers), &tbuf, + trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0) + return NULL; + } + } + } + + _Py_BEGIN_SUPPRESS_IPH + do { + Py_BEGIN_ALLOW_THREADS +#ifdef __APPLE__ + ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags); +#else + ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags); +#endif + Py_END_ALLOW_THREADS + } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + _Py_END_SUPPRESS_IPH + + if (sf.headers != NULL) + iov_cleanup(sf.headers, hbuf, sf.hdr_cnt); + if (sf.trailers != NULL) + iov_cleanup(sf.trailers, tbuf, sf.trl_cnt); + + if (ret < 0) { + if ((errno == EAGAIN) || (errno == EBUSY)) { + if (sbytes != 0) { + // some data has been sent + goto done; + } + else { + // no data has been sent; upper application is supposed + // to retry on EAGAIN or EBUSY + return posix_error(); + } + } + return (!async_err) ? posix_error() : NULL; + } + goto done; + +done: + #if !defined(HAVE_LARGEFILE_SUPPORT) + return Py_BuildValue("l", sbytes); + #else + return Py_BuildValue("L", sbytes); + #endif + +#else +#ifdef __linux__ + if (offobj == Py_None) { + do { + Py_BEGIN_ALLOW_THREADS + ret = sendfile(out_fd, in_fd, NULL, count); + Py_END_ALLOW_THREADS + } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (ret < 0) + return (!async_err) ? posix_error() : NULL; + return Py_BuildValue("n", ret); + } +#endif + off_t offset; + if (!Py_off_t_converter(offobj, &offset)) + return NULL; + +#if defined(__sun) && defined(__SVR4) + // On Solaris, sendfile raises EINVAL rather than returning 0 + // when the offset is equal or bigger than the in_fd size. + struct stat st; + + do { + Py_BEGIN_ALLOW_THREADS + ret = fstat(in_fd, &st); + Py_END_ALLOW_THREADS + } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (ret < 0) + return (!async_err) ? posix_error() : NULL; + + if (offset >= st.st_size) { + return Py_BuildValue("i", 0); + } + + // On illumos specifically sendfile() may perform a partial write but + // return -1/an error (in one confirmed case the destination socket + // had a 5 second timeout set and errno was EAGAIN) and it's on the client + // code to check if the offset parameter was modified by sendfile(). + // + // We need this variable to track said change. + off_t original_offset = offset; +#endif + + do { + Py_BEGIN_ALLOW_THREADS + ret = sendfile(out_fd, in_fd, &offset, count); +#if defined(__sun) && defined(__SVR4) + // This handles illumos-specific sendfile() partial write behavior, + // see a comment above for more details. + if (ret < 0 && offset != original_offset) { + ret = offset - original_offset; + } +#endif + Py_END_ALLOW_THREADS + } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (ret < 0) + return (!async_err) ? posix_error() : NULL; + return Py_BuildValue("n", ret); +#endif +} +#endif /* HAVE_SENDFILE */ + + +#if defined(__APPLE__) +/*[clinic input] +os._fcopyfile + + in_fd: int + out_fd: int + flags: int + / + +Efficiently copy content or metadata of 2 regular file descriptors (macOS). +[clinic start generated code]*/ + +static PyObject * +os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags) +/*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/ +{ + int ret; + + Py_BEGIN_ALLOW_THREADS + ret = fcopyfile(in_fd, out_fd, NULL, flags); + Py_END_ALLOW_THREADS + if (ret < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif + + +/*[clinic input] +os.fstat + + fd : int + +Perform a stat system call on the given file descriptor. + +Like stat(), but for an open file descriptor. +Equivalent to os.stat(fd). +[clinic start generated code]*/ + +static PyObject * +os_fstat_impl(PyObject *module, int fd) +/*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/ +{ + STRUCT_STAT st; + int res; + int async_err = 0; + + do { + Py_BEGIN_ALLOW_THREADS + res = FSTAT(fd, &st); + Py_END_ALLOW_THREADS + } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (res != 0) { +#ifdef MS_WINDOWS + return PyErr_SetFromWindowsErr(0); +#else + return (!async_err) ? posix_error() : NULL; +#endif + } + + return _pystat_fromstructstat(module, &st); +} + + +/*[clinic input] +os.isatty -> bool + fd: int + / + +Return True if the fd is connected to a terminal. + +Return True if the file descriptor is an open file descriptor +connected to the slave end of a terminal. +[clinic start generated code]*/ + +static int +os_isatty_impl(PyObject *module, int fd) +/*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/ +{ + int return_value; + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + return_value = isatty(fd); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + return return_value; +} + + +#ifdef HAVE_PIPE +/*[clinic input] +os.pipe + +Create a pipe. + +Returns a tuple of two file descriptors: + (read_fd, write_fd) +[clinic start generated code]*/ + +static PyObject * +os_pipe_impl(PyObject *module) +/*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/ +{ + int fds[2]; +#ifdef MS_WINDOWS + HANDLE read, write; + SECURITY_ATTRIBUTES attr; + BOOL ok; +#else + int res; +#endif + +#ifdef MS_WINDOWS + attr.nLength = sizeof(attr); + attr.lpSecurityDescriptor = NULL; + attr.bInheritHandle = FALSE; + + Py_BEGIN_ALLOW_THREADS + ok = CreatePipe(&read, &write, &attr, 0); + if (ok) { + fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY); + fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY); + if (fds[0] == -1 || fds[1] == -1) { + CloseHandle(read); + CloseHandle(write); + ok = 0; + } + } + Py_END_ALLOW_THREADS + + if (!ok) + return PyErr_SetFromWindowsErr(0); +#else + +#ifdef HAVE_PIPE2 + Py_BEGIN_ALLOW_THREADS + res = pipe2(fds, O_CLOEXEC); + Py_END_ALLOW_THREADS + + if (res != 0 && errno == ENOSYS) + { +#endif + Py_BEGIN_ALLOW_THREADS + res = pipe(fds); + Py_END_ALLOW_THREADS + + if (res == 0) { + if (_Py_set_inheritable(fds[0], 0, NULL) < 0) { + close(fds[0]); + close(fds[1]); + return NULL; + } + if (_Py_set_inheritable(fds[1], 0, NULL) < 0) { + close(fds[0]); + close(fds[1]); + return NULL; + } + } +#ifdef HAVE_PIPE2 + } +#endif + + if (res != 0) + return PyErr_SetFromErrno(PyExc_OSError); +#endif /* !MS_WINDOWS */ + return Py_BuildValue("(ii)", fds[0], fds[1]); +} +#endif /* HAVE_PIPE */ + + +#ifdef HAVE_PIPE2 +/*[clinic input] +os.pipe2 + + flags: int + / + +Create a pipe with flags set atomically. + +Returns a tuple of two file descriptors: + (read_fd, write_fd) + +flags can be constructed by ORing together one or more of these values: +O_NONBLOCK, O_CLOEXEC. +[clinic start generated code]*/ + +static PyObject * +os_pipe2_impl(PyObject *module, int flags) +/*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/ +{ + int fds[2]; + int res; + + res = pipe2(fds, flags); + if (res != 0) + return posix_error(); + return Py_BuildValue("(ii)", fds[0], fds[1]); +} +#endif /* HAVE_PIPE2 */ + + +#ifdef HAVE_WRITEV +/*[clinic input] +os.writev -> Py_ssize_t + fd: int + buffers: object + / + +Iterate over buffers, and write the contents of each to a file descriptor. + +Returns the total number of bytes written. +buffers must be a sequence of bytes-like objects. +[clinic start generated code]*/ + +static Py_ssize_t +os_writev_impl(PyObject *module, int fd, PyObject *buffers) +/*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/ +{ + Py_ssize_t cnt; + Py_ssize_t result; + int async_err = 0; + struct iovec *iov; + Py_buffer *buf; + + if (!PySequence_Check(buffers)) { + PyErr_SetString(PyExc_TypeError, + "writev() arg 2 must be a sequence"); + return -1; + } + cnt = PySequence_Size(buffers); + if (cnt < 0) + return -1; + + if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { + return -1; + } + + do { + Py_BEGIN_ALLOW_THREADS + result = writev(fd, iov, cnt); + Py_END_ALLOW_THREADS + } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + + iov_cleanup(iov, buf, cnt); + if (result < 0 && !async_err) + posix_error(); + + return result; +} +#endif /* HAVE_WRITEV */ + + +#ifdef HAVE_PWRITE +/*[clinic input] +os.pwrite -> Py_ssize_t + + fd: int + buffer: Py_buffer + offset: Py_off_t + / + +Write bytes to a file descriptor starting at a particular offset. + +Write buffer to fd, starting at offset bytes from the beginning of +the file. Returns the number of bytes writte. Does not change the +current file offset. +[clinic start generated code]*/ + +static Py_ssize_t +os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset) +/*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/ +{ + Py_ssize_t size; + int async_err = 0; + + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + + if (size < 0 && !async_err) + posix_error(); + return size; +} +#endif /* HAVE_PWRITE */ + +#if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2) +/*[clinic input] +os.pwritev -> Py_ssize_t + + fd: int + buffers: object + offset: Py_off_t + flags: int = 0 + / + +Writes the contents of bytes-like objects to a file descriptor at a given offset. + +Combines the functionality of writev() and pwrite(). All buffers must be a sequence +of bytes-like objects. Buffers are processed in array order. Entire contents of first +buffer is written before proceeding to second, and so on. The operating system may +set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used. +This function writes the contents of each object to the file descriptor and returns +the total number of bytes written. + +The flags argument contains a bitwise OR of zero or more of the following flags: + +- RWF_DSYNC +- RWF_SYNC +- RWF_APPEND + +Using non-zero flags requires Linux 4.7 or newer. +[clinic start generated code]*/ + +static Py_ssize_t +os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, + int flags) +/*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/ +{ + Py_ssize_t cnt; + Py_ssize_t result; + int async_err = 0; + struct iovec *iov; + Py_buffer *buf; + + if (!PySequence_Check(buffers)) { + PyErr_SetString(PyExc_TypeError, + "pwritev() arg 2 must be a sequence"); + return -1; + } + + cnt = PySequence_Size(buffers); + if (cnt < 0) { + return -1; + } + +#ifndef HAVE_PWRITEV2 + if(flags != 0) { + argument_unavailable_error("pwritev2", "flags"); + return -1; + } +#endif + + if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { + return -1; + } +#ifdef HAVE_PWRITEV2 + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + result = pwritev2(fd, iov, cnt, offset, flags); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); +#else + +#ifdef __APPLE__ +/* This entire function will be removed from the module dict when the API + * is not available. + */ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +#pragma clang diagnostic ignored "-Wunguarded-availability-new" +#endif + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + result = pwritev(fd, iov, cnt, offset); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + +#ifdef __APPLE__ +#pragma clang diagnostic pop +#endif + +#endif + + iov_cleanup(iov, buf, cnt); + if (result < 0) { + if (!async_err) { + posix_error(); + } + return -1; + } + + return result; +} +#endif /* HAVE_PWRITEV */ + +#ifdef HAVE_COPY_FILE_RANGE +/*[clinic input] + +os.copy_file_range + src: int + Source file descriptor. + dst: int + Destination file descriptor. + count: Py_ssize_t + Number of bytes to copy. + offset_src: object = None + Starting offset in src. + offset_dst: object = None + Starting offset in dst. + +Copy count bytes from one file descriptor to another. + +If offset_src is None, then src is read from the current position; +respectively for offset_dst. +[clinic start generated code]*/ + +static PyObject * +os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count, + PyObject *offset_src, PyObject *offset_dst) +/*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/ +{ + off_t offset_src_val, offset_dst_val; + off_t *p_offset_src = NULL; + off_t *p_offset_dst = NULL; + Py_ssize_t ret; + int async_err = 0; + /* The flags argument is provided to allow + * for future extensions and currently must be to 0. */ + int flags = 0; + + + if (count < 0) { + PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed"); + return NULL; + } + + if (offset_src != Py_None) { + if (!Py_off_t_converter(offset_src, &offset_src_val)) { + return NULL; + } + p_offset_src = &offset_src_val; + } + + if (offset_dst != Py_None) { + if (!Py_off_t_converter(offset_dst, &offset_dst_val)) { + return NULL; + } + p_offset_dst = &offset_dst_val; + } + + do { + Py_BEGIN_ALLOW_THREADS + ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags); + Py_END_ALLOW_THREADS + } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + + if (ret < 0) { + return (!async_err) ? posix_error() : NULL; + } + + return PyLong_FromSsize_t(ret); +} +#endif /* HAVE_COPY_FILE_RANGE*/ + +#if (defined(HAVE_SPLICE) && !defined(_AIX)) +/*[clinic input] + +os.splice + src: int + Source file descriptor. + dst: int + Destination file descriptor. + count: Py_ssize_t + Number of bytes to copy. + offset_src: object = None + Starting offset in src. + offset_dst: object = None + Starting offset in dst. + flags: unsigned_int = 0 + Flags to modify the semantics of the call. + +Transfer count bytes from one pipe to a descriptor or vice versa. + +If offset_src is None, then src is read from the current position; +respectively for offset_dst. The offset associated to the file +descriptor that refers to a pipe must be None. +[clinic start generated code]*/ + +static PyObject * +os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count, + PyObject *offset_src, PyObject *offset_dst, + unsigned int flags) +/*[clinic end generated code: output=d0386f25a8519dc5 input=047527c66c6d2e0a]*/ +{ + off_t offset_src_val, offset_dst_val; + off_t *p_offset_src = NULL; + off_t *p_offset_dst = NULL; + Py_ssize_t ret; + int async_err = 0; + + if (count < 0) { + PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed"); + return NULL; + } + + if (offset_src != Py_None) { + if (!Py_off_t_converter(offset_src, &offset_src_val)) { + return NULL; + } + p_offset_src = &offset_src_val; + } + + if (offset_dst != Py_None) { + if (!Py_off_t_converter(offset_dst, &offset_dst_val)) { + return NULL; + } + p_offset_dst = &offset_dst_val; + } + + do { + Py_BEGIN_ALLOW_THREADS + ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags); + Py_END_ALLOW_THREADS + } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + + if (ret < 0) { + return (!async_err) ? posix_error() : NULL; + } + + return PyLong_FromSsize_t(ret); +} +#endif /* HAVE_SPLICE*/ + +#ifdef HAVE_MKFIFO +/*[clinic input] +os.mkfifo + + path: path_t + mode: int=0o666 + * + dir_fd: dir_fd(requires='mkfifoat')=None + +Create a "fifo" (a POSIX named pipe). + +If dir_fd is not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that directory. +dir_fd may not be implemented on your platform. + If it is unavailable, using it will raise a NotImplementedError. +[clinic start generated code]*/ + +static PyObject * +os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd) +/*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/ +{ + int result; + int async_err = 0; +#ifdef HAVE_MKFIFOAT + int mkfifoat_unavailable = 0; +#endif + + do { + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_MKFIFOAT + if (dir_fd != DEFAULT_DIR_FD) { + if (HAVE_MKFIFOAT_RUNTIME) { + result = mkfifoat(dir_fd, path->narrow, mode); + + } else { + mkfifoat_unavailable = 1; + result = 0; + } + } else +#endif + result = mkfifo(path->narrow, mode); + Py_END_ALLOW_THREADS + } while (result != 0 && errno == EINTR && + !(async_err = PyErr_CheckSignals())); + +#ifdef HAVE_MKFIFOAT + if (mkfifoat_unavailable) { + argument_unavailable_error(NULL, "dir_fd"); + return NULL; + } +#endif + + if (result != 0) + return (!async_err) ? posix_error() : NULL; + + Py_RETURN_NONE; +} +#endif /* HAVE_MKFIFO */ + + +#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) +/*[clinic input] +os.mknod + + path: path_t + mode: int=0o600 + device: dev_t=0 + * + dir_fd: dir_fd(requires='mknodat')=None + +Create a node in the file system. + +Create a node in the file system (file, device special file or named pipe) +at path. mode specifies both the permissions to use and the +type of node to be created, being combined (bitwise OR) with one of +S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode, +device defines the newly created device special file (probably using +os.makedev()). Otherwise device is ignored. + +If dir_fd is not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that directory. +dir_fd may not be implemented on your platform. + If it is unavailable, using it will raise a NotImplementedError. +[clinic start generated code]*/ + +static PyObject * +os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device, + int dir_fd) +/*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/ +{ + int result; + int async_err = 0; +#ifdef HAVE_MKNODAT + int mknodat_unavailable = 0; +#endif + + do { + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_MKNODAT + if (dir_fd != DEFAULT_DIR_FD) { + if (HAVE_MKNODAT_RUNTIME) { + result = mknodat(dir_fd, path->narrow, mode, device); + + } else { + mknodat_unavailable = 1; + result = 0; + } + } else +#endif + result = mknod(path->narrow, mode, device); + Py_END_ALLOW_THREADS + } while (result != 0 && errno == EINTR && + !(async_err = PyErr_CheckSignals())); +#ifdef HAVE_MKNODAT + if (mknodat_unavailable) { + argument_unavailable_error(NULL, "dir_fd"); + return NULL; + } +#endif + if (result != 0) + return (!async_err) ? posix_error() : NULL; + + Py_RETURN_NONE; +} +#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */ + + +#ifdef HAVE_DEVICE_MACROS +/*[clinic input] +os.major -> unsigned_int + + device: dev_t + / + +Extracts a device major number from a raw device number. +[clinic start generated code]*/ + +static unsigned int +os_major_impl(PyObject *module, dev_t device) +/*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/ +{ + return major(device); +} + + +/*[clinic input] +os.minor -> unsigned_int + + device: dev_t + / + +Extracts a device minor number from a raw device number. +[clinic start generated code]*/ + +static unsigned int +os_minor_impl(PyObject *module, dev_t device) +/*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/ +{ + return minor(device); +} + + +/*[clinic input] +os.makedev -> dev_t + + major: int + minor: int + / + +Composes a raw device number from the major and minor device numbers. +[clinic start generated code]*/ + +static dev_t +os_makedev_impl(PyObject *module, int major, int minor) +/*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/ +{ + return makedev(major, minor); +} +#endif /* HAVE_DEVICE_MACROS */ + + +#if defined HAVE_FTRUNCATE || defined MS_WINDOWS +/*[clinic input] +os.ftruncate + + fd: int + length: Py_off_t + / + +Truncate a file, specified by file descriptor, to a specific length. +[clinic start generated code]*/ + +static PyObject * +os_ftruncate_impl(PyObject *module, int fd, Py_off_t length) +/*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/ +{ + int result; + int async_err = 0; + + if (PySys_Audit("os.truncate", "in", fd, length) < 0) { + return NULL; + } + + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH +#ifdef MS_WINDOWS + result = _chsize_s(fd, length); +#else + result = ftruncate(fd, length); +#endif + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (result != 0 && errno == EINTR && + !(async_err = PyErr_CheckSignals())); + if (result != 0) + return (!async_err) ? posix_error() : NULL; + Py_RETURN_NONE; +} +#endif /* HAVE_FTRUNCATE || MS_WINDOWS */ + + +#if defined HAVE_TRUNCATE || defined MS_WINDOWS +/*[clinic input] +os.truncate + path: path_t(allow_fd='PATH_HAVE_FTRUNCATE') + length: Py_off_t + +Truncate a file, specified by path, to a specific length. + +On some platforms, path may also be specified as an open file descriptor. + If this functionality is unavailable, using it raises an exception. +[clinic start generated code]*/ + +static PyObject * +os_truncate_impl(PyObject *module, path_t *path, Py_off_t length) +/*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/ +{ + int result; +#ifdef MS_WINDOWS + int fd; +#endif + + if (path->fd != -1) + return os_ftruncate_impl(module, path->fd, length); + + if (PySys_Audit("os.truncate", "On", path->object, length) < 0) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH +#ifdef MS_WINDOWS + fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT); + if (fd < 0) + result = -1; + else { + result = _chsize_s(fd, length); + close(fd); + if (result < 0) + errno = result; + } +#else + result = truncate(path->narrow, length); +#endif + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + if (result < 0) + return posix_path_error(path); + + Py_RETURN_NONE; +} +#endif /* HAVE_TRUNCATE || MS_WINDOWS */ + + +/* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise() + and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is + defined, which is the case in Python on AIX. AIX bug report: + http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */ +#if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__) +# define POSIX_FADVISE_AIX_BUG +#endif + + +#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) +/*[clinic input] +os.posix_fallocate + + fd: int + offset: Py_off_t + length: Py_off_t + / + +Ensure a file has allocated at least a particular number of bytes on disk. + +Ensure that the file specified by fd encompasses a range of bytes +starting at offset bytes from the beginning and continuing for length bytes. +[clinic start generated code]*/ + +static PyObject * +os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset, + Py_off_t length) +/*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/ +{ + int result; + int async_err = 0; + + do { + Py_BEGIN_ALLOW_THREADS + result = posix_fallocate(fd, offset, length); + Py_END_ALLOW_THREADS + } while (result == EINTR && !(async_err = PyErr_CheckSignals())); + + if (result == 0) + Py_RETURN_NONE; + + if (async_err) + return NULL; + + errno = result; + return posix_error(); +} +#endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */ + + +#if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG) +/*[clinic input] +os.posix_fadvise + + fd: int + offset: Py_off_t + length: Py_off_t + advice: int + / + +Announce an intention to access data in a specific pattern. + +Announce an intention to access data in a specific pattern, thus allowing +the kernel to make optimizations. +The advice applies to the region of the file specified by fd starting at +offset and continuing for length bytes. +advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL, +POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or +POSIX_FADV_DONTNEED. +[clinic start generated code]*/ + +static PyObject * +os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset, + Py_off_t length, int advice) +/*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/ +{ + int result; + int async_err = 0; + + do { + Py_BEGIN_ALLOW_THREADS + result = posix_fadvise(fd, offset, length, advice); + Py_END_ALLOW_THREADS + } while (result == EINTR && !(async_err = PyErr_CheckSignals())); + + if (result == 0) + Py_RETURN_NONE; + + if (async_err) + return NULL; + + errno = result; + return posix_error(); +} +#endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */ + + +#ifdef MS_WINDOWS +static PyObject* +win32_putenv(PyObject *name, PyObject *value) +{ + /* Search from index 1 because on Windows starting '=' is allowed for + defining hidden environment variables. */ + if (PyUnicode_GET_LENGTH(name) == 0 || + PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1) + { + PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); + return NULL; + } + PyObject *unicode; + if (value != NULL) { + unicode = PyUnicode_FromFormat("%U=%U", name, value); + } + else { + unicode = PyUnicode_FromFormat("%U=", name); + } + if (unicode == NULL) { + return NULL; + } + + Py_ssize_t size; + /* PyUnicode_AsWideCharString() rejects embedded null characters */ + wchar_t *env = PyUnicode_AsWideCharString(unicode, &size); + Py_DECREF(unicode); + + if (env == NULL) { + return NULL; + } + if (size > _MAX_ENV) { + PyErr_Format(PyExc_ValueError, + "the environment variable is longer than %u characters", + _MAX_ENV); + PyMem_Free(env); + return NULL; + } + + /* _wputenv() and SetEnvironmentVariableW() update the environment in the + Process Environment Block (PEB). _wputenv() also updates CRT 'environ' + and '_wenviron' variables, whereas SetEnvironmentVariableW() does not. + + Prefer _wputenv() to be compatible with C libraries using CRT + variables and CRT functions using these variables (ex: getenv()). */ + int err = _wputenv(env); + PyMem_Free(env); + + if (err) { + posix_error(); + return NULL; + } + + Py_RETURN_NONE; +} +#endif + + +#ifdef MS_WINDOWS +/*[clinic input] +os.putenv + + name: unicode + value: unicode + / + +Change or add an environment variable. +[clinic start generated code]*/ + +static PyObject * +os_putenv_impl(PyObject *module, PyObject *name, PyObject *value) +/*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/ +{ + if (PySys_Audit("os.putenv", "OO", name, value) < 0) { + return NULL; + } + return win32_putenv(name, value); +} +#else +/*[clinic input] +os.putenv + + name: FSConverter + value: FSConverter + / + +Change or add an environment variable. +[clinic start generated code]*/ + +static PyObject * +os_putenv_impl(PyObject *module, PyObject *name, PyObject *value) +/*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/ +{ + const char *name_string = PyBytes_AS_STRING(name); + const char *value_string = PyBytes_AS_STRING(value); + + if (strchr(name_string, '=') != NULL) { + PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); + return NULL; + } + + if (PySys_Audit("os.putenv", "OO", name, value) < 0) { + return NULL; + } + + if (setenv(name_string, value_string, 1)) { + return posix_error(); + } + Py_RETURN_NONE; +} +#endif /* !defined(MS_WINDOWS) */ + + +#ifdef MS_WINDOWS +/*[clinic input] +os.unsetenv + name: unicode + / + +Delete an environment variable. +[clinic start generated code]*/ + +static PyObject * +os_unsetenv_impl(PyObject *module, PyObject *name) +/*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/ +{ + if (PySys_Audit("os.unsetenv", "(O)", name) < 0) { + return NULL; + } + return win32_putenv(name, NULL); +} +#else +/*[clinic input] +os.unsetenv + name: FSConverter + / + +Delete an environment variable. +[clinic start generated code]*/ + +static PyObject * +os_unsetenv_impl(PyObject *module, PyObject *name) +/*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/ +{ + if (PySys_Audit("os.unsetenv", "(O)", name) < 0) { + return NULL; + } +#ifdef HAVE_BROKEN_UNSETENV + unsetenv(PyBytes_AS_STRING(name)); +#else + int err = unsetenv(PyBytes_AS_STRING(name)); + if (err) { + return posix_error(); + } +#endif + + Py_RETURN_NONE; +} +#endif /* !MS_WINDOWS */ + + +/*[clinic input] +os.strerror + + code: int + / + +Translate an error code to a message string. +[clinic start generated code]*/ + +static PyObject * +os_strerror_impl(PyObject *module, int code) +/*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/ +{ + char *message = strerror(code); + if (message == NULL) { + PyErr_SetString(PyExc_ValueError, + "strerror() argument out of range"); + return NULL; + } + return PyUnicode_DecodeLocale(message, "surrogateescape"); +} + + +#ifdef HAVE_SYS_WAIT_H +#ifdef WCOREDUMP +/*[clinic input] +os.WCOREDUMP -> bool + + status: int + / + +Return True if the process returning status was dumped to a core file. +[clinic start generated code]*/ + +static int +os_WCOREDUMP_impl(PyObject *module, int status) +/*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WCOREDUMP(wait_status); +} +#endif /* WCOREDUMP */ + + +#ifdef WIFCONTINUED +/*[clinic input] +os.WIFCONTINUED -> bool + + status: int + +Return True if a particular process was continued from a job control stop. + +Return True if the process returning status was continued from a +job control stop. +[clinic start generated code]*/ + +static int +os_WIFCONTINUED_impl(PyObject *module, int status) +/*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WIFCONTINUED(wait_status); +} +#endif /* WIFCONTINUED */ + + +#ifdef WIFSTOPPED +/*[clinic input] +os.WIFSTOPPED -> bool + + status: int + +Return True if the process returning status was stopped. +[clinic start generated code]*/ + +static int +os_WIFSTOPPED_impl(PyObject *module, int status) +/*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WIFSTOPPED(wait_status); +} +#endif /* WIFSTOPPED */ + + +#ifdef WIFSIGNALED +/*[clinic input] +os.WIFSIGNALED -> bool + + status: int + +Return True if the process returning status was terminated by a signal. +[clinic start generated code]*/ + +static int +os_WIFSIGNALED_impl(PyObject *module, int status) +/*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WIFSIGNALED(wait_status); +} +#endif /* WIFSIGNALED */ + + +#ifdef WIFEXITED +/*[clinic input] +os.WIFEXITED -> bool + + status: int + +Return True if the process returning status exited via the exit() system call. +[clinic start generated code]*/ + +static int +os_WIFEXITED_impl(PyObject *module, int status) +/*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WIFEXITED(wait_status); +} +#endif /* WIFEXITED */ + + +#ifdef WEXITSTATUS +/*[clinic input] +os.WEXITSTATUS -> int + + status: int + +Return the process return code from status. +[clinic start generated code]*/ + +static int +os_WEXITSTATUS_impl(PyObject *module, int status) +/*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WEXITSTATUS(wait_status); +} +#endif /* WEXITSTATUS */ + + +#ifdef WTERMSIG +/*[clinic input] +os.WTERMSIG -> int + + status: int + +Return the signal that terminated the process that provided the status value. +[clinic start generated code]*/ + +static int +os_WTERMSIG_impl(PyObject *module, int status) +/*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WTERMSIG(wait_status); +} +#endif /* WTERMSIG */ + + +#ifdef WSTOPSIG +/*[clinic input] +os.WSTOPSIG -> int + + status: int + +Return the signal that stopped the process that provided the status value. +[clinic start generated code]*/ + +static int +os_WSTOPSIG_impl(PyObject *module, int status) +/*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WSTOPSIG(wait_status); +} +#endif /* WSTOPSIG */ +#endif /* HAVE_SYS_WAIT_H */ + + +#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) +#ifdef _SCO_DS +/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the + needed definitions in sys/statvfs.h */ +#define _SVID3 +#endif +#include + +static PyObject* +_pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) { + PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType; + PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType); + if (v == NULL) + return NULL; + +#if !defined(HAVE_LARGEFILE_SUPPORT) + PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize)); + PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize)); + PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks)); + PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree)); + PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail)); + PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files)); + PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree)); + PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail)); + PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag)); + PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax)); +#else + PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize)); + PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize)); + PyStructSequence_SET_ITEM(v, 2, + PyLong_FromLongLong((long long) st.f_blocks)); + PyStructSequence_SET_ITEM(v, 3, + PyLong_FromLongLong((long long) st.f_bfree)); + PyStructSequence_SET_ITEM(v, 4, + PyLong_FromLongLong((long long) st.f_bavail)); + PyStructSequence_SET_ITEM(v, 5, + PyLong_FromLongLong((long long) st.f_files)); + PyStructSequence_SET_ITEM(v, 6, + PyLong_FromLongLong((long long) st.f_ffree)); + PyStructSequence_SET_ITEM(v, 7, + PyLong_FromLongLong((long long) st.f_favail)); + PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag)); + PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax)); +#endif +/* The _ALL_SOURCE feature test macro defines f_fsid as a structure + * (issue #32390). */ +#if defined(_AIX) && defined(_ALL_SOURCE) + PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0])); +#else + PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid)); +#endif + if (PyErr_Occurred()) { + Py_DECREF(v); + return NULL; + } + + return v; +} + + +/*[clinic input] +os.fstatvfs + fd: int + / + +Perform an fstatvfs system call on the given fd. + +Equivalent to statvfs(fd). +[clinic start generated code]*/ + +static PyObject * +os_fstatvfs_impl(PyObject *module, int fd) +/*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/ +{ + int result; + int async_err = 0; + struct statvfs st; + + do { + Py_BEGIN_ALLOW_THREADS + result = fstatvfs(fd, &st); + Py_END_ALLOW_THREADS + } while (result != 0 && errno == EINTR && + !(async_err = PyErr_CheckSignals())); + if (result != 0) + return (!async_err) ? posix_error() : NULL; + + return _pystatvfs_fromstructstatvfs(module, st); +} +#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */ + + +#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) +#include +/*[clinic input] +os.statvfs + + path: path_t(allow_fd='PATH_HAVE_FSTATVFS') + +Perform a statvfs system call on the given path. + +path may always be specified as a string. +On some platforms, path may also be specified as an open file descriptor. + If this functionality is unavailable, using it raises an exception. +[clinic start generated code]*/ + +static PyObject * +os_statvfs_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/ +{ + int result; + struct statvfs st; + + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_FSTATVFS + if (path->fd != -1) { + result = fstatvfs(path->fd, &st); + } + else +#endif + result = statvfs(path->narrow, &st); + Py_END_ALLOW_THREADS + + if (result) { + return path_error(path); + } + + return _pystatvfs_fromstructstatvfs(module, st); +} +#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */ + + +#ifdef MS_WINDOWS +/*[clinic input] +os._getdiskusage + + path: path_t + +Return disk usage statistics about the given path as a (total, free) tuple. +[clinic start generated code]*/ + +static PyObject * +os__getdiskusage_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/ +{ + BOOL retval; + ULARGE_INTEGER _, total, free; + DWORD err = 0; + + Py_BEGIN_ALLOW_THREADS + retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free); + Py_END_ALLOW_THREADS + if (retval == 0) { + if (GetLastError() == ERROR_DIRECTORY) { + wchar_t *dir_path = NULL; + + dir_path = PyMem_New(wchar_t, path->length + 1); + if (dir_path == NULL) { + return PyErr_NoMemory(); + } + + wcscpy_s(dir_path, path->length + 1, path->wide); + + if (_dirnameW(dir_path) != -1) { + Py_BEGIN_ALLOW_THREADS + retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free); + Py_END_ALLOW_THREADS + } + /* Record the last error in case it's modified by PyMem_Free. */ + err = GetLastError(); + PyMem_Free(dir_path); + if (retval) { + goto success; + } + } + return PyErr_SetFromWindowsErr(err); + } + +success: + return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart); +} +#endif /* MS_WINDOWS */ + + +/* This is used for fpathconf(), pathconf(), confstr() and sysconf(). + * It maps strings representing configuration variable names to + * integer values, allowing those functions to be called with the + * magic names instead of polluting the module's namespace with tons of + * rarely-used constants. There are three separate tables that use + * these definitions. + * + * This code is always included, even if none of the interfaces that + * need it are included. The #if hackery needed to avoid it would be + * sufficiently pervasive that it's not worth the loss of readability. + */ +struct constdef { + const char *name; + int value; +}; + +static int +conv_confname(PyObject *arg, int *valuep, struct constdef *table, + size_t tablesize) +{ + if (PyLong_Check(arg)) { + int value = _PyLong_AsInt(arg); + if (value == -1 && PyErr_Occurred()) + return 0; + *valuep = value; + return 1; + } + else { + /* look up the value in the table using a binary search */ + size_t lo = 0; + size_t mid; + size_t hi = tablesize; + int cmp; + const char *confname; + if (!PyUnicode_Check(arg)) { + PyErr_SetString(PyExc_TypeError, + "configuration names must be strings or integers"); + return 0; + } + confname = PyUnicode_AsUTF8(arg); + if (confname == NULL) + return 0; + while (lo < hi) { + mid = (lo + hi) / 2; + cmp = strcmp(confname, table[mid].name); + if (cmp < 0) + hi = mid; + else if (cmp > 0) + lo = mid + 1; + else { + *valuep = table[mid].value; + return 1; + } + } + PyErr_SetString(PyExc_ValueError, "unrecognized configuration name"); + return 0; + } +} + + +#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF) +static struct constdef posix_constants_pathconf[] = { +#ifdef _PC_ABI_AIO_XFER_MAX + {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX}, +#endif +#ifdef _PC_ABI_ASYNC_IO + {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO}, +#endif +#ifdef _PC_ASYNC_IO + {"PC_ASYNC_IO", _PC_ASYNC_IO}, +#endif +#ifdef _PC_CHOWN_RESTRICTED + {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED}, +#endif +#ifdef _PC_FILESIZEBITS + {"PC_FILESIZEBITS", _PC_FILESIZEBITS}, +#endif +#ifdef _PC_LAST + {"PC_LAST", _PC_LAST}, +#endif +#ifdef _PC_LINK_MAX + {"PC_LINK_MAX", _PC_LINK_MAX}, +#endif +#ifdef _PC_MAX_CANON + {"PC_MAX_CANON", _PC_MAX_CANON}, +#endif +#ifdef _PC_MAX_INPUT + {"PC_MAX_INPUT", _PC_MAX_INPUT}, +#endif +#ifdef _PC_NAME_MAX + {"PC_NAME_MAX", _PC_NAME_MAX}, +#endif +#ifdef _PC_NO_TRUNC + {"PC_NO_TRUNC", _PC_NO_TRUNC}, +#endif +#ifdef _PC_PATH_MAX + {"PC_PATH_MAX", _PC_PATH_MAX}, +#endif +#ifdef _PC_PIPE_BUF + {"PC_PIPE_BUF", _PC_PIPE_BUF}, +#endif +#ifdef _PC_PRIO_IO + {"PC_PRIO_IO", _PC_PRIO_IO}, +#endif +#ifdef _PC_SOCK_MAXBUF + {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF}, +#endif +#ifdef _PC_SYNC_IO + {"PC_SYNC_IO", _PC_SYNC_IO}, +#endif +#ifdef _PC_VDISABLE + {"PC_VDISABLE", _PC_VDISABLE}, +#endif +#ifdef _PC_ACL_ENABLED + {"PC_ACL_ENABLED", _PC_ACL_ENABLED}, +#endif +#ifdef _PC_MIN_HOLE_SIZE + {"PC_MIN_HOLE_SIZE", _PC_MIN_HOLE_SIZE}, +#endif +#ifdef _PC_ALLOC_SIZE_MIN + {"PC_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN}, +#endif +#ifdef _PC_REC_INCR_XFER_SIZE + {"PC_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE}, +#endif +#ifdef _PC_REC_MAX_XFER_SIZE + {"PC_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE}, +#endif +#ifdef _PC_REC_MIN_XFER_SIZE + {"PC_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE}, +#endif +#ifdef _PC_REC_XFER_ALIGN + {"PC_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN}, +#endif +#ifdef _PC_SYMLINK_MAX + {"PC_SYMLINK_MAX", _PC_SYMLINK_MAX}, +#endif +#ifdef _PC_XATTR_ENABLED + {"PC_XATTR_ENABLED", _PC_XATTR_ENABLED}, +#endif +#ifdef _PC_XATTR_EXISTS + {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS}, +#endif +#ifdef _PC_TIMESTAMP_RESOLUTION + {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION}, +#endif +}; + +static int +conv_path_confname(PyObject *arg, int *valuep) +{ + return conv_confname(arg, valuep, posix_constants_pathconf, + sizeof(posix_constants_pathconf) + / sizeof(struct constdef)); +} +#endif + + +#ifdef HAVE_FPATHCONF +/*[clinic input] +os.fpathconf -> long + + fd: fildes + name: path_confname + / + +Return the configuration limit name for the file descriptor fd. + +If there is no limit, return -1. +[clinic start generated code]*/ + +static long +os_fpathconf_impl(PyObject *module, int fd, int name) +/*[clinic end generated code: output=d5b7042425fc3e21 input=5b8d2471cfaae186]*/ +{ + long limit; + + errno = 0; + limit = fpathconf(fd, name); + if (limit == -1 && errno != 0) + posix_error(); + + return limit; +} +#endif /* HAVE_FPATHCONF */ + + +#ifdef HAVE_PATHCONF +/*[clinic input] +os.pathconf -> long + path: path_t(allow_fd='PATH_HAVE_FPATHCONF') + name: path_confname + +Return the configuration limit name for the file or directory path. + +If there is no limit, return -1. +On some platforms, path may also be specified as an open file descriptor. + If this functionality is unavailable, using it raises an exception. +[clinic start generated code]*/ + +static long +os_pathconf_impl(PyObject *module, path_t *path, int name) +/*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/ +{ + long limit; + + errno = 0; +#ifdef HAVE_FPATHCONF + if (path->fd != -1) + limit = fpathconf(path->fd, name); + else +#endif + limit = pathconf(path->narrow, name); + if (limit == -1 && errno != 0) { + if (errno == EINVAL) + /* could be a path or name problem */ + posix_error(); + else + path_error(path); + } + + return limit; +} +#endif /* HAVE_PATHCONF */ + +#ifdef HAVE_CONFSTR +static struct constdef posix_constants_confstr[] = { +#ifdef _CS_ARCHITECTURE + {"CS_ARCHITECTURE", _CS_ARCHITECTURE}, +#endif +#ifdef _CS_GNU_LIBC_VERSION + {"CS_GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION}, +#endif +#ifdef _CS_GNU_LIBPTHREAD_VERSION + {"CS_GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION}, +#endif +#ifdef _CS_HOSTNAME + {"CS_HOSTNAME", _CS_HOSTNAME}, +#endif +#ifdef _CS_HW_PROVIDER + {"CS_HW_PROVIDER", _CS_HW_PROVIDER}, +#endif +#ifdef _CS_HW_SERIAL + {"CS_HW_SERIAL", _CS_HW_SERIAL}, +#endif +#ifdef _CS_INITTAB_NAME + {"CS_INITTAB_NAME", _CS_INITTAB_NAME}, +#endif +#ifdef _CS_LFS64_CFLAGS + {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS}, +#endif +#ifdef _CS_LFS64_LDFLAGS + {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS}, +#endif +#ifdef _CS_LFS64_LIBS + {"CS_LFS64_LIBS", _CS_LFS64_LIBS}, +#endif +#ifdef _CS_LFS64_LINTFLAGS + {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS}, +#endif +#ifdef _CS_LFS_CFLAGS + {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS}, +#endif +#ifdef _CS_LFS_LDFLAGS + {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS}, +#endif +#ifdef _CS_LFS_LIBS + {"CS_LFS_LIBS", _CS_LFS_LIBS}, +#endif +#ifdef _CS_LFS_LINTFLAGS + {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS}, +#endif +#ifdef _CS_MACHINE + {"CS_MACHINE", _CS_MACHINE}, +#endif +#ifdef _CS_PATH + {"CS_PATH", _CS_PATH}, +#endif +#ifdef _CS_RELEASE + {"CS_RELEASE", _CS_RELEASE}, +#endif +#ifdef _CS_SRPC_DOMAIN + {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN}, +#endif +#ifdef _CS_SYSNAME + {"CS_SYSNAME", _CS_SYSNAME}, +#endif +#ifdef _CS_VERSION + {"CS_VERSION", _CS_VERSION}, +#endif +#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS + {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS}, +#endif +#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS + {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS}, +#endif +#ifdef _CS_XBS5_ILP32_OFF32_LIBS + {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS}, +#endif +#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS + {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS}, +#endif +#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS + {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS}, +#endif +#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS + {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS}, +#endif +#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS + {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS}, +#endif +#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS + {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS}, +#endif +#ifdef _CS_XBS5_LP64_OFF64_CFLAGS + {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS}, +#endif +#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS + {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS}, +#endif +#ifdef _CS_XBS5_LP64_OFF64_LIBS + {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS}, +#endif +#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS + {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS}, +#endif +#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS + {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS}, +#endif +#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS + {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS}, +#endif +#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS + {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS}, +#endif +#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS + {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS}, +#endif +#ifdef _MIPS_CS_AVAIL_PROCESSORS + {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS}, +#endif +#ifdef _MIPS_CS_BASE + {"MIPS_CS_BASE", _MIPS_CS_BASE}, +#endif +#ifdef _MIPS_CS_HOSTID + {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID}, +#endif +#ifdef _MIPS_CS_HW_NAME + {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME}, +#endif +#ifdef _MIPS_CS_NUM_PROCESSORS + {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS}, +#endif +#ifdef _MIPS_CS_OSREL_MAJ + {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ}, +#endif +#ifdef _MIPS_CS_OSREL_MIN + {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN}, +#endif +#ifdef _MIPS_CS_OSREL_PATCH + {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH}, +#endif +#ifdef _MIPS_CS_OS_NAME + {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME}, +#endif +#ifdef _MIPS_CS_OS_PROVIDER + {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER}, +#endif +#ifdef _MIPS_CS_PROCESSORS + {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS}, +#endif +#ifdef _MIPS_CS_SERIAL + {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL}, +#endif +#ifdef _MIPS_CS_VENDOR + {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR}, +#endif +}; + +static int +conv_confstr_confname(PyObject *arg, int *valuep) +{ + return conv_confname(arg, valuep, posix_constants_confstr, + sizeof(posix_constants_confstr) + / sizeof(struct constdef)); +} + + +/*[clinic input] +os.confstr + + name: confstr_confname + / + +Return a string-valued system configuration variable. +[clinic start generated code]*/ + +static PyObject * +os_confstr_impl(PyObject *module, int name) +/*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/ +{ + PyObject *result = NULL; + char buffer[255]; + size_t len; + + errno = 0; + len = confstr(name, buffer, sizeof(buffer)); + if (len == 0) { + if (errno) { + posix_error(); + return NULL; + } + else { + Py_RETURN_NONE; + } + } + + if (len >= sizeof(buffer)) { + size_t len2; + char *buf = PyMem_Malloc(len); + if (buf == NULL) + return PyErr_NoMemory(); + len2 = confstr(name, buf, len); + assert(len == len2); + result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1); + PyMem_Free(buf); + } + else + result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1); + return result; +} +#endif /* HAVE_CONFSTR */ + + +#ifdef HAVE_SYSCONF +static struct constdef posix_constants_sysconf[] = { +#ifdef _SC_2_CHAR_TERM + {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM}, +#endif +#ifdef _SC_2_C_BIND + {"SC_2_C_BIND", _SC_2_C_BIND}, +#endif +#ifdef _SC_2_C_DEV + {"SC_2_C_DEV", _SC_2_C_DEV}, +#endif +#ifdef _SC_2_C_VERSION + {"SC_2_C_VERSION", _SC_2_C_VERSION}, +#endif +#ifdef _SC_2_FORT_DEV + {"SC_2_FORT_DEV", _SC_2_FORT_DEV}, +#endif +#ifdef _SC_2_FORT_RUN + {"SC_2_FORT_RUN", _SC_2_FORT_RUN}, +#endif +#ifdef _SC_2_LOCALEDEF + {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF}, +#endif +#ifdef _SC_2_SW_DEV + {"SC_2_SW_DEV", _SC_2_SW_DEV}, +#endif +#ifdef _SC_2_UPE + {"SC_2_UPE", _SC_2_UPE}, +#endif +#ifdef _SC_2_VERSION + {"SC_2_VERSION", _SC_2_VERSION}, +#endif +#ifdef _SC_ABI_ASYNCHRONOUS_IO + {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO}, +#endif +#ifdef _SC_ACL + {"SC_ACL", _SC_ACL}, +#endif +#ifdef _SC_AIO_LISTIO_MAX + {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX}, +#endif +#ifdef _SC_AIO_MAX + {"SC_AIO_MAX", _SC_AIO_MAX}, +#endif +#ifdef _SC_AIO_PRIO_DELTA_MAX + {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX}, +#endif +#ifdef _SC_ARG_MAX + {"SC_ARG_MAX", _SC_ARG_MAX}, +#endif +#ifdef _SC_ASYNCHRONOUS_IO + {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO}, +#endif +#ifdef _SC_ATEXIT_MAX + {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX}, +#endif +#ifdef _SC_AUDIT + {"SC_AUDIT", _SC_AUDIT}, +#endif +#ifdef _SC_AVPHYS_PAGES + {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES}, +#endif +#ifdef _SC_BC_BASE_MAX + {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX}, +#endif +#ifdef _SC_BC_DIM_MAX + {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX}, +#endif +#ifdef _SC_BC_SCALE_MAX + {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX}, +#endif +#ifdef _SC_BC_STRING_MAX + {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX}, +#endif +#ifdef _SC_CAP + {"SC_CAP", _SC_CAP}, +#endif +#ifdef _SC_CHARCLASS_NAME_MAX + {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX}, +#endif +#ifdef _SC_CHAR_BIT + {"SC_CHAR_BIT", _SC_CHAR_BIT}, +#endif +#ifdef _SC_CHAR_MAX + {"SC_CHAR_MAX", _SC_CHAR_MAX}, +#endif +#ifdef _SC_CHAR_MIN + {"SC_CHAR_MIN", _SC_CHAR_MIN}, +#endif +#ifdef _SC_CHILD_MAX + {"SC_CHILD_MAX", _SC_CHILD_MAX}, +#endif +#ifdef _SC_CLK_TCK + {"SC_CLK_TCK", _SC_CLK_TCK}, +#endif +#ifdef _SC_COHER_BLKSZ + {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ}, +#endif +#ifdef _SC_COLL_WEIGHTS_MAX + {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX}, +#endif +#ifdef _SC_DCACHE_ASSOC + {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC}, +#endif +#ifdef _SC_DCACHE_BLKSZ + {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ}, +#endif +#ifdef _SC_DCACHE_LINESZ + {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ}, +#endif +#ifdef _SC_DCACHE_SZ + {"SC_DCACHE_SZ", _SC_DCACHE_SZ}, +#endif +#ifdef _SC_DCACHE_TBLKSZ + {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ}, +#endif +#ifdef _SC_DELAYTIMER_MAX + {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX}, +#endif +#ifdef _SC_EQUIV_CLASS_MAX + {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX}, +#endif +#ifdef _SC_EXPR_NEST_MAX + {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX}, +#endif +#ifdef _SC_FSYNC + {"SC_FSYNC", _SC_FSYNC}, +#endif +#ifdef _SC_GETGR_R_SIZE_MAX + {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX}, +#endif +#ifdef _SC_GETPW_R_SIZE_MAX + {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX}, +#endif +#ifdef _SC_ICACHE_ASSOC + {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC}, +#endif +#ifdef _SC_ICACHE_BLKSZ + {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ}, +#endif +#ifdef _SC_ICACHE_LINESZ + {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ}, +#endif +#ifdef _SC_ICACHE_SZ + {"SC_ICACHE_SZ", _SC_ICACHE_SZ}, +#endif +#ifdef _SC_INF + {"SC_INF", _SC_INF}, +#endif +#ifdef _SC_INT_MAX + {"SC_INT_MAX", _SC_INT_MAX}, +#endif +#ifdef _SC_INT_MIN + {"SC_INT_MIN", _SC_INT_MIN}, +#endif +#ifdef _SC_IOV_MAX + {"SC_IOV_MAX", _SC_IOV_MAX}, +#endif +#ifdef _SC_IP_SECOPTS + {"SC_IP_SECOPTS", _SC_IP_SECOPTS}, +#endif +#ifdef _SC_JOB_CONTROL + {"SC_JOB_CONTROL", _SC_JOB_CONTROL}, +#endif +#ifdef _SC_KERN_POINTERS + {"SC_KERN_POINTERS", _SC_KERN_POINTERS}, +#endif +#ifdef _SC_KERN_SIM + {"SC_KERN_SIM", _SC_KERN_SIM}, +#endif +#ifdef _SC_LINE_MAX + {"SC_LINE_MAX", _SC_LINE_MAX}, +#endif +#ifdef _SC_LOGIN_NAME_MAX + {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX}, +#endif +#ifdef _SC_LOGNAME_MAX + {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX}, +#endif +#ifdef _SC_LONG_BIT + {"SC_LONG_BIT", _SC_LONG_BIT}, +#endif +#ifdef _SC_MAC + {"SC_MAC", _SC_MAC}, +#endif +#ifdef _SC_MAPPED_FILES + {"SC_MAPPED_FILES", _SC_MAPPED_FILES}, +#endif +#ifdef _SC_MAXPID + {"SC_MAXPID", _SC_MAXPID}, +#endif +#ifdef _SC_MB_LEN_MAX + {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX}, +#endif +#ifdef _SC_MEMLOCK + {"SC_MEMLOCK", _SC_MEMLOCK}, +#endif +#ifdef _SC_MEMLOCK_RANGE + {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE}, +#endif +#ifdef _SC_MEMORY_PROTECTION + {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION}, +#endif +#ifdef _SC_MESSAGE_PASSING + {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING}, +#endif +#ifdef _SC_MMAP_FIXED_ALIGNMENT + {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT}, +#endif +#ifdef _SC_MQ_OPEN_MAX + {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX}, +#endif +#ifdef _SC_MQ_PRIO_MAX + {"SC_MQ_PRIO_MAX", _SC_MQ_PRIO_MAX}, +#endif +#ifdef _SC_NACLS_MAX + {"SC_NACLS_MAX", _SC_NACLS_MAX}, +#endif +#ifdef _SC_NGROUPS_MAX + {"SC_NGROUPS_MAX", _SC_NGROUPS_MAX}, +#endif +#ifdef _SC_NL_ARGMAX + {"SC_NL_ARGMAX", _SC_NL_ARGMAX}, +#endif +#ifdef _SC_NL_LANGMAX + {"SC_NL_LANGMAX", _SC_NL_LANGMAX}, +#endif +#ifdef _SC_NL_MSGMAX + {"SC_NL_MSGMAX", _SC_NL_MSGMAX}, +#endif +#ifdef _SC_NL_NMAX + {"SC_NL_NMAX", _SC_NL_NMAX}, +#endif +#ifdef _SC_NL_SETMAX + {"SC_NL_SETMAX", _SC_NL_SETMAX}, +#endif +#ifdef _SC_NL_TEXTMAX + {"SC_NL_TEXTMAX", _SC_NL_TEXTMAX}, +#endif +#ifdef _SC_NPROCESSORS_CONF + {"SC_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF}, +#endif +#ifdef _SC_NPROCESSORS_ONLN + {"SC_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN}, +#endif +#ifdef _SC_NPROC_CONF + {"SC_NPROC_CONF", _SC_NPROC_CONF}, +#endif +#ifdef _SC_NPROC_ONLN + {"SC_NPROC_ONLN", _SC_NPROC_ONLN}, +#endif +#ifdef _SC_NZERO + {"SC_NZERO", _SC_NZERO}, +#endif +#ifdef _SC_OPEN_MAX + {"SC_OPEN_MAX", _SC_OPEN_MAX}, +#endif +#ifdef _SC_PAGESIZE + {"SC_PAGESIZE", _SC_PAGESIZE}, +#endif +#ifdef _SC_PAGE_SIZE + {"SC_PAGE_SIZE", _SC_PAGE_SIZE}, +#endif +#ifdef _SC_AIX_REALMEM + {"SC_AIX_REALMEM", _SC_AIX_REALMEM}, +#endif +#ifdef _SC_PASS_MAX + {"SC_PASS_MAX", _SC_PASS_MAX}, +#endif +#ifdef _SC_PHYS_PAGES + {"SC_PHYS_PAGES", _SC_PHYS_PAGES}, +#endif +#ifdef _SC_PII + {"SC_PII", _SC_PII}, +#endif +#ifdef _SC_PII_INTERNET + {"SC_PII_INTERNET", _SC_PII_INTERNET}, +#endif +#ifdef _SC_PII_INTERNET_DGRAM + {"SC_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM}, +#endif +#ifdef _SC_PII_INTERNET_STREAM + {"SC_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM}, +#endif +#ifdef _SC_PII_OSI + {"SC_PII_OSI", _SC_PII_OSI}, +#endif +#ifdef _SC_PII_OSI_CLTS + {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS}, +#endif +#ifdef _SC_PII_OSI_COTS + {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS}, +#endif +#ifdef _SC_PII_OSI_M + {"SC_PII_OSI_M", _SC_PII_OSI_M}, +#endif +#ifdef _SC_PII_SOCKET + {"SC_PII_SOCKET", _SC_PII_SOCKET}, +#endif +#ifdef _SC_PII_XTI + {"SC_PII_XTI", _SC_PII_XTI}, +#endif +#ifdef _SC_POLL + {"SC_POLL", _SC_POLL}, +#endif +#ifdef _SC_PRIORITIZED_IO + {"SC_PRIORITIZED_IO", _SC_PRIORITIZED_IO}, +#endif +#ifdef _SC_PRIORITY_SCHEDULING + {"SC_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING}, +#endif +#ifdef _SC_REALTIME_SIGNALS + {"SC_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS}, +#endif +#ifdef _SC_RE_DUP_MAX + {"SC_RE_DUP_MAX", _SC_RE_DUP_MAX}, +#endif +#ifdef _SC_RTSIG_MAX + {"SC_RTSIG_MAX", _SC_RTSIG_MAX}, +#endif +#ifdef _SC_SAVED_IDS + {"SC_SAVED_IDS", _SC_SAVED_IDS}, +#endif +#ifdef _SC_SCHAR_MAX + {"SC_SCHAR_MAX", _SC_SCHAR_MAX}, +#endif +#ifdef _SC_SCHAR_MIN + {"SC_SCHAR_MIN", _SC_SCHAR_MIN}, +#endif +#ifdef _SC_SELECT + {"SC_SELECT", _SC_SELECT}, +#endif +#ifdef _SC_SEMAPHORES + {"SC_SEMAPHORES", _SC_SEMAPHORES}, +#endif +#ifdef _SC_SEM_NSEMS_MAX + {"SC_SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX}, +#endif +#ifdef _SC_SEM_VALUE_MAX + {"SC_SEM_VALUE_MAX", _SC_SEM_VALUE_MAX}, +#endif +#ifdef _SC_SHARED_MEMORY_OBJECTS + {"SC_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS}, +#endif +#ifdef _SC_SHRT_MAX + {"SC_SHRT_MAX", _SC_SHRT_MAX}, +#endif +#ifdef _SC_SHRT_MIN + {"SC_SHRT_MIN", _SC_SHRT_MIN}, +#endif +#ifdef _SC_SIGQUEUE_MAX + {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX}, +#endif +#ifdef _SC_SIGRT_MAX + {"SC_SIGRT_MAX", _SC_SIGRT_MAX}, +#endif +#ifdef _SC_SIGRT_MIN + {"SC_SIGRT_MIN", _SC_SIGRT_MIN}, +#endif +#ifdef _SC_SOFTPOWER + {"SC_SOFTPOWER", _SC_SOFTPOWER}, +#endif +#ifdef _SC_SPLIT_CACHE + {"SC_SPLIT_CACHE", _SC_SPLIT_CACHE}, +#endif +#ifdef _SC_SSIZE_MAX + {"SC_SSIZE_MAX", _SC_SSIZE_MAX}, +#endif +#ifdef _SC_STACK_PROT + {"SC_STACK_PROT", _SC_STACK_PROT}, +#endif +#ifdef _SC_STREAM_MAX + {"SC_STREAM_MAX", _SC_STREAM_MAX}, +#endif +#ifdef _SC_SYNCHRONIZED_IO + {"SC_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO}, +#endif +#ifdef _SC_THREADS + {"SC_THREADS", _SC_THREADS}, +#endif +#ifdef _SC_THREAD_ATTR_STACKADDR + {"SC_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR}, +#endif +#ifdef _SC_THREAD_ATTR_STACKSIZE + {"SC_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE}, +#endif +#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS + {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS}, +#endif +#ifdef _SC_THREAD_KEYS_MAX + {"SC_THREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX}, +#endif +#ifdef _SC_THREAD_PRIORITY_SCHEDULING + {"SC_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING}, +#endif +#ifdef _SC_THREAD_PRIO_INHERIT + {"SC_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT}, +#endif +#ifdef _SC_THREAD_PRIO_PROTECT + {"SC_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT}, +#endif +#ifdef _SC_THREAD_PROCESS_SHARED + {"SC_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED}, +#endif +#ifdef _SC_THREAD_SAFE_FUNCTIONS + {"SC_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS}, +#endif +#ifdef _SC_THREAD_STACK_MIN + {"SC_THREAD_STACK_MIN", _SC_THREAD_STACK_MIN}, +#endif +#ifdef _SC_THREAD_THREADS_MAX + {"SC_THREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX}, +#endif +#ifdef _SC_TIMERS + {"SC_TIMERS", _SC_TIMERS}, +#endif +#ifdef _SC_TIMER_MAX + {"SC_TIMER_MAX", _SC_TIMER_MAX}, +#endif +#ifdef _SC_TTY_NAME_MAX + {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX}, +#endif +#ifdef _SC_TZNAME_MAX + {"SC_TZNAME_MAX", _SC_TZNAME_MAX}, +#endif +#ifdef _SC_T_IOV_MAX + {"SC_T_IOV_MAX", _SC_T_IOV_MAX}, +#endif +#ifdef _SC_UCHAR_MAX + {"SC_UCHAR_MAX", _SC_UCHAR_MAX}, +#endif +#ifdef _SC_UINT_MAX + {"SC_UINT_MAX", _SC_UINT_MAX}, +#endif +#ifdef _SC_UIO_MAXIOV + {"SC_UIO_MAXIOV", _SC_UIO_MAXIOV}, +#endif +#ifdef _SC_ULONG_MAX + {"SC_ULONG_MAX", _SC_ULONG_MAX}, +#endif +#ifdef _SC_USHRT_MAX + {"SC_USHRT_MAX", _SC_USHRT_MAX}, +#endif +#ifdef _SC_VERSION + {"SC_VERSION", _SC_VERSION}, +#endif +#ifdef _SC_WORD_BIT + {"SC_WORD_BIT", _SC_WORD_BIT}, +#endif +#ifdef _SC_XBS5_ILP32_OFF32 + {"SC_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32}, +#endif +#ifdef _SC_XBS5_ILP32_OFFBIG + {"SC_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG}, +#endif +#ifdef _SC_XBS5_LP64_OFF64 + {"SC_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64}, +#endif +#ifdef _SC_XBS5_LPBIG_OFFBIG + {"SC_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG}, +#endif +#ifdef _SC_XOPEN_CRYPT + {"SC_XOPEN_CRYPT", _SC_XOPEN_CRYPT}, +#endif +#ifdef _SC_XOPEN_ENH_I18N + {"SC_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N}, +#endif +#ifdef _SC_XOPEN_LEGACY + {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY}, +#endif +#ifdef _SC_XOPEN_REALTIME + {"SC_XOPEN_REALTIME", _SC_XOPEN_REALTIME}, +#endif +#ifdef _SC_XOPEN_REALTIME_THREADS + {"SC_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS}, +#endif +#ifdef _SC_XOPEN_SHM + {"SC_XOPEN_SHM", _SC_XOPEN_SHM}, +#endif +#ifdef _SC_XOPEN_UNIX + {"SC_XOPEN_UNIX", _SC_XOPEN_UNIX}, +#endif +#ifdef _SC_XOPEN_VERSION + {"SC_XOPEN_VERSION", _SC_XOPEN_VERSION}, +#endif +#ifdef _SC_XOPEN_XCU_VERSION + {"SC_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION}, +#endif +#ifdef _SC_XOPEN_XPG2 + {"SC_XOPEN_XPG2", _SC_XOPEN_XPG2}, +#endif +#ifdef _SC_XOPEN_XPG3 + {"SC_XOPEN_XPG3", _SC_XOPEN_XPG3}, +#endif +#ifdef _SC_XOPEN_XPG4 + {"SC_XOPEN_XPG4", _SC_XOPEN_XPG4}, +#endif +#ifdef _SC_MINSIGSTKSZ + {"SC_MINSIGSTKSZ", _SC_MINSIGSTKSZ}, +#endif +}; + +static int +conv_sysconf_confname(PyObject *arg, int *valuep) +{ + return conv_confname(arg, valuep, posix_constants_sysconf, + sizeof(posix_constants_sysconf) + / sizeof(struct constdef)); +} + + +/*[clinic input] +os.sysconf -> long + name: sysconf_confname + / + +Return an integer-valued system configuration variable. +[clinic start generated code]*/ + +static long +os_sysconf_impl(PyObject *module, int name) +/*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/ +{ + long value; + + errno = 0; + value = sysconf(name); + if (value == -1 && errno != 0) + posix_error(); + return value; +} +#endif /* HAVE_SYSCONF */ + + +/* This code is used to ensure that the tables of configuration value names + * are in sorted order as required by conv_confname(), and also to build + * the exported dictionaries that are used to publish information about the + * names available on the host platform. + * + * Sorting the table at runtime ensures that the table is properly ordered + * when used, even for platforms we're not able to test on. It also makes + * it easier to add additional entries to the tables. + */ + +static int +cmp_constdefs(const void *v1, const void *v2) +{ + const struct constdef *c1 = + (const struct constdef *) v1; + const struct constdef *c2 = + (const struct constdef *) v2; + + return strcmp(c1->name, c2->name); +} + +static int +setup_confname_table(struct constdef *table, size_t tablesize, + const char *tablename, PyObject *module) +{ + PyObject *d = NULL; + size_t i; + + qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs); + d = PyDict_New(); + if (d == NULL) + return -1; + + for (i=0; i < tablesize; ++i) { + PyObject *o = PyLong_FromLong(table[i].value); + if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) { + Py_XDECREF(o); + Py_DECREF(d); + return -1; + } + Py_DECREF(o); + } + return PyModule_AddObject(module, tablename, d); +} + +/* Return -1 on failure, 0 on success. */ +static int +setup_confname_tables(PyObject *module) +{ +#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF) + if (setup_confname_table(posix_constants_pathconf, + sizeof(posix_constants_pathconf) + / sizeof(struct constdef), + "pathconf_names", module)) + return -1; +#endif +#ifdef HAVE_CONFSTR + if (setup_confname_table(posix_constants_confstr, + sizeof(posix_constants_confstr) + / sizeof(struct constdef), + "confstr_names", module)) + return -1; +#endif +#ifdef HAVE_SYSCONF + if (setup_confname_table(posix_constants_sysconf, + sizeof(posix_constants_sysconf) + / sizeof(struct constdef), + "sysconf_names", module)) + return -1; +#endif + return 0; +} + + +/*[clinic input] +os.abort + +Abort the interpreter immediately. + +This function 'dumps core' or otherwise fails in the hardest way possible +on the hosting operating system. This function never returns. +[clinic start generated code]*/ + +static PyObject * +os_abort_impl(PyObject *module) +/*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/ +{ + abort(); + /*NOTREACHED*/ +#ifndef __clang__ + /* Issue #28152: abort() is declared with __attribute__((__noreturn__)). + GCC emits a warning without "return NULL;" (compiler bug?), but Clang + is smarter and emits a warning on the return. */ + Py_FatalError("abort() called from Python code didn't abort!"); + return NULL; +#endif +} + +#ifdef MS_WINDOWS +/* Grab ShellExecute dynamically from shell32 */ +static int has_ShellExecute = -1; +static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR, + LPCWSTR, INT); +static int +check_ShellExecute() +{ + HINSTANCE hShell32; + + /* only recheck */ + if (-1 == has_ShellExecute) { + Py_BEGIN_ALLOW_THREADS + /* Security note: this call is not vulnerable to "DLL hijacking". + SHELL32 is part of "KnownDLLs" and so Windows always load + the system SHELL32.DLL, even if there is another SHELL32.DLL + in the DLL search path. */ + hShell32 = LoadLibraryW(L"SHELL32"); + if (hShell32) { + *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32, + "ShellExecuteW"); + has_ShellExecute = Py_ShellExecuteW != NULL; + } else { + has_ShellExecute = 0; + } + Py_END_ALLOW_THREADS + } + return has_ShellExecute; +} + + +/*[clinic input] +os.startfile + filepath: path_t + operation: Py_UNICODE = NULL + arguments: Py_UNICODE = NULL + cwd: path_t(nullable=True) = None + show_cmd: int = 1 + +Start a file with its associated application. + +When "operation" is not specified or "open", this acts like +double-clicking the file in Explorer, or giving the file name as an +argument to the DOS "start" command: the file is opened with whatever +application (if any) its extension is associated. +When another "operation" is given, it specifies what should be done with +the file. A typical operation is "print". + +"arguments" is passed to the application, but should be omitted if the +file is a document. + +"cwd" is the working directory for the operation. If "filepath" is +relative, it will be resolved against this directory. This argument +should usually be an absolute path. + +"show_cmd" can be used to override the recommended visibility option. +See the Windows ShellExecute documentation for values. + +startfile returns as soon as the associated application is launched. +There is no option to wait for the application to close, and no way +to retrieve the application's exit status. + +The filepath is relative to the current directory. If you want to use +an absolute path, make sure the first character is not a slash ("/"); +the underlying Win32 ShellExecute function doesn't work if it is. +[clinic start generated code]*/ + +static PyObject * +os_startfile_impl(PyObject *module, path_t *filepath, + const Py_UNICODE *operation, const Py_UNICODE *arguments, + path_t *cwd, int show_cmd) +/*[clinic end generated code: output=3baa4f9795841880 input=8248997b80669622]*/ +{ + HINSTANCE rc; + + if(!check_ShellExecute()) { + /* If the OS doesn't have ShellExecute, return a + NotImplementedError. */ + return PyErr_Format(PyExc_NotImplementedError, + "startfile not available on this platform"); + } + + if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) { + return NULL; + } + if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation, + arguments, cwd->object ? cwd->object : Py_None, + show_cmd) < 0) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide, + arguments, cwd->wide, show_cmd); + Py_END_ALLOW_THREADS + + if (rc <= (HINSTANCE)32) { + win32_error_object("startfile", filepath->object); + return NULL; + } + Py_RETURN_NONE; +} +#endif /* MS_WINDOWS */ + + +#ifdef HAVE_GETLOADAVG +/*[clinic input] +os.getloadavg + +Return average recent system load information. + +Return the number of processes in the system run queue averaged over +the last 1, 5, and 15 minutes as a tuple of three floats. +Raises OSError if the load average was unobtainable. +[clinic start generated code]*/ + +static PyObject * +os_getloadavg_impl(PyObject *module) +/*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/ +{ + double loadavg[3]; + if (getloadavg(loadavg, 3)!=3) { + PyErr_SetString(PyExc_OSError, "Load averages are unobtainable"); + return NULL; + } else + return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]); +} +#endif /* HAVE_GETLOADAVG */ + + +/*[clinic input] +os.device_encoding + fd: int + +Return a string describing the encoding of a terminal's file descriptor. + +The file descriptor must be attached to a terminal. +If the device is not a terminal, return None. +[clinic start generated code]*/ + +static PyObject * +os_device_encoding_impl(PyObject *module, int fd) +/*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/ +{ + return _Py_device_encoding(fd); +} + + +#ifdef HAVE_SETRESUID +/*[clinic input] +os.setresuid + + ruid: uid_t + euid: uid_t + suid: uid_t + / + +Set the current process's real, effective, and saved user ids. +[clinic start generated code]*/ + +static PyObject * +os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid) +/*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/ +{ + if (setresuid(ruid, euid, suid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETRESUID */ + + +#ifdef HAVE_SETRESGID +/*[clinic input] +os.setresgid + + rgid: gid_t + egid: gid_t + sgid: gid_t + / + +Set the current process's real, effective, and saved group ids. +[clinic start generated code]*/ + +static PyObject * +os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid) +/*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/ +{ + if (setresgid(rgid, egid, sgid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETRESGID */ + + +#ifdef HAVE_GETRESUID +/*[clinic input] +os.getresuid + +Return a tuple of the current process's real, effective, and saved user ids. +[clinic start generated code]*/ + +static PyObject * +os_getresuid_impl(PyObject *module) +/*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/ +{ + uid_t ruid, euid, suid; + if (getresuid(&ruid, &euid, &suid) < 0) + return posix_error(); + return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid), + _PyLong_FromUid(euid), + _PyLong_FromUid(suid)); +} +#endif /* HAVE_GETRESUID */ + + +#ifdef HAVE_GETRESGID +/*[clinic input] +os.getresgid + +Return a tuple of the current process's real, effective, and saved group ids. +[clinic start generated code]*/ + +static PyObject * +os_getresgid_impl(PyObject *module) +/*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/ +{ + gid_t rgid, egid, sgid; + if (getresgid(&rgid, &egid, &sgid) < 0) + return posix_error(); + return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid), + _PyLong_FromGid(egid), + _PyLong_FromGid(sgid)); +} +#endif /* HAVE_GETRESGID */ + + +#ifdef USE_XATTRS +/*[clinic input] +os.getxattr + + path: path_t(allow_fd=True) + attribute: path_t + * + follow_symlinks: bool = True + +Return the value of extended attribute attribute on path. + +path may be either a string, a path-like object, or an open file descriptor. +If follow_symlinks is False, and the last element of the path is a symbolic + link, getxattr will examine the symbolic link itself instead of the file + the link points to. + +[clinic start generated code]*/ + +static PyObject * +os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute, + int follow_symlinks) +/*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/ +{ + Py_ssize_t i; + PyObject *buffer = NULL; + + if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks)) + return NULL; + + if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) { + return NULL; + } + + for (i = 0; ; i++) { + void *ptr; + ssize_t result; + static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0}; + Py_ssize_t buffer_size = buffer_sizes[i]; + if (!buffer_size) { + path_error(path); + return NULL; + } + buffer = PyBytes_FromStringAndSize(NULL, buffer_size); + if (!buffer) + return NULL; + ptr = PyBytes_AS_STRING(buffer); + + Py_BEGIN_ALLOW_THREADS; + if (path->fd >= 0) + result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size); + else if (follow_symlinks) + result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size); + else + result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size); + Py_END_ALLOW_THREADS; + + if (result < 0) { + Py_DECREF(buffer); + if (errno == ERANGE) + continue; + path_error(path); + return NULL; + } + + if (result != buffer_size) { + /* Can only shrink. */ + _PyBytes_Resize(&buffer, result); + } + break; + } + + return buffer; +} + + +/*[clinic input] +os.setxattr + + path: path_t(allow_fd=True) + attribute: path_t + value: Py_buffer + flags: int = 0 + * + follow_symlinks: bool = True + +Set extended attribute attribute on path to value. + +path may be either a string, a path-like object, or an open file descriptor. +If follow_symlinks is False, and the last element of the path is a symbolic + link, setxattr will modify the symbolic link itself instead of the file + the link points to. + +[clinic start generated code]*/ + +static PyObject * +os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute, + Py_buffer *value, int flags, int follow_symlinks) +/*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/ +{ + ssize_t result; + + if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks)) + return NULL; + + if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object, + value->buf, value->len, flags) < 0) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS; + if (path->fd > -1) + result = fsetxattr(path->fd, attribute->narrow, + value->buf, value->len, flags); + else if (follow_symlinks) + result = setxattr(path->narrow, attribute->narrow, + value->buf, value->len, flags); + else + result = lsetxattr(path->narrow, attribute->narrow, + value->buf, value->len, flags); + Py_END_ALLOW_THREADS; + + if (result) { + path_error(path); + return NULL; + } + + Py_RETURN_NONE; +} + + +/*[clinic input] +os.removexattr + + path: path_t(allow_fd=True) + attribute: path_t + * + follow_symlinks: bool = True + +Remove extended attribute attribute on path. + +path may be either a string, a path-like object, or an open file descriptor. +If follow_symlinks is False, and the last element of the path is a symbolic + link, removexattr will modify the symbolic link itself instead of the file + the link points to. + +[clinic start generated code]*/ + +static PyObject * +os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute, + int follow_symlinks) +/*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/ +{ + ssize_t result; + + if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks)) + return NULL; + + if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS; + if (path->fd > -1) + result = fremovexattr(path->fd, attribute->narrow); + else if (follow_symlinks) + result = removexattr(path->narrow, attribute->narrow); + else + result = lremovexattr(path->narrow, attribute->narrow); + Py_END_ALLOW_THREADS; + + if (result) { + return path_error(path); + } + + Py_RETURN_NONE; +} + + +/*[clinic input] +os.listxattr + + path: path_t(allow_fd=True, nullable=True) = None + * + follow_symlinks: bool = True + +Return a list of extended attributes on path. + +path may be either None, a string, a path-like object, or an open file descriptor. +if path is None, listxattr will examine the current directory. +If follow_symlinks is False, and the last element of the path is a symbolic + link, listxattr will examine the symbolic link itself instead of the file + the link points to. +[clinic start generated code]*/ + +static PyObject * +os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks) +/*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/ +{ + Py_ssize_t i; + PyObject *result = NULL; + const char *name; + char *buffer = NULL; + + if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks)) + goto exit; + + if (PySys_Audit("os.listxattr", "(O)", + path->object ? path->object : Py_None) < 0) { + return NULL; + } + + name = path->narrow ? path->narrow : "."; + + for (i = 0; ; i++) { + const char *start, *trace, *end; + ssize_t length; + static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 }; + Py_ssize_t buffer_size = buffer_sizes[i]; + if (!buffer_size) { + /* ERANGE */ + path_error(path); + break; + } + buffer = PyMem_Malloc(buffer_size); + if (!buffer) { + PyErr_NoMemory(); + break; + } + + Py_BEGIN_ALLOW_THREADS; + if (path->fd > -1) + length = flistxattr(path->fd, buffer, buffer_size); + else if (follow_symlinks) + length = listxattr(name, buffer, buffer_size); + else + length = llistxattr(name, buffer, buffer_size); + Py_END_ALLOW_THREADS; + + if (length < 0) { + if (errno == ERANGE) { + PyMem_Free(buffer); + buffer = NULL; + continue; + } + path_error(path); + break; + } + + result = PyList_New(0); + if (!result) { + goto exit; + } + + end = buffer + length; + for (trace = start = buffer; trace != end; trace++) { + if (!*trace) { + int error; + PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start, + trace - start); + if (!attribute) { + Py_DECREF(result); + result = NULL; + goto exit; + } + error = PyList_Append(result, attribute); + Py_DECREF(attribute); + if (error) { + Py_DECREF(result); + result = NULL; + goto exit; + } + start = trace + 1; + } + } + break; + } +exit: + if (buffer) + PyMem_Free(buffer); + return result; +} +#endif /* USE_XATTRS */ + + +/*[clinic input] +os.urandom + + size: Py_ssize_t + / + +Return a bytes object containing random bytes suitable for cryptographic use. +[clinic start generated code]*/ + +static PyObject * +os_urandom_impl(PyObject *module, Py_ssize_t size) +/*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/ +{ + PyObject *bytes; + int result; + + if (size < 0) + return PyErr_Format(PyExc_ValueError, + "negative argument not allowed"); + bytes = PyBytes_FromStringAndSize(NULL, size); + if (bytes == NULL) + return NULL; + + result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes)); + if (result == -1) { + Py_DECREF(bytes); + return NULL; + } + return bytes; +} + +#ifdef HAVE_MEMFD_CREATE +/*[clinic input] +os.memfd_create + + name: FSConverter + flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC + +[clinic start generated code]*/ + +static PyObject * +os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags) +/*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/ +{ + int fd; + const char *bytes = PyBytes_AS_STRING(name); + Py_BEGIN_ALLOW_THREADS + fd = memfd_create(bytes, flags); + Py_END_ALLOW_THREADS + if (fd == -1) { + return PyErr_SetFromErrno(PyExc_OSError); + } + return PyLong_FromLong(fd); +} +#endif + +#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC) +/*[clinic input] +os.eventfd + + initval: unsigned_int + flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC + +Creates and returns an event notification file descriptor. +[clinic start generated code]*/ + +static PyObject * +os_eventfd_impl(PyObject *module, unsigned int initval, int flags) +/*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/ + +{ + /* initval is limited to uint32_t, internal counter is uint64_t */ + int fd; + Py_BEGIN_ALLOW_THREADS + fd = eventfd(initval, flags); + Py_END_ALLOW_THREADS + if (fd == -1) { + return PyErr_SetFromErrno(PyExc_OSError); + } + return PyLong_FromLong(fd); +} + +/*[clinic input] +os.eventfd_read + + fd: fildes + +Read eventfd value +[clinic start generated code]*/ + +static PyObject * +os_eventfd_read_impl(PyObject *module, int fd) +/*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/ +{ + eventfd_t value; + int result; + Py_BEGIN_ALLOW_THREADS + result = eventfd_read(fd, &value); + Py_END_ALLOW_THREADS + if (result == -1) { + return PyErr_SetFromErrno(PyExc_OSError); + } + return PyLong_FromUnsignedLongLong(value); +} + +/*[clinic input] +os.eventfd_write + + fd: fildes + value: unsigned_long_long + +Write eventfd value. +[clinic start generated code]*/ + +static PyObject * +os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value) +/*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/ +{ + int result; + Py_BEGIN_ALLOW_THREADS + result = eventfd_write(fd, value); + Py_END_ALLOW_THREADS + if (result == -1) { + return PyErr_SetFromErrno(PyExc_OSError); + } + Py_RETURN_NONE; +} +#endif /* HAVE_EVENTFD && EFD_CLOEXEC */ + +/* Terminal size querying */ + +PyDoc_STRVAR(TerminalSize_docstring, + "A tuple of (columns, lines) for holding terminal window size"); + +static PyStructSequence_Field TerminalSize_fields[] = { + {"columns", "width of the terminal window in characters"}, + {"lines", "height of the terminal window in characters"}, + {NULL, NULL} +}; + +static PyStructSequence_Desc TerminalSize_desc = { + "os.terminal_size", + TerminalSize_docstring, + TerminalSize_fields, + 2, +}; + +#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) +/*[clinic input] +os.get_terminal_size + + fd: int(c_default="fileno(stdout)", py_default="") = -1 + / + +Return the size of the terminal window as (columns, lines). + +The optional argument fd (default standard output) specifies +which file descriptor should be queried. + +If the file descriptor is not connected to a terminal, an OSError +is thrown. + +This function will only be defined if an implementation is +available for this system. + +shutil.get_terminal_size is the high-level function which should +normally be used, os.get_terminal_size is the low-level implementation. +[clinic start generated code]*/ + +static PyObject * +os_get_terminal_size_impl(PyObject *module, int fd) +/*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/ +{ + int columns, lines; + PyObject *termsize; + + /* Under some conditions stdout may not be connected and + * fileno(stdout) may point to an invalid file descriptor. For example + * GUI apps don't have valid standard streams by default. + * + * If this happens, and the optional fd argument is not present, + * the ioctl below will fail returning EBADF. This is what we want. + */ + +#ifdef TERMSIZE_USE_IOCTL + { + struct winsize w; + if (ioctl(fd, TIOCGWINSZ, &w)) + return PyErr_SetFromErrno(PyExc_OSError); + columns = w.ws_col; + lines = w.ws_row; + } +#endif /* TERMSIZE_USE_IOCTL */ + +#ifdef TERMSIZE_USE_CONIO + { + HANDLE handle; + CONSOLE_SCREEN_BUFFER_INFO csbi; + handle = _Py_get_osfhandle(fd); + if (handle == INVALID_HANDLE_VALUE) + return NULL; + + if (!GetConsoleScreenBufferInfo(handle, &csbi)) + return PyErr_SetFromWindowsErr(0); + + columns = csbi.srWindow.Right - csbi.srWindow.Left + 1; + lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; + } +#endif /* TERMSIZE_USE_CONIO */ + + PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType; + termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType); + if (termsize == NULL) + return NULL; + PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns)); + PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines)); + if (PyErr_Occurred()) { + Py_DECREF(termsize); + return NULL; + } + return termsize; +} +#endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */ + + +/*[clinic input] +os.cpu_count + +Return the number of CPUs in the system; return None if indeterminable. + +This number is not equivalent to the number of CPUs the current process can +use. The number of usable CPUs can be obtained with +``len(os.sched_getaffinity(0))`` +[clinic start generated code]*/ + +static PyObject * +os_cpu_count_impl(PyObject *module) +/*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/ +{ + int ncpu = 0; +#ifdef MS_WINDOWS + ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS); +#elif defined(__hpux) + ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL); +#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) + ncpu = sysconf(_SC_NPROCESSORS_ONLN); +#elif defined(__VXWORKS__) + ncpu = _Py_popcount32(vxCpuEnabledGet()); +#elif defined(__DragonFly__) || \ + defined(__OpenBSD__) || \ + defined(__FreeBSD__) || \ + defined(__NetBSD__) || \ + defined(__APPLE__) + int mib[2]; + size_t len = sizeof(ncpu); + mib[0] = CTL_HW; + mib[1] = HW_NCPU; + if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) + ncpu = 0; +#endif + if (ncpu >= 1) + return PyLong_FromLong(ncpu); + else + Py_RETURN_NONE; +} + + +/*[clinic input] +os.get_inheritable -> bool + + fd: int + / + +Get the close-on-exe flag of the specified file descriptor. +[clinic start generated code]*/ + +static int +os_get_inheritable_impl(PyObject *module, int fd) +/*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/ +{ + int return_value; + _Py_BEGIN_SUPPRESS_IPH + return_value = _Py_get_inheritable(fd); + _Py_END_SUPPRESS_IPH + return return_value; +} + + +/*[clinic input] +os.set_inheritable + fd: int + inheritable: int + / + +Set the inheritable flag of the specified file descriptor. +[clinic start generated code]*/ + +static PyObject * +os_set_inheritable_impl(PyObject *module, int fd, int inheritable) +/*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/ +{ + int result; + + _Py_BEGIN_SUPPRESS_IPH + result = _Py_set_inheritable(fd, inheritable, NULL); + _Py_END_SUPPRESS_IPH + if (result < 0) + return NULL; + Py_RETURN_NONE; +} + + +#ifdef MS_WINDOWS +/*[clinic input] +os.get_handle_inheritable -> bool + handle: intptr_t + / + +Get the close-on-exe flag of the specified file descriptor. +[clinic start generated code]*/ + +static int +os_get_handle_inheritable_impl(PyObject *module, intptr_t handle) +/*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/ +{ + DWORD flags; + + if (!GetHandleInformation((HANDLE)handle, &flags)) { + PyErr_SetFromWindowsErr(0); + return -1; + } + + return flags & HANDLE_FLAG_INHERIT; +} + + +/*[clinic input] +os.set_handle_inheritable + handle: intptr_t + inheritable: bool + / + +Set the inheritable flag of the specified handle. +[clinic start generated code]*/ + +static PyObject * +os_set_handle_inheritable_impl(PyObject *module, intptr_t handle, + int inheritable) +/*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/ +{ + DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0; + if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) { + PyErr_SetFromWindowsErr(0); + return NULL; + } + Py_RETURN_NONE; +} +#endif /* MS_WINDOWS */ + +#ifndef MS_WINDOWS +/*[clinic input] +os.get_blocking -> bool + fd: int + / + +Get the blocking mode of the file descriptor. + +Return False if the O_NONBLOCK flag is set, True if the flag is cleared. +[clinic start generated code]*/ + +static int +os_get_blocking_impl(PyObject *module, int fd) +/*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/ +{ + int blocking; + + _Py_BEGIN_SUPPRESS_IPH + blocking = _Py_get_blocking(fd); + _Py_END_SUPPRESS_IPH + return blocking; +} + +/*[clinic input] +os.set_blocking + fd: int + blocking: bool(accept={int}) + / + +Set the blocking mode of the specified file descriptor. + +Set the O_NONBLOCK flag if blocking is False, +clear the O_NONBLOCK flag otherwise. +[clinic start generated code]*/ + +static PyObject * +os_set_blocking_impl(PyObject *module, int fd, int blocking) +/*[clinic end generated code: output=384eb43aa0762a9d input=bf5c8efdc5860ff3]*/ +{ + int result; + + _Py_BEGIN_SUPPRESS_IPH + result = _Py_set_blocking(fd, blocking); + _Py_END_SUPPRESS_IPH + if (result < 0) + return NULL; + Py_RETURN_NONE; +} +#endif /* !MS_WINDOWS */ + + +/*[clinic input] +class os.DirEntry "DirEntry *" "DirEntryType" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/ + +typedef struct { + PyObject_HEAD + PyObject *name; + PyObject *path; + PyObject *stat; + PyObject *lstat; +#ifdef MS_WINDOWS + struct _Py_stat_struct win32_lstat; + uint64_t win32_file_index; + int got_file_index; +#else /* POSIX */ +#ifdef HAVE_DIRENT_D_TYPE + unsigned char d_type; +#endif + ino_t d_ino; + int dir_fd; +#endif +} DirEntry; + +static void +DirEntry_dealloc(DirEntry *entry) +{ + PyTypeObject *tp = Py_TYPE(entry); + Py_XDECREF(entry->name); + Py_XDECREF(entry->path); + Py_XDECREF(entry->stat); + Py_XDECREF(entry->lstat); + freefunc free_func = PyType_GetSlot(tp, Py_tp_free); + free_func(entry); + Py_DECREF(tp); +} + +/* Forward reference */ +static int +DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self, + int follow_symlinks, unsigned short mode_bits); + +/*[clinic input] +os.DirEntry.is_symlink -> bool + defining_class: defining_class + / + +Return True if the entry is a symbolic link; cached per entry. +[clinic start generated code]*/ + +static int +os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class) +/*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/ +{ +#ifdef MS_WINDOWS + return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK; +#elif defined(HAVE_DIRENT_D_TYPE) + /* POSIX */ + if (self->d_type != DT_UNKNOWN) + return self->d_type == DT_LNK; + else + return DirEntry_test_mode(defining_class, self, 0, S_IFLNK); +#else + /* POSIX without d_type */ + return DirEntry_test_mode(defining_class, self, 0, S_IFLNK); +#endif +} + +/*[clinic input] +os.DirEntry.is_junction -> bool + defining_class: defining_class + / + +Return True if the entry is a junction; cached per entry. +[clinic start generated code]*/ + +static int +os_DirEntry_is_junction_impl(DirEntry *self, PyTypeObject *defining_class) +/*[clinic end generated code: output=7061a07b0ef2cd1f input=475cd36fb7d4723f]*/ +{ +#ifdef MS_WINDOWS + return self->win32_lstat.st_reparse_tag == IO_REPARSE_TAG_MOUNT_POINT; +#else + return 0; +#endif +} + +static PyObject * +DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks) +{ + int result; + STRUCT_STAT st; + PyObject *ub; + +#ifdef MS_WINDOWS + if (!PyUnicode_FSDecoder(self->path, &ub)) + return NULL; + wchar_t *path = PyUnicode_AsWideCharString(ub, NULL); + Py_DECREF(ub); +#else /* POSIX */ + if (!PyUnicode_FSConverter(self->path, &ub)) + return NULL; + const char *path = PyBytes_AS_STRING(ub); + if (self->dir_fd != DEFAULT_DIR_FD) { +#ifdef HAVE_FSTATAT + if (HAVE_FSTATAT_RUNTIME) { + Py_BEGIN_ALLOW_THREADS + result = fstatat(self->dir_fd, path, &st, + follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); + Py_END_ALLOW_THREADS + } else + +#endif /* HAVE_FSTATAT */ + { + Py_DECREF(ub); + PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat"); + return NULL; + } + } + else +#endif + { + Py_BEGIN_ALLOW_THREADS + if (follow_symlinks) { + result = STAT(path, &st); + } + else { + result = LSTAT(path, &st); + } + Py_END_ALLOW_THREADS + } +#if defined(MS_WINDOWS) + PyMem_Free(path); +#else + Py_DECREF(ub); +#endif + + if (result != 0) + return path_object_error(self->path); + + return _pystat_fromstructstat(module, &st); +} + +static PyObject * +DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self) +{ + if (!self->lstat) { + PyObject *module = PyType_GetModule(defining_class); +#ifdef MS_WINDOWS + self->lstat = _pystat_fromstructstat(module, &self->win32_lstat); +#else /* POSIX */ + self->lstat = DirEntry_fetch_stat(module, self, 0); +#endif + } + return Py_XNewRef(self->lstat); +} + +/*[clinic input] +os.DirEntry.stat + defining_class: defining_class + / + * + follow_symlinks: bool = True + +Return stat_result object for the entry; cached per entry. +[clinic start generated code]*/ + +static PyObject * +os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class, + int follow_symlinks) +/*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/ +{ + if (!follow_symlinks) { + return DirEntry_get_lstat(defining_class, self); + } + + if (!self->stat) { + int result = os_DirEntry_is_symlink_impl(self, defining_class); + if (result == -1) { + return NULL; + } + if (result) { + PyObject *module = PyType_GetModule(defining_class); + self->stat = DirEntry_fetch_stat(module, self, 1); + } + else { + self->stat = DirEntry_get_lstat(defining_class, self); + } + } + + return Py_XNewRef(self->stat); +} + +/* Set exception and return -1 on error, 0 for False, 1 for True */ +static int +DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self, + int follow_symlinks, unsigned short mode_bits) +{ + PyObject *stat = NULL; + PyObject *st_mode = NULL; + long mode; + int result; +#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE) + int is_symlink; + int need_stat; +#endif +#ifdef MS_WINDOWS + unsigned long dir_bits; +#endif + +#ifdef MS_WINDOWS + is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK; + need_stat = follow_symlinks && is_symlink; +#elif defined(HAVE_DIRENT_D_TYPE) + is_symlink = self->d_type == DT_LNK; + need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink); +#endif + +#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE) + if (need_stat) { +#endif + stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks); + if (!stat) { + if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) { + /* If file doesn't exist (anymore), then return False + (i.e., say it's not a file/directory) */ + PyErr_Clear(); + return 0; + } + goto error; + } + _posixstate* state = get_posix_state(PyType_GetModule(defining_class)); + st_mode = PyObject_GetAttr(stat, state->st_mode); + if (!st_mode) + goto error; + + mode = PyLong_AsLong(st_mode); + if (mode == -1 && PyErr_Occurred()) + goto error; + Py_CLEAR(st_mode); + Py_CLEAR(stat); + result = (mode & S_IFMT) == mode_bits; +#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE) + } + else if (is_symlink) { + assert(mode_bits != S_IFLNK); + result = 0; + } + else { + assert(mode_bits == S_IFDIR || mode_bits == S_IFREG); +#ifdef MS_WINDOWS + dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY; + if (mode_bits == S_IFDIR) + result = dir_bits != 0; + else + result = dir_bits == 0; +#else /* POSIX */ + if (mode_bits == S_IFDIR) + result = self->d_type == DT_DIR; + else + result = self->d_type == DT_REG; +#endif + } +#endif + + return result; + +error: + Py_XDECREF(st_mode); + Py_XDECREF(stat); + return -1; +} + +/*[clinic input] +os.DirEntry.is_dir -> bool + defining_class: defining_class + / + * + follow_symlinks: bool = True + +Return True if the entry is a directory; cached per entry. +[clinic start generated code]*/ + +static int +os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class, + int follow_symlinks) +/*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/ +{ + return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR); +} + +/*[clinic input] +os.DirEntry.is_file -> bool + defining_class: defining_class + / + * + follow_symlinks: bool = True + +Return True if the entry is a file; cached per entry. +[clinic start generated code]*/ + +static int +os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class, + int follow_symlinks) +/*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/ +{ + return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG); +} + +/*[clinic input] +os.DirEntry.inode + +Return inode of the entry; cached per entry. +[clinic start generated code]*/ + +static PyObject * +os_DirEntry_inode_impl(DirEntry *self) +/*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/ +{ +#ifdef MS_WINDOWS + if (!self->got_file_index) { + PyObject *unicode; + STRUCT_STAT stat; + int result; + + if (!PyUnicode_FSDecoder(self->path, &unicode)) + return NULL; + wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL); + Py_DECREF(unicode); + result = LSTAT(path, &stat); + PyMem_Free(path); + + if (result != 0) + return path_object_error(self->path); + + self->win32_file_index = stat.st_ino; + self->got_file_index = 1; + } + static_assert(sizeof(unsigned long long) >= sizeof(self->win32_file_index), + "DirEntry.win32_file_index is larger than unsigned long long"); + return PyLong_FromUnsignedLongLong(self->win32_file_index); +#else /* POSIX */ + static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino), + "DirEntry.d_ino is larger than unsigned long long"); + return PyLong_FromUnsignedLongLong(self->d_ino); +#endif +} + +static PyObject * +DirEntry_repr(DirEntry *self) +{ + return PyUnicode_FromFormat("", self->name); +} + +/*[clinic input] +os.DirEntry.__fspath__ + +Returns the path for the entry. +[clinic start generated code]*/ + +static PyObject * +os_DirEntry___fspath___impl(DirEntry *self) +/*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/ +{ + return Py_NewRef(self->path); +} + +static PyMemberDef DirEntry_members[] = { + {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY, + "the entry's base filename, relative to scandir() \"path\" argument"}, + {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY, + "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"}, + {NULL} +}; + +#include "clinic/posixmodule.c.h" + +static PyMethodDef DirEntry_methods[] = { + OS_DIRENTRY_IS_DIR_METHODDEF + OS_DIRENTRY_IS_FILE_METHODDEF + OS_DIRENTRY_IS_SYMLINK_METHODDEF + OS_DIRENTRY_IS_JUNCTION_METHODDEF + OS_DIRENTRY_STAT_METHODDEF + OS_DIRENTRY_INODE_METHODDEF + OS_DIRENTRY___FSPATH___METHODDEF + {"__class_getitem__", Py_GenericAlias, + METH_O|METH_CLASS, PyDoc_STR("See PEP 585")}, + {NULL} +}; + +static PyType_Slot DirEntryType_slots[] = { + {Py_tp_dealloc, DirEntry_dealloc}, + {Py_tp_repr, DirEntry_repr}, + {Py_tp_methods, DirEntry_methods}, + {Py_tp_members, DirEntry_members}, + {0, 0}, +}; + +static PyType_Spec DirEntryType_spec = { + MODNAME ".DirEntry", + sizeof(DirEntry), + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, + DirEntryType_slots +}; + + +#ifdef MS_WINDOWS + +static wchar_t * +join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename) +{ + Py_ssize_t path_len; + Py_ssize_t size; + wchar_t *result; + wchar_t ch; + + if (!path_wide) { /* Default arg: "." */ + path_wide = L"."; + path_len = 1; + } + else { + path_len = wcslen(path_wide); + } + + /* The +1's are for the path separator and the NUL */ + size = path_len + 1 + wcslen(filename) + 1; + result = PyMem_New(wchar_t, size); + if (!result) { + PyErr_NoMemory(); + return NULL; + } + wcscpy(result, path_wide); + if (path_len > 0) { + ch = result[path_len - 1]; + if (ch != SEP && ch != ALTSEP && ch != L':') + result[path_len++] = SEP; + wcscpy(result + path_len, filename); + } + return result; +} + +static PyObject * +DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW) +{ + DirEntry *entry; + BY_HANDLE_FILE_INFORMATION file_info; + ULONG reparse_tag; + wchar_t *joined_path; + + PyObject *DirEntryType = get_posix_state(module)->DirEntryType; + entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType); + if (!entry) + return NULL; + entry->name = NULL; + entry->path = NULL; + entry->stat = NULL; + entry->lstat = NULL; + entry->got_file_index = 0; + + entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1); + if (!entry->name) + goto error; + if (path->narrow) { + Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name)); + if (!entry->name) + goto error; + } + + joined_path = join_path_filenameW(path->wide, dataW->cFileName); + if (!joined_path) + goto error; + + entry->path = PyUnicode_FromWideChar(joined_path, -1); + PyMem_Free(joined_path); + if (!entry->path) + goto error; + if (path->narrow) { + Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path)); + if (!entry->path) + goto error; + } + + find_data_to_file_info(dataW, &file_info, &reparse_tag); + _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat); + + return (PyObject *)entry; + +error: + Py_DECREF(entry); + return NULL; +} + +#else /* POSIX */ + +static char * +join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len) +{ + Py_ssize_t path_len; + Py_ssize_t size; + char *result; + + if (!path_narrow) { /* Default arg: "." */ + path_narrow = "."; + path_len = 1; + } + else { + path_len = strlen(path_narrow); + } + + if (filename_len == -1) + filename_len = strlen(filename); + + /* The +1's are for the path separator and the NUL */ + size = path_len + 1 + filename_len + 1; + result = PyMem_New(char, size); + if (!result) { + PyErr_NoMemory(); + return NULL; + } + strcpy(result, path_narrow); + if (path_len > 0 && result[path_len - 1] != '/') + result[path_len++] = '/'; + strcpy(result + path_len, filename); + return result; +} + +static PyObject * +DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name, + Py_ssize_t name_len, ino_t d_ino +#ifdef HAVE_DIRENT_D_TYPE + , unsigned char d_type +#endif + ) +{ + DirEntry *entry; + char *joined_path; + + PyObject *DirEntryType = get_posix_state(module)->DirEntryType; + entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType); + if (!entry) + return NULL; + entry->name = NULL; + entry->path = NULL; + entry->stat = NULL; + entry->lstat = NULL; + + if (path->fd != -1) { + entry->dir_fd = path->fd; + joined_path = NULL; + } + else { + entry->dir_fd = DEFAULT_DIR_FD; + joined_path = join_path_filename(path->narrow, name, name_len); + if (!joined_path) + goto error; + } + + if (!path->narrow || !PyBytes_Check(path->object)) { + entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len); + if (joined_path) + entry->path = PyUnicode_DecodeFSDefault(joined_path); + } + else { + entry->name = PyBytes_FromStringAndSize(name, name_len); + if (joined_path) + entry->path = PyBytes_FromString(joined_path); + } + PyMem_Free(joined_path); + if (!entry->name) + goto error; + + if (path->fd != -1) { + entry->path = Py_NewRef(entry->name); + } + else if (!entry->path) + goto error; + +#ifdef HAVE_DIRENT_D_TYPE + entry->d_type = d_type; +#endif + entry->d_ino = d_ino; + + return (PyObject *)entry; + +error: + Py_XDECREF(entry); + return NULL; +} + +#endif + + +typedef struct { + PyObject_HEAD + path_t path; +#ifdef MS_WINDOWS + HANDLE handle; + WIN32_FIND_DATAW file_data; + int first_time; +#else /* POSIX */ + DIR *dirp; +#endif +#ifdef HAVE_FDOPENDIR + int fd; +#endif +} ScandirIterator; + +#ifdef MS_WINDOWS + +static int +ScandirIterator_is_closed(ScandirIterator *iterator) +{ + return iterator->handle == INVALID_HANDLE_VALUE; +} + +static void +ScandirIterator_closedir(ScandirIterator *iterator) +{ + HANDLE handle = iterator->handle; + + if (handle == INVALID_HANDLE_VALUE) + return; + + iterator->handle = INVALID_HANDLE_VALUE; + Py_BEGIN_ALLOW_THREADS + FindClose(handle); + Py_END_ALLOW_THREADS +} + +static PyObject * +ScandirIterator_iternext(ScandirIterator *iterator) +{ + WIN32_FIND_DATAW *file_data = &iterator->file_data; + BOOL success; + PyObject *entry; + + /* Happens if the iterator is iterated twice, or closed explicitly */ + if (iterator->handle == INVALID_HANDLE_VALUE) + return NULL; + + while (1) { + if (!iterator->first_time) { + Py_BEGIN_ALLOW_THREADS + success = FindNextFileW(iterator->handle, file_data); + Py_END_ALLOW_THREADS + if (!success) { + /* Error or no more files */ + if (GetLastError() != ERROR_NO_MORE_FILES) + path_error(&iterator->path); + break; + } + } + iterator->first_time = 0; + + /* Skip over . and .. */ + if (wcscmp(file_data->cFileName, L".") != 0 && + wcscmp(file_data->cFileName, L"..") != 0) + { + PyObject *module = PyType_GetModule(Py_TYPE(iterator)); + entry = DirEntry_from_find_data(module, &iterator->path, file_data); + if (!entry) + break; + return entry; + } + + /* Loop till we get a non-dot directory or finish iterating */ + } + + /* Error or no more files */ + ScandirIterator_closedir(iterator); + return NULL; +} + +#else /* POSIX */ + +static int +ScandirIterator_is_closed(ScandirIterator *iterator) +{ + return !iterator->dirp; +} + +static void +ScandirIterator_closedir(ScandirIterator *iterator) +{ + DIR *dirp = iterator->dirp; + + if (!dirp) + return; + + iterator->dirp = NULL; + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_FDOPENDIR + if (iterator->path.fd != -1) + rewinddir(dirp); +#endif + closedir(dirp); + Py_END_ALLOW_THREADS + return; +} + +static PyObject * +ScandirIterator_iternext(ScandirIterator *iterator) +{ + struct dirent *direntp; + Py_ssize_t name_len; + int is_dot; + PyObject *entry; + + /* Happens if the iterator is iterated twice, or closed explicitly */ + if (!iterator->dirp) + return NULL; + + while (1) { + errno = 0; + Py_BEGIN_ALLOW_THREADS + direntp = readdir(iterator->dirp); + Py_END_ALLOW_THREADS + + if (!direntp) { + /* Error or no more files */ + if (errno != 0) + path_error(&iterator->path); + break; + } + + /* Skip over . and .. */ + name_len = NAMLEN(direntp); + is_dot = direntp->d_name[0] == '.' && + (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2)); + if (!is_dot) { + PyObject *module = PyType_GetModule(Py_TYPE(iterator)); + entry = DirEntry_from_posix_info(module, + &iterator->path, direntp->d_name, + name_len, direntp->d_ino +#ifdef HAVE_DIRENT_D_TYPE + , direntp->d_type +#endif + ); + if (!entry) + break; + return entry; + } + + /* Loop till we get a non-dot directory or finish iterating */ + } + + /* Error or no more files */ + ScandirIterator_closedir(iterator); + return NULL; +} + +#endif + +static PyObject * +ScandirIterator_close(ScandirIterator *self, PyObject *args) +{ + ScandirIterator_closedir(self); + Py_RETURN_NONE; +} + +static PyObject * +ScandirIterator_enter(PyObject *self, PyObject *args) +{ + return Py_NewRef(self); +} + +static PyObject * +ScandirIterator_exit(ScandirIterator *self, PyObject *args) +{ + ScandirIterator_closedir(self); + Py_RETURN_NONE; +} + +static void +ScandirIterator_finalize(ScandirIterator *iterator) +{ + PyObject *error_type, *error_value, *error_traceback; + + /* Save the current exception, if any. */ + PyErr_Fetch(&error_type, &error_value, &error_traceback); + + if (!ScandirIterator_is_closed(iterator)) { + ScandirIterator_closedir(iterator); + + if (PyErr_ResourceWarning((PyObject *)iterator, 1, + "unclosed scandir iterator %R", iterator)) { + /* Spurious errors can appear at shutdown */ + if (PyErr_ExceptionMatches(PyExc_Warning)) { + PyErr_WriteUnraisable((PyObject *) iterator); + } + } + } + + path_cleanup(&iterator->path); + + /* Restore the saved exception. */ + PyErr_Restore(error_type, error_value, error_traceback); +} + +static void +ScandirIterator_dealloc(ScandirIterator *iterator) +{ + PyTypeObject *tp = Py_TYPE(iterator); + if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0) + return; + + freefunc free_func = PyType_GetSlot(tp, Py_tp_free); + free_func(iterator); + Py_DECREF(tp); +} + +static PyMethodDef ScandirIterator_methods[] = { + {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS}, + {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS}, + {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS}, + {NULL} +}; + +static PyType_Slot ScandirIteratorType_slots[] = { + {Py_tp_dealloc, ScandirIterator_dealloc}, + {Py_tp_finalize, ScandirIterator_finalize}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, ScandirIterator_iternext}, + {Py_tp_methods, ScandirIterator_methods}, + {0, 0}, +}; + +static PyType_Spec ScandirIteratorType_spec = { + MODNAME ".ScandirIterator", + sizeof(ScandirIterator), + 0, + // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since + // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance. + (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE + | Py_TPFLAGS_DISALLOW_INSTANTIATION), + ScandirIteratorType_slots +}; + +/*[clinic input] +os.scandir + + path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None + +Return an iterator of DirEntry objects for given path. + +path can be specified as either str, bytes, or a path-like object. If path +is bytes, the names of yielded DirEntry objects will also be bytes; in +all other circumstances they will be str. + +If path is None, uses the path='.'. +[clinic start generated code]*/ + +static PyObject * +os_scandir_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/ +{ + ScandirIterator *iterator; +#ifdef MS_WINDOWS + wchar_t *path_strW; +#else + const char *path_str; +#ifdef HAVE_FDOPENDIR + int fd = -1; +#endif +#endif + + if (PySys_Audit("os.scandir", "O", + path->object ? path->object : Py_None) < 0) { + return NULL; + } + + PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType; + iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType); + if (!iterator) + return NULL; + +#ifdef MS_WINDOWS + iterator->handle = INVALID_HANDLE_VALUE; +#else + iterator->dirp = NULL; +#endif + + /* Move the ownership to iterator->path */ + memcpy(&iterator->path, path, sizeof(path_t)); + memset(path, 0, sizeof(path_t)); + +#ifdef MS_WINDOWS + iterator->first_time = 1; + + path_strW = join_path_filenameW(iterator->path.wide, L"*.*"); + if (!path_strW) + goto error; + + Py_BEGIN_ALLOW_THREADS + iterator->handle = FindFirstFileW(path_strW, &iterator->file_data); + Py_END_ALLOW_THREADS + + PyMem_Free(path_strW); + + if (iterator->handle == INVALID_HANDLE_VALUE) { + path_error(&iterator->path); + goto error; + } +#else /* POSIX */ + errno = 0; +#ifdef HAVE_FDOPENDIR + if (iterator->path.fd != -1) { + if (HAVE_FDOPENDIR_RUNTIME) { + /* closedir() closes the FD, so we duplicate it */ + fd = _Py_dup(iterator->path.fd); + if (fd == -1) + goto error; + + Py_BEGIN_ALLOW_THREADS + iterator->dirp = fdopendir(fd); + Py_END_ALLOW_THREADS + } else { + PyErr_SetString(PyExc_TypeError, + "scandir: path should be string, bytes, os.PathLike or None, not int"); + return NULL; + } + } + else +#endif + { + if (iterator->path.narrow) + path_str = iterator->path.narrow; + else + path_str = "."; + + Py_BEGIN_ALLOW_THREADS + iterator->dirp = opendir(path_str); + Py_END_ALLOW_THREADS + } + + if (!iterator->dirp) { + path_error(&iterator->path); +#ifdef HAVE_FDOPENDIR + if (fd != -1) { + Py_BEGIN_ALLOW_THREADS + close(fd); + Py_END_ALLOW_THREADS + } +#endif + goto error; + } +#endif + + return (PyObject *)iterator; + +error: + Py_DECREF(iterator); + return NULL; +} + +/* + Return the file system path representation of the object. + + If the object is str or bytes, then allow it to pass through with + an incremented refcount. If the object defines __fspath__(), then + return the result of that method. All other types raise a TypeError. +*/ +PyObject * +PyOS_FSPath(PyObject *path) +{ + /* For error message reasons, this function is manually inlined in + path_converter(). */ + PyObject *func = NULL; + PyObject *path_repr = NULL; + + if (PyUnicode_Check(path) || PyBytes_Check(path)) { + return Py_NewRef(path); + } + + func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__)); + if (NULL == func) { + return PyErr_Format(PyExc_TypeError, + "expected str, bytes or os.PathLike object, " + "not %.200s", + _PyType_Name(Py_TYPE(path))); + } + + path_repr = _PyObject_CallNoArgs(func); + Py_DECREF(func); + if (NULL == path_repr) { + return NULL; + } + + if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) { + PyErr_Format(PyExc_TypeError, + "expected %.200s.__fspath__() to return str or bytes, " + "not %.200s", _PyType_Name(Py_TYPE(path)), + _PyType_Name(Py_TYPE(path_repr))); + Py_DECREF(path_repr); + return NULL; + } + + return path_repr; +} + +/*[clinic input] +os.fspath + + path: object + +Return the file system path representation of the object. + +If the object is str or bytes, then allow it to pass through as-is. If the +object defines __fspath__(), then return the result of that method. All other +types raise a TypeError. +[clinic start generated code]*/ + +static PyObject * +os_fspath_impl(PyObject *module, PyObject *path) +/*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/ +{ + return PyOS_FSPath(path); +} + +#ifdef HAVE_GETRANDOM_SYSCALL +/*[clinic input] +os.getrandom + + size: Py_ssize_t + flags: int=0 + +Obtain a series of random bytes. +[clinic start generated code]*/ + +static PyObject * +os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags) +/*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/ +{ + PyObject *bytes; + Py_ssize_t n; + + if (size < 0) { + errno = EINVAL; + return posix_error(); + } + + bytes = PyBytes_FromStringAndSize(NULL, size); + if (bytes == NULL) { + PyErr_NoMemory(); + return NULL; + } + + while (1) { + n = syscall(SYS_getrandom, + PyBytes_AS_STRING(bytes), + PyBytes_GET_SIZE(bytes), + flags); + if (n < 0 && errno == EINTR) { + if (PyErr_CheckSignals() < 0) { + goto error; + } + + /* getrandom() was interrupted by a signal: retry */ + continue; + } + break; + } + + if (n < 0) { + PyErr_SetFromErrno(PyExc_OSError); + goto error; + } + + if (n != size) { + _PyBytes_Resize(&bytes, n); + } + + return bytes; + +error: + Py_DECREF(bytes); + return NULL; +} +#endif /* HAVE_GETRANDOM_SYSCALL */ + +#ifdef MS_WINDOWS +/* bpo-36085: Helper functions for managing DLL search directories + * on win32 + */ + +typedef DLL_DIRECTORY_COOKIE (WINAPI *PAddDllDirectory)(PCWSTR newDirectory); +typedef BOOL (WINAPI *PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie); + +/*[clinic input] +os._add_dll_directory + + path: path_t + +Add a path to the DLL search path. + +This search path is used when resolving dependencies for imported +extension modules (the module itself is resolved through sys.path), +and also by ctypes. + +Returns an opaque value that may be passed to os.remove_dll_directory +to remove this directory from the search path. +[clinic start generated code]*/ + +static PyObject * +os__add_dll_directory_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/ +{ + HMODULE hKernel32; + PAddDllDirectory AddDllDirectory; + DLL_DIRECTORY_COOKIE cookie = 0; + DWORD err = 0; + + if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) { + return NULL; + } + + /* For Windows 7, we have to load this. As this will be a fairly + infrequent operation, just do it each time. Kernel32 is always + loaded. */ + Py_BEGIN_ALLOW_THREADS + if (!(hKernel32 = GetModuleHandleW(L"kernel32")) || + !(AddDllDirectory = (PAddDllDirectory)GetProcAddress( + hKernel32, "AddDllDirectory")) || + !(cookie = (*AddDllDirectory)(path->wide))) { + err = GetLastError(); + } + Py_END_ALLOW_THREADS + + if (err) { + return win32_error_object_err("add_dll_directory", + path->object, err); + } + + return PyCapsule_New(cookie, "DLL directory cookie", NULL); +} + +/*[clinic input] +os._remove_dll_directory + + cookie: object + +Removes a path from the DLL search path. + +The parameter is an opaque value that was returned from +os.add_dll_directory. You can only remove directories that you added +yourself. +[clinic start generated code]*/ + +static PyObject * +os__remove_dll_directory_impl(PyObject *module, PyObject *cookie) +/*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/ +{ + HMODULE hKernel32; + PRemoveDllDirectory RemoveDllDirectory; + DLL_DIRECTORY_COOKIE cookieValue; + DWORD err = 0; + + if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) { + PyErr_SetString(PyExc_TypeError, + "Provided cookie was not returned from os.add_dll_directory"); + return NULL; + } + + cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer( + cookie, "DLL directory cookie"); + + /* For Windows 7, we have to load this. As this will be a fairly + infrequent operation, just do it each time. Kernel32 is always + loaded. */ + Py_BEGIN_ALLOW_THREADS + if (!(hKernel32 = GetModuleHandleW(L"kernel32")) || + !(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress( + hKernel32, "RemoveDllDirectory")) || + !(*RemoveDllDirectory)(cookieValue)) { + err = GetLastError(); + } + Py_END_ALLOW_THREADS + + if (err) { + return win32_error_object_err("remove_dll_directory", + NULL, err); + } + + if (PyCapsule_SetName(cookie, NULL)) { + return NULL; + } + + Py_RETURN_NONE; +} + +#endif + + +/* Only check if WIFEXITED is available: expect that it comes + with WEXITSTATUS, WIFSIGNALED, etc. + + os.waitstatus_to_exitcode() is implemented in C and not in Python, so + subprocess can safely call it during late Python finalization without + risking that used os attributes were set to None by finalize_modules(). */ +#if defined(WIFEXITED) || defined(MS_WINDOWS) +/*[clinic input] +os.waitstatus_to_exitcode + + status as status_obj: object + +Convert a wait status to an exit code. + +On Unix: + +* If WIFEXITED(status) is true, return WEXITSTATUS(status). +* If WIFSIGNALED(status) is true, return -WTERMSIG(status). +* Otherwise, raise a ValueError. + +On Windows, return status shifted right by 8 bits. + +On Unix, if the process is being traced or if waitpid() was called with +WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true. +This function must not be called if WIFSTOPPED(status) is true. +[clinic start generated code]*/ + +static PyObject * +os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj) +/*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/ +{ +#ifndef MS_WINDOWS + int status = _PyLong_AsInt(status_obj); + if (status == -1 && PyErr_Occurred()) { + return NULL; + } + + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + int exitcode; + if (WIFEXITED(wait_status)) { + exitcode = WEXITSTATUS(wait_status); + /* Sanity check to provide warranty on the function behavior. + It should not occur in practice */ + if (exitcode < 0) { + PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode); + return NULL; + } + } + else if (WIFSIGNALED(wait_status)) { + int signum = WTERMSIG(wait_status); + /* Sanity check to provide warranty on the function behavior. + It should not occurs in practice */ + if (signum <= 0) { + PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum); + return NULL; + } + exitcode = -signum; + } else if (WIFSTOPPED(wait_status)) { + /* Status only received if the process is being traced + or if waitpid() was called with WUNTRACED option. */ + int signum = WSTOPSIG(wait_status); + PyErr_Format(PyExc_ValueError, + "process stopped by delivery of signal %i", + signum); + return NULL; + } + else { + PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status); + return NULL; + } + return PyLong_FromLong(exitcode); +#else + /* Windows implementation: see os.waitpid() implementation + which uses _cwait(). */ + unsigned long long status = PyLong_AsUnsignedLongLong(status_obj); + if (status == (unsigned long long)-1 && PyErr_Occurred()) { + return NULL; + } + + unsigned long long exitcode = (status >> 8); + /* ExitProcess() accepts an UINT type: + reject exit code which doesn't fit in an UINT */ + if (exitcode > UINT_MAX) { + PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode); + return NULL; + } + return PyLong_FromUnsignedLong((unsigned long)exitcode); +#endif +} +#endif + + +static PyMethodDef posix_methods[] = { + + OS_STAT_METHODDEF + OS_ACCESS_METHODDEF + OS_TTYNAME_METHODDEF + OS_CHDIR_METHODDEF + OS_CHFLAGS_METHODDEF + OS_CHMOD_METHODDEF + OS_FCHMOD_METHODDEF + OS_LCHMOD_METHODDEF + OS_CHOWN_METHODDEF + OS_FCHOWN_METHODDEF + OS_LCHOWN_METHODDEF + OS_LCHFLAGS_METHODDEF + OS_CHROOT_METHODDEF + OS_CTERMID_METHODDEF + OS_GETCWD_METHODDEF + OS_GETCWDB_METHODDEF + OS_LINK_METHODDEF + OS_LISTDIR_METHODDEF + OS_LSTAT_METHODDEF + OS_MKDIR_METHODDEF + OS_NICE_METHODDEF + OS_GETPRIORITY_METHODDEF + OS_SETPRIORITY_METHODDEF + OS_POSIX_SPAWN_METHODDEF + OS_POSIX_SPAWNP_METHODDEF + OS_READLINK_METHODDEF + OS_COPY_FILE_RANGE_METHODDEF + OS_SPLICE_METHODDEF + OS_RENAME_METHODDEF + OS_REPLACE_METHODDEF + OS_RMDIR_METHODDEF + OS_SYMLINK_METHODDEF + OS_SYSTEM_METHODDEF + OS_UMASK_METHODDEF + OS_UNAME_METHODDEF + OS_UNLINK_METHODDEF + OS_REMOVE_METHODDEF + OS_UTIME_METHODDEF + OS_TIMES_METHODDEF + OS__EXIT_METHODDEF + OS__FCOPYFILE_METHODDEF + OS_EXECV_METHODDEF + OS_EXECVE_METHODDEF + OS_SPAWNV_METHODDEF + OS_SPAWNVE_METHODDEF + OS_FORK1_METHODDEF + OS_FORK_METHODDEF + OS_REGISTER_AT_FORK_METHODDEF + OS_SCHED_GET_PRIORITY_MAX_METHODDEF + OS_SCHED_GET_PRIORITY_MIN_METHODDEF + OS_SCHED_GETPARAM_METHODDEF + OS_SCHED_GETSCHEDULER_METHODDEF + OS_SCHED_RR_GET_INTERVAL_METHODDEF + OS_SCHED_SETPARAM_METHODDEF + OS_SCHED_SETSCHEDULER_METHODDEF + OS_SCHED_YIELD_METHODDEF + OS_SCHED_SETAFFINITY_METHODDEF + OS_SCHED_GETAFFINITY_METHODDEF + OS_OPENPTY_METHODDEF + OS_LOGIN_TTY_METHODDEF + OS_FORKPTY_METHODDEF + OS_GETEGID_METHODDEF + OS_GETEUID_METHODDEF + OS_GETGID_METHODDEF + OS_GETGROUPLIST_METHODDEF + OS_GETGROUPS_METHODDEF + OS_GETPID_METHODDEF + OS_GETPGRP_METHODDEF + OS_GETPPID_METHODDEF + OS_GETUID_METHODDEF + OS_GETLOGIN_METHODDEF + OS_KILL_METHODDEF + OS_KILLPG_METHODDEF + OS_PLOCK_METHODDEF + OS_STARTFILE_METHODDEF + OS_SETUID_METHODDEF + OS_SETEUID_METHODDEF + OS_SETREUID_METHODDEF + OS_SETGID_METHODDEF + OS_SETEGID_METHODDEF + OS_SETREGID_METHODDEF + OS_SETGROUPS_METHODDEF + OS_INITGROUPS_METHODDEF + OS_GETPGID_METHODDEF + OS_SETPGRP_METHODDEF + OS_WAIT_METHODDEF + OS_WAIT3_METHODDEF + OS_WAIT4_METHODDEF + OS_WAITID_METHODDEF + OS_WAITPID_METHODDEF + OS_PIDFD_OPEN_METHODDEF + OS_GETSID_METHODDEF + OS_SETSID_METHODDEF + OS_SETPGID_METHODDEF + OS_TCGETPGRP_METHODDEF + OS_TCSETPGRP_METHODDEF + OS_OPEN_METHODDEF + OS_CLOSE_METHODDEF + OS_CLOSERANGE_METHODDEF + OS_DEVICE_ENCODING_METHODDEF + OS_DUP_METHODDEF + OS_DUP2_METHODDEF + OS_LOCKF_METHODDEF + OS_LSEEK_METHODDEF + OS_READ_METHODDEF + OS_READV_METHODDEF + OS_PREAD_METHODDEF + OS_PREADV_METHODDEF + OS_WRITE_METHODDEF + OS_WRITEV_METHODDEF + OS_PWRITE_METHODDEF + OS_PWRITEV_METHODDEF + OS_SENDFILE_METHODDEF + OS_FSTAT_METHODDEF + OS_ISATTY_METHODDEF + OS_PIPE_METHODDEF + OS_PIPE2_METHODDEF + OS_MKFIFO_METHODDEF + OS_MKNOD_METHODDEF + OS_MAJOR_METHODDEF + OS_MINOR_METHODDEF + OS_MAKEDEV_METHODDEF + OS_FTRUNCATE_METHODDEF + OS_TRUNCATE_METHODDEF + OS_POSIX_FALLOCATE_METHODDEF + OS_POSIX_FADVISE_METHODDEF + OS_PUTENV_METHODDEF + OS_UNSETENV_METHODDEF + OS_STRERROR_METHODDEF + OS_FCHDIR_METHODDEF + OS_FSYNC_METHODDEF + OS_SYNC_METHODDEF + OS_FDATASYNC_METHODDEF + OS_WCOREDUMP_METHODDEF + OS_WIFCONTINUED_METHODDEF + OS_WIFSTOPPED_METHODDEF + OS_WIFSIGNALED_METHODDEF + OS_WIFEXITED_METHODDEF + OS_WEXITSTATUS_METHODDEF + OS_WTERMSIG_METHODDEF + OS_WSTOPSIG_METHODDEF + OS_FSTATVFS_METHODDEF + OS_STATVFS_METHODDEF + OS_CONFSTR_METHODDEF + OS_SYSCONF_METHODDEF + OS_FPATHCONF_METHODDEF + OS_PATHCONF_METHODDEF + OS_ABORT_METHODDEF + OS__GETFULLPATHNAME_METHODDEF + OS__GETDISKUSAGE_METHODDEF + OS__GETFINALPATHNAME_METHODDEF + OS__GETVOLUMEPATHNAME_METHODDEF + OS__PATH_SPLITROOT_METHODDEF + OS__PATH_NORMPATH_METHODDEF + OS_GETLOADAVG_METHODDEF + OS_URANDOM_METHODDEF + OS_SETRESUID_METHODDEF + OS_SETRESGID_METHODDEF + OS_GETRESUID_METHODDEF + OS_GETRESGID_METHODDEF + + OS_GETXATTR_METHODDEF + OS_SETXATTR_METHODDEF + OS_REMOVEXATTR_METHODDEF + OS_LISTXATTR_METHODDEF + + OS_GET_TERMINAL_SIZE_METHODDEF + OS_CPU_COUNT_METHODDEF + OS_GET_INHERITABLE_METHODDEF + OS_SET_INHERITABLE_METHODDEF + OS_GET_HANDLE_INHERITABLE_METHODDEF + OS_SET_HANDLE_INHERITABLE_METHODDEF + OS_GET_BLOCKING_METHODDEF + OS_SET_BLOCKING_METHODDEF + OS_SCANDIR_METHODDEF + OS_FSPATH_METHODDEF + OS_GETRANDOM_METHODDEF + OS_MEMFD_CREATE_METHODDEF + OS_EVENTFD_METHODDEF + OS_EVENTFD_READ_METHODDEF + OS_EVENTFD_WRITE_METHODDEF + OS__ADD_DLL_DIRECTORY_METHODDEF + OS__REMOVE_DLL_DIRECTORY_METHODDEF + OS_WAITSTATUS_TO_EXITCODE_METHODDEF + OS_SETNS_METHODDEF + OS_UNSHARE_METHODDEF + {NULL, NULL} /* Sentinel */ +}; + +static int +all_ins(PyObject *m) +{ +#ifdef F_OK + if (PyModule_AddIntMacro(m, F_OK)) return -1; +#endif +#ifdef R_OK + if (PyModule_AddIntMacro(m, R_OK)) return -1; +#endif +#ifdef W_OK + if (PyModule_AddIntMacro(m, W_OK)) return -1; +#endif +#ifdef X_OK + if (PyModule_AddIntMacro(m, X_OK)) return -1; +#endif +#ifdef NGROUPS_MAX + if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1; +#endif +#ifdef TMP_MAX + if (PyModule_AddIntMacro(m, TMP_MAX)) return -1; +#endif +#ifdef WCONTINUED + if (PyModule_AddIntMacro(m, WCONTINUED)) return -1; +#endif +#ifdef WNOHANG + if (PyModule_AddIntMacro(m, WNOHANG)) return -1; +#endif +#ifdef WUNTRACED + if (PyModule_AddIntMacro(m, WUNTRACED)) return -1; +#endif +#ifdef O_RDONLY + if (PyModule_AddIntMacro(m, O_RDONLY)) return -1; +#endif +#ifdef O_WRONLY + if (PyModule_AddIntMacro(m, O_WRONLY)) return -1; +#endif +#ifdef O_RDWR + if (PyModule_AddIntMacro(m, O_RDWR)) return -1; +#endif +#ifdef O_NDELAY + if (PyModule_AddIntMacro(m, O_NDELAY)) return -1; +#endif +#ifdef O_NONBLOCK + if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1; +#endif +#ifdef O_APPEND + if (PyModule_AddIntMacro(m, O_APPEND)) return -1; +#endif +#ifdef O_DSYNC + if (PyModule_AddIntMacro(m, O_DSYNC)) return -1; +#endif +#ifdef O_RSYNC + if (PyModule_AddIntMacro(m, O_RSYNC)) return -1; +#endif +#ifdef O_SYNC + if (PyModule_AddIntMacro(m, O_SYNC)) return -1; +#endif +#ifdef O_NOCTTY + if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1; +#endif +#ifdef O_CREAT + if (PyModule_AddIntMacro(m, O_CREAT)) return -1; +#endif +#ifdef O_EXCL + if (PyModule_AddIntMacro(m, O_EXCL)) return -1; +#endif +#ifdef O_TRUNC + if (PyModule_AddIntMacro(m, O_TRUNC)) return -1; +#endif +#ifdef O_BINARY + if (PyModule_AddIntMacro(m, O_BINARY)) return -1; +#endif +#ifdef O_TEXT + if (PyModule_AddIntMacro(m, O_TEXT)) return -1; +#endif +#ifdef O_XATTR + if (PyModule_AddIntMacro(m, O_XATTR)) return -1; +#endif +#ifdef O_LARGEFILE + if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1; +#endif +#ifndef __GNU__ +#ifdef O_SHLOCK + if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1; +#endif +#ifdef O_EXLOCK + if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1; +#endif +#endif +#ifdef O_EXEC + if (PyModule_AddIntMacro(m, O_EXEC)) return -1; +#endif +#ifdef O_SEARCH + if (PyModule_AddIntMacro(m, O_SEARCH)) return -1; +#endif +#ifdef O_PATH + if (PyModule_AddIntMacro(m, O_PATH)) return -1; +#endif +#ifdef O_TTY_INIT + if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1; +#endif +#ifdef O_TMPFILE + if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1; +#endif +#ifdef PRIO_PROCESS + if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1; +#endif +#ifdef PRIO_PGRP + if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1; +#endif +#ifdef PRIO_USER + if (PyModule_AddIntMacro(m, PRIO_USER)) return -1; +#endif +#ifdef O_CLOEXEC + if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1; +#endif +#ifdef O_ACCMODE + if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1; +#endif +#ifdef O_EVTONLY + if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1; +#endif +#ifdef O_FSYNC + if (PyModule_AddIntMacro(m, O_FSYNC)) return -1; +#endif +#ifdef O_SYMLINK + if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1; +#endif + +#ifdef SEEK_HOLE + if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1; +#endif +#ifdef SEEK_DATA + if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1; +#endif + +/* MS Windows */ +#ifdef O_NOINHERIT + /* Don't inherit in child processes. */ + if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1; +#endif +#ifdef _O_SHORT_LIVED + /* Optimize for short life (keep in memory). */ + /* MS forgot to define this one with a non-underscore form too. */ + if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1; +#endif +#ifdef O_TEMPORARY + /* Automatically delete when last handle is closed. */ + if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1; +#endif +#ifdef O_RANDOM + /* Optimize for random access. */ + if (PyModule_AddIntMacro(m, O_RANDOM)) return -1; +#endif +#ifdef O_SEQUENTIAL + /* Optimize for sequential access. */ + if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1; +#endif + +/* GNU extensions. */ +#ifdef O_ASYNC + /* Send a SIGIO signal whenever input or output + becomes available on file descriptor */ + if (PyModule_AddIntMacro(m, O_ASYNC)) return -1; +#endif +#ifdef O_DIRECT + /* Direct disk access. */ + if (PyModule_AddIntMacro(m, O_DIRECT)) return -1; +#endif +#ifdef O_DIRECTORY + /* Must be a directory. */ + if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1; +#endif +#ifdef O_NOFOLLOW + /* Do not follow links. */ + if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1; +#endif +#ifdef O_NOFOLLOW_ANY + if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1; +#endif +#ifdef O_NOLINKS + /* Fails if link count of the named file is greater than 1 */ + if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1; +#endif +#ifdef O_NOATIME + /* Do not update the access time. */ + if (PyModule_AddIntMacro(m, O_NOATIME)) return -1; +#endif + + /* These come from sysexits.h */ +#ifdef EX_OK + if (PyModule_AddIntMacro(m, EX_OK)) return -1; +#endif /* EX_OK */ +#ifdef EX_USAGE + if (PyModule_AddIntMacro(m, EX_USAGE)) return -1; +#endif /* EX_USAGE */ +#ifdef EX_DATAERR + if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1; +#endif /* EX_DATAERR */ +#ifdef EX_NOINPUT + if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1; +#endif /* EX_NOINPUT */ +#ifdef EX_NOUSER + if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1; +#endif /* EX_NOUSER */ +#ifdef EX_NOHOST + if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1; +#endif /* EX_NOHOST */ +#ifdef EX_UNAVAILABLE + if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1; +#endif /* EX_UNAVAILABLE */ +#ifdef EX_SOFTWARE + if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1; +#endif /* EX_SOFTWARE */ +#ifdef EX_OSERR + if (PyModule_AddIntMacro(m, EX_OSERR)) return -1; +#endif /* EX_OSERR */ +#ifdef EX_OSFILE + if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1; +#endif /* EX_OSFILE */ +#ifdef EX_CANTCREAT + if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1; +#endif /* EX_CANTCREAT */ +#ifdef EX_IOERR + if (PyModule_AddIntMacro(m, EX_IOERR)) return -1; +#endif /* EX_IOERR */ +#ifdef EX_TEMPFAIL + if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1; +#endif /* EX_TEMPFAIL */ +#ifdef EX_PROTOCOL + if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1; +#endif /* EX_PROTOCOL */ +#ifdef EX_NOPERM + if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1; +#endif /* EX_NOPERM */ +#ifdef EX_CONFIG + if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1; +#endif /* EX_CONFIG */ +#ifdef EX_NOTFOUND + if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1; +#endif /* EX_NOTFOUND */ + + /* statvfs */ +#ifdef ST_RDONLY + if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1; +#endif /* ST_RDONLY */ +#ifdef ST_NOSUID + if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1; +#endif /* ST_NOSUID */ + + /* GNU extensions */ +#ifdef ST_NODEV + if (PyModule_AddIntMacro(m, ST_NODEV)) return -1; +#endif /* ST_NODEV */ +#ifdef ST_NOEXEC + if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1; +#endif /* ST_NOEXEC */ +#ifdef ST_SYNCHRONOUS + if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1; +#endif /* ST_SYNCHRONOUS */ +#ifdef ST_MANDLOCK + if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1; +#endif /* ST_MANDLOCK */ +#ifdef ST_WRITE + if (PyModule_AddIntMacro(m, ST_WRITE)) return -1; +#endif /* ST_WRITE */ +#ifdef ST_APPEND + if (PyModule_AddIntMacro(m, ST_APPEND)) return -1; +#endif /* ST_APPEND */ +#ifdef ST_NOATIME + if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1; +#endif /* ST_NOATIME */ +#ifdef ST_NODIRATIME + if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1; +#endif /* ST_NODIRATIME */ +#ifdef ST_RELATIME + if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1; +#endif /* ST_RELATIME */ + + /* FreeBSD sendfile() constants */ +#ifdef SF_NODISKIO + if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1; +#endif + /* is obsolete since the 11.x release */ +#ifdef SF_MNOWAIT + if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1; +#endif +#ifdef SF_SYNC + if (PyModule_AddIntMacro(m, SF_SYNC)) return -1; +#endif +#ifdef SF_NOCACHE + if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1; +#endif + + /* constants for posix_fadvise */ +#ifdef POSIX_FADV_NORMAL + if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1; +#endif +#ifdef POSIX_FADV_SEQUENTIAL + if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1; +#endif +#ifdef POSIX_FADV_RANDOM + if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1; +#endif +#ifdef POSIX_FADV_NOREUSE + if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1; +#endif +#ifdef POSIX_FADV_WILLNEED + if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1; +#endif +#ifdef POSIX_FADV_DONTNEED + if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1; +#endif + + /* constants for waitid */ +#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID) + if (PyModule_AddIntMacro(m, P_PID)) return -1; + if (PyModule_AddIntMacro(m, P_PGID)) return -1; + if (PyModule_AddIntMacro(m, P_ALL)) return -1; +#ifdef P_PIDFD + if (PyModule_AddIntMacro(m, P_PIDFD)) return -1; +#endif +#ifdef PIDFD_NONBLOCK + if (PyModule_AddIntMacro(m, PIDFD_NONBLOCK)) return -1; +#endif +#endif +#ifdef WEXITED + if (PyModule_AddIntMacro(m, WEXITED)) return -1; +#endif +#ifdef WNOWAIT + if (PyModule_AddIntMacro(m, WNOWAIT)) return -1; +#endif +#ifdef WSTOPPED + if (PyModule_AddIntMacro(m, WSTOPPED)) return -1; +#endif +#ifdef CLD_EXITED + if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1; +#endif +#ifdef CLD_KILLED + if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1; +#endif +#ifdef CLD_DUMPED + if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1; +#endif +#ifdef CLD_TRAPPED + if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1; +#endif +#ifdef CLD_STOPPED + if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1; +#endif +#ifdef CLD_CONTINUED + if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1; +#endif + + /* constants for lockf */ +#ifdef F_LOCK + if (PyModule_AddIntMacro(m, F_LOCK)) return -1; +#endif +#ifdef F_TLOCK + if (PyModule_AddIntMacro(m, F_TLOCK)) return -1; +#endif +#ifdef F_ULOCK + if (PyModule_AddIntMacro(m, F_ULOCK)) return -1; +#endif +#ifdef F_TEST + if (PyModule_AddIntMacro(m, F_TEST)) return -1; +#endif + +#ifdef RWF_DSYNC + if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1; +#endif +#ifdef RWF_HIPRI + if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1; +#endif +#ifdef RWF_SYNC + if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1; +#endif +#ifdef RWF_NOWAIT + if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1; +#endif +#ifdef RWF_APPEND + if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1; +#endif + +/* constants for splice */ +#if defined(HAVE_SPLICE) && defined(__linux__) + if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1; + if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1; + if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1; +#endif + +/* constants for posix_spawn */ +#ifdef HAVE_POSIX_SPAWN + if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1; + if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1; + if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1; +#endif + +#if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN) + if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1; + if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1; + if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1; +#endif +#ifdef HAVE_SPAWNV + if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1; + if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1; +#endif + +#ifdef HAVE_SCHED_H +#ifdef SCHED_OTHER + if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1; +#endif +#ifdef SCHED_FIFO + if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1; +#endif +#ifdef SCHED_RR + if (PyModule_AddIntMacro(m, SCHED_RR)) return -1; +#endif +#ifdef SCHED_SPORADIC + if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1; +#endif +#ifdef SCHED_BATCH + if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1; +#endif +#ifdef SCHED_IDLE + if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1; +#endif +#ifdef SCHED_RESET_ON_FORK + if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1; +#endif +#ifdef SCHED_SYS + if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1; +#endif +#ifdef SCHED_IA + if (PyModule_AddIntMacro(m, SCHED_IA)) return -1; +#endif +#ifdef SCHED_FSS + if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1; +#endif +#ifdef SCHED_FX + if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1; +#endif + +/* constants for namespaces */ +#if defined(HAVE_SETNS) || defined(HAVE_UNSHARE) +#ifdef CLONE_FS + if (PyModule_AddIntMacro(m, CLONE_FS)) return -1; +#endif +#ifdef CLONE_FILES + if (PyModule_AddIntMacro(m, CLONE_FILES)) return -1; +#endif +#ifdef CLONE_NEWNS + if (PyModule_AddIntMacro(m, CLONE_NEWNS)) return -1; +#endif +#ifdef CLONE_NEWCGROUP + if (PyModule_AddIntMacro(m, CLONE_NEWCGROUP)) return -1; +#endif +#ifdef CLONE_NEWUTS + if (PyModule_AddIntMacro(m, CLONE_NEWUTS)) return -1; +#endif +#ifdef CLONE_NEWIPC + if (PyModule_AddIntMacro(m, CLONE_NEWIPC)) return -1; +#endif +#ifdef CLONE_NEWUSER + if (PyModule_AddIntMacro(m, CLONE_NEWUSER)) return -1; +#endif +#ifdef CLONE_NEWPID + if (PyModule_AddIntMacro(m, CLONE_NEWPID)) return -1; +#endif +#ifdef CLONE_NEWNET + if (PyModule_AddIntMacro(m, CLONE_NEWNET)) return -1; +#endif +#ifdef CLONE_NEWTIME + if (PyModule_AddIntMacro(m, CLONE_NEWTIME)) return -1; +#endif +#ifdef CLONE_SYSVSEM + if (PyModule_AddIntMacro(m, CLONE_SYSVSEM)) return -1; +#endif +#ifdef CLONE_THREAD + if (PyModule_AddIntMacro(m, CLONE_THREAD)) return -1; +#endif +#ifdef CLONE_SIGHAND + if (PyModule_AddIntMacro(m, CLONE_SIGHAND)) return -1; +#endif +#ifdef CLONE_VM + if (PyModule_AddIntMacro(m, CLONE_VM)) return -1; +#endif +#endif + +#endif + +#ifdef USE_XATTRS + if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1; + if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1; + if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1; +#endif + +#if HAVE_DECL_RTLD_LAZY + if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1; +#endif +#if HAVE_DECL_RTLD_NOW + if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1; +#endif +#if HAVE_DECL_RTLD_GLOBAL + if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1; +#endif +#if HAVE_DECL_RTLD_LOCAL + if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1; +#endif +#if HAVE_DECL_RTLD_NODELETE + if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1; +#endif +#if HAVE_DECL_RTLD_NOLOAD + if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1; +#endif +#if HAVE_DECL_RTLD_DEEPBIND + if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1; +#endif +#if HAVE_DECL_RTLD_MEMBER + if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1; +#endif + +#ifdef HAVE_GETRANDOM_SYSCALL + if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1; + if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1; +#endif +#ifdef HAVE_MEMFD_CREATE + if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1; + if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1; +#ifdef MFD_HUGETLB + if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1; +#endif +#ifdef MFD_HUGE_SHIFT + if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1; +#endif +#ifdef MFD_HUGE_MASK + if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1; +#endif +#ifdef MFD_HUGE_64KB + if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1; +#endif +#ifdef MFD_HUGE_512KB + if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1; +#endif +#ifdef MFD_HUGE_1MB + if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1; +#endif +#ifdef MFD_HUGE_2MB + if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1; +#endif +#ifdef MFD_HUGE_8MB + if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1; +#endif +#ifdef MFD_HUGE_16MB + if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1; +#endif +#ifdef MFD_HUGE_32MB + if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1; +#endif +#ifdef MFD_HUGE_256MB + if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1; +#endif +#ifdef MFD_HUGE_512MB + if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1; +#endif +#ifdef MFD_HUGE_1GB + if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1; +#endif +#ifdef MFD_HUGE_2GB + if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1; +#endif +#ifdef MFD_HUGE_16GB + if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1; +#endif +#endif /* HAVE_MEMFD_CREATE */ + +#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC) + if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1; +#ifdef EFD_NONBLOCK + if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1; +#endif +#ifdef EFD_SEMAPHORE + if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1; +#endif +#endif /* HAVE_EVENTFD && EFD_CLOEXEC */ + +#if defined(__APPLE__) + if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1; + if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1; + if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1; + if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1; +#endif + +#ifdef MS_WINDOWS + if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1; + if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1; + if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1; + if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1; + if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1; +#endif + + return 0; +} + + + +#define PROBE(name, test) \ + static int name(void) \ + { \ + if (test) { \ + return 1; \ + } else { \ + return 0; \ + } \ + } + +#ifdef HAVE_FSTATAT +PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME) +#endif + +#ifdef HAVE_FACCESSAT +PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME) +#endif + +#ifdef HAVE_FCHMODAT +PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME) +#endif + +#ifdef HAVE_FCHOWNAT +PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME) +#endif + +#ifdef HAVE_LINKAT +PROBE(probe_linkat, HAVE_LINKAT_RUNTIME) +#endif + +#ifdef HAVE_FDOPENDIR +PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME) +#endif + +#ifdef HAVE_MKDIRAT +PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME) +#endif + +#ifdef HAVE_MKFIFOAT +PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME) +#endif + +#ifdef HAVE_MKNODAT +PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME) +#endif + +#ifdef HAVE_RENAMEAT +PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME) +#endif + +#ifdef HAVE_UNLINKAT +PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME) +#endif + +#ifdef HAVE_OPENAT +PROBE(probe_openat, HAVE_OPENAT_RUNTIME) +#endif + +#ifdef HAVE_READLINKAT +PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME) +#endif + +#ifdef HAVE_SYMLINKAT +PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME) +#endif + +#ifdef HAVE_FUTIMENS +PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME) +#endif + +#ifdef HAVE_UTIMENSAT +PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME) +#endif + + + + +static const struct have_function { + const char * const label; + int (*probe)(void); +} have_functions[] = { + +#ifdef HAVE_EVENTFD + {"HAVE_EVENTFD", NULL}, +#endif + +#ifdef HAVE_FACCESSAT + { "HAVE_FACCESSAT", probe_faccessat }, +#endif + +#ifdef HAVE_FCHDIR + { "HAVE_FCHDIR", NULL }, +#endif + +#ifdef HAVE_FCHMOD + { "HAVE_FCHMOD", NULL }, +#endif + +#ifdef HAVE_FCHMODAT + { "HAVE_FCHMODAT", probe_fchmodat }, +#endif + +#ifdef HAVE_FCHOWN + { "HAVE_FCHOWN", NULL }, +#endif + +#ifdef HAVE_FCHOWNAT + { "HAVE_FCHOWNAT", probe_fchownat }, +#endif + +#ifdef HAVE_FEXECVE + { "HAVE_FEXECVE", NULL }, +#endif + +#ifdef HAVE_FDOPENDIR + { "HAVE_FDOPENDIR", probe_fdopendir }, +#endif + +#ifdef HAVE_FPATHCONF + { "HAVE_FPATHCONF", NULL }, +#endif + +#ifdef HAVE_FSTATAT + { "HAVE_FSTATAT", probe_fstatat }, +#endif + +#ifdef HAVE_FSTATVFS + { "HAVE_FSTATVFS", NULL }, +#endif + +#if defined HAVE_FTRUNCATE || defined MS_WINDOWS + { "HAVE_FTRUNCATE", NULL }, +#endif + +#ifdef HAVE_FUTIMENS + { "HAVE_FUTIMENS", probe_futimens }, +#endif + +#ifdef HAVE_FUTIMES + { "HAVE_FUTIMES", NULL }, +#endif + +#ifdef HAVE_FUTIMESAT + { "HAVE_FUTIMESAT", NULL }, +#endif + +#ifdef HAVE_LINKAT + { "HAVE_LINKAT", probe_linkat }, +#endif + +#ifdef HAVE_LCHFLAGS + { "HAVE_LCHFLAGS", NULL }, +#endif + +#ifdef HAVE_LCHMOD + { "HAVE_LCHMOD", NULL }, +#endif + +#ifdef HAVE_LCHOWN + { "HAVE_LCHOWN", NULL }, +#endif + +#ifdef HAVE_LSTAT + { "HAVE_LSTAT", NULL }, +#endif + +#ifdef HAVE_LUTIMES + { "HAVE_LUTIMES", NULL }, +#endif + +#ifdef HAVE_MEMFD_CREATE + { "HAVE_MEMFD_CREATE", NULL }, +#endif + +#ifdef HAVE_MKDIRAT + { "HAVE_MKDIRAT", probe_mkdirat }, +#endif + +#ifdef HAVE_MKFIFOAT + { "HAVE_MKFIFOAT", probe_mkfifoat }, +#endif + +#ifdef HAVE_MKNODAT + { "HAVE_MKNODAT", probe_mknodat }, +#endif + +#ifdef HAVE_OPENAT + { "HAVE_OPENAT", probe_openat }, +#endif + +#ifdef HAVE_READLINKAT + { "HAVE_READLINKAT", probe_readlinkat }, +#endif + +#ifdef HAVE_RENAMEAT + { "HAVE_RENAMEAT", probe_renameat }, +#endif + +#ifdef HAVE_SYMLINKAT + { "HAVE_SYMLINKAT", probe_symlinkat }, +#endif + +#ifdef HAVE_UNLINKAT + { "HAVE_UNLINKAT", probe_unlinkat }, +#endif + +#ifdef HAVE_UTIMENSAT + { "HAVE_UTIMENSAT", probe_utimensat }, +#endif + +#ifdef MS_WINDOWS + { "MS_WINDOWS", NULL }, +#endif + + { NULL, NULL } +}; + + +static int +posixmodule_exec(PyObject *m) +{ + _posixstate *state = get_posix_state(m); + +#if defined(HAVE_PWRITEV) + if (HAVE_PWRITEV_RUNTIME) {} else { + PyObject* dct = PyModule_GetDict(m); + + if (dct == NULL) { + return -1; + } + + if (PyDict_DelItemString(dct, "pwritev") == -1) { + PyErr_Clear(); + } + if (PyDict_DelItemString(dct, "preadv") == -1) { + PyErr_Clear(); + } + } +#endif + + /* Initialize environ dictionary */ + PyObject *v = convertenviron(); + Py_XINCREF(v); + if (v == NULL || PyModule_AddObject(m, "environ", v) != 0) + return -1; + Py_DECREF(v); + + if (all_ins(m)) + return -1; + + if (setup_confname_tables(m)) + return -1; + + PyModule_AddObject(m, "error", Py_NewRef(PyExc_OSError)); + +#if defined(HAVE_WAITID) && !defined(__APPLE__) + waitid_result_desc.name = MODNAME ".waitid_result"; + PyObject *WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc); + if (WaitidResultType == NULL) { + return -1; + } + PyModule_AddObject(m, "waitid_result", Py_NewRef(WaitidResultType)); + state->WaitidResultType = WaitidResultType; +#endif + + stat_result_desc.name = "os.stat_result"; /* see issue #19209 */ + stat_result_desc.fields[7].name = PyStructSequence_UnnamedField; + stat_result_desc.fields[8].name = PyStructSequence_UnnamedField; + stat_result_desc.fields[9].name = PyStructSequence_UnnamedField; + PyObject *StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc); + if (StatResultType == NULL) { + return -1; + } + PyModule_AddObject(m, "stat_result", Py_NewRef(StatResultType)); + state->StatResultType = StatResultType; + structseq_new = ((PyTypeObject *)StatResultType)->tp_new; + ((PyTypeObject *)StatResultType)->tp_new = statresult_new; + + statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */ + PyObject *StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc); + if (StatVFSResultType == NULL) { + return -1; + } + PyModule_AddObject(m, "statvfs_result", Py_NewRef(StatVFSResultType)); + state->StatVFSResultType = StatVFSResultType; +#ifdef NEED_TICKS_PER_SECOND +# if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK) + ticks_per_second = sysconf(_SC_CLK_TCK); +# elif defined(HZ) + ticks_per_second = HZ; +# else + ticks_per_second = 60; /* magic fallback value; may be bogus */ +# endif +#endif + +#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) + sched_param_desc.name = MODNAME ".sched_param"; + PyObject *SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc); + if (SchedParamType == NULL) { + return -1; + } + PyModule_AddObject(m, "sched_param", Py_NewRef(SchedParamType)); + state->SchedParamType = SchedParamType; + ((PyTypeObject *)SchedParamType)->tp_new = os_sched_param; +#endif + + /* initialize TerminalSize_info */ + PyObject *TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc); + if (TerminalSizeType == NULL) { + return -1; + } + PyModule_AddObject(m, "terminal_size", Py_NewRef(TerminalSizeType)); + state->TerminalSizeType = TerminalSizeType; + + /* initialize scandir types */ + PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL); + if (ScandirIteratorType == NULL) { + return -1; + } + state->ScandirIteratorType = ScandirIteratorType; + + PyObject *DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL); + if (DirEntryType == NULL) { + return -1; + } + PyModule_AddObject(m, "DirEntry", Py_NewRef(DirEntryType)); + state->DirEntryType = DirEntryType; + + times_result_desc.name = MODNAME ".times_result"; + PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(×_result_desc); + if (TimesResultType == NULL) { + return -1; + } + PyModule_AddObject(m, "times_result", Py_NewRef(TimesResultType)); + state->TimesResultType = TimesResultType; + + PyTypeObject *UnameResultType = PyStructSequence_NewType(&uname_result_desc); + if (UnameResultType == NULL) { + return -1; + } + ; + PyModule_AddObject(m, "uname_result", Py_NewRef(UnameResultType)); + state->UnameResultType = (PyObject *)UnameResultType; + + if ((state->billion = PyLong_FromLong(1000000000)) == NULL) + return -1; +#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) + state->struct_rusage = PyUnicode_InternFromString("struct_rusage"); + if (state->struct_rusage == NULL) + return -1; +#endif + state->st_mode = PyUnicode_InternFromString("st_mode"); + if (state->st_mode == NULL) + return -1; + + /* suppress "function not used" warnings */ + { + int ignored; + fd_specified("", -1); + follow_symlinks_specified("", 1); + dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1); + dir_fd_converter(Py_None, &ignored); + dir_fd_unavailable(Py_None, &ignored); + } + + /* + * provide list of locally available functions + * so os.py can populate support_* lists + */ + PyObject *list = PyList_New(0); + if (!list) { + return -1; + } + for (const struct have_function *trace = have_functions; trace->label; trace++) { + PyObject *unicode; + if (trace->probe && !trace->probe()) continue; + unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL); + if (!unicode) + return -1; + if (PyList_Append(list, unicode)) + return -1; + Py_DECREF(unicode); + } + + PyModule_AddObject(m, "_have_functions", list); + + return 0; +} + + +static PyModuleDef_Slot posixmodile_slots[] = { + {Py_mod_exec, posixmodule_exec}, + {0, NULL} +}; + +static struct PyModuleDef posixmodule = { + PyModuleDef_HEAD_INIT, + .m_name = MODNAME, + .m_doc = posix__doc__, + .m_size = sizeof(_posixstate), + .m_methods = posix_methods, + .m_slots = posixmodile_slots, + .m_traverse = _posix_traverse, + .m_clear = _posix_clear, + .m_free = _posix_free, +}; + +PyMODINIT_FUNC +INITFUNC(void) +{ + return PyModuleDef_Init(&posixmodule); +} + +#ifdef __cplusplus +} +#endif diff --git a/Programs/test_frozenmain.h b/Programs/test_frozenmain.h index 96be3ce3c25c3f..f2cf1978367eab 100644 --- a/Programs/test_frozenmain.h +++ b/Programs/test_frozenmain.h @@ -1,42 +1,42 @@ -// Auto-generated by Programs/freeze_test_frozenmain.py -unsigned char M_test_frozenmain[] = { - 227,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0, - 0,0,0,0,0,243,184,0,0,0,151,0,100,0,100,1, - 108,0,90,0,100,0,100,1,108,1,90,1,2,0,101,2, - 100,2,171,1,0,0,0,0,0,0,0,0,1,0,2,0, - 101,2,100,3,101,0,106,6,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,171,2,0,0,0,0, - 0,0,0,0,1,0,2,0,101,1,106,8,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,171,0, - 0,0,0,0,0,0,0,0,100,4,25,0,0,0,0,0, - 0,0,0,0,90,5,100,5,68,0,93,23,0,0,90,6, - 2,0,101,2,100,6,101,6,155,0,100,7,101,5,101,6, - 25,0,0,0,0,0,0,0,0,0,155,0,157,4,171,1, - 0,0,0,0,0,0,0,0,1,0,140,25,4,0,100,1, - 83,0,41,8,233,0,0,0,0,78,122,18,70,114,111,122, - 101,110,32,72,101,108,108,111,32,87,111,114,108,100,122,8, - 115,121,115,46,97,114,103,118,218,6,99,111,110,102,105,103, - 41,5,218,12,112,114,111,103,114,97,109,95,110,97,109,101, - 218,10,101,120,101,99,117,116,97,98,108,101,218,15,117,115, - 101,95,101,110,118,105,114,111,110,109,101,110,116,218,17,99, - 111,110,102,105,103,117,114,101,95,99,95,115,116,100,105,111, - 218,14,98,117,102,102,101,114,101,100,95,115,116,100,105,111, - 122,7,99,111,110,102,105,103,32,122,2,58,32,41,7,218, - 3,115,121,115,218,17,95,116,101,115,116,105,110,116,101,114, - 110,97,108,99,97,112,105,218,5,112,114,105,110,116,218,4, - 97,114,103,118,218,11,103,101,116,95,99,111,110,102,105,103, - 115,114,3,0,0,0,218,3,107,101,121,169,0,243,0,0, - 0,0,250,18,116,101,115,116,95,102,114,111,122,101,110,109, - 97,105,110,46,112,121,250,8,60,109,111,100,117,108,101,62, - 114,18,0,0,0,1,0,0,0,115,154,0,0,0,240,3, - 1,1,1,240,8,0,1,11,128,10,128,10,128,10,216,0, - 24,208,0,24,208,0,24,208,0,24,224,0,5,128,5,208, - 6,26,212,0,27,208,0,27,216,0,5,128,5,128,106,144, - 35,151,40,145,40,212,0,27,208,0,27,216,9,38,208,9, - 26,215,9,38,209,9,38,212,9,40,168,24,212,9,50,128, - 6,240,2,6,12,2,240,0,7,1,42,241,0,7,1,42, - 128,67,240,14,0,5,10,128,69,208,10,40,144,67,208,10, - 40,208,10,40,152,54,160,35,156,59,208,10,40,208,10,40, - 212,4,41,208,4,41,208,4,41,240,15,7,1,42,240,0, - 7,1,42,240,0,7,1,42,114,16,0,0,0, -}; +// Auto-generated by Programs/freeze_test_frozenmain.py +unsigned char M_test_frozenmain[] = { + 227,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0, + 0,0,0,0,0,243,184,0,0,0,151,0,100,0,100,1, + 108,0,90,0,100,0,100,1,108,1,90,1,2,0,101,2, + 100,2,171,1,0,0,0,0,0,0,0,0,1,0,2,0, + 101,2,100,3,101,0,106,6,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,171,2,0,0,0,0, + 0,0,0,0,1,0,2,0,101,1,106,8,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,171,0, + 0,0,0,0,0,0,0,0,100,4,25,0,0,0,0,0, + 0,0,0,0,90,5,100,5,68,0,93,23,0,0,90,6, + 2,0,101,2,100,6,101,6,155,0,100,7,101,5,101,6, + 25,0,0,0,0,0,0,0,0,0,155,0,157,4,171,1, + 0,0,0,0,0,0,0,0,1,0,140,25,4,0,100,1, + 83,0,41,8,233,0,0,0,0,78,122,18,70,114,111,122, + 101,110,32,72,101,108,108,111,32,87,111,114,108,100,122,8, + 115,121,115,46,97,114,103,118,218,6,99,111,110,102,105,103, + 41,5,218,12,112,114,111,103,114,97,109,95,110,97,109,101, + 218,10,101,120,101,99,117,116,97,98,108,101,218,15,117,115, + 101,95,101,110,118,105,114,111,110,109,101,110,116,218,17,99, + 111,110,102,105,103,117,114,101,95,99,95,115,116,100,105,111, + 218,14,98,117,102,102,101,114,101,100,95,115,116,100,105,111, + 122,7,99,111,110,102,105,103,32,122,2,58,32,41,7,218, + 3,115,121,115,218,17,95,116,101,115,116,105,110,116,101,114, + 110,97,108,99,97,112,105,218,5,112,114,105,110,116,218,4, + 97,114,103,118,218,11,103,101,116,95,99,111,110,102,105,103, + 115,114,3,0,0,0,218,3,107,101,121,169,0,243,0,0, + 0,0,250,18,116,101,115,116,95,102,114,111,122,101,110,109, + 97,105,110,46,112,121,250,8,60,109,111,100,117,108,101,62, + 114,18,0,0,0,1,0,0,0,115,154,0,0,0,240,3, + 1,1,1,240,8,0,1,11,128,10,128,10,128,10,216,0, + 24,208,0,24,208,0,24,208,0,24,224,0,5,128,5,208, + 6,26,212,0,27,208,0,27,216,0,5,128,5,128,106,144, + 35,151,40,145,40,212,0,27,208,0,27,216,9,38,208,9, + 26,215,9,38,209,9,38,212,9,40,168,24,212,9,50,128, + 6,240,2,6,12,2,240,0,7,1,42,241,0,7,1,42, + 128,67,240,14,0,5,10,128,69,208,10,40,144,67,208,10, + 40,208,10,40,152,54,160,35,156,59,208,10,40,208,10,40, + 212,4,41,208,4,41,208,4,41,240,15,7,1,42,240,0, + 7,1,42,240,0,7,1,42,114,16,0,0,0, +}; From b71a0db57b5fca3f475fa1d1a47fd76c839c7582 Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Thu, 17 Nov 2022 21:51:39 -0800 Subject: [PATCH 23/35] Swap back to LF line endings --- Modules/clinic/posixmodule.c.h | 23104 +++++++++++----------- Modules/posixmodule.c | 32112 +++++++++++++++---------------- Programs/test_frozenmain.h | 84 +- 3 files changed, 27650 insertions(+), 27650 deletions(-) diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index 4cc4f5d46521b4..f9f6ca372ec6c7 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -1,11552 +1,11552 @@ -/*[clinic input] -preserve -[clinic start generated code]*/ - -#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) -# include "pycore_gc.h" // PyGC_Head -# include "pycore_runtime.h" // _Py_ID() -#endif - - -PyDoc_STRVAR(os_stat__doc__, -"stat($module, /, path, *, dir_fd=None, follow_symlinks=True)\n" -"--\n" -"\n" -"Perform a stat system call on the given path.\n" -"\n" -" path\n" -" Path to be examined; can be string, bytes, a path-like object or\n" -" open-file-descriptor int.\n" -" dir_fd\n" -" If not None, it should be a file descriptor open to a directory,\n" -" and path should be a relative string; path will then be relative to\n" -" that directory.\n" -" follow_symlinks\n" -" If False, and the last element of the path is a symbolic link,\n" -" stat will examine the symbolic link itself instead of the file\n" -" the link points to.\n" -"\n" -"dir_fd and follow_symlinks may not be implemented\n" -" on your platform. If they are unavailable, using them will raise a\n" -" NotImplementedError.\n" -"\n" -"It\'s an error to use dir_fd or follow_symlinks when specifying path as\n" -" an open file descriptor."); - -#define OS_STAT_METHODDEF \ - {"stat", _PyCFunction_CAST(os_stat), METH_FASTCALL|METH_KEYWORDS, os_stat__doc__}, - -static PyObject * -os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks); - -static PyObject * -os_stat(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(dir_fd), &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "dir_fd", "follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "stat", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("stat", "path", 0, 1); - int dir_fd = DEFAULT_DIR_FD; - int follow_symlinks = 1; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (args[1]) { - if (!FSTATAT_DIR_FD_CONVERTER(args[1], &dir_fd)) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - follow_symlinks = PyObject_IsTrue(args[2]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - return_value = os_stat_impl(module, &path, dir_fd, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -PyDoc_STRVAR(os_lstat__doc__, -"lstat($module, /, path, *, dir_fd=None)\n" -"--\n" -"\n" -"Perform a stat system call on the given path, without following symbolic links.\n" -"\n" -"Like stat(), but do not follow symbolic links.\n" -"Equivalent to stat(path, follow_symlinks=False)."); - -#define OS_LSTAT_METHODDEF \ - {"lstat", _PyCFunction_CAST(os_lstat), METH_FASTCALL|METH_KEYWORDS, os_lstat__doc__}, - -static PyObject * -os_lstat_impl(PyObject *module, path_t *path, int dir_fd); - -static PyObject * -os_lstat(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(dir_fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "dir_fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "lstat", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("lstat", "path", 0, 0); - int dir_fd = DEFAULT_DIR_FD; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (!FSTATAT_DIR_FD_CONVERTER(args[1], &dir_fd)) { - goto exit; - } -skip_optional_kwonly: - return_value = os_lstat_impl(module, &path, dir_fd); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -PyDoc_STRVAR(os_access__doc__, -"access($module, /, path, mode, *, dir_fd=None, effective_ids=False,\n" -" follow_symlinks=True)\n" -"--\n" -"\n" -"Use the real uid/gid to test for access to a path.\n" -"\n" -" path\n" -" Path to be tested; can be string, bytes, or a path-like object.\n" -" mode\n" -" Operating-system mode bitfield. Can be F_OK to test existence,\n" -" or the inclusive-OR of R_OK, W_OK, and X_OK.\n" -" dir_fd\n" -" If not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that\n" -" directory.\n" -" effective_ids\n" -" If True, access will use the effective uid/gid instead of\n" -" the real uid/gid.\n" -" follow_symlinks\n" -" If False, and the last element of the path is a symbolic link,\n" -" access will examine the symbolic link itself instead of the file\n" -" the link points to.\n" -"\n" -"dir_fd, effective_ids, and follow_symlinks may not be implemented\n" -" on your platform. If they are unavailable, using them will raise a\n" -" NotImplementedError.\n" -"\n" -"Note that most operations will use the effective uid/gid, therefore this\n" -" routine can be used in a suid/sgid environment to test if the invoking user\n" -" has the specified access to the path."); - -#define OS_ACCESS_METHODDEF \ - {"access", _PyCFunction_CAST(os_access), METH_FASTCALL|METH_KEYWORDS, os_access__doc__}, - -static int -os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd, - int effective_ids, int follow_symlinks); - -static PyObject * -os_access(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 5 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(mode), &_Py_ID(dir_fd), &_Py_ID(effective_ids), &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "mode", "dir_fd", "effective_ids", "follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "access", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[5]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("access", "path", 0, 0); - int mode; - int dir_fd = DEFAULT_DIR_FD; - int effective_ids = 0; - int follow_symlinks = 1; - int _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - mode = _PyLong_AsInt(args[1]); - if (mode == -1 && PyErr_Occurred()) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (args[2]) { - if (!FACCESSAT_DIR_FD_CONVERTER(args[2], &dir_fd)) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[3]) { - effective_ids = PyObject_IsTrue(args[3]); - if (effective_ids < 0) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - follow_symlinks = PyObject_IsTrue(args[4]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - _return_value = os_access_impl(module, &path, mode, dir_fd, effective_ids, follow_symlinks); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#if defined(HAVE_TTYNAME) - -PyDoc_STRVAR(os_ttyname__doc__, -"ttyname($module, fd, /)\n" -"--\n" -"\n" -"Return the name of the terminal device connected to \'fd\'.\n" -"\n" -" fd\n" -" Integer file descriptor handle."); - -#define OS_TTYNAME_METHODDEF \ - {"ttyname", (PyCFunction)os_ttyname, METH_O, os_ttyname__doc__}, - -static PyObject * -os_ttyname_impl(PyObject *module, int fd); - -static PyObject * -os_ttyname(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int fd; - - fd = _PyLong_AsInt(arg); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_ttyname_impl(module, fd); - -exit: - return return_value; -} - -#endif /* defined(HAVE_TTYNAME) */ - -#if defined(HAVE_CTERMID) - -PyDoc_STRVAR(os_ctermid__doc__, -"ctermid($module, /)\n" -"--\n" -"\n" -"Return the name of the controlling terminal for this process."); - -#define OS_CTERMID_METHODDEF \ - {"ctermid", (PyCFunction)os_ctermid, METH_NOARGS, os_ctermid__doc__}, - -static PyObject * -os_ctermid_impl(PyObject *module); - -static PyObject * -os_ctermid(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_ctermid_impl(module); -} - -#endif /* defined(HAVE_CTERMID) */ - -PyDoc_STRVAR(os_chdir__doc__, -"chdir($module, /, path)\n" -"--\n" -"\n" -"Change the current working directory to the specified path.\n" -"\n" -"path may always be specified as a string.\n" -"On some platforms, path may also be specified as an open file descriptor.\n" -" If this functionality is unavailable, using it raises an exception."); - -#define OS_CHDIR_METHODDEF \ - {"chdir", _PyCFunction_CAST(os_chdir), METH_FASTCALL|METH_KEYWORDS, os_chdir__doc__}, - -static PyObject * -os_chdir_impl(PyObject *module, path_t *path); - -static PyObject * -os_chdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "chdir", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("chdir", "path", 0, PATH_HAVE_FCHDIR); - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - return_value = os_chdir_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#if defined(HAVE_FCHDIR) - -PyDoc_STRVAR(os_fchdir__doc__, -"fchdir($module, /, fd)\n" -"--\n" -"\n" -"Change to the directory of the given file descriptor.\n" -"\n" -"fd must be opened on a directory, not a file.\n" -"Equivalent to os.chdir(fd)."); - -#define OS_FCHDIR_METHODDEF \ - {"fchdir", _PyCFunction_CAST(os_fchdir), METH_FASTCALL|METH_KEYWORDS, os_fchdir__doc__}, - -static PyObject * -os_fchdir_impl(PyObject *module, int fd); - -static PyObject * -os_fchdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "fchdir", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int fd; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { - goto exit; - } - return_value = os_fchdir_impl(module, fd); - -exit: - return return_value; -} - -#endif /* defined(HAVE_FCHDIR) */ - -PyDoc_STRVAR(os_chmod__doc__, -"chmod($module, /, path, mode, *, dir_fd=None, follow_symlinks=True)\n" -"--\n" -"\n" -"Change the access permissions of a file.\n" -"\n" -" path\n" -" Path to be modified. May always be specified as a str, bytes, or a path-like object.\n" -" On some platforms, path may also be specified as an open file descriptor.\n" -" If this functionality is unavailable, using it raises an exception.\n" -" mode\n" -" Operating-system mode bitfield.\n" -" dir_fd\n" -" If not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that\n" -" directory.\n" -" follow_symlinks\n" -" If False, and the last element of the path is a symbolic link,\n" -" chmod will modify the symbolic link itself instead of the file\n" -" the link points to.\n" -"\n" -"It is an error to use dir_fd or follow_symlinks when specifying path as\n" -" an open file descriptor.\n" -"dir_fd and follow_symlinks may not be implemented on your platform.\n" -" If they are unavailable, using them will raise a NotImplementedError."); - -#define OS_CHMOD_METHODDEF \ - {"chmod", _PyCFunction_CAST(os_chmod), METH_FASTCALL|METH_KEYWORDS, os_chmod__doc__}, - -static PyObject * -os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, - int follow_symlinks); - -static PyObject * -os_chmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 4 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(mode), &_Py_ID(dir_fd), &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "mode", "dir_fd", "follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "chmod", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[4]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("chmod", "path", 0, PATH_HAVE_FCHMOD); - int mode; - int dir_fd = DEFAULT_DIR_FD; - int follow_symlinks = 1; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - mode = _PyLong_AsInt(args[1]); - if (mode == -1 && PyErr_Occurred()) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (args[2]) { - if (!FCHMODAT_DIR_FD_CONVERTER(args[2], &dir_fd)) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - follow_symlinks = PyObject_IsTrue(args[3]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - return_value = os_chmod_impl(module, &path, mode, dir_fd, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#if defined(HAVE_FCHMOD) - -PyDoc_STRVAR(os_fchmod__doc__, -"fchmod($module, /, fd, mode)\n" -"--\n" -"\n" -"Change the access permissions of the file given by file descriptor fd.\n" -"\n" -"Equivalent to os.chmod(fd, mode)."); - -#define OS_FCHMOD_METHODDEF \ - {"fchmod", _PyCFunction_CAST(os_fchmod), METH_FASTCALL|METH_KEYWORDS, os_fchmod__doc__}, - -static PyObject * -os_fchmod_impl(PyObject *module, int fd, int mode); - -static PyObject * -os_fchmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(fd), &_Py_ID(mode), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"fd", "mode", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "fchmod", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - int fd; - int mode; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - mode = _PyLong_AsInt(args[1]); - if (mode == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_fchmod_impl(module, fd, mode); - -exit: - return return_value; -} - -#endif /* defined(HAVE_FCHMOD) */ - -#if defined(HAVE_LCHMOD) - -PyDoc_STRVAR(os_lchmod__doc__, -"lchmod($module, /, path, mode)\n" -"--\n" -"\n" -"Change the access permissions of a file, without following symbolic links.\n" -"\n" -"If path is a symlink, this affects the link itself rather than the target.\n" -"Equivalent to chmod(path, mode, follow_symlinks=False).\""); - -#define OS_LCHMOD_METHODDEF \ - {"lchmod", _PyCFunction_CAST(os_lchmod), METH_FASTCALL|METH_KEYWORDS, os_lchmod__doc__}, - -static PyObject * -os_lchmod_impl(PyObject *module, path_t *path, int mode); - -static PyObject * -os_lchmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(mode), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "mode", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "lchmod", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - path_t path = PATH_T_INITIALIZE("lchmod", "path", 0, 0); - int mode; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - mode = _PyLong_AsInt(args[1]); - if (mode == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_lchmod_impl(module, &path, mode); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(HAVE_LCHMOD) */ - -#if defined(HAVE_CHFLAGS) - -PyDoc_STRVAR(os_chflags__doc__, -"chflags($module, /, path, flags, follow_symlinks=True)\n" -"--\n" -"\n" -"Set file flags.\n" -"\n" -"If follow_symlinks is False, and the last element of the path is a symbolic\n" -" link, chflags will change flags on the symbolic link itself instead of the\n" -" file the link points to.\n" -"follow_symlinks may not be implemented on your platform. If it is\n" -"unavailable, using it will raise a NotImplementedError."); - -#define OS_CHFLAGS_METHODDEF \ - {"chflags", _PyCFunction_CAST(os_chflags), METH_FASTCALL|METH_KEYWORDS, os_chflags__doc__}, - -static PyObject * -os_chflags_impl(PyObject *module, path_t *path, unsigned long flags, - int follow_symlinks); - -static PyObject * -os_chflags(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(flags), &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "flags", "follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "chflags", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("chflags", "path", 0, 0); - unsigned long flags; - int follow_symlinks = 1; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!PyLong_Check(args[1])) { - _PyArg_BadArgument("chflags", "argument 'flags'", "int", args[1]); - goto exit; - } - flags = PyLong_AsUnsignedLongMask(args[1]); - if (!noptargs) { - goto skip_optional_pos; - } - follow_symlinks = PyObject_IsTrue(args[2]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_pos: - return_value = os_chflags_impl(module, &path, flags, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(HAVE_CHFLAGS) */ - -#if defined(HAVE_LCHFLAGS) - -PyDoc_STRVAR(os_lchflags__doc__, -"lchflags($module, /, path, flags)\n" -"--\n" -"\n" -"Set file flags.\n" -"\n" -"This function will not follow symbolic links.\n" -"Equivalent to chflags(path, flags, follow_symlinks=False)."); - -#define OS_LCHFLAGS_METHODDEF \ - {"lchflags", _PyCFunction_CAST(os_lchflags), METH_FASTCALL|METH_KEYWORDS, os_lchflags__doc__}, - -static PyObject * -os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags); - -static PyObject * -os_lchflags(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(flags), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "flags", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "lchflags", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - path_t path = PATH_T_INITIALIZE("lchflags", "path", 0, 0); - unsigned long flags; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!PyLong_Check(args[1])) { - _PyArg_BadArgument("lchflags", "argument 'flags'", "int", args[1]); - goto exit; - } - flags = PyLong_AsUnsignedLongMask(args[1]); - return_value = os_lchflags_impl(module, &path, flags); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(HAVE_LCHFLAGS) */ - -#if defined(HAVE_CHROOT) - -PyDoc_STRVAR(os_chroot__doc__, -"chroot($module, /, path)\n" -"--\n" -"\n" -"Change root directory to path."); - -#define OS_CHROOT_METHODDEF \ - {"chroot", _PyCFunction_CAST(os_chroot), METH_FASTCALL|METH_KEYWORDS, os_chroot__doc__}, - -static PyObject * -os_chroot_impl(PyObject *module, path_t *path); - -static PyObject * -os_chroot(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "chroot", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("chroot", "path", 0, 0); - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - return_value = os_chroot_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(HAVE_CHROOT) */ - -#if defined(HAVE_FSYNC) - -PyDoc_STRVAR(os_fsync__doc__, -"fsync($module, /, fd)\n" -"--\n" -"\n" -"Force write of fd to disk."); - -#define OS_FSYNC_METHODDEF \ - {"fsync", _PyCFunction_CAST(os_fsync), METH_FASTCALL|METH_KEYWORDS, os_fsync__doc__}, - -static PyObject * -os_fsync_impl(PyObject *module, int fd); - -static PyObject * -os_fsync(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "fsync", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int fd; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { - goto exit; - } - return_value = os_fsync_impl(module, fd); - -exit: - return return_value; -} - -#endif /* defined(HAVE_FSYNC) */ - -#if defined(HAVE_SYNC) - -PyDoc_STRVAR(os_sync__doc__, -"sync($module, /)\n" -"--\n" -"\n" -"Force write of everything to disk."); - -#define OS_SYNC_METHODDEF \ - {"sync", (PyCFunction)os_sync, METH_NOARGS, os_sync__doc__}, - -static PyObject * -os_sync_impl(PyObject *module); - -static PyObject * -os_sync(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_sync_impl(module); -} - -#endif /* defined(HAVE_SYNC) */ - -#if defined(HAVE_FDATASYNC) - -PyDoc_STRVAR(os_fdatasync__doc__, -"fdatasync($module, /, fd)\n" -"--\n" -"\n" -"Force write of fd to disk without forcing update of metadata."); - -#define OS_FDATASYNC_METHODDEF \ - {"fdatasync", _PyCFunction_CAST(os_fdatasync), METH_FASTCALL|METH_KEYWORDS, os_fdatasync__doc__}, - -static PyObject * -os_fdatasync_impl(PyObject *module, int fd); - -static PyObject * -os_fdatasync(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "fdatasync", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int fd; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { - goto exit; - } - return_value = os_fdatasync_impl(module, fd); - -exit: - return return_value; -} - -#endif /* defined(HAVE_FDATASYNC) */ - -#if defined(HAVE_CHOWN) - -PyDoc_STRVAR(os_chown__doc__, -"chown($module, /, path, uid, gid, *, dir_fd=None, follow_symlinks=True)\n" -"--\n" -"\n" -"Change the owner and group id of path to the numeric uid and gid.\\\n" -"\n" -" path\n" -" Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.\n" -" dir_fd\n" -" If not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that\n" -" directory.\n" -" follow_symlinks\n" -" If False, and the last element of the path is a symbolic link,\n" -" stat will examine the symbolic link itself instead of the file\n" -" the link points to.\n" -"\n" -"path may always be specified as a string.\n" -"On some platforms, path may also be specified as an open file descriptor.\n" -" If this functionality is unavailable, using it raises an exception.\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"If follow_symlinks is False, and the last element of the path is a symbolic\n" -" link, chown will modify the symbolic link itself instead of the file the\n" -" link points to.\n" -"It is an error to use dir_fd or follow_symlinks when specifying path as\n" -" an open file descriptor.\n" -"dir_fd and follow_symlinks may not be implemented on your platform.\n" -" If they are unavailable, using them will raise a NotImplementedError."); - -#define OS_CHOWN_METHODDEF \ - {"chown", _PyCFunction_CAST(os_chown), METH_FASTCALL|METH_KEYWORDS, os_chown__doc__}, - -static PyObject * -os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid, - int dir_fd, int follow_symlinks); - -static PyObject * -os_chown(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 5 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(uid), &_Py_ID(gid), &_Py_ID(dir_fd), &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "uid", "gid", "dir_fd", "follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "chown", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[5]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - path_t path = PATH_T_INITIALIZE("chown", "path", 0, PATH_HAVE_FCHOWN); - uid_t uid; - gid_t gid; - int dir_fd = DEFAULT_DIR_FD; - int follow_symlinks = 1; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!_Py_Uid_Converter(args[1], &uid)) { - goto exit; - } - if (!_Py_Gid_Converter(args[2], &gid)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (args[3]) { - if (!FCHOWNAT_DIR_FD_CONVERTER(args[3], &dir_fd)) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - follow_symlinks = PyObject_IsTrue(args[4]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - return_value = os_chown_impl(module, &path, uid, gid, dir_fd, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(HAVE_CHOWN) */ - -#if defined(HAVE_FCHOWN) - -PyDoc_STRVAR(os_fchown__doc__, -"fchown($module, /, fd, uid, gid)\n" -"--\n" -"\n" -"Change the owner and group id of the file specified by file descriptor.\n" -"\n" -"Equivalent to os.chown(fd, uid, gid)."); - -#define OS_FCHOWN_METHODDEF \ - {"fchown", _PyCFunction_CAST(os_fchown), METH_FASTCALL|METH_KEYWORDS, os_fchown__doc__}, - -static PyObject * -os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid); - -static PyObject * -os_fchown(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(fd), &_Py_ID(uid), &_Py_ID(gid), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"fd", "uid", "gid", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "fchown", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - int fd; - uid_t uid; - gid_t gid; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); - if (!args) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - if (!_Py_Uid_Converter(args[1], &uid)) { - goto exit; - } - if (!_Py_Gid_Converter(args[2], &gid)) { - goto exit; - } - return_value = os_fchown_impl(module, fd, uid, gid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_FCHOWN) */ - -#if defined(HAVE_LCHOWN) - -PyDoc_STRVAR(os_lchown__doc__, -"lchown($module, /, path, uid, gid)\n" -"--\n" -"\n" -"Change the owner and group id of path to the numeric uid and gid.\n" -"\n" -"This function will not follow symbolic links.\n" -"Equivalent to os.chown(path, uid, gid, follow_symlinks=False)."); - -#define OS_LCHOWN_METHODDEF \ - {"lchown", _PyCFunction_CAST(os_lchown), METH_FASTCALL|METH_KEYWORDS, os_lchown__doc__}, - -static PyObject * -os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid); - -static PyObject * -os_lchown(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(uid), &_Py_ID(gid), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "uid", "gid", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "lchown", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - path_t path = PATH_T_INITIALIZE("lchown", "path", 0, 0); - uid_t uid; - gid_t gid; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!_Py_Uid_Converter(args[1], &uid)) { - goto exit; - } - if (!_Py_Gid_Converter(args[2], &gid)) { - goto exit; - } - return_value = os_lchown_impl(module, &path, uid, gid); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(HAVE_LCHOWN) */ - -PyDoc_STRVAR(os_getcwd__doc__, -"getcwd($module, /)\n" -"--\n" -"\n" -"Return a unicode string representing the current working directory."); - -#define OS_GETCWD_METHODDEF \ - {"getcwd", (PyCFunction)os_getcwd, METH_NOARGS, os_getcwd__doc__}, - -static PyObject * -os_getcwd_impl(PyObject *module); - -static PyObject * -os_getcwd(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getcwd_impl(module); -} - -PyDoc_STRVAR(os_getcwdb__doc__, -"getcwdb($module, /)\n" -"--\n" -"\n" -"Return a bytes string representing the current working directory."); - -#define OS_GETCWDB_METHODDEF \ - {"getcwdb", (PyCFunction)os_getcwdb, METH_NOARGS, os_getcwdb__doc__}, - -static PyObject * -os_getcwdb_impl(PyObject *module); - -static PyObject * -os_getcwdb(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getcwdb_impl(module); -} - -#if defined(HAVE_LINK) - -PyDoc_STRVAR(os_link__doc__, -"link($module, /, src, dst, *, src_dir_fd=None, dst_dir_fd=None,\n" -" follow_symlinks=True)\n" -"--\n" -"\n" -"Create a hard link to a file.\n" -"\n" -"If either src_dir_fd or dst_dir_fd is not None, it should be a file\n" -" descriptor open to a directory, and the respective path string (src or dst)\n" -" should be relative; the path will then be relative to that directory.\n" -"If follow_symlinks is False, and the last element of src is a symbolic\n" -" link, link will create a link to the symbolic link itself instead of the\n" -" file the link points to.\n" -"src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your\n" -" platform. If they are unavailable, using them will raise a\n" -" NotImplementedError."); - -#define OS_LINK_METHODDEF \ - {"link", _PyCFunction_CAST(os_link), METH_FASTCALL|METH_KEYWORDS, os_link__doc__}, - -static PyObject * -os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, - int dst_dir_fd, int follow_symlinks); - -static PyObject * -os_link(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 5 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(src), &_Py_ID(dst), &_Py_ID(src_dir_fd), &_Py_ID(dst_dir_fd), &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", "follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "link", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[5]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t src = PATH_T_INITIALIZE("link", "src", 0, 0); - path_t dst = PATH_T_INITIALIZE("link", "dst", 0, 0); - int src_dir_fd = DEFAULT_DIR_FD; - int dst_dir_fd = DEFAULT_DIR_FD; - int follow_symlinks = 1; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &src)) { - goto exit; - } - if (!path_converter(args[1], &dst)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (args[2]) { - if (!dir_fd_converter(args[2], &src_dir_fd)) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[3]) { - if (!dir_fd_converter(args[3], &dst_dir_fd)) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - follow_symlinks = PyObject_IsTrue(args[4]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - return_value = os_link_impl(module, &src, &dst, src_dir_fd, dst_dir_fd, follow_symlinks); - -exit: - /* Cleanup for src */ - path_cleanup(&src); - /* Cleanup for dst */ - path_cleanup(&dst); - - return return_value; -} - -#endif /* defined(HAVE_LINK) */ - -PyDoc_STRVAR(os_listdir__doc__, -"listdir($module, /, path=None)\n" -"--\n" -"\n" -"Return a list containing the names of the files in the directory.\n" -"\n" -"path can be specified as either str, bytes, or a path-like object. If path is bytes,\n" -" the filenames returned will also be bytes; in all other circumstances\n" -" the filenames returned will be str.\n" -"If path is None, uses the path=\'.\'.\n" -"On some platforms, path may also be specified as an open file descriptor;\\\n" -" the file descriptor must refer to a directory.\n" -" If this functionality is unavailable, using it raises NotImplementedError.\n" -"\n" -"The list is in arbitrary order. It does not include the special\n" -"entries \'.\' and \'..\' even if they are present in the directory."); - -#define OS_LISTDIR_METHODDEF \ - {"listdir", _PyCFunction_CAST(os_listdir), METH_FASTCALL|METH_KEYWORDS, os_listdir__doc__}, - -static PyObject * -os_listdir_impl(PyObject *module, path_t *path); - -static PyObject * -os_listdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "listdir", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - path_t path = PATH_T_INITIALIZE("listdir", "path", 1, PATH_HAVE_FDOPENDIR); - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (!path_converter(args[0], &path)) { - goto exit; - } -skip_optional_pos: - return_value = os_listdir_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#if defined(MS_WINDOWS) - -PyDoc_STRVAR(os__getfullpathname__doc__, -"_getfullpathname($module, path, /)\n" -"--\n" -"\n"); - -#define OS__GETFULLPATHNAME_METHODDEF \ - {"_getfullpathname", (PyCFunction)os__getfullpathname, METH_O, os__getfullpathname__doc__}, - -static PyObject * -os__getfullpathname_impl(PyObject *module, path_t *path); - -static PyObject * -os__getfullpathname(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - path_t path = PATH_T_INITIALIZE("_getfullpathname", "path", 0, 0); - - if (!path_converter(arg, &path)) { - goto exit; - } - return_value = os__getfullpathname_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(MS_WINDOWS) */ - -#if defined(MS_WINDOWS) - -PyDoc_STRVAR(os__getfinalpathname__doc__, -"_getfinalpathname($module, path, /)\n" -"--\n" -"\n" -"A helper function for samepath on windows."); - -#define OS__GETFINALPATHNAME_METHODDEF \ - {"_getfinalpathname", (PyCFunction)os__getfinalpathname, METH_O, os__getfinalpathname__doc__}, - -static PyObject * -os__getfinalpathname_impl(PyObject *module, path_t *path); - -static PyObject * -os__getfinalpathname(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - path_t path = PATH_T_INITIALIZE("_getfinalpathname", "path", 0, 0); - - if (!path_converter(arg, &path)) { - goto exit; - } - return_value = os__getfinalpathname_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(MS_WINDOWS) */ - -#if defined(MS_WINDOWS) - -PyDoc_STRVAR(os__getvolumepathname__doc__, -"_getvolumepathname($module, /, path)\n" -"--\n" -"\n" -"A helper function for ismount on Win32."); - -#define OS__GETVOLUMEPATHNAME_METHODDEF \ - {"_getvolumepathname", _PyCFunction_CAST(os__getvolumepathname), METH_FASTCALL|METH_KEYWORDS, os__getvolumepathname__doc__}, - -static PyObject * -os__getvolumepathname_impl(PyObject *module, path_t *path); - -static PyObject * -os__getvolumepathname(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "_getvolumepathname", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_getvolumepathname", "path", 0, 0); - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - return_value = os__getvolumepathname_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(MS_WINDOWS) */ - -#if defined(MS_WINDOWS) - -PyDoc_STRVAR(os__path_splitroot__doc__, -"_path_splitroot($module, /, path)\n" -"--\n" -"\n" -"Removes everything after the root on Win32."); - -#define OS__PATH_SPLITROOT_METHODDEF \ - {"_path_splitroot", _PyCFunction_CAST(os__path_splitroot), METH_FASTCALL|METH_KEYWORDS, os__path_splitroot__doc__}, - -static PyObject * -os__path_splitroot_impl(PyObject *module, path_t *path); - -static PyObject * -os__path_splitroot(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "_path_splitroot", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_path_splitroot", "path", 0, 0); - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - return_value = os__path_splitroot_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(MS_WINDOWS) */ - -PyDoc_STRVAR(os__path_normpath__doc__, -"_path_normpath($module, /, path)\n" -"--\n" -"\n" -"Basic path normalization."); - -#define OS__PATH_NORMPATH_METHODDEF \ - {"_path_normpath", _PyCFunction_CAST(os__path_normpath), METH_FASTCALL|METH_KEYWORDS, os__path_normpath__doc__}, - -static PyObject * -os__path_normpath_impl(PyObject *module, PyObject *path); - -static PyObject * -os__path_normpath(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "_path_normpath", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - PyObject *path; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - path = args[0]; - return_value = os__path_normpath_impl(module, path); - -exit: - return return_value; -} - -PyDoc_STRVAR(os_mkdir__doc__, -"mkdir($module, /, path, mode=511, *, dir_fd=None)\n" -"--\n" -"\n" -"Create a directory.\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"dir_fd may not be implemented on your platform.\n" -" If it is unavailable, using it will raise a NotImplementedError.\n" -"\n" -"The mode argument is ignored on Windows. Where it is used, the current umask\n" -"value is first masked out."); - -#define OS_MKDIR_METHODDEF \ - {"mkdir", _PyCFunction_CAST(os_mkdir), METH_FASTCALL|METH_KEYWORDS, os_mkdir__doc__}, - -static PyObject * -os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd); - -static PyObject * -os_mkdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(mode), &_Py_ID(dir_fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "mode", "dir_fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "mkdir", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("mkdir", "path", 0, 0); - int mode = 511; - int dir_fd = DEFAULT_DIR_FD; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[1]) { - mode = _PyLong_AsInt(args[1]); - if (mode == -1 && PyErr_Occurred()) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } -skip_optional_pos: - if (!noptargs) { - goto skip_optional_kwonly; - } - if (!MKDIRAT_DIR_FD_CONVERTER(args[2], &dir_fd)) { - goto exit; - } -skip_optional_kwonly: - return_value = os_mkdir_impl(module, &path, mode, dir_fd); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#if defined(HAVE_NICE) - -PyDoc_STRVAR(os_nice__doc__, -"nice($module, increment, /)\n" -"--\n" -"\n" -"Add increment to the priority of process and return the new priority."); - -#define OS_NICE_METHODDEF \ - {"nice", (PyCFunction)os_nice, METH_O, os_nice__doc__}, - -static PyObject * -os_nice_impl(PyObject *module, int increment); - -static PyObject * -os_nice(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int increment; - - increment = _PyLong_AsInt(arg); - if (increment == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_nice_impl(module, increment); - -exit: - return return_value; -} - -#endif /* defined(HAVE_NICE) */ - -#if defined(HAVE_GETPRIORITY) - -PyDoc_STRVAR(os_getpriority__doc__, -"getpriority($module, /, which, who)\n" -"--\n" -"\n" -"Return program scheduling priority."); - -#define OS_GETPRIORITY_METHODDEF \ - {"getpriority", _PyCFunction_CAST(os_getpriority), METH_FASTCALL|METH_KEYWORDS, os_getpriority__doc__}, - -static PyObject * -os_getpriority_impl(PyObject *module, int which, int who); - -static PyObject * -os_getpriority(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(which), &_Py_ID(who), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"which", "who", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "getpriority", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - int which; - int who; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - which = _PyLong_AsInt(args[0]); - if (which == -1 && PyErr_Occurred()) { - goto exit; - } - who = _PyLong_AsInt(args[1]); - if (who == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_getpriority_impl(module, which, who); - -exit: - return return_value; -} - -#endif /* defined(HAVE_GETPRIORITY) */ - -#if defined(HAVE_SETPRIORITY) - -PyDoc_STRVAR(os_setpriority__doc__, -"setpriority($module, /, which, who, priority)\n" -"--\n" -"\n" -"Set program scheduling priority."); - -#define OS_SETPRIORITY_METHODDEF \ - {"setpriority", _PyCFunction_CAST(os_setpriority), METH_FASTCALL|METH_KEYWORDS, os_setpriority__doc__}, - -static PyObject * -os_setpriority_impl(PyObject *module, int which, int who, int priority); - -static PyObject * -os_setpriority(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(which), &_Py_ID(who), &_Py_ID(priority), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"which", "who", "priority", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "setpriority", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - int which; - int who; - int priority; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); - if (!args) { - goto exit; - } - which = _PyLong_AsInt(args[0]); - if (which == -1 && PyErr_Occurred()) { - goto exit; - } - who = _PyLong_AsInt(args[1]); - if (who == -1 && PyErr_Occurred()) { - goto exit; - } - priority = _PyLong_AsInt(args[2]); - if (priority == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_setpriority_impl(module, which, who, priority); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SETPRIORITY) */ - -PyDoc_STRVAR(os_rename__doc__, -"rename($module, /, src, dst, *, src_dir_fd=None, dst_dir_fd=None)\n" -"--\n" -"\n" -"Rename a file or directory.\n" -"\n" -"If either src_dir_fd or dst_dir_fd is not None, it should be a file\n" -" descriptor open to a directory, and the respective path string (src or dst)\n" -" should be relative; the path will then be relative to that directory.\n" -"src_dir_fd and dst_dir_fd, may not be implemented on your platform.\n" -" If they are unavailable, using them will raise a NotImplementedError."); - -#define OS_RENAME_METHODDEF \ - {"rename", _PyCFunction_CAST(os_rename), METH_FASTCALL|METH_KEYWORDS, os_rename__doc__}, - -static PyObject * -os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, - int dst_dir_fd); - -static PyObject * -os_rename(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 4 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(src), &_Py_ID(dst), &_Py_ID(src_dir_fd), &_Py_ID(dst_dir_fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "rename", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[4]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t src = PATH_T_INITIALIZE("rename", "src", 0, 0); - path_t dst = PATH_T_INITIALIZE("rename", "dst", 0, 0); - int src_dir_fd = DEFAULT_DIR_FD; - int dst_dir_fd = DEFAULT_DIR_FD; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &src)) { - goto exit; - } - if (!path_converter(args[1], &dst)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (args[2]) { - if (!dir_fd_converter(args[2], &src_dir_fd)) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (!dir_fd_converter(args[3], &dst_dir_fd)) { - goto exit; - } -skip_optional_kwonly: - return_value = os_rename_impl(module, &src, &dst, src_dir_fd, dst_dir_fd); - -exit: - /* Cleanup for src */ - path_cleanup(&src); - /* Cleanup for dst */ - path_cleanup(&dst); - - return return_value; -} - -PyDoc_STRVAR(os_replace__doc__, -"replace($module, /, src, dst, *, src_dir_fd=None, dst_dir_fd=None)\n" -"--\n" -"\n" -"Rename a file or directory, overwriting the destination.\n" -"\n" -"If either src_dir_fd or dst_dir_fd is not None, it should be a file\n" -" descriptor open to a directory, and the respective path string (src or dst)\n" -" should be relative; the path will then be relative to that directory.\n" -"src_dir_fd and dst_dir_fd, may not be implemented on your platform.\n" -" If they are unavailable, using them will raise a NotImplementedError."); - -#define OS_REPLACE_METHODDEF \ - {"replace", _PyCFunction_CAST(os_replace), METH_FASTCALL|METH_KEYWORDS, os_replace__doc__}, - -static PyObject * -os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, - int dst_dir_fd); - -static PyObject * -os_replace(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 4 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(src), &_Py_ID(dst), &_Py_ID(src_dir_fd), &_Py_ID(dst_dir_fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "replace", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[4]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t src = PATH_T_INITIALIZE("replace", "src", 0, 0); - path_t dst = PATH_T_INITIALIZE("replace", "dst", 0, 0); - int src_dir_fd = DEFAULT_DIR_FD; - int dst_dir_fd = DEFAULT_DIR_FD; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &src)) { - goto exit; - } - if (!path_converter(args[1], &dst)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (args[2]) { - if (!dir_fd_converter(args[2], &src_dir_fd)) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (!dir_fd_converter(args[3], &dst_dir_fd)) { - goto exit; - } -skip_optional_kwonly: - return_value = os_replace_impl(module, &src, &dst, src_dir_fd, dst_dir_fd); - -exit: - /* Cleanup for src */ - path_cleanup(&src); - /* Cleanup for dst */ - path_cleanup(&dst); - - return return_value; -} - -PyDoc_STRVAR(os_rmdir__doc__, -"rmdir($module, /, path, *, dir_fd=None)\n" -"--\n" -"\n" -"Remove a directory.\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"dir_fd may not be implemented on your platform.\n" -" If it is unavailable, using it will raise a NotImplementedError."); - -#define OS_RMDIR_METHODDEF \ - {"rmdir", _PyCFunction_CAST(os_rmdir), METH_FASTCALL|METH_KEYWORDS, os_rmdir__doc__}, - -static PyObject * -os_rmdir_impl(PyObject *module, path_t *path, int dir_fd); - -static PyObject * -os_rmdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(dir_fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "dir_fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "rmdir", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("rmdir", "path", 0, 0); - int dir_fd = DEFAULT_DIR_FD; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (!UNLINKAT_DIR_FD_CONVERTER(args[1], &dir_fd)) { - goto exit; - } -skip_optional_kwonly: - return_value = os_rmdir_impl(module, &path, dir_fd); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#if defined(HAVE_SYSTEM) && defined(MS_WINDOWS) - -PyDoc_STRVAR(os_system__doc__, -"system($module, /, command)\n" -"--\n" -"\n" -"Execute the command in a subshell."); - -#define OS_SYSTEM_METHODDEF \ - {"system", _PyCFunction_CAST(os_system), METH_FASTCALL|METH_KEYWORDS, os_system__doc__}, - -static long -os_system_impl(PyObject *module, const Py_UNICODE *command); - -static PyObject * -os_system(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(command), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"command", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "system", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - const Py_UNICODE *command = NULL; - long _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("system", "argument 'command'", "str", args[0]); - goto exit; - } - command = PyUnicode_AsWideCharString(args[0], NULL); - if (command == NULL) { - goto exit; - } - _return_value = os_system_impl(module, command); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromLong(_return_value); - -exit: - /* Cleanup for command */ - PyMem_Free((void *)command); - - return return_value; -} - -#endif /* defined(HAVE_SYSTEM) && defined(MS_WINDOWS) */ - -#if defined(HAVE_SYSTEM) && !defined(MS_WINDOWS) - -PyDoc_STRVAR(os_system__doc__, -"system($module, /, command)\n" -"--\n" -"\n" -"Execute the command in a subshell."); - -#define OS_SYSTEM_METHODDEF \ - {"system", _PyCFunction_CAST(os_system), METH_FASTCALL|METH_KEYWORDS, os_system__doc__}, - -static long -os_system_impl(PyObject *module, PyObject *command); - -static PyObject * -os_system(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(command), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"command", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "system", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - PyObject *command = NULL; - long _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!PyUnicode_FSConverter(args[0], &command)) { - goto exit; - } - _return_value = os_system_impl(module, command); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromLong(_return_value); - -exit: - /* Cleanup for command */ - Py_XDECREF(command); - - return return_value; -} - -#endif /* defined(HAVE_SYSTEM) && !defined(MS_WINDOWS) */ - -#if defined(HAVE_UMASK) - -PyDoc_STRVAR(os_umask__doc__, -"umask($module, mask, /)\n" -"--\n" -"\n" -"Set the current numeric umask and return the previous umask."); - -#define OS_UMASK_METHODDEF \ - {"umask", (PyCFunction)os_umask, METH_O, os_umask__doc__}, - -static PyObject * -os_umask_impl(PyObject *module, int mask); - -static PyObject * -os_umask(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int mask; - - mask = _PyLong_AsInt(arg); - if (mask == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_umask_impl(module, mask); - -exit: - return return_value; -} - -#endif /* defined(HAVE_UMASK) */ - -PyDoc_STRVAR(os_unlink__doc__, -"unlink($module, /, path, *, dir_fd=None)\n" -"--\n" -"\n" -"Remove a file (same as remove()).\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"dir_fd may not be implemented on your platform.\n" -" If it is unavailable, using it will raise a NotImplementedError."); - -#define OS_UNLINK_METHODDEF \ - {"unlink", _PyCFunction_CAST(os_unlink), METH_FASTCALL|METH_KEYWORDS, os_unlink__doc__}, - -static PyObject * -os_unlink_impl(PyObject *module, path_t *path, int dir_fd); - -static PyObject * -os_unlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(dir_fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "dir_fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "unlink", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("unlink", "path", 0, 0); - int dir_fd = DEFAULT_DIR_FD; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (!UNLINKAT_DIR_FD_CONVERTER(args[1], &dir_fd)) { - goto exit; - } -skip_optional_kwonly: - return_value = os_unlink_impl(module, &path, dir_fd); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -PyDoc_STRVAR(os_remove__doc__, -"remove($module, /, path, *, dir_fd=None)\n" -"--\n" -"\n" -"Remove a file (same as unlink()).\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"dir_fd may not be implemented on your platform.\n" -" If it is unavailable, using it will raise a NotImplementedError."); - -#define OS_REMOVE_METHODDEF \ - {"remove", _PyCFunction_CAST(os_remove), METH_FASTCALL|METH_KEYWORDS, os_remove__doc__}, - -static PyObject * -os_remove_impl(PyObject *module, path_t *path, int dir_fd); - -static PyObject * -os_remove(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(dir_fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "dir_fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "remove", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("remove", "path", 0, 0); - int dir_fd = DEFAULT_DIR_FD; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (!UNLINKAT_DIR_FD_CONVERTER(args[1], &dir_fd)) { - goto exit; - } -skip_optional_kwonly: - return_value = os_remove_impl(module, &path, dir_fd); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#if defined(HAVE_UNAME) - -PyDoc_STRVAR(os_uname__doc__, -"uname($module, /)\n" -"--\n" -"\n" -"Return an object identifying the current operating system.\n" -"\n" -"The object behaves like a named tuple with the following fields:\n" -" (sysname, nodename, release, version, machine)"); - -#define OS_UNAME_METHODDEF \ - {"uname", (PyCFunction)os_uname, METH_NOARGS, os_uname__doc__}, - -static PyObject * -os_uname_impl(PyObject *module); - -static PyObject * -os_uname(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_uname_impl(module); -} - -#endif /* defined(HAVE_UNAME) */ - -PyDoc_STRVAR(os_utime__doc__, -"utime($module, /, path, times=None, *, ns=,\n" -" dir_fd=None, follow_symlinks=True)\n" -"--\n" -"\n" -"Set the access and modified time of path.\n" -"\n" -"path may always be specified as a string.\n" -"On some platforms, path may also be specified as an open file descriptor.\n" -" If this functionality is unavailable, using it raises an exception.\n" -"\n" -"If times is not None, it must be a tuple (atime, mtime);\n" -" atime and mtime should be expressed as float seconds since the epoch.\n" -"If ns is specified, it must be a tuple (atime_ns, mtime_ns);\n" -" atime_ns and mtime_ns should be expressed as integer nanoseconds\n" -" since the epoch.\n" -"If times is None and ns is unspecified, utime uses the current time.\n" -"Specifying tuples for both times and ns is an error.\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"If follow_symlinks is False, and the last element of the path is a symbolic\n" -" link, utime will modify the symbolic link itself instead of the file the\n" -" link points to.\n" -"It is an error to use dir_fd or follow_symlinks when specifying path\n" -" as an open file descriptor.\n" -"dir_fd and follow_symlinks may not be available on your platform.\n" -" If they are unavailable, using them will raise a NotImplementedError."); - -#define OS_UTIME_METHODDEF \ - {"utime", _PyCFunction_CAST(os_utime), METH_FASTCALL|METH_KEYWORDS, os_utime__doc__}, - -static PyObject * -os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, - int dir_fd, int follow_symlinks); - -static PyObject * -os_utime(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 5 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(times), &_Py_ID(ns), &_Py_ID(dir_fd), &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "times", "ns", "dir_fd", "follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "utime", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[5]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("utime", "path", 0, PATH_UTIME_HAVE_FD); - PyObject *times = Py_None; - PyObject *ns = NULL; - int dir_fd = DEFAULT_DIR_FD; - int follow_symlinks = 1; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[1]) { - times = args[1]; - if (!--noptargs) { - goto skip_optional_pos; - } - } -skip_optional_pos: - if (!noptargs) { - goto skip_optional_kwonly; - } - if (args[2]) { - ns = args[2]; - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[3]) { - if (!FUTIMENSAT_DIR_FD_CONVERTER(args[3], &dir_fd)) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - follow_symlinks = PyObject_IsTrue(args[4]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - return_value = os_utime_impl(module, &path, times, ns, dir_fd, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -PyDoc_STRVAR(os__exit__doc__, -"_exit($module, /, status)\n" -"--\n" -"\n" -"Exit to the system with specified status, without normal exit processing."); - -#define OS__EXIT_METHODDEF \ - {"_exit", _PyCFunction_CAST(os__exit), METH_FASTCALL|METH_KEYWORDS, os__exit__doc__}, - -static PyObject * -os__exit_impl(PyObject *module, int status); - -static PyObject * -os__exit(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(status), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"status", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "_exit", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int status; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - status = _PyLong_AsInt(args[0]); - if (status == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os__exit_impl(module, status); - -exit: - return return_value; -} - -#if defined(HAVE_EXECV) - -PyDoc_STRVAR(os_execv__doc__, -"execv($module, path, argv, /)\n" -"--\n" -"\n" -"Execute an executable path with arguments, replacing current process.\n" -"\n" -" path\n" -" Path of executable file.\n" -" argv\n" -" Tuple or list of strings."); - -#define OS_EXECV_METHODDEF \ - {"execv", _PyCFunction_CAST(os_execv), METH_FASTCALL, os_execv__doc__}, - -static PyObject * -os_execv_impl(PyObject *module, path_t *path, PyObject *argv); - -static PyObject * -os_execv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - path_t path = PATH_T_INITIALIZE("execv", "path", 0, 0); - PyObject *argv; - - if (!_PyArg_CheckPositional("execv", nargs, 2, 2)) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - argv = args[1]; - return_value = os_execv_impl(module, &path, argv); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(HAVE_EXECV) */ - -#if defined(HAVE_EXECV) - -PyDoc_STRVAR(os_execve__doc__, -"execve($module, /, path, argv, env)\n" -"--\n" -"\n" -"Execute an executable path with arguments, replacing current process.\n" -"\n" -" path\n" -" Path of executable file.\n" -" argv\n" -" Tuple or list of strings.\n" -" env\n" -" Dictionary of strings mapping to strings."); - -#define OS_EXECVE_METHODDEF \ - {"execve", _PyCFunction_CAST(os_execve), METH_FASTCALL|METH_KEYWORDS, os_execve__doc__}, - -static PyObject * -os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env); - -static PyObject * -os_execve(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(argv), &_Py_ID(env), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "argv", "env", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "execve", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - path_t path = PATH_T_INITIALIZE("execve", "path", 0, PATH_HAVE_FEXECVE); - PyObject *argv; - PyObject *env; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - argv = args[1]; - env = args[2]; - return_value = os_execve_impl(module, &path, argv, env); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(HAVE_EXECV) */ - -#if defined(HAVE_POSIX_SPAWN) - -PyDoc_STRVAR(os_posix_spawn__doc__, -"posix_spawn($module, path, argv, env, /, *, file_actions=(),\n" -" setpgroup=, resetids=False, setsid=False,\n" -" setsigmask=(), setsigdef=(), scheduler=)\n" -"--\n" -"\n" -"Execute the program specified by path in a new process.\n" -"\n" -" path\n" -" Path of executable file.\n" -" argv\n" -" Tuple or list of strings.\n" -" env\n" -" Dictionary of strings mapping to strings.\n" -" file_actions\n" -" A sequence of file action tuples.\n" -" setpgroup\n" -" The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.\n" -" resetids\n" -" If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.\n" -" setsid\n" -" If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.\n" -" setsigmask\n" -" The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.\n" -" setsigdef\n" -" The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.\n" -" scheduler\n" -" A tuple with the scheduler policy (optional) and parameters."); - -#define OS_POSIX_SPAWN_METHODDEF \ - {"posix_spawn", _PyCFunction_CAST(os_posix_spawn), METH_FASTCALL|METH_KEYWORDS, os_posix_spawn__doc__}, - -static PyObject * -os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, - PyObject *env, PyObject *file_actions, - PyObject *setpgroup, int resetids, int setsid, - PyObject *setsigmask, PyObject *setsigdef, - PyObject *scheduler); - -static PyObject * -os_posix_spawn(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 7 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(file_actions), &_Py_ID(setpgroup), &_Py_ID(resetids), &_Py_ID(setsid), &_Py_ID(setsigmask), &_Py_ID(setsigdef), &_Py_ID(scheduler), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"", "", "", "file_actions", "setpgroup", "resetids", "setsid", "setsigmask", "setsigdef", "scheduler", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "posix_spawn", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[10]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - path_t path = PATH_T_INITIALIZE("posix_spawn", "path", 0, 0); - PyObject *argv; - PyObject *env; - PyObject *file_actions = NULL; - PyObject *setpgroup = NULL; - int resetids = 0; - int setsid = 0; - PyObject *setsigmask = NULL; - PyObject *setsigdef = NULL; - PyObject *scheduler = NULL; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - argv = args[1]; - env = args[2]; - if (!noptargs) { - goto skip_optional_kwonly; - } - if (args[3]) { - file_actions = args[3]; - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[4]) { - setpgroup = args[4]; - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[5]) { - resetids = _PyLong_AsInt(args[5]); - if (resetids == -1 && PyErr_Occurred()) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[6]) { - setsid = _PyLong_AsInt(args[6]); - if (setsid == -1 && PyErr_Occurred()) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[7]) { - setsigmask = args[7]; - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[8]) { - setsigdef = args[8]; - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - scheduler = args[9]; -skip_optional_kwonly: - return_value = os_posix_spawn_impl(module, &path, argv, env, file_actions, setpgroup, resetids, setsid, setsigmask, setsigdef, scheduler); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(HAVE_POSIX_SPAWN) */ - -#if defined(HAVE_POSIX_SPAWNP) - -PyDoc_STRVAR(os_posix_spawnp__doc__, -"posix_spawnp($module, path, argv, env, /, *, file_actions=(),\n" -" setpgroup=, resetids=False, setsid=False,\n" -" setsigmask=(), setsigdef=(), scheduler=)\n" -"--\n" -"\n" -"Execute the program specified by path in a new process.\n" -"\n" -" path\n" -" Path of executable file.\n" -" argv\n" -" Tuple or list of strings.\n" -" env\n" -" Dictionary of strings mapping to strings.\n" -" file_actions\n" -" A sequence of file action tuples.\n" -" setpgroup\n" -" The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.\n" -" resetids\n" -" If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.\n" -" setsid\n" -" If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.\n" -" setsigmask\n" -" The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.\n" -" setsigdef\n" -" The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.\n" -" scheduler\n" -" A tuple with the scheduler policy (optional) and parameters."); - -#define OS_POSIX_SPAWNP_METHODDEF \ - {"posix_spawnp", _PyCFunction_CAST(os_posix_spawnp), METH_FASTCALL|METH_KEYWORDS, os_posix_spawnp__doc__}, - -static PyObject * -os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv, - PyObject *env, PyObject *file_actions, - PyObject *setpgroup, int resetids, int setsid, - PyObject *setsigmask, PyObject *setsigdef, - PyObject *scheduler); - -static PyObject * -os_posix_spawnp(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 7 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(file_actions), &_Py_ID(setpgroup), &_Py_ID(resetids), &_Py_ID(setsid), &_Py_ID(setsigmask), &_Py_ID(setsigdef), &_Py_ID(scheduler), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"", "", "", "file_actions", "setpgroup", "resetids", "setsid", "setsigmask", "setsigdef", "scheduler", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "posix_spawnp", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[10]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - path_t path = PATH_T_INITIALIZE("posix_spawnp", "path", 0, 0); - PyObject *argv; - PyObject *env; - PyObject *file_actions = NULL; - PyObject *setpgroup = NULL; - int resetids = 0; - int setsid = 0; - PyObject *setsigmask = NULL; - PyObject *setsigdef = NULL; - PyObject *scheduler = NULL; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - argv = args[1]; - env = args[2]; - if (!noptargs) { - goto skip_optional_kwonly; - } - if (args[3]) { - file_actions = args[3]; - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[4]) { - setpgroup = args[4]; - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[5]) { - resetids = _PyLong_AsInt(args[5]); - if (resetids == -1 && PyErr_Occurred()) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[6]) { - setsid = _PyLong_AsInt(args[6]); - if (setsid == -1 && PyErr_Occurred()) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[7]) { - setsigmask = args[7]; - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[8]) { - setsigdef = args[8]; - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - scheduler = args[9]; -skip_optional_kwonly: - return_value = os_posix_spawnp_impl(module, &path, argv, env, file_actions, setpgroup, resetids, setsid, setsigmask, setsigdef, scheduler); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(HAVE_POSIX_SPAWNP) */ - -#if (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)) - -PyDoc_STRVAR(os_spawnv__doc__, -"spawnv($module, mode, path, argv, /)\n" -"--\n" -"\n" -"Execute the program specified by path in a new process.\n" -"\n" -" mode\n" -" Mode of process creation.\n" -" path\n" -" Path of executable file.\n" -" argv\n" -" Tuple or list of strings."); - -#define OS_SPAWNV_METHODDEF \ - {"spawnv", _PyCFunction_CAST(os_spawnv), METH_FASTCALL, os_spawnv__doc__}, - -static PyObject * -os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv); - -static PyObject * -os_spawnv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int mode; - path_t path = PATH_T_INITIALIZE("spawnv", "path", 0, 0); - PyObject *argv; - - if (!_PyArg_CheckPositional("spawnv", nargs, 3, 3)) { - goto exit; - } - mode = _PyLong_AsInt(args[0]); - if (mode == -1 && PyErr_Occurred()) { - goto exit; - } - if (!path_converter(args[1], &path)) { - goto exit; - } - argv = args[2]; - return_value = os_spawnv_impl(module, mode, &path, argv); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)) */ - -#if (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)) - -PyDoc_STRVAR(os_spawnve__doc__, -"spawnve($module, mode, path, argv, env, /)\n" -"--\n" -"\n" -"Execute the program specified by path in a new process.\n" -"\n" -" mode\n" -" Mode of process creation.\n" -" path\n" -" Path of executable file.\n" -" argv\n" -" Tuple or list of strings.\n" -" env\n" -" Dictionary of strings mapping to strings."); - -#define OS_SPAWNVE_METHODDEF \ - {"spawnve", _PyCFunction_CAST(os_spawnve), METH_FASTCALL, os_spawnve__doc__}, - -static PyObject * -os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv, - PyObject *env); - -static PyObject * -os_spawnve(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int mode; - path_t path = PATH_T_INITIALIZE("spawnve", "path", 0, 0); - PyObject *argv; - PyObject *env; - - if (!_PyArg_CheckPositional("spawnve", nargs, 4, 4)) { - goto exit; - } - mode = _PyLong_AsInt(args[0]); - if (mode == -1 && PyErr_Occurred()) { - goto exit; - } - if (!path_converter(args[1], &path)) { - goto exit; - } - argv = args[2]; - env = args[3]; - return_value = os_spawnve_impl(module, mode, &path, argv, env); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)) */ - -#if defined(HAVE_FORK) - -PyDoc_STRVAR(os_register_at_fork__doc__, -"register_at_fork($module, /, *, before=,\n" -" after_in_child=,\n" -" after_in_parent=)\n" -"--\n" -"\n" -"Register callables to be called when forking a new process.\n" -"\n" -" before\n" -" A callable to be called in the parent before the fork() syscall.\n" -" after_in_child\n" -" A callable to be called in the child after fork().\n" -" after_in_parent\n" -" A callable to be called in the parent after fork().\n" -"\n" -"\'before\' callbacks are called in reverse order.\n" -"\'after_in_child\' and \'after_in_parent\' callbacks are called in order."); - -#define OS_REGISTER_AT_FORK_METHODDEF \ - {"register_at_fork", _PyCFunction_CAST(os_register_at_fork), METH_FASTCALL|METH_KEYWORDS, os_register_at_fork__doc__}, - -static PyObject * -os_register_at_fork_impl(PyObject *module, PyObject *before, - PyObject *after_in_child, PyObject *after_in_parent); - -static PyObject * -os_register_at_fork(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(before), &_Py_ID(after_in_child), &_Py_ID(after_in_parent), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"before", "after_in_child", "after_in_parent", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "register_at_fork", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - PyObject *before = NULL; - PyObject *after_in_child = NULL; - PyObject *after_in_parent = NULL; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf); - if (!args) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (args[0]) { - before = args[0]; - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - if (args[1]) { - after_in_child = args[1]; - if (!--noptargs) { - goto skip_optional_kwonly; - } - } - after_in_parent = args[2]; -skip_optional_kwonly: - return_value = os_register_at_fork_impl(module, before, after_in_child, after_in_parent); - -exit: - return return_value; -} - -#endif /* defined(HAVE_FORK) */ - -#if defined(HAVE_FORK1) - -PyDoc_STRVAR(os_fork1__doc__, -"fork1($module, /)\n" -"--\n" -"\n" -"Fork a child process with a single multiplexed (i.e., not bound) thread.\n" -"\n" -"Return 0 to child process and PID of child to parent process."); - -#define OS_FORK1_METHODDEF \ - {"fork1", (PyCFunction)os_fork1, METH_NOARGS, os_fork1__doc__}, - -static PyObject * -os_fork1_impl(PyObject *module); - -static PyObject * -os_fork1(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_fork1_impl(module); -} - -#endif /* defined(HAVE_FORK1) */ - -#if defined(HAVE_FORK) - -PyDoc_STRVAR(os_fork__doc__, -"fork($module, /)\n" -"--\n" -"\n" -"Fork a child process.\n" -"\n" -"Return 0 to child process and PID of child to parent process."); - -#define OS_FORK_METHODDEF \ - {"fork", (PyCFunction)os_fork, METH_NOARGS, os_fork__doc__}, - -static PyObject * -os_fork_impl(PyObject *module); - -static PyObject * -os_fork(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_fork_impl(module); -} - -#endif /* defined(HAVE_FORK) */ - -#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_GET_PRIORITY_MAX) - -PyDoc_STRVAR(os_sched_get_priority_max__doc__, -"sched_get_priority_max($module, /, policy)\n" -"--\n" -"\n" -"Get the maximum scheduling priority for policy."); - -#define OS_SCHED_GET_PRIORITY_MAX_METHODDEF \ - {"sched_get_priority_max", _PyCFunction_CAST(os_sched_get_priority_max), METH_FASTCALL|METH_KEYWORDS, os_sched_get_priority_max__doc__}, - -static PyObject * -os_sched_get_priority_max_impl(PyObject *module, int policy); - -static PyObject * -os_sched_get_priority_max(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(policy), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"policy", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "sched_get_priority_max", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int policy; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - policy = _PyLong_AsInt(args[0]); - if (policy == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_sched_get_priority_max_impl(module, policy); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_GET_PRIORITY_MAX) */ - -#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_GET_PRIORITY_MAX) - -PyDoc_STRVAR(os_sched_get_priority_min__doc__, -"sched_get_priority_min($module, /, policy)\n" -"--\n" -"\n" -"Get the minimum scheduling priority for policy."); - -#define OS_SCHED_GET_PRIORITY_MIN_METHODDEF \ - {"sched_get_priority_min", _PyCFunction_CAST(os_sched_get_priority_min), METH_FASTCALL|METH_KEYWORDS, os_sched_get_priority_min__doc__}, - -static PyObject * -os_sched_get_priority_min_impl(PyObject *module, int policy); - -static PyObject * -os_sched_get_priority_min(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(policy), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"policy", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "sched_get_priority_min", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int policy; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - policy = _PyLong_AsInt(args[0]); - if (policy == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_sched_get_priority_min_impl(module, policy); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_GET_PRIORITY_MAX) */ - -#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETSCHEDULER) - -PyDoc_STRVAR(os_sched_getscheduler__doc__, -"sched_getscheduler($module, pid, /)\n" -"--\n" -"\n" -"Get the scheduling policy for the process identified by pid.\n" -"\n" -"Passing 0 for pid returns the scheduling policy for the calling process."); - -#define OS_SCHED_GETSCHEDULER_METHODDEF \ - {"sched_getscheduler", (PyCFunction)os_sched_getscheduler, METH_O, os_sched_getscheduler__doc__}, - -static PyObject * -os_sched_getscheduler_impl(PyObject *module, pid_t pid); - -static PyObject * -os_sched_getscheduler(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - pid_t pid; - - if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":sched_getscheduler", &pid)) { - goto exit; - } - return_value = os_sched_getscheduler_impl(module, pid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETSCHEDULER) */ - -#if defined(HAVE_SCHED_H) && (defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)) - -PyDoc_STRVAR(os_sched_param__doc__, -"sched_param(sched_priority)\n" -"--\n" -"\n" -"Currently has only one field: sched_priority\n" -"\n" -" sched_priority\n" -" A scheduling parameter."); - -static PyObject * -os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority); - -static PyObject * -os_sched_param(PyTypeObject *type, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(sched_priority), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"sched_priority", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "sched_param", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - PyObject * const *fastargs; - Py_ssize_t nargs = PyTuple_GET_SIZE(args); - PyObject *sched_priority; - - fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, argsbuf); - if (!fastargs) { - goto exit; - } - sched_priority = fastargs[0]; - return_value = os_sched_param_impl(type, sched_priority); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SCHED_H) && (defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)) */ - -#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETSCHEDULER) - -PyDoc_STRVAR(os_sched_setscheduler__doc__, -"sched_setscheduler($module, pid, policy, param, /)\n" -"--\n" -"\n" -"Set the scheduling policy for the process identified by pid.\n" -"\n" -"If pid is 0, the calling process is changed.\n" -"param is an instance of sched_param."); - -#define OS_SCHED_SETSCHEDULER_METHODDEF \ - {"sched_setscheduler", _PyCFunction_CAST(os_sched_setscheduler), METH_FASTCALL, os_sched_setscheduler__doc__}, - -static PyObject * -os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy, - PyObject *param_obj); - -static PyObject * -os_sched_setscheduler(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - pid_t pid; - int policy; - PyObject *param_obj; - - if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "iO:sched_setscheduler", - &pid, &policy, ¶m_obj)) { - goto exit; - } - return_value = os_sched_setscheduler_impl(module, pid, policy, param_obj); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETSCHEDULER) */ - -#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETPARAM) - -PyDoc_STRVAR(os_sched_getparam__doc__, -"sched_getparam($module, pid, /)\n" -"--\n" -"\n" -"Returns scheduling parameters for the process identified by pid.\n" -"\n" -"If pid is 0, returns parameters for the calling process.\n" -"Return value is an instance of sched_param."); - -#define OS_SCHED_GETPARAM_METHODDEF \ - {"sched_getparam", (PyCFunction)os_sched_getparam, METH_O, os_sched_getparam__doc__}, - -static PyObject * -os_sched_getparam_impl(PyObject *module, pid_t pid); - -static PyObject * -os_sched_getparam(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - pid_t pid; - - if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":sched_getparam", &pid)) { - goto exit; - } - return_value = os_sched_getparam_impl(module, pid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETPARAM) */ - -#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETPARAM) - -PyDoc_STRVAR(os_sched_setparam__doc__, -"sched_setparam($module, pid, param, /)\n" -"--\n" -"\n" -"Set scheduling parameters for the process identified by pid.\n" -"\n" -"If pid is 0, sets parameters for the calling process.\n" -"param should be an instance of sched_param."); - -#define OS_SCHED_SETPARAM_METHODDEF \ - {"sched_setparam", _PyCFunction_CAST(os_sched_setparam), METH_FASTCALL, os_sched_setparam__doc__}, - -static PyObject * -os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj); - -static PyObject * -os_sched_setparam(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - pid_t pid; - PyObject *param_obj; - - if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "O:sched_setparam", - &pid, ¶m_obj)) { - goto exit; - } - return_value = os_sched_setparam_impl(module, pid, param_obj); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETPARAM) */ - -#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_RR_GET_INTERVAL) - -PyDoc_STRVAR(os_sched_rr_get_interval__doc__, -"sched_rr_get_interval($module, pid, /)\n" -"--\n" -"\n" -"Return the round-robin quantum for the process identified by pid, in seconds.\n" -"\n" -"Value returned is a float."); - -#define OS_SCHED_RR_GET_INTERVAL_METHODDEF \ - {"sched_rr_get_interval", (PyCFunction)os_sched_rr_get_interval, METH_O, os_sched_rr_get_interval__doc__}, - -static double -os_sched_rr_get_interval_impl(PyObject *module, pid_t pid); - -static PyObject * -os_sched_rr_get_interval(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - pid_t pid; - double _return_value; - - if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":sched_rr_get_interval", &pid)) { - goto exit; - } - _return_value = os_sched_rr_get_interval_impl(module, pid); - if ((_return_value == -1.0) && PyErr_Occurred()) { - goto exit; - } - return_value = PyFloat_FromDouble(_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_RR_GET_INTERVAL) */ - -#if defined(HAVE_SCHED_H) - -PyDoc_STRVAR(os_sched_yield__doc__, -"sched_yield($module, /)\n" -"--\n" -"\n" -"Voluntarily relinquish the CPU."); - -#define OS_SCHED_YIELD_METHODDEF \ - {"sched_yield", (PyCFunction)os_sched_yield, METH_NOARGS, os_sched_yield__doc__}, - -static PyObject * -os_sched_yield_impl(PyObject *module); - -static PyObject * -os_sched_yield(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_sched_yield_impl(module); -} - -#endif /* defined(HAVE_SCHED_H) */ - -#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETAFFINITY) - -PyDoc_STRVAR(os_sched_setaffinity__doc__, -"sched_setaffinity($module, pid, mask, /)\n" -"--\n" -"\n" -"Set the CPU affinity of the process identified by pid to mask.\n" -"\n" -"mask should be an iterable of integers identifying CPUs."); - -#define OS_SCHED_SETAFFINITY_METHODDEF \ - {"sched_setaffinity", _PyCFunction_CAST(os_sched_setaffinity), METH_FASTCALL, os_sched_setaffinity__doc__}, - -static PyObject * -os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask); - -static PyObject * -os_sched_setaffinity(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - pid_t pid; - PyObject *mask; - - if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "O:sched_setaffinity", - &pid, &mask)) { - goto exit; - } - return_value = os_sched_setaffinity_impl(module, pid, mask); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETAFFINITY) */ - -#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETAFFINITY) - -PyDoc_STRVAR(os_sched_getaffinity__doc__, -"sched_getaffinity($module, pid, /)\n" -"--\n" -"\n" -"Return the affinity of the process identified by pid (or the current process if zero).\n" -"\n" -"The affinity is returned as a set of CPU identifiers."); - -#define OS_SCHED_GETAFFINITY_METHODDEF \ - {"sched_getaffinity", (PyCFunction)os_sched_getaffinity, METH_O, os_sched_getaffinity__doc__}, - -static PyObject * -os_sched_getaffinity_impl(PyObject *module, pid_t pid); - -static PyObject * -os_sched_getaffinity(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - pid_t pid; - - if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":sched_getaffinity", &pid)) { - goto exit; - } - return_value = os_sched_getaffinity_impl(module, pid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETAFFINITY) */ - -#if (defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)) - -PyDoc_STRVAR(os_openpty__doc__, -"openpty($module, /)\n" -"--\n" -"\n" -"Open a pseudo-terminal.\n" -"\n" -"Return a tuple of (master_fd, slave_fd) containing open file descriptors\n" -"for both the master and slave ends."); - -#define OS_OPENPTY_METHODDEF \ - {"openpty", (PyCFunction)os_openpty, METH_NOARGS, os_openpty__doc__}, - -static PyObject * -os_openpty_impl(PyObject *module); - -static PyObject * -os_openpty(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_openpty_impl(module); -} - -#endif /* (defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)) */ - -#if (defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)) - -PyDoc_STRVAR(os_login_tty__doc__, -"login_tty($module, fd, /)\n" -"--\n" -"\n" -"Prepare the tty of which fd is a file descriptor for a new login session.\n" -"\n" -"Make the calling process a session leader; make the tty the\n" -"controlling tty, the stdin, the stdout, and the stderr of the\n" -"calling process; close fd."); - -#define OS_LOGIN_TTY_METHODDEF \ - {"login_tty", (PyCFunction)os_login_tty, METH_O, os_login_tty__doc__}, - -static PyObject * -os_login_tty_impl(PyObject *module, int fd); - -static PyObject * -os_login_tty(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int fd; - - if (!_PyLong_FileDescriptor_Converter(arg, &fd)) { - goto exit; - } - return_value = os_login_tty_impl(module, fd); - -exit: - return return_value; -} - -#endif /* (defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)) */ - -#if defined(HAVE_FORKPTY) - -PyDoc_STRVAR(os_forkpty__doc__, -"forkpty($module, /)\n" -"--\n" -"\n" -"Fork a new process with a new pseudo-terminal as controlling tty.\n" -"\n" -"Returns a tuple of (pid, master_fd).\n" -"Like fork(), return pid of 0 to the child process,\n" -"and pid of child to the parent process.\n" -"To both, return fd of newly opened pseudo-terminal."); - -#define OS_FORKPTY_METHODDEF \ - {"forkpty", (PyCFunction)os_forkpty, METH_NOARGS, os_forkpty__doc__}, - -static PyObject * -os_forkpty_impl(PyObject *module); - -static PyObject * -os_forkpty(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_forkpty_impl(module); -} - -#endif /* defined(HAVE_FORKPTY) */ - -#if defined(HAVE_GETEGID) - -PyDoc_STRVAR(os_getegid__doc__, -"getegid($module, /)\n" -"--\n" -"\n" -"Return the current process\'s effective group id."); - -#define OS_GETEGID_METHODDEF \ - {"getegid", (PyCFunction)os_getegid, METH_NOARGS, os_getegid__doc__}, - -static PyObject * -os_getegid_impl(PyObject *module); - -static PyObject * -os_getegid(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getegid_impl(module); -} - -#endif /* defined(HAVE_GETEGID) */ - -#if defined(HAVE_GETEUID) - -PyDoc_STRVAR(os_geteuid__doc__, -"geteuid($module, /)\n" -"--\n" -"\n" -"Return the current process\'s effective user id."); - -#define OS_GETEUID_METHODDEF \ - {"geteuid", (PyCFunction)os_geteuid, METH_NOARGS, os_geteuid__doc__}, - -static PyObject * -os_geteuid_impl(PyObject *module); - -static PyObject * -os_geteuid(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_geteuid_impl(module); -} - -#endif /* defined(HAVE_GETEUID) */ - -#if defined(HAVE_GETGID) - -PyDoc_STRVAR(os_getgid__doc__, -"getgid($module, /)\n" -"--\n" -"\n" -"Return the current process\'s group id."); - -#define OS_GETGID_METHODDEF \ - {"getgid", (PyCFunction)os_getgid, METH_NOARGS, os_getgid__doc__}, - -static PyObject * -os_getgid_impl(PyObject *module); - -static PyObject * -os_getgid(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getgid_impl(module); -} - -#endif /* defined(HAVE_GETGID) */ - -#if defined(HAVE_GETPID) - -PyDoc_STRVAR(os_getpid__doc__, -"getpid($module, /)\n" -"--\n" -"\n" -"Return the current process id."); - -#define OS_GETPID_METHODDEF \ - {"getpid", (PyCFunction)os_getpid, METH_NOARGS, os_getpid__doc__}, - -static PyObject * -os_getpid_impl(PyObject *module); - -static PyObject * -os_getpid(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getpid_impl(module); -} - -#endif /* defined(HAVE_GETPID) */ - -#if defined(HAVE_GETGROUPLIST) && defined(__APPLE__) - -PyDoc_STRVAR(os_getgrouplist__doc__, -"getgrouplist($module, user, group, /)\n" -"--\n" -"\n" -"Returns a list of groups to which a user belongs.\n" -"\n" -" user\n" -" username to lookup\n" -" group\n" -" base group id of the user"); - -#define OS_GETGROUPLIST_METHODDEF \ - {"getgrouplist", _PyCFunction_CAST(os_getgrouplist), METH_FASTCALL, os_getgrouplist__doc__}, - -static PyObject * -os_getgrouplist_impl(PyObject *module, const char *user, int basegid); - -static PyObject * -os_getgrouplist(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - const char *user; - int basegid; - - if (!_PyArg_CheckPositional("getgrouplist", nargs, 2, 2)) { - goto exit; - } - if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("getgrouplist", "argument 1", "str", args[0]); - goto exit; - } - Py_ssize_t user_length; - user = PyUnicode_AsUTF8AndSize(args[0], &user_length); - if (user == NULL) { - goto exit; - } - if (strlen(user) != (size_t)user_length) { - PyErr_SetString(PyExc_ValueError, "embedded null character"); - goto exit; - } - basegid = _PyLong_AsInt(args[1]); - if (basegid == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_getgrouplist_impl(module, user, basegid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_GETGROUPLIST) && defined(__APPLE__) */ - -#if defined(HAVE_GETGROUPLIST) && !defined(__APPLE__) - -PyDoc_STRVAR(os_getgrouplist__doc__, -"getgrouplist($module, user, group, /)\n" -"--\n" -"\n" -"Returns a list of groups to which a user belongs.\n" -"\n" -" user\n" -" username to lookup\n" -" group\n" -" base group id of the user"); - -#define OS_GETGROUPLIST_METHODDEF \ - {"getgrouplist", _PyCFunction_CAST(os_getgrouplist), METH_FASTCALL, os_getgrouplist__doc__}, - -static PyObject * -os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid); - -static PyObject * -os_getgrouplist(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - const char *user; - gid_t basegid; - - if (!_PyArg_CheckPositional("getgrouplist", nargs, 2, 2)) { - goto exit; - } - if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("getgrouplist", "argument 1", "str", args[0]); - goto exit; - } - Py_ssize_t user_length; - user = PyUnicode_AsUTF8AndSize(args[0], &user_length); - if (user == NULL) { - goto exit; - } - if (strlen(user) != (size_t)user_length) { - PyErr_SetString(PyExc_ValueError, "embedded null character"); - goto exit; - } - if (!_Py_Gid_Converter(args[1], &basegid)) { - goto exit; - } - return_value = os_getgrouplist_impl(module, user, basegid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_GETGROUPLIST) && !defined(__APPLE__) */ - -#if defined(HAVE_GETGROUPS) - -PyDoc_STRVAR(os_getgroups__doc__, -"getgroups($module, /)\n" -"--\n" -"\n" -"Return list of supplemental group IDs for the process."); - -#define OS_GETGROUPS_METHODDEF \ - {"getgroups", (PyCFunction)os_getgroups, METH_NOARGS, os_getgroups__doc__}, - -static PyObject * -os_getgroups_impl(PyObject *module); - -static PyObject * -os_getgroups(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getgroups_impl(module); -} - -#endif /* defined(HAVE_GETGROUPS) */ - -#if defined(HAVE_INITGROUPS) && defined(__APPLE__) - -PyDoc_STRVAR(os_initgroups__doc__, -"initgroups($module, username, gid, /)\n" -"--\n" -"\n" -"Initialize the group access list.\n" -"\n" -"Call the system initgroups() to initialize the group access list with all of\n" -"the groups of which the specified username is a member, plus the specified\n" -"group id."); - -#define OS_INITGROUPS_METHODDEF \ - {"initgroups", _PyCFunction_CAST(os_initgroups), METH_FASTCALL, os_initgroups__doc__}, - -static PyObject * -os_initgroups_impl(PyObject *module, PyObject *oname, int gid); - -static PyObject * -os_initgroups(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - PyObject *oname = NULL; - int gid; - - if (!_PyArg_CheckPositional("initgroups", nargs, 2, 2)) { - goto exit; - } - if (!PyUnicode_FSConverter(args[0], &oname)) { - goto exit; - } - gid = _PyLong_AsInt(args[1]); - if (gid == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_initgroups_impl(module, oname, gid); - -exit: - /* Cleanup for oname */ - Py_XDECREF(oname); - - return return_value; -} - -#endif /* defined(HAVE_INITGROUPS) && defined(__APPLE__) */ - -#if defined(HAVE_INITGROUPS) && !defined(__APPLE__) - -PyDoc_STRVAR(os_initgroups__doc__, -"initgroups($module, username, gid, /)\n" -"--\n" -"\n" -"Initialize the group access list.\n" -"\n" -"Call the system initgroups() to initialize the group access list with all of\n" -"the groups of which the specified username is a member, plus the specified\n" -"group id."); - -#define OS_INITGROUPS_METHODDEF \ - {"initgroups", _PyCFunction_CAST(os_initgroups), METH_FASTCALL, os_initgroups__doc__}, - -static PyObject * -os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid); - -static PyObject * -os_initgroups(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - PyObject *oname = NULL; - gid_t gid; - - if (!_PyArg_CheckPositional("initgroups", nargs, 2, 2)) { - goto exit; - } - if (!PyUnicode_FSConverter(args[0], &oname)) { - goto exit; - } - if (!_Py_Gid_Converter(args[1], &gid)) { - goto exit; - } - return_value = os_initgroups_impl(module, oname, gid); - -exit: - /* Cleanup for oname */ - Py_XDECREF(oname); - - return return_value; -} - -#endif /* defined(HAVE_INITGROUPS) && !defined(__APPLE__) */ - -#if defined(HAVE_GETPGID) - -PyDoc_STRVAR(os_getpgid__doc__, -"getpgid($module, /, pid)\n" -"--\n" -"\n" -"Call the system call getpgid(), and return the result."); - -#define OS_GETPGID_METHODDEF \ - {"getpgid", _PyCFunction_CAST(os_getpgid), METH_FASTCALL|METH_KEYWORDS, os_getpgid__doc__}, - -static PyObject * -os_getpgid_impl(PyObject *module, pid_t pid); - -static PyObject * -os_getpgid(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(pid), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"pid", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .format = "" _Py_PARSE_PID ":getpgid", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - pid_t pid; - - if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &pid)) { - goto exit; - } - return_value = os_getpgid_impl(module, pid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_GETPGID) */ - -#if defined(HAVE_GETPGRP) - -PyDoc_STRVAR(os_getpgrp__doc__, -"getpgrp($module, /)\n" -"--\n" -"\n" -"Return the current process group id."); - -#define OS_GETPGRP_METHODDEF \ - {"getpgrp", (PyCFunction)os_getpgrp, METH_NOARGS, os_getpgrp__doc__}, - -static PyObject * -os_getpgrp_impl(PyObject *module); - -static PyObject * -os_getpgrp(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getpgrp_impl(module); -} - -#endif /* defined(HAVE_GETPGRP) */ - -#if defined(HAVE_SETPGRP) - -PyDoc_STRVAR(os_setpgrp__doc__, -"setpgrp($module, /)\n" -"--\n" -"\n" -"Make the current process the leader of its process group."); - -#define OS_SETPGRP_METHODDEF \ - {"setpgrp", (PyCFunction)os_setpgrp, METH_NOARGS, os_setpgrp__doc__}, - -static PyObject * -os_setpgrp_impl(PyObject *module); - -static PyObject * -os_setpgrp(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_setpgrp_impl(module); -} - -#endif /* defined(HAVE_SETPGRP) */ - -#if defined(HAVE_GETPPID) - -PyDoc_STRVAR(os_getppid__doc__, -"getppid($module, /)\n" -"--\n" -"\n" -"Return the parent\'s process id.\n" -"\n" -"If the parent process has already exited, Windows machines will still\n" -"return its id; others systems will return the id of the \'init\' process (1)."); - -#define OS_GETPPID_METHODDEF \ - {"getppid", (PyCFunction)os_getppid, METH_NOARGS, os_getppid__doc__}, - -static PyObject * -os_getppid_impl(PyObject *module); - -static PyObject * -os_getppid(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getppid_impl(module); -} - -#endif /* defined(HAVE_GETPPID) */ - -#if defined(HAVE_GETLOGIN) - -PyDoc_STRVAR(os_getlogin__doc__, -"getlogin($module, /)\n" -"--\n" -"\n" -"Return the actual login name."); - -#define OS_GETLOGIN_METHODDEF \ - {"getlogin", (PyCFunction)os_getlogin, METH_NOARGS, os_getlogin__doc__}, - -static PyObject * -os_getlogin_impl(PyObject *module); - -static PyObject * -os_getlogin(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getlogin_impl(module); -} - -#endif /* defined(HAVE_GETLOGIN) */ - -#if defined(HAVE_GETUID) - -PyDoc_STRVAR(os_getuid__doc__, -"getuid($module, /)\n" -"--\n" -"\n" -"Return the current process\'s user id."); - -#define OS_GETUID_METHODDEF \ - {"getuid", (PyCFunction)os_getuid, METH_NOARGS, os_getuid__doc__}, - -static PyObject * -os_getuid_impl(PyObject *module); - -static PyObject * -os_getuid(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getuid_impl(module); -} - -#endif /* defined(HAVE_GETUID) */ - -#if defined(HAVE_KILL) - -PyDoc_STRVAR(os_kill__doc__, -"kill($module, pid, signal, /)\n" -"--\n" -"\n" -"Kill a process with a signal."); - -#define OS_KILL_METHODDEF \ - {"kill", _PyCFunction_CAST(os_kill), METH_FASTCALL, os_kill__doc__}, - -static PyObject * -os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal); - -static PyObject * -os_kill(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - pid_t pid; - Py_ssize_t signal; - - if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "n:kill", - &pid, &signal)) { - goto exit; - } - return_value = os_kill_impl(module, pid, signal); - -exit: - return return_value; -} - -#endif /* defined(HAVE_KILL) */ - -#if defined(HAVE_KILLPG) - -PyDoc_STRVAR(os_killpg__doc__, -"killpg($module, pgid, signal, /)\n" -"--\n" -"\n" -"Kill a process group with a signal."); - -#define OS_KILLPG_METHODDEF \ - {"killpg", _PyCFunction_CAST(os_killpg), METH_FASTCALL, os_killpg__doc__}, - -static PyObject * -os_killpg_impl(PyObject *module, pid_t pgid, int signal); - -static PyObject * -os_killpg(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - pid_t pgid; - int signal; - - if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "i:killpg", - &pgid, &signal)) { - goto exit; - } - return_value = os_killpg_impl(module, pgid, signal); - -exit: - return return_value; -} - -#endif /* defined(HAVE_KILLPG) */ - -#if defined(HAVE_PLOCK) - -PyDoc_STRVAR(os_plock__doc__, -"plock($module, op, /)\n" -"--\n" -"\n" -"Lock program segments into memory.\");"); - -#define OS_PLOCK_METHODDEF \ - {"plock", (PyCFunction)os_plock, METH_O, os_plock__doc__}, - -static PyObject * -os_plock_impl(PyObject *module, int op); - -static PyObject * -os_plock(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int op; - - op = _PyLong_AsInt(arg); - if (op == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_plock_impl(module, op); - -exit: - return return_value; -} - -#endif /* defined(HAVE_PLOCK) */ - -#if defined(HAVE_SETUID) - -PyDoc_STRVAR(os_setuid__doc__, -"setuid($module, uid, /)\n" -"--\n" -"\n" -"Set the current process\'s user id."); - -#define OS_SETUID_METHODDEF \ - {"setuid", (PyCFunction)os_setuid, METH_O, os_setuid__doc__}, - -static PyObject * -os_setuid_impl(PyObject *module, uid_t uid); - -static PyObject * -os_setuid(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - uid_t uid; - - if (!_Py_Uid_Converter(arg, &uid)) { - goto exit; - } - return_value = os_setuid_impl(module, uid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SETUID) */ - -#if defined(HAVE_SETEUID) - -PyDoc_STRVAR(os_seteuid__doc__, -"seteuid($module, euid, /)\n" -"--\n" -"\n" -"Set the current process\'s effective user id."); - -#define OS_SETEUID_METHODDEF \ - {"seteuid", (PyCFunction)os_seteuid, METH_O, os_seteuid__doc__}, - -static PyObject * -os_seteuid_impl(PyObject *module, uid_t euid); - -static PyObject * -os_seteuid(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - uid_t euid; - - if (!_Py_Uid_Converter(arg, &euid)) { - goto exit; - } - return_value = os_seteuid_impl(module, euid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SETEUID) */ - -#if defined(HAVE_SETEGID) - -PyDoc_STRVAR(os_setegid__doc__, -"setegid($module, egid, /)\n" -"--\n" -"\n" -"Set the current process\'s effective group id."); - -#define OS_SETEGID_METHODDEF \ - {"setegid", (PyCFunction)os_setegid, METH_O, os_setegid__doc__}, - -static PyObject * -os_setegid_impl(PyObject *module, gid_t egid); - -static PyObject * -os_setegid(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - gid_t egid; - - if (!_Py_Gid_Converter(arg, &egid)) { - goto exit; - } - return_value = os_setegid_impl(module, egid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SETEGID) */ - -#if defined(HAVE_SETREUID) - -PyDoc_STRVAR(os_setreuid__doc__, -"setreuid($module, ruid, euid, /)\n" -"--\n" -"\n" -"Set the current process\'s real and effective user ids."); - -#define OS_SETREUID_METHODDEF \ - {"setreuid", _PyCFunction_CAST(os_setreuid), METH_FASTCALL, os_setreuid__doc__}, - -static PyObject * -os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid); - -static PyObject * -os_setreuid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - uid_t ruid; - uid_t euid; - - if (!_PyArg_CheckPositional("setreuid", nargs, 2, 2)) { - goto exit; - } - if (!_Py_Uid_Converter(args[0], &ruid)) { - goto exit; - } - if (!_Py_Uid_Converter(args[1], &euid)) { - goto exit; - } - return_value = os_setreuid_impl(module, ruid, euid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SETREUID) */ - -#if defined(HAVE_SETREGID) - -PyDoc_STRVAR(os_setregid__doc__, -"setregid($module, rgid, egid, /)\n" -"--\n" -"\n" -"Set the current process\'s real and effective group ids."); - -#define OS_SETREGID_METHODDEF \ - {"setregid", _PyCFunction_CAST(os_setregid), METH_FASTCALL, os_setregid__doc__}, - -static PyObject * -os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid); - -static PyObject * -os_setregid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - gid_t rgid; - gid_t egid; - - if (!_PyArg_CheckPositional("setregid", nargs, 2, 2)) { - goto exit; - } - if (!_Py_Gid_Converter(args[0], &rgid)) { - goto exit; - } - if (!_Py_Gid_Converter(args[1], &egid)) { - goto exit; - } - return_value = os_setregid_impl(module, rgid, egid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SETREGID) */ - -#if defined(HAVE_SETGID) - -PyDoc_STRVAR(os_setgid__doc__, -"setgid($module, gid, /)\n" -"--\n" -"\n" -"Set the current process\'s group id."); - -#define OS_SETGID_METHODDEF \ - {"setgid", (PyCFunction)os_setgid, METH_O, os_setgid__doc__}, - -static PyObject * -os_setgid_impl(PyObject *module, gid_t gid); - -static PyObject * -os_setgid(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - gid_t gid; - - if (!_Py_Gid_Converter(arg, &gid)) { - goto exit; - } - return_value = os_setgid_impl(module, gid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SETGID) */ - -#if defined(HAVE_SETGROUPS) - -PyDoc_STRVAR(os_setgroups__doc__, -"setgroups($module, groups, /)\n" -"--\n" -"\n" -"Set the groups of the current process to list."); - -#define OS_SETGROUPS_METHODDEF \ - {"setgroups", (PyCFunction)os_setgroups, METH_O, os_setgroups__doc__}, - -#endif /* defined(HAVE_SETGROUPS) */ - -#if defined(HAVE_WAIT3) - -PyDoc_STRVAR(os_wait3__doc__, -"wait3($module, /, options)\n" -"--\n" -"\n" -"Wait for completion of a child process.\n" -"\n" -"Returns a tuple of information about the child process:\n" -" (pid, status, rusage)"); - -#define OS_WAIT3_METHODDEF \ - {"wait3", _PyCFunction_CAST(os_wait3), METH_FASTCALL|METH_KEYWORDS, os_wait3__doc__}, - -static PyObject * -os_wait3_impl(PyObject *module, int options); - -static PyObject * -os_wait3(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(options), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"options", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "wait3", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int options; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - options = _PyLong_AsInt(args[0]); - if (options == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_wait3_impl(module, options); - -exit: - return return_value; -} - -#endif /* defined(HAVE_WAIT3) */ - -#if defined(HAVE_WAIT4) - -PyDoc_STRVAR(os_wait4__doc__, -"wait4($module, /, pid, options)\n" -"--\n" -"\n" -"Wait for completion of a specific child process.\n" -"\n" -"Returns a tuple of information about the child process:\n" -" (pid, status, rusage)"); - -#define OS_WAIT4_METHODDEF \ - {"wait4", _PyCFunction_CAST(os_wait4), METH_FASTCALL|METH_KEYWORDS, os_wait4__doc__}, - -static PyObject * -os_wait4_impl(PyObject *module, pid_t pid, int options); - -static PyObject * -os_wait4(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(pid), &_Py_ID(options), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"pid", "options", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .format = "" _Py_PARSE_PID "i:wait4", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - pid_t pid; - int options; - - if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &pid, &options)) { - goto exit; - } - return_value = os_wait4_impl(module, pid, options); - -exit: - return return_value; -} - -#endif /* defined(HAVE_WAIT4) */ - -#if (defined(HAVE_WAITID) && !defined(__APPLE__)) - -PyDoc_STRVAR(os_waitid__doc__, -"waitid($module, idtype, id, options, /)\n" -"--\n" -"\n" -"Returns the result of waiting for a process or processes.\n" -"\n" -" idtype\n" -" Must be one of be P_PID, P_PGID or P_ALL.\n" -" id\n" -" The id to wait on.\n" -" options\n" -" Constructed from the ORing of one or more of WEXITED, WSTOPPED\n" -" or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.\n" -"\n" -"Returns either waitid_result or None if WNOHANG is specified and there are\n" -"no children in a waitable state."); - -#define OS_WAITID_METHODDEF \ - {"waitid", _PyCFunction_CAST(os_waitid), METH_FASTCALL, os_waitid__doc__}, - -static PyObject * -os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options); - -static PyObject * -os_waitid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - idtype_t idtype; - id_t id; - int options; - - if (!_PyArg_ParseStack(args, nargs, "i" _Py_PARSE_PID "i:waitid", - &idtype, &id, &options)) { - goto exit; - } - return_value = os_waitid_impl(module, idtype, id, options); - -exit: - return return_value; -} - -#endif /* (defined(HAVE_WAITID) && !defined(__APPLE__)) */ - -#if defined(HAVE_WAITPID) - -PyDoc_STRVAR(os_waitpid__doc__, -"waitpid($module, pid, options, /)\n" -"--\n" -"\n" -"Wait for completion of a given child process.\n" -"\n" -"Returns a tuple of information regarding the child process:\n" -" (pid, status)\n" -"\n" -"The options argument is ignored on Windows."); - -#define OS_WAITPID_METHODDEF \ - {"waitpid", _PyCFunction_CAST(os_waitpid), METH_FASTCALL, os_waitpid__doc__}, - -static PyObject * -os_waitpid_impl(PyObject *module, pid_t pid, int options); - -static PyObject * -os_waitpid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - pid_t pid; - int options; - - if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "i:waitpid", - &pid, &options)) { - goto exit; - } - return_value = os_waitpid_impl(module, pid, options); - -exit: - return return_value; -} - -#endif /* defined(HAVE_WAITPID) */ - -#if !defined(HAVE_WAITPID) && defined(HAVE_CWAIT) - -PyDoc_STRVAR(os_waitpid__doc__, -"waitpid($module, pid, options, /)\n" -"--\n" -"\n" -"Wait for completion of a given process.\n" -"\n" -"Returns a tuple of information regarding the process:\n" -" (pid, status << 8)\n" -"\n" -"The options argument is ignored on Windows."); - -#define OS_WAITPID_METHODDEF \ - {"waitpid", _PyCFunction_CAST(os_waitpid), METH_FASTCALL, os_waitpid__doc__}, - -static PyObject * -os_waitpid_impl(PyObject *module, intptr_t pid, int options); - -static PyObject * -os_waitpid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - intptr_t pid; - int options; - - if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_INTPTR "i:waitpid", - &pid, &options)) { - goto exit; - } - return_value = os_waitpid_impl(module, pid, options); - -exit: - return return_value; -} - -#endif /* !defined(HAVE_WAITPID) && defined(HAVE_CWAIT) */ - -#if defined(HAVE_WAIT) - -PyDoc_STRVAR(os_wait__doc__, -"wait($module, /)\n" -"--\n" -"\n" -"Wait for completion of a child process.\n" -"\n" -"Returns a tuple of information about the child process:\n" -" (pid, status)"); - -#define OS_WAIT_METHODDEF \ - {"wait", (PyCFunction)os_wait, METH_NOARGS, os_wait__doc__}, - -static PyObject * -os_wait_impl(PyObject *module); - -static PyObject * -os_wait(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_wait_impl(module); -} - -#endif /* defined(HAVE_WAIT) */ - -#if (defined(__linux__) && defined(__NR_pidfd_open)) - -PyDoc_STRVAR(os_pidfd_open__doc__, -"pidfd_open($module, /, pid, flags=0)\n" -"--\n" -"\n" -"Return a file descriptor referring to the process *pid*.\n" -"\n" -"The descriptor can be used to perform process management without races and\n" -"signals."); - -#define OS_PIDFD_OPEN_METHODDEF \ - {"pidfd_open", _PyCFunction_CAST(os_pidfd_open), METH_FASTCALL|METH_KEYWORDS, os_pidfd_open__doc__}, - -static PyObject * -os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags); - -static PyObject * -os_pidfd_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(pid), &_Py_ID(flags), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"pid", "flags", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .format = "" _Py_PARSE_PID "|O&:pidfd_open", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - pid_t pid; - unsigned int flags = 0; - - if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &pid, _PyLong_UnsignedInt_Converter, &flags)) { - goto exit; - } - return_value = os_pidfd_open_impl(module, pid, flags); - -exit: - return return_value; -} - -#endif /* (defined(__linux__) && defined(__NR_pidfd_open)) */ - -#if defined(HAVE_SETNS) - -PyDoc_STRVAR(os_setns__doc__, -"setns($module, /, fd, nstype=0)\n" -"--\n" -"\n" -"Move the calling thread into different namespaces.\n" -"\n" -" fd\n" -" A file descriptor to a namespace.\n" -" nstype\n" -" Type of namespace."); - -#define OS_SETNS_METHODDEF \ - {"setns", _PyCFunction_CAST(os_setns), METH_FASTCALL|METH_KEYWORDS, os_setns__doc__}, - -static PyObject * -os_setns_impl(PyObject *module, int fd, int nstype); - -static PyObject * -os_setns(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(fd), &_Py_ID(nstype), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"fd", "nstype", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "setns", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - int fd; - int nstype = 0; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - nstype = _PyLong_AsInt(args[1]); - if (nstype == -1 && PyErr_Occurred()) { - goto exit; - } -skip_optional_pos: - return_value = os_setns_impl(module, fd, nstype); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SETNS) */ - -#if defined(HAVE_UNSHARE) - -PyDoc_STRVAR(os_unshare__doc__, -"unshare($module, /, flags)\n" -"--\n" -"\n" -"Disassociate parts of a process (or thread) execution context.\n" -"\n" -" flags\n" -" Namespaces to be unshared."); - -#define OS_UNSHARE_METHODDEF \ - {"unshare", _PyCFunction_CAST(os_unshare), METH_FASTCALL|METH_KEYWORDS, os_unshare__doc__}, - -static PyObject * -os_unshare_impl(PyObject *module, int flags); - -static PyObject * -os_unshare(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(flags), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"flags", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "unshare", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int flags; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - flags = _PyLong_AsInt(args[0]); - if (flags == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_unshare_impl(module, flags); - -exit: - return return_value; -} - -#endif /* defined(HAVE_UNSHARE) */ - -#if (defined(HAVE_READLINK) || defined(MS_WINDOWS)) - -PyDoc_STRVAR(os_readlink__doc__, -"readlink($module, /, path, *, dir_fd=None)\n" -"--\n" -"\n" -"Return a string representing the path to which the symbolic link points.\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -"and path should be relative; path will then be relative to that directory.\n" -"\n" -"dir_fd may not be implemented on your platform. If it is unavailable,\n" -"using it will raise a NotImplementedError."); - -#define OS_READLINK_METHODDEF \ - {"readlink", _PyCFunction_CAST(os_readlink), METH_FASTCALL|METH_KEYWORDS, os_readlink__doc__}, - -static PyObject * -os_readlink_impl(PyObject *module, path_t *path, int dir_fd); - -static PyObject * -os_readlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(dir_fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "dir_fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "readlink", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("readlink", "path", 0, 0); - int dir_fd = DEFAULT_DIR_FD; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (!READLINKAT_DIR_FD_CONVERTER(args[1], &dir_fd)) { - goto exit; - } -skip_optional_kwonly: - return_value = os_readlink_impl(module, &path, dir_fd); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* (defined(HAVE_READLINK) || defined(MS_WINDOWS)) */ - -#if defined(HAVE_SYMLINK) - -PyDoc_STRVAR(os_symlink__doc__, -"symlink($module, /, src, dst, target_is_directory=False, *, dir_fd=None)\n" -"--\n" -"\n" -"Create a symbolic link pointing to src named dst.\n" -"\n" -"target_is_directory is required on Windows if the target is to be\n" -" interpreted as a directory. (On Windows, symlink requires\n" -" Windows 6.0 or greater, and raises a NotImplementedError otherwise.)\n" -" target_is_directory is ignored on non-Windows platforms.\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"dir_fd may not be implemented on your platform.\n" -" If it is unavailable, using it will raise a NotImplementedError."); - -#define OS_SYMLINK_METHODDEF \ - {"symlink", _PyCFunction_CAST(os_symlink), METH_FASTCALL|METH_KEYWORDS, os_symlink__doc__}, - -static PyObject * -os_symlink_impl(PyObject *module, path_t *src, path_t *dst, - int target_is_directory, int dir_fd); - -static PyObject * -os_symlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 4 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(src), &_Py_ID(dst), &_Py_ID(target_is_directory), &_Py_ID(dir_fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"src", "dst", "target_is_directory", "dir_fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "symlink", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[4]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t src = PATH_T_INITIALIZE("symlink", "src", 0, 0); - path_t dst = PATH_T_INITIALIZE("symlink", "dst", 0, 0); - int target_is_directory = 0; - int dir_fd = DEFAULT_DIR_FD; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &src)) { - goto exit; - } - if (!path_converter(args[1], &dst)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[2]) { - target_is_directory = PyObject_IsTrue(args[2]); - if (target_is_directory < 0) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } -skip_optional_pos: - if (!noptargs) { - goto skip_optional_kwonly; - } - if (!SYMLINKAT_DIR_FD_CONVERTER(args[3], &dir_fd)) { - goto exit; - } -skip_optional_kwonly: - return_value = os_symlink_impl(module, &src, &dst, target_is_directory, dir_fd); - -exit: - /* Cleanup for src */ - path_cleanup(&src); - /* Cleanup for dst */ - path_cleanup(&dst); - - return return_value; -} - -#endif /* defined(HAVE_SYMLINK) */ - -#if defined(HAVE_TIMES) - -PyDoc_STRVAR(os_times__doc__, -"times($module, /)\n" -"--\n" -"\n" -"Return a collection containing process timing information.\n" -"\n" -"The object returned behaves like a named tuple with these fields:\n" -" (utime, stime, cutime, cstime, elapsed_time)\n" -"All fields are floating point numbers."); - -#define OS_TIMES_METHODDEF \ - {"times", (PyCFunction)os_times, METH_NOARGS, os_times__doc__}, - -static PyObject * -os_times_impl(PyObject *module); - -static PyObject * -os_times(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_times_impl(module); -} - -#endif /* defined(HAVE_TIMES) */ - -#if defined(HAVE_GETSID) - -PyDoc_STRVAR(os_getsid__doc__, -"getsid($module, pid, /)\n" -"--\n" -"\n" -"Call the system call getsid(pid) and return the result."); - -#define OS_GETSID_METHODDEF \ - {"getsid", (PyCFunction)os_getsid, METH_O, os_getsid__doc__}, - -static PyObject * -os_getsid_impl(PyObject *module, pid_t pid); - -static PyObject * -os_getsid(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - pid_t pid; - - if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":getsid", &pid)) { - goto exit; - } - return_value = os_getsid_impl(module, pid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_GETSID) */ - -#if defined(HAVE_SETSID) - -PyDoc_STRVAR(os_setsid__doc__, -"setsid($module, /)\n" -"--\n" -"\n" -"Call the system call setsid()."); - -#define OS_SETSID_METHODDEF \ - {"setsid", (PyCFunction)os_setsid, METH_NOARGS, os_setsid__doc__}, - -static PyObject * -os_setsid_impl(PyObject *module); - -static PyObject * -os_setsid(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_setsid_impl(module); -} - -#endif /* defined(HAVE_SETSID) */ - -#if defined(HAVE_SETPGID) - -PyDoc_STRVAR(os_setpgid__doc__, -"setpgid($module, pid, pgrp, /)\n" -"--\n" -"\n" -"Call the system call setpgid(pid, pgrp)."); - -#define OS_SETPGID_METHODDEF \ - {"setpgid", _PyCFunction_CAST(os_setpgid), METH_FASTCALL, os_setpgid__doc__}, - -static PyObject * -os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp); - -static PyObject * -os_setpgid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - pid_t pid; - pid_t pgrp; - - if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "" _Py_PARSE_PID ":setpgid", - &pid, &pgrp)) { - goto exit; - } - return_value = os_setpgid_impl(module, pid, pgrp); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SETPGID) */ - -#if defined(HAVE_TCGETPGRP) - -PyDoc_STRVAR(os_tcgetpgrp__doc__, -"tcgetpgrp($module, fd, /)\n" -"--\n" -"\n" -"Return the process group associated with the terminal specified by fd."); - -#define OS_TCGETPGRP_METHODDEF \ - {"tcgetpgrp", (PyCFunction)os_tcgetpgrp, METH_O, os_tcgetpgrp__doc__}, - -static PyObject * -os_tcgetpgrp_impl(PyObject *module, int fd); - -static PyObject * -os_tcgetpgrp(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int fd; - - fd = _PyLong_AsInt(arg); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_tcgetpgrp_impl(module, fd); - -exit: - return return_value; -} - -#endif /* defined(HAVE_TCGETPGRP) */ - -#if defined(HAVE_TCSETPGRP) - -PyDoc_STRVAR(os_tcsetpgrp__doc__, -"tcsetpgrp($module, fd, pgid, /)\n" -"--\n" -"\n" -"Set the process group associated with the terminal specified by fd."); - -#define OS_TCSETPGRP_METHODDEF \ - {"tcsetpgrp", _PyCFunction_CAST(os_tcsetpgrp), METH_FASTCALL, os_tcsetpgrp__doc__}, - -static PyObject * -os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid); - -static PyObject * -os_tcsetpgrp(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - pid_t pgid; - - if (!_PyArg_ParseStack(args, nargs, "i" _Py_PARSE_PID ":tcsetpgrp", - &fd, &pgid)) { - goto exit; - } - return_value = os_tcsetpgrp_impl(module, fd, pgid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_TCSETPGRP) */ - -PyDoc_STRVAR(os_open__doc__, -"open($module, /, path, flags, mode=511, *, dir_fd=None)\n" -"--\n" -"\n" -"Open a file for low level IO. Returns a file descriptor (integer).\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"dir_fd may not be implemented on your platform.\n" -" If it is unavailable, using it will raise a NotImplementedError."); - -#define OS_OPEN_METHODDEF \ - {"open", _PyCFunction_CAST(os_open), METH_FASTCALL|METH_KEYWORDS, os_open__doc__}, - -static int -os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd); - -static PyObject * -os_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 4 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(flags), &_Py_ID(mode), &_Py_ID(dir_fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "flags", "mode", "dir_fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "open", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[4]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("open", "path", 0, 0); - int flags; - int mode = 511; - int dir_fd = DEFAULT_DIR_FD; - int _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - flags = _PyLong_AsInt(args[1]); - if (flags == -1 && PyErr_Occurred()) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[2]) { - mode = _PyLong_AsInt(args[2]); - if (mode == -1 && PyErr_Occurred()) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } -skip_optional_pos: - if (!noptargs) { - goto skip_optional_kwonly; - } - if (!OPENAT_DIR_FD_CONVERTER(args[3], &dir_fd)) { - goto exit; - } -skip_optional_kwonly: - _return_value = os_open_impl(module, &path, flags, mode, dir_fd); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromLong((long)_return_value); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -PyDoc_STRVAR(os_close__doc__, -"close($module, /, fd)\n" -"--\n" -"\n" -"Close a file descriptor."); - -#define OS_CLOSE_METHODDEF \ - {"close", _PyCFunction_CAST(os_close), METH_FASTCALL|METH_KEYWORDS, os_close__doc__}, - -static PyObject * -os_close_impl(PyObject *module, int fd); - -static PyObject * -os_close(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "close", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int fd; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_close_impl(module, fd); - -exit: - return return_value; -} - -PyDoc_STRVAR(os_closerange__doc__, -"closerange($module, fd_low, fd_high, /)\n" -"--\n" -"\n" -"Closes all file descriptors in [fd_low, fd_high), ignoring errors."); - -#define OS_CLOSERANGE_METHODDEF \ - {"closerange", _PyCFunction_CAST(os_closerange), METH_FASTCALL, os_closerange__doc__}, - -static PyObject * -os_closerange_impl(PyObject *module, int fd_low, int fd_high); - -static PyObject * -os_closerange(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd_low; - int fd_high; - - if (!_PyArg_CheckPositional("closerange", nargs, 2, 2)) { - goto exit; - } - fd_low = _PyLong_AsInt(args[0]); - if (fd_low == -1 && PyErr_Occurred()) { - goto exit; - } - fd_high = _PyLong_AsInt(args[1]); - if (fd_high == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_closerange_impl(module, fd_low, fd_high); - -exit: - return return_value; -} - -PyDoc_STRVAR(os_dup__doc__, -"dup($module, fd, /)\n" -"--\n" -"\n" -"Return a duplicate of a file descriptor."); - -#define OS_DUP_METHODDEF \ - {"dup", (PyCFunction)os_dup, METH_O, os_dup__doc__}, - -static int -os_dup_impl(PyObject *module, int fd); - -static PyObject * -os_dup(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int fd; - int _return_value; - - fd = _PyLong_AsInt(arg); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_dup_impl(module, fd); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromLong((long)_return_value); - -exit: - return return_value; -} - -#if ((defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))) - -PyDoc_STRVAR(os_dup2__doc__, -"dup2($module, /, fd, fd2, inheritable=True)\n" -"--\n" -"\n" -"Duplicate file descriptor."); - -#define OS_DUP2_METHODDEF \ - {"dup2", _PyCFunction_CAST(os_dup2), METH_FASTCALL|METH_KEYWORDS, os_dup2__doc__}, - -static int -os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable); - -static PyObject * -os_dup2(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(fd), &_Py_ID(fd2), &_Py_ID(inheritable), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"fd", "fd2", "inheritable", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "dup2", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - int fd; - int fd2; - int inheritable = 1; - int _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf); - if (!args) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - fd2 = _PyLong_AsInt(args[1]); - if (fd2 == -1 && PyErr_Occurred()) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - inheritable = PyObject_IsTrue(args[2]); - if (inheritable < 0) { - goto exit; - } -skip_optional_pos: - _return_value = os_dup2_impl(module, fd, fd2, inheritable); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromLong((long)_return_value); - -exit: - return return_value; -} - -#endif /* ((defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))) */ - -#if defined(HAVE_LOCKF) - -PyDoc_STRVAR(os_lockf__doc__, -"lockf($module, fd, command, length, /)\n" -"--\n" -"\n" -"Apply, test or remove a POSIX lock on an open file descriptor.\n" -"\n" -" fd\n" -" An open file descriptor.\n" -" command\n" -" One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.\n" -" length\n" -" The number of bytes to lock, starting at the current position."); - -#define OS_LOCKF_METHODDEF \ - {"lockf", _PyCFunction_CAST(os_lockf), METH_FASTCALL, os_lockf__doc__}, - -static PyObject * -os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length); - -static PyObject * -os_lockf(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - int command; - Py_off_t length; - - if (!_PyArg_CheckPositional("lockf", nargs, 3, 3)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - command = _PyLong_AsInt(args[1]); - if (command == -1 && PyErr_Occurred()) { - goto exit; - } - if (!Py_off_t_converter(args[2], &length)) { - goto exit; - } - return_value = os_lockf_impl(module, fd, command, length); - -exit: - return return_value; -} - -#endif /* defined(HAVE_LOCKF) */ - -PyDoc_STRVAR(os_lseek__doc__, -"lseek($module, fd, position, how, /)\n" -"--\n" -"\n" -"Set the position of a file descriptor. Return the new position.\n" -"\n" -"Return the new cursor position in number of bytes\n" -"relative to the beginning of the file."); - -#define OS_LSEEK_METHODDEF \ - {"lseek", _PyCFunction_CAST(os_lseek), METH_FASTCALL, os_lseek__doc__}, - -static Py_off_t -os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how); - -static PyObject * -os_lseek(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - Py_off_t position; - int how; - Py_off_t _return_value; - - if (!_PyArg_CheckPositional("lseek", nargs, 3, 3)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - if (!Py_off_t_converter(args[1], &position)) { - goto exit; - } - how = _PyLong_AsInt(args[2]); - if (how == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_lseek_impl(module, fd, position, how); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromPy_off_t(_return_value); - -exit: - return return_value; -} - -PyDoc_STRVAR(os_read__doc__, -"read($module, fd, length, /)\n" -"--\n" -"\n" -"Read from a file descriptor. Returns a bytes object."); - -#define OS_READ_METHODDEF \ - {"read", _PyCFunction_CAST(os_read), METH_FASTCALL, os_read__doc__}, - -static PyObject * -os_read_impl(PyObject *module, int fd, Py_ssize_t length); - -static PyObject * -os_read(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - Py_ssize_t length; - - if (!_PyArg_CheckPositional("read", nargs, 2, 2)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[1]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - length = ival; - } - return_value = os_read_impl(module, fd, length); - -exit: - return return_value; -} - -#if defined(HAVE_READV) - -PyDoc_STRVAR(os_readv__doc__, -"readv($module, fd, buffers, /)\n" -"--\n" -"\n" -"Read from a file descriptor fd into an iterable of buffers.\n" -"\n" -"The buffers should be mutable buffers accepting bytes.\n" -"readv will transfer data into each buffer until it is full\n" -"and then move on to the next buffer in the sequence to hold\n" -"the rest of the data.\n" -"\n" -"readv returns the total number of bytes read,\n" -"which may be less than the total capacity of all the buffers."); - -#define OS_READV_METHODDEF \ - {"readv", _PyCFunction_CAST(os_readv), METH_FASTCALL, os_readv__doc__}, - -static Py_ssize_t -os_readv_impl(PyObject *module, int fd, PyObject *buffers); - -static PyObject * -os_readv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - PyObject *buffers; - Py_ssize_t _return_value; - - if (!_PyArg_CheckPositional("readv", nargs, 2, 2)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - buffers = args[1]; - _return_value = os_readv_impl(module, fd, buffers); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromSsize_t(_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_READV) */ - -#if defined(HAVE_PREAD) - -PyDoc_STRVAR(os_pread__doc__, -"pread($module, fd, length, offset, /)\n" -"--\n" -"\n" -"Read a number of bytes from a file descriptor starting at a particular offset.\n" -"\n" -"Read length bytes from file descriptor fd, starting at offset bytes from\n" -"the beginning of the file. The file offset remains unchanged."); - -#define OS_PREAD_METHODDEF \ - {"pread", _PyCFunction_CAST(os_pread), METH_FASTCALL, os_pread__doc__}, - -static PyObject * -os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset); - -static PyObject * -os_pread(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - Py_ssize_t length; - Py_off_t offset; - - if (!_PyArg_CheckPositional("pread", nargs, 3, 3)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[1]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - length = ival; - } - if (!Py_off_t_converter(args[2], &offset)) { - goto exit; - } - return_value = os_pread_impl(module, fd, length, offset); - -exit: - return return_value; -} - -#endif /* defined(HAVE_PREAD) */ - -#if (defined(HAVE_PREADV) || defined (HAVE_PREADV2)) - -PyDoc_STRVAR(os_preadv__doc__, -"preadv($module, fd, buffers, offset, flags=0, /)\n" -"--\n" -"\n" -"Reads from a file descriptor into a number of mutable bytes-like objects.\n" -"\n" -"Combines the functionality of readv() and pread(). As readv(), it will\n" -"transfer data into each buffer until it is full and then move on to the next\n" -"buffer in the sequence to hold the rest of the data. Its fourth argument,\n" -"specifies the file offset at which the input operation is to be performed. It\n" -"will return the total number of bytes read (which can be less than the total\n" -"capacity of all the objects).\n" -"\n" -"The flags argument contains a bitwise OR of zero or more of the following flags:\n" -"\n" -"- RWF_HIPRI\n" -"- RWF_NOWAIT\n" -"\n" -"Using non-zero flags requires Linux 4.6 or newer."); - -#define OS_PREADV_METHODDEF \ - {"preadv", _PyCFunction_CAST(os_preadv), METH_FASTCALL, os_preadv__doc__}, - -static Py_ssize_t -os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, - int flags); - -static PyObject * -os_preadv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - PyObject *buffers; - Py_off_t offset; - int flags = 0; - Py_ssize_t _return_value; - - if (!_PyArg_CheckPositional("preadv", nargs, 3, 4)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - buffers = args[1]; - if (!Py_off_t_converter(args[2], &offset)) { - goto exit; - } - if (nargs < 4) { - goto skip_optional; - } - flags = _PyLong_AsInt(args[3]); - if (flags == -1 && PyErr_Occurred()) { - goto exit; - } -skip_optional: - _return_value = os_preadv_impl(module, fd, buffers, offset, flags); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromSsize_t(_return_value); - -exit: - return return_value; -} - -#endif /* (defined(HAVE_PREADV) || defined (HAVE_PREADV2)) */ - -PyDoc_STRVAR(os_write__doc__, -"write($module, fd, data, /)\n" -"--\n" -"\n" -"Write a bytes object to a file descriptor."); - -#define OS_WRITE_METHODDEF \ - {"write", _PyCFunction_CAST(os_write), METH_FASTCALL, os_write__doc__}, - -static Py_ssize_t -os_write_impl(PyObject *module, int fd, Py_buffer *data); - -static PyObject * -os_write(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - Py_buffer data = {NULL, NULL}; - Py_ssize_t _return_value; - - if (!_PyArg_CheckPositional("write", nargs, 2, 2)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - if (PyObject_GetBuffer(args[1], &data, PyBUF_SIMPLE) != 0) { - goto exit; - } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("write", "argument 2", "contiguous buffer", args[1]); - goto exit; - } - _return_value = os_write_impl(module, fd, &data); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromSsize_t(_return_value); - -exit: - /* Cleanup for data */ - if (data.obj) { - PyBuffer_Release(&data); - } - - return return_value; -} - -#if defined(HAVE_SENDFILE) && defined(__APPLE__) - -PyDoc_STRVAR(os_sendfile__doc__, -"sendfile($module, /, out_fd, in_fd, offset, count, headers=(),\n" -" trailers=(), flags=0)\n" -"--\n" -"\n" -"Copy count bytes from file descriptor in_fd to file descriptor out_fd."); - -#define OS_SENDFILE_METHODDEF \ - {"sendfile", _PyCFunction_CAST(os_sendfile), METH_FASTCALL|METH_KEYWORDS, os_sendfile__doc__}, - -static PyObject * -os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset, - Py_off_t sbytes, PyObject *headers, PyObject *trailers, - int flags); - -static PyObject * -os_sendfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 7 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(out_fd), &_Py_ID(in_fd), &_Py_ID(offset), &_Py_ID(count), &_Py_ID(headers), &_Py_ID(trailers), &_Py_ID(flags), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"out_fd", "in_fd", "offset", "count", "headers", "trailers", "flags", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "sendfile", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[7]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 4; - int out_fd; - int in_fd; - Py_off_t offset; - Py_off_t sbytes; - PyObject *headers = NULL; - PyObject *trailers = NULL; - int flags = 0; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 4, 7, 0, argsbuf); - if (!args) { - goto exit; - } - out_fd = _PyLong_AsInt(args[0]); - if (out_fd == -1 && PyErr_Occurred()) { - goto exit; - } - in_fd = _PyLong_AsInt(args[1]); - if (in_fd == -1 && PyErr_Occurred()) { - goto exit; - } - if (!Py_off_t_converter(args[2], &offset)) { - goto exit; - } - if (!Py_off_t_converter(args[3], &sbytes)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[4]) { - headers = args[4]; - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (args[5]) { - trailers = args[5]; - if (!--noptargs) { - goto skip_optional_pos; - } - } - flags = _PyLong_AsInt(args[6]); - if (flags == -1 && PyErr_Occurred()) { - goto exit; - } -skip_optional_pos: - return_value = os_sendfile_impl(module, out_fd, in_fd, offset, sbytes, headers, trailers, flags); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SENDFILE) && defined(__APPLE__) */ - -#if defined(HAVE_SENDFILE) && !defined(__APPLE__) && (defined(__FreeBSD__) || defined(__DragonFly__)) - -PyDoc_STRVAR(os_sendfile__doc__, -"sendfile($module, /, out_fd, in_fd, offset, count, headers=(),\n" -" trailers=(), flags=0)\n" -"--\n" -"\n" -"Copy count bytes from file descriptor in_fd to file descriptor out_fd."); - -#define OS_SENDFILE_METHODDEF \ - {"sendfile", _PyCFunction_CAST(os_sendfile), METH_FASTCALL|METH_KEYWORDS, os_sendfile__doc__}, - -static PyObject * -os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset, - Py_ssize_t count, PyObject *headers, PyObject *trailers, - int flags); - -static PyObject * -os_sendfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 7 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(out_fd), &_Py_ID(in_fd), &_Py_ID(offset), &_Py_ID(count), &_Py_ID(headers), &_Py_ID(trailers), &_Py_ID(flags), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"out_fd", "in_fd", "offset", "count", "headers", "trailers", "flags", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "sendfile", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[7]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 4; - int out_fd; - int in_fd; - Py_off_t offset; - Py_ssize_t count; - PyObject *headers = NULL; - PyObject *trailers = NULL; - int flags = 0; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 4, 7, 0, argsbuf); - if (!args) { - goto exit; - } - out_fd = _PyLong_AsInt(args[0]); - if (out_fd == -1 && PyErr_Occurred()) { - goto exit; - } - in_fd = _PyLong_AsInt(args[1]); - if (in_fd == -1 && PyErr_Occurred()) { - goto exit; - } - if (!Py_off_t_converter(args[2], &offset)) { - goto exit; - } - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[3]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - count = ival; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[4]) { - headers = args[4]; - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (args[5]) { - trailers = args[5]; - if (!--noptargs) { - goto skip_optional_pos; - } - } - flags = _PyLong_AsInt(args[6]); - if (flags == -1 && PyErr_Occurred()) { - goto exit; - } -skip_optional_pos: - return_value = os_sendfile_impl(module, out_fd, in_fd, offset, count, headers, trailers, flags); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SENDFILE) && !defined(__APPLE__) && (defined(__FreeBSD__) || defined(__DragonFly__)) */ - -#if defined(HAVE_SENDFILE) && !defined(__APPLE__) && !(defined(__FreeBSD__) || defined(__DragonFly__)) - -PyDoc_STRVAR(os_sendfile__doc__, -"sendfile($module, /, out_fd, in_fd, offset, count)\n" -"--\n" -"\n" -"Copy count bytes from file descriptor in_fd to file descriptor out_fd."); - -#define OS_SENDFILE_METHODDEF \ - {"sendfile", _PyCFunction_CAST(os_sendfile), METH_FASTCALL|METH_KEYWORDS, os_sendfile__doc__}, - -static PyObject * -os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj, - Py_ssize_t count); - -static PyObject * -os_sendfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 4 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(out_fd), &_Py_ID(in_fd), &_Py_ID(offset), &_Py_ID(count), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"out_fd", "in_fd", "offset", "count", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "sendfile", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[4]; - int out_fd; - int in_fd; - PyObject *offobj; - Py_ssize_t count; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 4, 4, 0, argsbuf); - if (!args) { - goto exit; - } - out_fd = _PyLong_AsInt(args[0]); - if (out_fd == -1 && PyErr_Occurred()) { - goto exit; - } - in_fd = _PyLong_AsInt(args[1]); - if (in_fd == -1 && PyErr_Occurred()) { - goto exit; - } - offobj = args[2]; - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[3]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - count = ival; - } - return_value = os_sendfile_impl(module, out_fd, in_fd, offobj, count); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SENDFILE) && !defined(__APPLE__) && !(defined(__FreeBSD__) || defined(__DragonFly__)) */ - -#if defined(__APPLE__) - -PyDoc_STRVAR(os__fcopyfile__doc__, -"_fcopyfile($module, in_fd, out_fd, flags, /)\n" -"--\n" -"\n" -"Efficiently copy content or metadata of 2 regular file descriptors (macOS)."); - -#define OS__FCOPYFILE_METHODDEF \ - {"_fcopyfile", _PyCFunction_CAST(os__fcopyfile), METH_FASTCALL, os__fcopyfile__doc__}, - -static PyObject * -os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags); - -static PyObject * -os__fcopyfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int in_fd; - int out_fd; - int flags; - - if (!_PyArg_CheckPositional("_fcopyfile", nargs, 3, 3)) { - goto exit; - } - in_fd = _PyLong_AsInt(args[0]); - if (in_fd == -1 && PyErr_Occurred()) { - goto exit; - } - out_fd = _PyLong_AsInt(args[1]); - if (out_fd == -1 && PyErr_Occurred()) { - goto exit; - } - flags = _PyLong_AsInt(args[2]); - if (flags == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os__fcopyfile_impl(module, in_fd, out_fd, flags); - -exit: - return return_value; -} - -#endif /* defined(__APPLE__) */ - -PyDoc_STRVAR(os_fstat__doc__, -"fstat($module, /, fd)\n" -"--\n" -"\n" -"Perform a stat system call on the given file descriptor.\n" -"\n" -"Like stat(), but for an open file descriptor.\n" -"Equivalent to os.stat(fd)."); - -#define OS_FSTAT_METHODDEF \ - {"fstat", _PyCFunction_CAST(os_fstat), METH_FASTCALL|METH_KEYWORDS, os_fstat__doc__}, - -static PyObject * -os_fstat_impl(PyObject *module, int fd); - -static PyObject * -os_fstat(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "fstat", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int fd; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_fstat_impl(module, fd); - -exit: - return return_value; -} - -PyDoc_STRVAR(os_isatty__doc__, -"isatty($module, fd, /)\n" -"--\n" -"\n" -"Return True if the fd is connected to a terminal.\n" -"\n" -"Return True if the file descriptor is an open file descriptor\n" -"connected to the slave end of a terminal."); - -#define OS_ISATTY_METHODDEF \ - {"isatty", (PyCFunction)os_isatty, METH_O, os_isatty__doc__}, - -static int -os_isatty_impl(PyObject *module, int fd); - -static PyObject * -os_isatty(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int fd; - int _return_value; - - fd = _PyLong_AsInt(arg); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_isatty_impl(module, fd); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - -#if defined(HAVE_PIPE) - -PyDoc_STRVAR(os_pipe__doc__, -"pipe($module, /)\n" -"--\n" -"\n" -"Create a pipe.\n" -"\n" -"Returns a tuple of two file descriptors:\n" -" (read_fd, write_fd)"); - -#define OS_PIPE_METHODDEF \ - {"pipe", (PyCFunction)os_pipe, METH_NOARGS, os_pipe__doc__}, - -static PyObject * -os_pipe_impl(PyObject *module); - -static PyObject * -os_pipe(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_pipe_impl(module); -} - -#endif /* defined(HAVE_PIPE) */ - -#if defined(HAVE_PIPE2) - -PyDoc_STRVAR(os_pipe2__doc__, -"pipe2($module, flags, /)\n" -"--\n" -"\n" -"Create a pipe with flags set atomically.\n" -"\n" -"Returns a tuple of two file descriptors:\n" -" (read_fd, write_fd)\n" -"\n" -"flags can be constructed by ORing together one or more of these values:\n" -"O_NONBLOCK, O_CLOEXEC."); - -#define OS_PIPE2_METHODDEF \ - {"pipe2", (PyCFunction)os_pipe2, METH_O, os_pipe2__doc__}, - -static PyObject * -os_pipe2_impl(PyObject *module, int flags); - -static PyObject * -os_pipe2(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int flags; - - flags = _PyLong_AsInt(arg); - if (flags == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_pipe2_impl(module, flags); - -exit: - return return_value; -} - -#endif /* defined(HAVE_PIPE2) */ - -#if defined(HAVE_WRITEV) - -PyDoc_STRVAR(os_writev__doc__, -"writev($module, fd, buffers, /)\n" -"--\n" -"\n" -"Iterate over buffers, and write the contents of each to a file descriptor.\n" -"\n" -"Returns the total number of bytes written.\n" -"buffers must be a sequence of bytes-like objects."); - -#define OS_WRITEV_METHODDEF \ - {"writev", _PyCFunction_CAST(os_writev), METH_FASTCALL, os_writev__doc__}, - -static Py_ssize_t -os_writev_impl(PyObject *module, int fd, PyObject *buffers); - -static PyObject * -os_writev(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - PyObject *buffers; - Py_ssize_t _return_value; - - if (!_PyArg_CheckPositional("writev", nargs, 2, 2)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - buffers = args[1]; - _return_value = os_writev_impl(module, fd, buffers); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromSsize_t(_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_WRITEV) */ - -#if defined(HAVE_PWRITE) - -PyDoc_STRVAR(os_pwrite__doc__, -"pwrite($module, fd, buffer, offset, /)\n" -"--\n" -"\n" -"Write bytes to a file descriptor starting at a particular offset.\n" -"\n" -"Write buffer to fd, starting at offset bytes from the beginning of\n" -"the file. Returns the number of bytes writte. Does not change the\n" -"current file offset."); - -#define OS_PWRITE_METHODDEF \ - {"pwrite", _PyCFunction_CAST(os_pwrite), METH_FASTCALL, os_pwrite__doc__}, - -static Py_ssize_t -os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset); - -static PyObject * -os_pwrite(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - Py_buffer buffer = {NULL, NULL}; - Py_off_t offset; - Py_ssize_t _return_value; - - if (!_PyArg_CheckPositional("pwrite", nargs, 3, 3)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - if (PyObject_GetBuffer(args[1], &buffer, PyBUF_SIMPLE) != 0) { - goto exit; - } - if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("pwrite", "argument 2", "contiguous buffer", args[1]); - goto exit; - } - if (!Py_off_t_converter(args[2], &offset)) { - goto exit; - } - _return_value = os_pwrite_impl(module, fd, &buffer, offset); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromSsize_t(_return_value); - -exit: - /* Cleanup for buffer */ - if (buffer.obj) { - PyBuffer_Release(&buffer); - } - - return return_value; -} - -#endif /* defined(HAVE_PWRITE) */ - -#if (defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)) - -PyDoc_STRVAR(os_pwritev__doc__, -"pwritev($module, fd, buffers, offset, flags=0, /)\n" -"--\n" -"\n" -"Writes the contents of bytes-like objects to a file descriptor at a given offset.\n" -"\n" -"Combines the functionality of writev() and pwrite(). All buffers must be a sequence\n" -"of bytes-like objects. Buffers are processed in array order. Entire contents of first\n" -"buffer is written before proceeding to second, and so on. The operating system may\n" -"set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.\n" -"This function writes the contents of each object to the file descriptor and returns\n" -"the total number of bytes written.\n" -"\n" -"The flags argument contains a bitwise OR of zero or more of the following flags:\n" -"\n" -"- RWF_DSYNC\n" -"- RWF_SYNC\n" -"- RWF_APPEND\n" -"\n" -"Using non-zero flags requires Linux 4.7 or newer."); - -#define OS_PWRITEV_METHODDEF \ - {"pwritev", _PyCFunction_CAST(os_pwritev), METH_FASTCALL, os_pwritev__doc__}, - -static Py_ssize_t -os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, - int flags); - -static PyObject * -os_pwritev(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - PyObject *buffers; - Py_off_t offset; - int flags = 0; - Py_ssize_t _return_value; - - if (!_PyArg_CheckPositional("pwritev", nargs, 3, 4)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - buffers = args[1]; - if (!Py_off_t_converter(args[2], &offset)) { - goto exit; - } - if (nargs < 4) { - goto skip_optional; - } - flags = _PyLong_AsInt(args[3]); - if (flags == -1 && PyErr_Occurred()) { - goto exit; - } -skip_optional: - _return_value = os_pwritev_impl(module, fd, buffers, offset, flags); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromSsize_t(_return_value); - -exit: - return return_value; -} - -#endif /* (defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)) */ - -#if defined(HAVE_COPY_FILE_RANGE) - -PyDoc_STRVAR(os_copy_file_range__doc__, -"copy_file_range($module, /, src, dst, count, offset_src=None,\n" -" offset_dst=None)\n" -"--\n" -"\n" -"Copy count bytes from one file descriptor to another.\n" -"\n" -" src\n" -" Source file descriptor.\n" -" dst\n" -" Destination file descriptor.\n" -" count\n" -" Number of bytes to copy.\n" -" offset_src\n" -" Starting offset in src.\n" -" offset_dst\n" -" Starting offset in dst.\n" -"\n" -"If offset_src is None, then src is read from the current position;\n" -"respectively for offset_dst."); - -#define OS_COPY_FILE_RANGE_METHODDEF \ - {"copy_file_range", _PyCFunction_CAST(os_copy_file_range), METH_FASTCALL|METH_KEYWORDS, os_copy_file_range__doc__}, - -static PyObject * -os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count, - PyObject *offset_src, PyObject *offset_dst); - -static PyObject * -os_copy_file_range(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 5 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(src), &_Py_ID(dst), &_Py_ID(count), &_Py_ID(offset_src), &_Py_ID(offset_dst), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"src", "dst", "count", "offset_src", "offset_dst", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "copy_file_range", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[5]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - int src; - int dst; - Py_ssize_t count; - PyObject *offset_src = Py_None; - PyObject *offset_dst = Py_None; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 5, 0, argsbuf); - if (!args) { - goto exit; - } - src = _PyLong_AsInt(args[0]); - if (src == -1 && PyErr_Occurred()) { - goto exit; - } - dst = _PyLong_AsInt(args[1]); - if (dst == -1 && PyErr_Occurred()) { - goto exit; - } - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[2]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - count = ival; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[3]) { - offset_src = args[3]; - if (!--noptargs) { - goto skip_optional_pos; - } - } - offset_dst = args[4]; -skip_optional_pos: - return_value = os_copy_file_range_impl(module, src, dst, count, offset_src, offset_dst); - -exit: - return return_value; -} - -#endif /* defined(HAVE_COPY_FILE_RANGE) */ - -#if ((defined(HAVE_SPLICE) && !defined(_AIX))) - -PyDoc_STRVAR(os_splice__doc__, -"splice($module, /, src, dst, count, offset_src=None, offset_dst=None,\n" -" flags=0)\n" -"--\n" -"\n" -"Transfer count bytes from one pipe to a descriptor or vice versa.\n" -"\n" -" src\n" -" Source file descriptor.\n" -" dst\n" -" Destination file descriptor.\n" -" count\n" -" Number of bytes to copy.\n" -" offset_src\n" -" Starting offset in src.\n" -" offset_dst\n" -" Starting offset in dst.\n" -" flags\n" -" Flags to modify the semantics of the call.\n" -"\n" -"If offset_src is None, then src is read from the current position;\n" -"respectively for offset_dst. The offset associated to the file\n" -"descriptor that refers to a pipe must be None."); - -#define OS_SPLICE_METHODDEF \ - {"splice", _PyCFunction_CAST(os_splice), METH_FASTCALL|METH_KEYWORDS, os_splice__doc__}, - -static PyObject * -os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count, - PyObject *offset_src, PyObject *offset_dst, - unsigned int flags); - -static PyObject * -os_splice(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 6 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(src), &_Py_ID(dst), &_Py_ID(count), &_Py_ID(offset_src), &_Py_ID(offset_dst), &_Py_ID(flags), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"src", "dst", "count", "offset_src", "offset_dst", "flags", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "splice", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[6]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - int src; - int dst; - Py_ssize_t count; - PyObject *offset_src = Py_None; - PyObject *offset_dst = Py_None; - unsigned int flags = 0; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 6, 0, argsbuf); - if (!args) { - goto exit; - } - src = _PyLong_AsInt(args[0]); - if (src == -1 && PyErr_Occurred()) { - goto exit; - } - dst = _PyLong_AsInt(args[1]); - if (dst == -1 && PyErr_Occurred()) { - goto exit; - } - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[2]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - count = ival; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[3]) { - offset_src = args[3]; - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (args[4]) { - offset_dst = args[4]; - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (!_PyLong_UnsignedInt_Converter(args[5], &flags)) { - goto exit; - } -skip_optional_pos: - return_value = os_splice_impl(module, src, dst, count, offset_src, offset_dst, flags); - -exit: - return return_value; -} - -#endif /* ((defined(HAVE_SPLICE) && !defined(_AIX))) */ - -#if defined(HAVE_MKFIFO) - -PyDoc_STRVAR(os_mkfifo__doc__, -"mkfifo($module, /, path, mode=438, *, dir_fd=None)\n" -"--\n" -"\n" -"Create a \"fifo\" (a POSIX named pipe).\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"dir_fd may not be implemented on your platform.\n" -" If it is unavailable, using it will raise a NotImplementedError."); - -#define OS_MKFIFO_METHODDEF \ - {"mkfifo", _PyCFunction_CAST(os_mkfifo), METH_FASTCALL|METH_KEYWORDS, os_mkfifo__doc__}, - -static PyObject * -os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd); - -static PyObject * -os_mkfifo(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(mode), &_Py_ID(dir_fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "mode", "dir_fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "mkfifo", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("mkfifo", "path", 0, 0); - int mode = 438; - int dir_fd = DEFAULT_DIR_FD; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[1]) { - mode = _PyLong_AsInt(args[1]); - if (mode == -1 && PyErr_Occurred()) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } -skip_optional_pos: - if (!noptargs) { - goto skip_optional_kwonly; - } - if (!MKFIFOAT_DIR_FD_CONVERTER(args[2], &dir_fd)) { - goto exit; - } -skip_optional_kwonly: - return_value = os_mkfifo_impl(module, &path, mode, dir_fd); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(HAVE_MKFIFO) */ - -#if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) - -PyDoc_STRVAR(os_mknod__doc__, -"mknod($module, /, path, mode=384, device=0, *, dir_fd=None)\n" -"--\n" -"\n" -"Create a node in the file system.\n" -"\n" -"Create a node in the file system (file, device special file or named pipe)\n" -"at path. mode specifies both the permissions to use and the\n" -"type of node to be created, being combined (bitwise OR) with one of\n" -"S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode,\n" -"device defines the newly created device special file (probably using\n" -"os.makedev()). Otherwise device is ignored.\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"dir_fd may not be implemented on your platform.\n" -" If it is unavailable, using it will raise a NotImplementedError."); - -#define OS_MKNOD_METHODDEF \ - {"mknod", _PyCFunction_CAST(os_mknod), METH_FASTCALL|METH_KEYWORDS, os_mknod__doc__}, - -static PyObject * -os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device, - int dir_fd); - -static PyObject * -os_mknod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 4 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(mode), &_Py_ID(device), &_Py_ID(dir_fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "mode", "device", "dir_fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "mknod", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[4]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t path = PATH_T_INITIALIZE("mknod", "path", 0, 0); - int mode = 384; - dev_t device = 0; - int dir_fd = DEFAULT_DIR_FD; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[1]) { - mode = _PyLong_AsInt(args[1]); - if (mode == -1 && PyErr_Occurred()) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (args[2]) { - if (!_Py_Dev_Converter(args[2], &device)) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } -skip_optional_pos: - if (!noptargs) { - goto skip_optional_kwonly; - } - if (!MKNODAT_DIR_FD_CONVERTER(args[3], &dir_fd)) { - goto exit; - } -skip_optional_kwonly: - return_value = os_mknod_impl(module, &path, mode, device, dir_fd); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) */ - -#if defined(HAVE_DEVICE_MACROS) - -PyDoc_STRVAR(os_major__doc__, -"major($module, device, /)\n" -"--\n" -"\n" -"Extracts a device major number from a raw device number."); - -#define OS_MAJOR_METHODDEF \ - {"major", (PyCFunction)os_major, METH_O, os_major__doc__}, - -static unsigned int -os_major_impl(PyObject *module, dev_t device); - -static PyObject * -os_major(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - dev_t device; - unsigned int _return_value; - - if (!_Py_Dev_Converter(arg, &device)) { - goto exit; - } - _return_value = os_major_impl(module, device); - if ((_return_value == (unsigned int)-1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromUnsignedLong((unsigned long)_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_DEVICE_MACROS) */ - -#if defined(HAVE_DEVICE_MACROS) - -PyDoc_STRVAR(os_minor__doc__, -"minor($module, device, /)\n" -"--\n" -"\n" -"Extracts a device minor number from a raw device number."); - -#define OS_MINOR_METHODDEF \ - {"minor", (PyCFunction)os_minor, METH_O, os_minor__doc__}, - -static unsigned int -os_minor_impl(PyObject *module, dev_t device); - -static PyObject * -os_minor(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - dev_t device; - unsigned int _return_value; - - if (!_Py_Dev_Converter(arg, &device)) { - goto exit; - } - _return_value = os_minor_impl(module, device); - if ((_return_value == (unsigned int)-1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromUnsignedLong((unsigned long)_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_DEVICE_MACROS) */ - -#if defined(HAVE_DEVICE_MACROS) - -PyDoc_STRVAR(os_makedev__doc__, -"makedev($module, major, minor, /)\n" -"--\n" -"\n" -"Composes a raw device number from the major and minor device numbers."); - -#define OS_MAKEDEV_METHODDEF \ - {"makedev", _PyCFunction_CAST(os_makedev), METH_FASTCALL, os_makedev__doc__}, - -static dev_t -os_makedev_impl(PyObject *module, int major, int minor); - -static PyObject * -os_makedev(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int major; - int minor; - dev_t _return_value; - - if (!_PyArg_CheckPositional("makedev", nargs, 2, 2)) { - goto exit; - } - major = _PyLong_AsInt(args[0]); - if (major == -1 && PyErr_Occurred()) { - goto exit; - } - minor = _PyLong_AsInt(args[1]); - if (minor == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_makedev_impl(module, major, minor); - if ((_return_value == (dev_t)-1) && PyErr_Occurred()) { - goto exit; - } - return_value = _PyLong_FromDev(_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_DEVICE_MACROS) */ - -#if (defined HAVE_FTRUNCATE || defined MS_WINDOWS) - -PyDoc_STRVAR(os_ftruncate__doc__, -"ftruncate($module, fd, length, /)\n" -"--\n" -"\n" -"Truncate a file, specified by file descriptor, to a specific length."); - -#define OS_FTRUNCATE_METHODDEF \ - {"ftruncate", _PyCFunction_CAST(os_ftruncate), METH_FASTCALL, os_ftruncate__doc__}, - -static PyObject * -os_ftruncate_impl(PyObject *module, int fd, Py_off_t length); - -static PyObject * -os_ftruncate(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - Py_off_t length; - - if (!_PyArg_CheckPositional("ftruncate", nargs, 2, 2)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - if (!Py_off_t_converter(args[1], &length)) { - goto exit; - } - return_value = os_ftruncate_impl(module, fd, length); - -exit: - return return_value; -} - -#endif /* (defined HAVE_FTRUNCATE || defined MS_WINDOWS) */ - -#if (defined HAVE_TRUNCATE || defined MS_WINDOWS) - -PyDoc_STRVAR(os_truncate__doc__, -"truncate($module, /, path, length)\n" -"--\n" -"\n" -"Truncate a file, specified by path, to a specific length.\n" -"\n" -"On some platforms, path may also be specified as an open file descriptor.\n" -" If this functionality is unavailable, using it raises an exception."); - -#define OS_TRUNCATE_METHODDEF \ - {"truncate", _PyCFunction_CAST(os_truncate), METH_FASTCALL|METH_KEYWORDS, os_truncate__doc__}, - -static PyObject * -os_truncate_impl(PyObject *module, path_t *path, Py_off_t length); - -static PyObject * -os_truncate(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(length), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "length", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "truncate", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - path_t path = PATH_T_INITIALIZE("truncate", "path", 0, PATH_HAVE_FTRUNCATE); - Py_off_t length; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!Py_off_t_converter(args[1], &length)) { - goto exit; - } - return_value = os_truncate_impl(module, &path, length); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* (defined HAVE_TRUNCATE || defined MS_WINDOWS) */ - -#if (defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)) - -PyDoc_STRVAR(os_posix_fallocate__doc__, -"posix_fallocate($module, fd, offset, length, /)\n" -"--\n" -"\n" -"Ensure a file has allocated at least a particular number of bytes on disk.\n" -"\n" -"Ensure that the file specified by fd encompasses a range of bytes\n" -"starting at offset bytes from the beginning and continuing for length bytes."); - -#define OS_POSIX_FALLOCATE_METHODDEF \ - {"posix_fallocate", _PyCFunction_CAST(os_posix_fallocate), METH_FASTCALL, os_posix_fallocate__doc__}, - -static PyObject * -os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset, - Py_off_t length); - -static PyObject * -os_posix_fallocate(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - Py_off_t offset; - Py_off_t length; - - if (!_PyArg_CheckPositional("posix_fallocate", nargs, 3, 3)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - if (!Py_off_t_converter(args[1], &offset)) { - goto exit; - } - if (!Py_off_t_converter(args[2], &length)) { - goto exit; - } - return_value = os_posix_fallocate_impl(module, fd, offset, length); - -exit: - return return_value; -} - -#endif /* (defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)) */ - -#if (defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)) - -PyDoc_STRVAR(os_posix_fadvise__doc__, -"posix_fadvise($module, fd, offset, length, advice, /)\n" -"--\n" -"\n" -"Announce an intention to access data in a specific pattern.\n" -"\n" -"Announce an intention to access data in a specific pattern, thus allowing\n" -"the kernel to make optimizations.\n" -"The advice applies to the region of the file specified by fd starting at\n" -"offset and continuing for length bytes.\n" -"advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,\n" -"POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or\n" -"POSIX_FADV_DONTNEED."); - -#define OS_POSIX_FADVISE_METHODDEF \ - {"posix_fadvise", _PyCFunction_CAST(os_posix_fadvise), METH_FASTCALL, os_posix_fadvise__doc__}, - -static PyObject * -os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset, - Py_off_t length, int advice); - -static PyObject * -os_posix_fadvise(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - Py_off_t offset; - Py_off_t length; - int advice; - - if (!_PyArg_CheckPositional("posix_fadvise", nargs, 4, 4)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - if (!Py_off_t_converter(args[1], &offset)) { - goto exit; - } - if (!Py_off_t_converter(args[2], &length)) { - goto exit; - } - advice = _PyLong_AsInt(args[3]); - if (advice == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_posix_fadvise_impl(module, fd, offset, length, advice); - -exit: - return return_value; -} - -#endif /* (defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)) */ - -#if defined(MS_WINDOWS) - -PyDoc_STRVAR(os_putenv__doc__, -"putenv($module, name, value, /)\n" -"--\n" -"\n" -"Change or add an environment variable."); - -#define OS_PUTENV_METHODDEF \ - {"putenv", _PyCFunction_CAST(os_putenv), METH_FASTCALL, os_putenv__doc__}, - -static PyObject * -os_putenv_impl(PyObject *module, PyObject *name, PyObject *value); - -static PyObject * -os_putenv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - PyObject *name; - PyObject *value; - - if (!_PyArg_CheckPositional("putenv", nargs, 2, 2)) { - goto exit; - } - if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("putenv", "argument 1", "str", args[0]); - goto exit; - } - if (PyUnicode_READY(args[0]) == -1) { - goto exit; - } - name = args[0]; - if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("putenv", "argument 2", "str", args[1]); - goto exit; - } - if (PyUnicode_READY(args[1]) == -1) { - goto exit; - } - value = args[1]; - return_value = os_putenv_impl(module, name, value); - -exit: - return return_value; -} - -#endif /* defined(MS_WINDOWS) */ - -#if !defined(MS_WINDOWS) - -PyDoc_STRVAR(os_putenv__doc__, -"putenv($module, name, value, /)\n" -"--\n" -"\n" -"Change or add an environment variable."); - -#define OS_PUTENV_METHODDEF \ - {"putenv", _PyCFunction_CAST(os_putenv), METH_FASTCALL, os_putenv__doc__}, - -static PyObject * -os_putenv_impl(PyObject *module, PyObject *name, PyObject *value); - -static PyObject * -os_putenv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - PyObject *name = NULL; - PyObject *value = NULL; - - if (!_PyArg_CheckPositional("putenv", nargs, 2, 2)) { - goto exit; - } - if (!PyUnicode_FSConverter(args[0], &name)) { - goto exit; - } - if (!PyUnicode_FSConverter(args[1], &value)) { - goto exit; - } - return_value = os_putenv_impl(module, name, value); - -exit: - /* Cleanup for name */ - Py_XDECREF(name); - /* Cleanup for value */ - Py_XDECREF(value); - - return return_value; -} - -#endif /* !defined(MS_WINDOWS) */ - -#if defined(MS_WINDOWS) - -PyDoc_STRVAR(os_unsetenv__doc__, -"unsetenv($module, name, /)\n" -"--\n" -"\n" -"Delete an environment variable."); - -#define OS_UNSETENV_METHODDEF \ - {"unsetenv", (PyCFunction)os_unsetenv, METH_O, os_unsetenv__doc__}, - -static PyObject * -os_unsetenv_impl(PyObject *module, PyObject *name); - -static PyObject * -os_unsetenv(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - PyObject *name; - - if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("unsetenv", "argument", "str", arg); - goto exit; - } - if (PyUnicode_READY(arg) == -1) { - goto exit; - } - name = arg; - return_value = os_unsetenv_impl(module, name); - -exit: - return return_value; -} - -#endif /* defined(MS_WINDOWS) */ - -#if !defined(MS_WINDOWS) - -PyDoc_STRVAR(os_unsetenv__doc__, -"unsetenv($module, name, /)\n" -"--\n" -"\n" -"Delete an environment variable."); - -#define OS_UNSETENV_METHODDEF \ - {"unsetenv", (PyCFunction)os_unsetenv, METH_O, os_unsetenv__doc__}, - -static PyObject * -os_unsetenv_impl(PyObject *module, PyObject *name); - -static PyObject * -os_unsetenv(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - PyObject *name = NULL; - - if (!PyUnicode_FSConverter(arg, &name)) { - goto exit; - } - return_value = os_unsetenv_impl(module, name); - -exit: - /* Cleanup for name */ - Py_XDECREF(name); - - return return_value; -} - -#endif /* !defined(MS_WINDOWS) */ - -PyDoc_STRVAR(os_strerror__doc__, -"strerror($module, code, /)\n" -"--\n" -"\n" -"Translate an error code to a message string."); - -#define OS_STRERROR_METHODDEF \ - {"strerror", (PyCFunction)os_strerror, METH_O, os_strerror__doc__}, - -static PyObject * -os_strerror_impl(PyObject *module, int code); - -static PyObject * -os_strerror(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int code; - - code = _PyLong_AsInt(arg); - if (code == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_strerror_impl(module, code); - -exit: - return return_value; -} - -#if defined(HAVE_SYS_WAIT_H) && defined(WCOREDUMP) - -PyDoc_STRVAR(os_WCOREDUMP__doc__, -"WCOREDUMP($module, status, /)\n" -"--\n" -"\n" -"Return True if the process returning status was dumped to a core file."); - -#define OS_WCOREDUMP_METHODDEF \ - {"WCOREDUMP", (PyCFunction)os_WCOREDUMP, METH_O, os_WCOREDUMP__doc__}, - -static int -os_WCOREDUMP_impl(PyObject *module, int status); - -static PyObject * -os_WCOREDUMP(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int status; - int _return_value; - - status = _PyLong_AsInt(arg); - if (status == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_WCOREDUMP_impl(module, status); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SYS_WAIT_H) && defined(WCOREDUMP) */ - -#if defined(HAVE_SYS_WAIT_H) && defined(WIFCONTINUED) - -PyDoc_STRVAR(os_WIFCONTINUED__doc__, -"WIFCONTINUED($module, /, status)\n" -"--\n" -"\n" -"Return True if a particular process was continued from a job control stop.\n" -"\n" -"Return True if the process returning status was continued from a\n" -"job control stop."); - -#define OS_WIFCONTINUED_METHODDEF \ - {"WIFCONTINUED", _PyCFunction_CAST(os_WIFCONTINUED), METH_FASTCALL|METH_KEYWORDS, os_WIFCONTINUED__doc__}, - -static int -os_WIFCONTINUED_impl(PyObject *module, int status); - -static PyObject * -os_WIFCONTINUED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(status), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"status", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "WIFCONTINUED", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int status; - int _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - status = _PyLong_AsInt(args[0]); - if (status == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_WIFCONTINUED_impl(module, status); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SYS_WAIT_H) && defined(WIFCONTINUED) */ - -#if defined(HAVE_SYS_WAIT_H) && defined(WIFSTOPPED) - -PyDoc_STRVAR(os_WIFSTOPPED__doc__, -"WIFSTOPPED($module, /, status)\n" -"--\n" -"\n" -"Return True if the process returning status was stopped."); - -#define OS_WIFSTOPPED_METHODDEF \ - {"WIFSTOPPED", _PyCFunction_CAST(os_WIFSTOPPED), METH_FASTCALL|METH_KEYWORDS, os_WIFSTOPPED__doc__}, - -static int -os_WIFSTOPPED_impl(PyObject *module, int status); - -static PyObject * -os_WIFSTOPPED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(status), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"status", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "WIFSTOPPED", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int status; - int _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - status = _PyLong_AsInt(args[0]); - if (status == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_WIFSTOPPED_impl(module, status); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SYS_WAIT_H) && defined(WIFSTOPPED) */ - -#if defined(HAVE_SYS_WAIT_H) && defined(WIFSIGNALED) - -PyDoc_STRVAR(os_WIFSIGNALED__doc__, -"WIFSIGNALED($module, /, status)\n" -"--\n" -"\n" -"Return True if the process returning status was terminated by a signal."); - -#define OS_WIFSIGNALED_METHODDEF \ - {"WIFSIGNALED", _PyCFunction_CAST(os_WIFSIGNALED), METH_FASTCALL|METH_KEYWORDS, os_WIFSIGNALED__doc__}, - -static int -os_WIFSIGNALED_impl(PyObject *module, int status); - -static PyObject * -os_WIFSIGNALED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(status), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"status", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "WIFSIGNALED", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int status; - int _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - status = _PyLong_AsInt(args[0]); - if (status == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_WIFSIGNALED_impl(module, status); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SYS_WAIT_H) && defined(WIFSIGNALED) */ - -#if defined(HAVE_SYS_WAIT_H) && defined(WIFEXITED) - -PyDoc_STRVAR(os_WIFEXITED__doc__, -"WIFEXITED($module, /, status)\n" -"--\n" -"\n" -"Return True if the process returning status exited via the exit() system call."); - -#define OS_WIFEXITED_METHODDEF \ - {"WIFEXITED", _PyCFunction_CAST(os_WIFEXITED), METH_FASTCALL|METH_KEYWORDS, os_WIFEXITED__doc__}, - -static int -os_WIFEXITED_impl(PyObject *module, int status); - -static PyObject * -os_WIFEXITED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(status), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"status", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "WIFEXITED", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int status; - int _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - status = _PyLong_AsInt(args[0]); - if (status == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_WIFEXITED_impl(module, status); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SYS_WAIT_H) && defined(WIFEXITED) */ - -#if defined(HAVE_SYS_WAIT_H) && defined(WEXITSTATUS) - -PyDoc_STRVAR(os_WEXITSTATUS__doc__, -"WEXITSTATUS($module, /, status)\n" -"--\n" -"\n" -"Return the process return code from status."); - -#define OS_WEXITSTATUS_METHODDEF \ - {"WEXITSTATUS", _PyCFunction_CAST(os_WEXITSTATUS), METH_FASTCALL|METH_KEYWORDS, os_WEXITSTATUS__doc__}, - -static int -os_WEXITSTATUS_impl(PyObject *module, int status); - -static PyObject * -os_WEXITSTATUS(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(status), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"status", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "WEXITSTATUS", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int status; - int _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - status = _PyLong_AsInt(args[0]); - if (status == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_WEXITSTATUS_impl(module, status); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromLong((long)_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SYS_WAIT_H) && defined(WEXITSTATUS) */ - -#if defined(HAVE_SYS_WAIT_H) && defined(WTERMSIG) - -PyDoc_STRVAR(os_WTERMSIG__doc__, -"WTERMSIG($module, /, status)\n" -"--\n" -"\n" -"Return the signal that terminated the process that provided the status value."); - -#define OS_WTERMSIG_METHODDEF \ - {"WTERMSIG", _PyCFunction_CAST(os_WTERMSIG), METH_FASTCALL|METH_KEYWORDS, os_WTERMSIG__doc__}, - -static int -os_WTERMSIG_impl(PyObject *module, int status); - -static PyObject * -os_WTERMSIG(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(status), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"status", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "WTERMSIG", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int status; - int _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - status = _PyLong_AsInt(args[0]); - if (status == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_WTERMSIG_impl(module, status); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromLong((long)_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SYS_WAIT_H) && defined(WTERMSIG) */ - -#if defined(HAVE_SYS_WAIT_H) && defined(WSTOPSIG) - -PyDoc_STRVAR(os_WSTOPSIG__doc__, -"WSTOPSIG($module, /, status)\n" -"--\n" -"\n" -"Return the signal that stopped the process that provided the status value."); - -#define OS_WSTOPSIG_METHODDEF \ - {"WSTOPSIG", _PyCFunction_CAST(os_WSTOPSIG), METH_FASTCALL|METH_KEYWORDS, os_WSTOPSIG__doc__}, - -static int -os_WSTOPSIG_impl(PyObject *module, int status); - -static PyObject * -os_WSTOPSIG(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(status), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"status", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "WSTOPSIG", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int status; - int _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - status = _PyLong_AsInt(args[0]); - if (status == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_WSTOPSIG_impl(module, status); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromLong((long)_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SYS_WAIT_H) && defined(WSTOPSIG) */ - -#if (defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)) - -PyDoc_STRVAR(os_fstatvfs__doc__, -"fstatvfs($module, fd, /)\n" -"--\n" -"\n" -"Perform an fstatvfs system call on the given fd.\n" -"\n" -"Equivalent to statvfs(fd)."); - -#define OS_FSTATVFS_METHODDEF \ - {"fstatvfs", (PyCFunction)os_fstatvfs, METH_O, os_fstatvfs__doc__}, - -static PyObject * -os_fstatvfs_impl(PyObject *module, int fd); - -static PyObject * -os_fstatvfs(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int fd; - - fd = _PyLong_AsInt(arg); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_fstatvfs_impl(module, fd); - -exit: - return return_value; -} - -#endif /* (defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)) */ - -#if (defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)) - -PyDoc_STRVAR(os_statvfs__doc__, -"statvfs($module, /, path)\n" -"--\n" -"\n" -"Perform a statvfs system call on the given path.\n" -"\n" -"path may always be specified as a string.\n" -"On some platforms, path may also be specified as an open file descriptor.\n" -" If this functionality is unavailable, using it raises an exception."); - -#define OS_STATVFS_METHODDEF \ - {"statvfs", _PyCFunction_CAST(os_statvfs), METH_FASTCALL|METH_KEYWORDS, os_statvfs__doc__}, - -static PyObject * -os_statvfs_impl(PyObject *module, path_t *path); - -static PyObject * -os_statvfs(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "statvfs", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("statvfs", "path", 0, PATH_HAVE_FSTATVFS); - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - return_value = os_statvfs_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* (defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)) */ - -#if defined(MS_WINDOWS) - -PyDoc_STRVAR(os__getdiskusage__doc__, -"_getdiskusage($module, /, path)\n" -"--\n" -"\n" -"Return disk usage statistics about the given path as a (total, free) tuple."); - -#define OS__GETDISKUSAGE_METHODDEF \ - {"_getdiskusage", _PyCFunction_CAST(os__getdiskusage), METH_FASTCALL|METH_KEYWORDS, os__getdiskusage__doc__}, - -static PyObject * -os__getdiskusage_impl(PyObject *module, path_t *path); - -static PyObject * -os__getdiskusage(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "_getdiskusage", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_getdiskusage", "path", 0, 0); - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - return_value = os__getdiskusage_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(MS_WINDOWS) */ - -#if defined(HAVE_FPATHCONF) - -PyDoc_STRVAR(os_fpathconf__doc__, -"fpathconf($module, fd, name, /)\n" -"--\n" -"\n" -"Return the configuration limit name for the file descriptor fd.\n" -"\n" -"If there is no limit, return -1."); - -#define OS_FPATHCONF_METHODDEF \ - {"fpathconf", _PyCFunction_CAST(os_fpathconf), METH_FASTCALL, os_fpathconf__doc__}, - -static long -os_fpathconf_impl(PyObject *module, int fd, int name); - -static PyObject * -os_fpathconf(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - int name; - long _return_value; - - if (!_PyArg_CheckPositional("fpathconf", nargs, 2, 2)) { - goto exit; - } - if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { - goto exit; - } - if (!conv_path_confname(args[1], &name)) { - goto exit; - } - _return_value = os_fpathconf_impl(module, fd, name); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromLong(_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_FPATHCONF) */ - -#if defined(HAVE_PATHCONF) - -PyDoc_STRVAR(os_pathconf__doc__, -"pathconf($module, /, path, name)\n" -"--\n" -"\n" -"Return the configuration limit name for the file or directory path.\n" -"\n" -"If there is no limit, return -1.\n" -"On some platforms, path may also be specified as an open file descriptor.\n" -" If this functionality is unavailable, using it raises an exception."); - -#define OS_PATHCONF_METHODDEF \ - {"pathconf", _PyCFunction_CAST(os_pathconf), METH_FASTCALL|METH_KEYWORDS, os_pathconf__doc__}, - -static long -os_pathconf_impl(PyObject *module, path_t *path, int name); - -static PyObject * -os_pathconf(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(name), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "name", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "pathconf", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - path_t path = PATH_T_INITIALIZE("pathconf", "path", 0, PATH_HAVE_FPATHCONF); - int name; - long _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!conv_path_confname(args[1], &name)) { - goto exit; - } - _return_value = os_pathconf_impl(module, &path, name); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromLong(_return_value); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(HAVE_PATHCONF) */ - -#if defined(HAVE_CONFSTR) - -PyDoc_STRVAR(os_confstr__doc__, -"confstr($module, name, /)\n" -"--\n" -"\n" -"Return a string-valued system configuration variable."); - -#define OS_CONFSTR_METHODDEF \ - {"confstr", (PyCFunction)os_confstr, METH_O, os_confstr__doc__}, - -static PyObject * -os_confstr_impl(PyObject *module, int name); - -static PyObject * -os_confstr(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int name; - - if (!conv_confstr_confname(arg, &name)) { - goto exit; - } - return_value = os_confstr_impl(module, name); - -exit: - return return_value; -} - -#endif /* defined(HAVE_CONFSTR) */ - -#if defined(HAVE_SYSCONF) - -PyDoc_STRVAR(os_sysconf__doc__, -"sysconf($module, name, /)\n" -"--\n" -"\n" -"Return an integer-valued system configuration variable."); - -#define OS_SYSCONF_METHODDEF \ - {"sysconf", (PyCFunction)os_sysconf, METH_O, os_sysconf__doc__}, - -static long -os_sysconf_impl(PyObject *module, int name); - -static PyObject * -os_sysconf(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int name; - long _return_value; - - if (!conv_sysconf_confname(arg, &name)) { - goto exit; - } - _return_value = os_sysconf_impl(module, name); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromLong(_return_value); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SYSCONF) */ - -PyDoc_STRVAR(os_abort__doc__, -"abort($module, /)\n" -"--\n" -"\n" -"Abort the interpreter immediately.\n" -"\n" -"This function \'dumps core\' or otherwise fails in the hardest way possible\n" -"on the hosting operating system. This function never returns."); - -#define OS_ABORT_METHODDEF \ - {"abort", (PyCFunction)os_abort, METH_NOARGS, os_abort__doc__}, - -static PyObject * -os_abort_impl(PyObject *module); - -static PyObject * -os_abort(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_abort_impl(module); -} - -#if defined(MS_WINDOWS) - -PyDoc_STRVAR(os_startfile__doc__, -"startfile($module, /, filepath, operation=,\n" -" arguments=, cwd=None, show_cmd=1)\n" -"--\n" -"\n" -"Start a file with its associated application.\n" -"\n" -"When \"operation\" is not specified or \"open\", this acts like\n" -"double-clicking the file in Explorer, or giving the file name as an\n" -"argument to the DOS \"start\" command: the file is opened with whatever\n" -"application (if any) its extension is associated.\n" -"When another \"operation\" is given, it specifies what should be done with\n" -"the file. A typical operation is \"print\".\n" -"\n" -"\"arguments\" is passed to the application, but should be omitted if the\n" -"file is a document.\n" -"\n" -"\"cwd\" is the working directory for the operation. If \"filepath\" is\n" -"relative, it will be resolved against this directory. This argument\n" -"should usually be an absolute path.\n" -"\n" -"\"show_cmd\" can be used to override the recommended visibility option.\n" -"See the Windows ShellExecute documentation for values.\n" -"\n" -"startfile returns as soon as the associated application is launched.\n" -"There is no option to wait for the application to close, and no way\n" -"to retrieve the application\'s exit status.\n" -"\n" -"The filepath is relative to the current directory. If you want to use\n" -"an absolute path, make sure the first character is not a slash (\"/\");\n" -"the underlying Win32 ShellExecute function doesn\'t work if it is."); - -#define OS_STARTFILE_METHODDEF \ - {"startfile", _PyCFunction_CAST(os_startfile), METH_FASTCALL|METH_KEYWORDS, os_startfile__doc__}, - -static PyObject * -os_startfile_impl(PyObject *module, path_t *filepath, - const Py_UNICODE *operation, const Py_UNICODE *arguments, - path_t *cwd, int show_cmd); - -static PyObject * -os_startfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 5 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(filepath), &_Py_ID(operation), &_Py_ID(arguments), &_Py_ID(cwd), &_Py_ID(show_cmd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"filepath", "operation", "arguments", "cwd", "show_cmd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "startfile", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[5]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - path_t filepath = PATH_T_INITIALIZE("startfile", "filepath", 0, 0); - const Py_UNICODE *operation = NULL; - const Py_UNICODE *arguments = NULL; - path_t cwd = PATH_T_INITIALIZE("startfile", "cwd", 1, 0); - int show_cmd = 1; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 5, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &filepath)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[1]) { - if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("startfile", "argument 'operation'", "str", args[1]); - goto exit; - } - operation = PyUnicode_AsWideCharString(args[1], NULL); - if (operation == NULL) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (args[2]) { - if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("startfile", "argument 'arguments'", "str", args[2]); - goto exit; - } - arguments = PyUnicode_AsWideCharString(args[2], NULL); - if (arguments == NULL) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (args[3]) { - if (!path_converter(args[3], &cwd)) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - show_cmd = _PyLong_AsInt(args[4]); - if (show_cmd == -1 && PyErr_Occurred()) { - goto exit; - } -skip_optional_pos: - return_value = os_startfile_impl(module, &filepath, operation, arguments, &cwd, show_cmd); - -exit: - /* Cleanup for filepath */ - path_cleanup(&filepath); - /* Cleanup for operation */ - PyMem_Free((void *)operation); - /* Cleanup for arguments */ - PyMem_Free((void *)arguments); - /* Cleanup for cwd */ - path_cleanup(&cwd); - - return return_value; -} - -#endif /* defined(MS_WINDOWS) */ - -#if defined(HAVE_GETLOADAVG) - -PyDoc_STRVAR(os_getloadavg__doc__, -"getloadavg($module, /)\n" -"--\n" -"\n" -"Return average recent system load information.\n" -"\n" -"Return the number of processes in the system run queue averaged over\n" -"the last 1, 5, and 15 minutes as a tuple of three floats.\n" -"Raises OSError if the load average was unobtainable."); - -#define OS_GETLOADAVG_METHODDEF \ - {"getloadavg", (PyCFunction)os_getloadavg, METH_NOARGS, os_getloadavg__doc__}, - -static PyObject * -os_getloadavg_impl(PyObject *module); - -static PyObject * -os_getloadavg(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getloadavg_impl(module); -} - -#endif /* defined(HAVE_GETLOADAVG) */ - -PyDoc_STRVAR(os_device_encoding__doc__, -"device_encoding($module, /, fd)\n" -"--\n" -"\n" -"Return a string describing the encoding of a terminal\'s file descriptor.\n" -"\n" -"The file descriptor must be attached to a terminal.\n" -"If the device is not a terminal, return None."); - -#define OS_DEVICE_ENCODING_METHODDEF \ - {"device_encoding", _PyCFunction_CAST(os_device_encoding), METH_FASTCALL|METH_KEYWORDS, os_device_encoding__doc__}, - -static PyObject * -os_device_encoding_impl(PyObject *module, int fd); - -static PyObject * -os_device_encoding(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "device_encoding", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int fd; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_device_encoding_impl(module, fd); - -exit: - return return_value; -} - -#if defined(HAVE_SETRESUID) - -PyDoc_STRVAR(os_setresuid__doc__, -"setresuid($module, ruid, euid, suid, /)\n" -"--\n" -"\n" -"Set the current process\'s real, effective, and saved user ids."); - -#define OS_SETRESUID_METHODDEF \ - {"setresuid", _PyCFunction_CAST(os_setresuid), METH_FASTCALL, os_setresuid__doc__}, - -static PyObject * -os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid); - -static PyObject * -os_setresuid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - uid_t ruid; - uid_t euid; - uid_t suid; - - if (!_PyArg_CheckPositional("setresuid", nargs, 3, 3)) { - goto exit; - } - if (!_Py_Uid_Converter(args[0], &ruid)) { - goto exit; - } - if (!_Py_Uid_Converter(args[1], &euid)) { - goto exit; - } - if (!_Py_Uid_Converter(args[2], &suid)) { - goto exit; - } - return_value = os_setresuid_impl(module, ruid, euid, suid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SETRESUID) */ - -#if defined(HAVE_SETRESGID) - -PyDoc_STRVAR(os_setresgid__doc__, -"setresgid($module, rgid, egid, sgid, /)\n" -"--\n" -"\n" -"Set the current process\'s real, effective, and saved group ids."); - -#define OS_SETRESGID_METHODDEF \ - {"setresgid", _PyCFunction_CAST(os_setresgid), METH_FASTCALL, os_setresgid__doc__}, - -static PyObject * -os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid); - -static PyObject * -os_setresgid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - gid_t rgid; - gid_t egid; - gid_t sgid; - - if (!_PyArg_CheckPositional("setresgid", nargs, 3, 3)) { - goto exit; - } - if (!_Py_Gid_Converter(args[0], &rgid)) { - goto exit; - } - if (!_Py_Gid_Converter(args[1], &egid)) { - goto exit; - } - if (!_Py_Gid_Converter(args[2], &sgid)) { - goto exit; - } - return_value = os_setresgid_impl(module, rgid, egid, sgid); - -exit: - return return_value; -} - -#endif /* defined(HAVE_SETRESGID) */ - -#if defined(HAVE_GETRESUID) - -PyDoc_STRVAR(os_getresuid__doc__, -"getresuid($module, /)\n" -"--\n" -"\n" -"Return a tuple of the current process\'s real, effective, and saved user ids."); - -#define OS_GETRESUID_METHODDEF \ - {"getresuid", (PyCFunction)os_getresuid, METH_NOARGS, os_getresuid__doc__}, - -static PyObject * -os_getresuid_impl(PyObject *module); - -static PyObject * -os_getresuid(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getresuid_impl(module); -} - -#endif /* defined(HAVE_GETRESUID) */ - -#if defined(HAVE_GETRESGID) - -PyDoc_STRVAR(os_getresgid__doc__, -"getresgid($module, /)\n" -"--\n" -"\n" -"Return a tuple of the current process\'s real, effective, and saved group ids."); - -#define OS_GETRESGID_METHODDEF \ - {"getresgid", (PyCFunction)os_getresgid, METH_NOARGS, os_getresgid__doc__}, - -static PyObject * -os_getresgid_impl(PyObject *module); - -static PyObject * -os_getresgid(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getresgid_impl(module); -} - -#endif /* defined(HAVE_GETRESGID) */ - -#if defined(USE_XATTRS) - -PyDoc_STRVAR(os_getxattr__doc__, -"getxattr($module, /, path, attribute, *, follow_symlinks=True)\n" -"--\n" -"\n" -"Return the value of extended attribute attribute on path.\n" -"\n" -"path may be either a string, a path-like object, or an open file descriptor.\n" -"If follow_symlinks is False, and the last element of the path is a symbolic\n" -" link, getxattr will examine the symbolic link itself instead of the file\n" -" the link points to."); - -#define OS_GETXATTR_METHODDEF \ - {"getxattr", _PyCFunction_CAST(os_getxattr), METH_FASTCALL|METH_KEYWORDS, os_getxattr__doc__}, - -static PyObject * -os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute, - int follow_symlinks); - -static PyObject * -os_getxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(attribute), &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "attribute", "follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "getxattr", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("getxattr", "path", 0, 1); - path_t attribute = PATH_T_INITIALIZE("getxattr", "attribute", 0, 0); - int follow_symlinks = 1; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!path_converter(args[1], &attribute)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - follow_symlinks = PyObject_IsTrue(args[2]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - return_value = os_getxattr_impl(module, &path, &attribute, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - /* Cleanup for attribute */ - path_cleanup(&attribute); - - return return_value; -} - -#endif /* defined(USE_XATTRS) */ - -#if defined(USE_XATTRS) - -PyDoc_STRVAR(os_setxattr__doc__, -"setxattr($module, /, path, attribute, value, flags=0, *,\n" -" follow_symlinks=True)\n" -"--\n" -"\n" -"Set extended attribute attribute on path to value.\n" -"\n" -"path may be either a string, a path-like object, or an open file descriptor.\n" -"If follow_symlinks is False, and the last element of the path is a symbolic\n" -" link, setxattr will modify the symbolic link itself instead of the file\n" -" the link points to."); - -#define OS_SETXATTR_METHODDEF \ - {"setxattr", _PyCFunction_CAST(os_setxattr), METH_FASTCALL|METH_KEYWORDS, os_setxattr__doc__}, - -static PyObject * -os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute, - Py_buffer *value, int flags, int follow_symlinks); - -static PyObject * -os_setxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 5 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(attribute), &_Py_ID(value), &_Py_ID(flags), &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "attribute", "value", "flags", "follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "setxattr", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[5]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; - path_t path = PATH_T_INITIALIZE("setxattr", "path", 0, 1); - path_t attribute = PATH_T_INITIALIZE("setxattr", "attribute", 0, 0); - Py_buffer value = {NULL, NULL}; - int flags = 0; - int follow_symlinks = 1; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 4, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!path_converter(args[1], &attribute)) { - goto exit; - } - if (PyObject_GetBuffer(args[2], &value, PyBUF_SIMPLE) != 0) { - goto exit; - } - if (!PyBuffer_IsContiguous(&value, 'C')) { - _PyArg_BadArgument("setxattr", "argument 'value'", "contiguous buffer", args[2]); - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[3]) { - flags = _PyLong_AsInt(args[3]); - if (flags == -1 && PyErr_Occurred()) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } -skip_optional_pos: - if (!noptargs) { - goto skip_optional_kwonly; - } - follow_symlinks = PyObject_IsTrue(args[4]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - return_value = os_setxattr_impl(module, &path, &attribute, &value, flags, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - /* Cleanup for attribute */ - path_cleanup(&attribute); - /* Cleanup for value */ - if (value.obj) { - PyBuffer_Release(&value); - } - - return return_value; -} - -#endif /* defined(USE_XATTRS) */ - -#if defined(USE_XATTRS) - -PyDoc_STRVAR(os_removexattr__doc__, -"removexattr($module, /, path, attribute, *, follow_symlinks=True)\n" -"--\n" -"\n" -"Remove extended attribute attribute on path.\n" -"\n" -"path may be either a string, a path-like object, or an open file descriptor.\n" -"If follow_symlinks is False, and the last element of the path is a symbolic\n" -" link, removexattr will modify the symbolic link itself instead of the file\n" -" the link points to."); - -#define OS_REMOVEXATTR_METHODDEF \ - {"removexattr", _PyCFunction_CAST(os_removexattr), METH_FASTCALL|METH_KEYWORDS, os_removexattr__doc__}, - -static PyObject * -os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute, - int follow_symlinks); - -static PyObject * -os_removexattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 3 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(attribute), &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "attribute", "follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "removexattr", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; - path_t path = PATH_T_INITIALIZE("removexattr", "path", 0, 1); - path_t attribute = PATH_T_INITIALIZE("removexattr", "attribute", 0, 0); - int follow_symlinks = 1; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!path_converter(args[1], &attribute)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - follow_symlinks = PyObject_IsTrue(args[2]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - return_value = os_removexattr_impl(module, &path, &attribute, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - /* Cleanup for attribute */ - path_cleanup(&attribute); - - return return_value; -} - -#endif /* defined(USE_XATTRS) */ - -#if defined(USE_XATTRS) - -PyDoc_STRVAR(os_listxattr__doc__, -"listxattr($module, /, path=None, *, follow_symlinks=True)\n" -"--\n" -"\n" -"Return a list of extended attributes on path.\n" -"\n" -"path may be either None, a string, a path-like object, or an open file descriptor.\n" -"if path is None, listxattr will examine the current directory.\n" -"If follow_symlinks is False, and the last element of the path is a symbolic\n" -" link, listxattr will examine the symbolic link itself instead of the file\n" -" the link points to."); - -#define OS_LISTXATTR_METHODDEF \ - {"listxattr", _PyCFunction_CAST(os_listxattr), METH_FASTCALL|METH_KEYWORDS, os_listxattr__doc__}, - -static PyObject * -os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks); - -static PyObject * -os_listxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", "follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "listxattr", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - path_t path = PATH_T_INITIALIZE("listxattr", "path", 1, 1); - int follow_symlinks = 1; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[0]) { - if (!path_converter(args[0], &path)) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } -skip_optional_pos: - if (!noptargs) { - goto skip_optional_kwonly; - } - follow_symlinks = PyObject_IsTrue(args[1]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - return_value = os_listxattr_impl(module, &path, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(USE_XATTRS) */ - -PyDoc_STRVAR(os_urandom__doc__, -"urandom($module, size, /)\n" -"--\n" -"\n" -"Return a bytes object containing random bytes suitable for cryptographic use."); - -#define OS_URANDOM_METHODDEF \ - {"urandom", (PyCFunction)os_urandom, METH_O, os_urandom__doc__}, - -static PyObject * -os_urandom_impl(PyObject *module, Py_ssize_t size); - -static PyObject * -os_urandom(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - Py_ssize_t size; - - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(arg); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - size = ival; - } - return_value = os_urandom_impl(module, size); - -exit: - return return_value; -} - -#if defined(HAVE_MEMFD_CREATE) - -PyDoc_STRVAR(os_memfd_create__doc__, -"memfd_create($module, /, name, flags=MFD_CLOEXEC)\n" -"--\n" -"\n"); - -#define OS_MEMFD_CREATE_METHODDEF \ - {"memfd_create", _PyCFunction_CAST(os_memfd_create), METH_FASTCALL|METH_KEYWORDS, os_memfd_create__doc__}, - -static PyObject * -os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags); - -static PyObject * -os_memfd_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(name), &_Py_ID(flags), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"name", "flags", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "memfd_create", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - PyObject *name = NULL; - unsigned int flags = MFD_CLOEXEC; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!PyUnicode_FSConverter(args[0], &name)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - flags = (unsigned int)PyLong_AsUnsignedLongMask(args[1]); - if (flags == (unsigned int)-1 && PyErr_Occurred()) { - goto exit; - } -skip_optional_pos: - return_value = os_memfd_create_impl(module, name, flags); - -exit: - /* Cleanup for name */ - Py_XDECREF(name); - - return return_value; -} - -#endif /* defined(HAVE_MEMFD_CREATE) */ - -#if (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) - -PyDoc_STRVAR(os_eventfd__doc__, -"eventfd($module, /, initval, flags=EFD_CLOEXEC)\n" -"--\n" -"\n" -"Creates and returns an event notification file descriptor."); - -#define OS_EVENTFD_METHODDEF \ - {"eventfd", _PyCFunction_CAST(os_eventfd), METH_FASTCALL|METH_KEYWORDS, os_eventfd__doc__}, - -static PyObject * -os_eventfd_impl(PyObject *module, unsigned int initval, int flags); - -static PyObject * -os_eventfd(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(initval), &_Py_ID(flags), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"initval", "flags", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "eventfd", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - unsigned int initval; - int flags = EFD_CLOEXEC; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!_PyLong_UnsignedInt_Converter(args[0], &initval)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - flags = _PyLong_AsInt(args[1]); - if (flags == -1 && PyErr_Occurred()) { - goto exit; - } -skip_optional_pos: - return_value = os_eventfd_impl(module, initval, flags); - -exit: - return return_value; -} - -#endif /* (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) */ - -#if (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) - -PyDoc_STRVAR(os_eventfd_read__doc__, -"eventfd_read($module, /, fd)\n" -"--\n" -"\n" -"Read eventfd value"); - -#define OS_EVENTFD_READ_METHODDEF \ - {"eventfd_read", _PyCFunction_CAST(os_eventfd_read), METH_FASTCALL|METH_KEYWORDS, os_eventfd_read__doc__}, - -static PyObject * -os_eventfd_read_impl(PyObject *module, int fd); - -static PyObject * -os_eventfd_read(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(fd), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"fd", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "eventfd_read", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - int fd; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { - goto exit; - } - return_value = os_eventfd_read_impl(module, fd); - -exit: - return return_value; -} - -#endif /* (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) */ - -#if (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) - -PyDoc_STRVAR(os_eventfd_write__doc__, -"eventfd_write($module, /, fd, value)\n" -"--\n" -"\n" -"Write eventfd value."); - -#define OS_EVENTFD_WRITE_METHODDEF \ - {"eventfd_write", _PyCFunction_CAST(os_eventfd_write), METH_FASTCALL|METH_KEYWORDS, os_eventfd_write__doc__}, - -static PyObject * -os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value); - -static PyObject * -os_eventfd_write(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(fd), &_Py_ID(value), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"fd", "value", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "eventfd_write", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - int fd; - unsigned long long value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { - goto exit; - } - if (!_PyLong_UnsignedLongLong_Converter(args[1], &value)) { - goto exit; - } - return_value = os_eventfd_write_impl(module, fd, value); - -exit: - return return_value; -} - -#endif /* (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) */ - -#if (defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)) - -PyDoc_STRVAR(os_get_terminal_size__doc__, -"get_terminal_size($module, fd=, /)\n" -"--\n" -"\n" -"Return the size of the terminal window as (columns, lines).\n" -"\n" -"The optional argument fd (default standard output) specifies\n" -"which file descriptor should be queried.\n" -"\n" -"If the file descriptor is not connected to a terminal, an OSError\n" -"is thrown.\n" -"\n" -"This function will only be defined if an implementation is\n" -"available for this system.\n" -"\n" -"shutil.get_terminal_size is the high-level function which should\n" -"normally be used, os.get_terminal_size is the low-level implementation."); - -#define OS_GET_TERMINAL_SIZE_METHODDEF \ - {"get_terminal_size", _PyCFunction_CAST(os_get_terminal_size), METH_FASTCALL, os_get_terminal_size__doc__}, - -static PyObject * -os_get_terminal_size_impl(PyObject *module, int fd); - -static PyObject * -os_get_terminal_size(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd = fileno(stdout); - - if (!_PyArg_CheckPositional("get_terminal_size", nargs, 0, 1)) { - goto exit; - } - if (nargs < 1) { - goto skip_optional; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } -skip_optional: - return_value = os_get_terminal_size_impl(module, fd); - -exit: - return return_value; -} - -#endif /* (defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)) */ - -PyDoc_STRVAR(os_cpu_count__doc__, -"cpu_count($module, /)\n" -"--\n" -"\n" -"Return the number of CPUs in the system; return None if indeterminable.\n" -"\n" -"This number is not equivalent to the number of CPUs the current process can\n" -"use. The number of usable CPUs can be obtained with\n" -"``len(os.sched_getaffinity(0))``"); - -#define OS_CPU_COUNT_METHODDEF \ - {"cpu_count", (PyCFunction)os_cpu_count, METH_NOARGS, os_cpu_count__doc__}, - -static PyObject * -os_cpu_count_impl(PyObject *module); - -static PyObject * -os_cpu_count(PyObject *module, PyObject *Py_UNUSED(ignored)) -{ - return os_cpu_count_impl(module); -} - -PyDoc_STRVAR(os_get_inheritable__doc__, -"get_inheritable($module, fd, /)\n" -"--\n" -"\n" -"Get the close-on-exe flag of the specified file descriptor."); - -#define OS_GET_INHERITABLE_METHODDEF \ - {"get_inheritable", (PyCFunction)os_get_inheritable, METH_O, os_get_inheritable__doc__}, - -static int -os_get_inheritable_impl(PyObject *module, int fd); - -static PyObject * -os_get_inheritable(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int fd; - int _return_value; - - fd = _PyLong_AsInt(arg); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_get_inheritable_impl(module, fd); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - -PyDoc_STRVAR(os_set_inheritable__doc__, -"set_inheritable($module, fd, inheritable, /)\n" -"--\n" -"\n" -"Set the inheritable flag of the specified file descriptor."); - -#define OS_SET_INHERITABLE_METHODDEF \ - {"set_inheritable", _PyCFunction_CAST(os_set_inheritable), METH_FASTCALL, os_set_inheritable__doc__}, - -static PyObject * -os_set_inheritable_impl(PyObject *module, int fd, int inheritable); - -static PyObject * -os_set_inheritable(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - int inheritable; - - if (!_PyArg_CheckPositional("set_inheritable", nargs, 2, 2)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - inheritable = _PyLong_AsInt(args[1]); - if (inheritable == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_set_inheritable_impl(module, fd, inheritable); - -exit: - return return_value; -} - -#if defined(MS_WINDOWS) - -PyDoc_STRVAR(os_get_handle_inheritable__doc__, -"get_handle_inheritable($module, handle, /)\n" -"--\n" -"\n" -"Get the close-on-exe flag of the specified file descriptor."); - -#define OS_GET_HANDLE_INHERITABLE_METHODDEF \ - {"get_handle_inheritable", (PyCFunction)os_get_handle_inheritable, METH_O, os_get_handle_inheritable__doc__}, - -static int -os_get_handle_inheritable_impl(PyObject *module, intptr_t handle); - -static PyObject * -os_get_handle_inheritable(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - intptr_t handle; - int _return_value; - - if (!PyArg_Parse(arg, "" _Py_PARSE_INTPTR ":get_handle_inheritable", &handle)) { - goto exit; - } - _return_value = os_get_handle_inheritable_impl(module, handle); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - -#endif /* defined(MS_WINDOWS) */ - -#if defined(MS_WINDOWS) - -PyDoc_STRVAR(os_set_handle_inheritable__doc__, -"set_handle_inheritable($module, handle, inheritable, /)\n" -"--\n" -"\n" -"Set the inheritable flag of the specified handle."); - -#define OS_SET_HANDLE_INHERITABLE_METHODDEF \ - {"set_handle_inheritable", _PyCFunction_CAST(os_set_handle_inheritable), METH_FASTCALL, os_set_handle_inheritable__doc__}, - -static PyObject * -os_set_handle_inheritable_impl(PyObject *module, intptr_t handle, - int inheritable); - -static PyObject * -os_set_handle_inheritable(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - intptr_t handle; - int inheritable; - - if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_INTPTR "p:set_handle_inheritable", - &handle, &inheritable)) { - goto exit; - } - return_value = os_set_handle_inheritable_impl(module, handle, inheritable); - -exit: - return return_value; -} - -#endif /* defined(MS_WINDOWS) */ - -#if !defined(MS_WINDOWS) - -PyDoc_STRVAR(os_get_blocking__doc__, -"get_blocking($module, fd, /)\n" -"--\n" -"\n" -"Get the blocking mode of the file descriptor.\n" -"\n" -"Return False if the O_NONBLOCK flag is set, True if the flag is cleared."); - -#define OS_GET_BLOCKING_METHODDEF \ - {"get_blocking", (PyCFunction)os_get_blocking, METH_O, os_get_blocking__doc__}, - -static int -os_get_blocking_impl(PyObject *module, int fd); - -static PyObject * -os_get_blocking(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - int fd; - int _return_value; - - fd = _PyLong_AsInt(arg); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - _return_value = os_get_blocking_impl(module, fd); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - -#endif /* !defined(MS_WINDOWS) */ - -#if !defined(MS_WINDOWS) - -PyDoc_STRVAR(os_set_blocking__doc__, -"set_blocking($module, fd, blocking, /)\n" -"--\n" -"\n" -"Set the blocking mode of the specified file descriptor.\n" -"\n" -"Set the O_NONBLOCK flag if blocking is False,\n" -"clear the O_NONBLOCK flag otherwise."); - -#define OS_SET_BLOCKING_METHODDEF \ - {"set_blocking", _PyCFunction_CAST(os_set_blocking), METH_FASTCALL, os_set_blocking__doc__}, - -static PyObject * -os_set_blocking_impl(PyObject *module, int fd, int blocking); - -static PyObject * -os_set_blocking(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - int fd; - int blocking; - - if (!_PyArg_CheckPositional("set_blocking", nargs, 2, 2)) { - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { - goto exit; - } - blocking = _PyLong_AsInt(args[1]); - if (blocking == -1 && PyErr_Occurred()) { - goto exit; - } - return_value = os_set_blocking_impl(module, fd, blocking); - -exit: - return return_value; -} - -#endif /* !defined(MS_WINDOWS) */ - -PyDoc_STRVAR(os_DirEntry_is_symlink__doc__, -"is_symlink($self, /)\n" -"--\n" -"\n" -"Return True if the entry is a symbolic link; cached per entry."); - -#define OS_DIRENTRY_IS_SYMLINK_METHODDEF \ - {"is_symlink", _PyCFunction_CAST(os_DirEntry_is_symlink), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, os_DirEntry_is_symlink__doc__}, - -static int -os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class); - -static PyObject * -os_DirEntry_is_symlink(DirEntry *self, PyTypeObject *defining_class, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - int _return_value; - - if (nargs) { - PyErr_SetString(PyExc_TypeError, "is_symlink() takes no arguments"); - goto exit; - } - _return_value = os_DirEntry_is_symlink_impl(self, defining_class); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - -PyDoc_STRVAR(os_DirEntry_is_junction__doc__, -"is_junction($self, /)\n" -"--\n" -"\n" -"Return True if the entry is a junction; cached per entry."); - -#define OS_DIRENTRY_IS_JUNCTION_METHODDEF \ - {"is_junction", _PyCFunction_CAST(os_DirEntry_is_junction), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, os_DirEntry_is_junction__doc__}, - -static int -os_DirEntry_is_junction_impl(DirEntry *self, PyTypeObject *defining_class); - -static PyObject * -os_DirEntry_is_junction(DirEntry *self, PyTypeObject *defining_class, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - int _return_value; - - if (nargs) { - PyErr_SetString(PyExc_TypeError, "is_junction() takes no arguments"); - goto exit; - } - _return_value = os_DirEntry_is_junction_impl(self, defining_class); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - -PyDoc_STRVAR(os_DirEntry_stat__doc__, -"stat($self, /, *, follow_symlinks=True)\n" -"--\n" -"\n" -"Return stat_result object for the entry; cached per entry."); - -#define OS_DIRENTRY_STAT_METHODDEF \ - {"stat", _PyCFunction_CAST(os_DirEntry_stat), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, os_DirEntry_stat__doc__}, - -static PyObject * -os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class, - int follow_symlinks); - -static PyObject * -os_DirEntry_stat(DirEntry *self, PyTypeObject *defining_class, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "stat", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - int follow_symlinks = 1; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf); - if (!args) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - follow_symlinks = PyObject_IsTrue(args[0]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - return_value = os_DirEntry_stat_impl(self, defining_class, follow_symlinks); - -exit: - return return_value; -} - -PyDoc_STRVAR(os_DirEntry_is_dir__doc__, -"is_dir($self, /, *, follow_symlinks=True)\n" -"--\n" -"\n" -"Return True if the entry is a directory; cached per entry."); - -#define OS_DIRENTRY_IS_DIR_METHODDEF \ - {"is_dir", _PyCFunction_CAST(os_DirEntry_is_dir), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, os_DirEntry_is_dir__doc__}, - -static int -os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class, - int follow_symlinks); - -static PyObject * -os_DirEntry_is_dir(DirEntry *self, PyTypeObject *defining_class, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "is_dir", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - int follow_symlinks = 1; - int _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf); - if (!args) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - follow_symlinks = PyObject_IsTrue(args[0]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - _return_value = os_DirEntry_is_dir_impl(self, defining_class, follow_symlinks); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - -PyDoc_STRVAR(os_DirEntry_is_file__doc__, -"is_file($self, /, *, follow_symlinks=True)\n" -"--\n" -"\n" -"Return True if the entry is a file; cached per entry."); - -#define OS_DIRENTRY_IS_FILE_METHODDEF \ - {"is_file", _PyCFunction_CAST(os_DirEntry_is_file), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, os_DirEntry_is_file__doc__}, - -static int -os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class, - int follow_symlinks); - -static PyObject * -os_DirEntry_is_file(DirEntry *self, PyTypeObject *defining_class, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(follow_symlinks), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"follow_symlinks", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "is_file", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - int follow_symlinks = 1; - int _return_value; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf); - if (!args) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - follow_symlinks = PyObject_IsTrue(args[0]); - if (follow_symlinks < 0) { - goto exit; - } -skip_optional_kwonly: - _return_value = os_DirEntry_is_file_impl(self, defining_class, follow_symlinks); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - -PyDoc_STRVAR(os_DirEntry_inode__doc__, -"inode($self, /)\n" -"--\n" -"\n" -"Return inode of the entry; cached per entry."); - -#define OS_DIRENTRY_INODE_METHODDEF \ - {"inode", (PyCFunction)os_DirEntry_inode, METH_NOARGS, os_DirEntry_inode__doc__}, - -static PyObject * -os_DirEntry_inode_impl(DirEntry *self); - -static PyObject * -os_DirEntry_inode(DirEntry *self, PyObject *Py_UNUSED(ignored)) -{ - return os_DirEntry_inode_impl(self); -} - -PyDoc_STRVAR(os_DirEntry___fspath____doc__, -"__fspath__($self, /)\n" -"--\n" -"\n" -"Returns the path for the entry."); - -#define OS_DIRENTRY___FSPATH___METHODDEF \ - {"__fspath__", (PyCFunction)os_DirEntry___fspath__, METH_NOARGS, os_DirEntry___fspath____doc__}, - -static PyObject * -os_DirEntry___fspath___impl(DirEntry *self); - -static PyObject * -os_DirEntry___fspath__(DirEntry *self, PyObject *Py_UNUSED(ignored)) -{ - return os_DirEntry___fspath___impl(self); -} - -PyDoc_STRVAR(os_scandir__doc__, -"scandir($module, /, path=None)\n" -"--\n" -"\n" -"Return an iterator of DirEntry objects for given path.\n" -"\n" -"path can be specified as either str, bytes, or a path-like object. If path\n" -"is bytes, the names of yielded DirEntry objects will also be bytes; in\n" -"all other circumstances they will be str.\n" -"\n" -"If path is None, uses the path=\'.\'."); - -#define OS_SCANDIR_METHODDEF \ - {"scandir", _PyCFunction_CAST(os_scandir), METH_FASTCALL|METH_KEYWORDS, os_scandir__doc__}, - -static PyObject * -os_scandir_impl(PyObject *module, path_t *path); - -static PyObject * -os_scandir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "scandir", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - path_t path = PATH_T_INITIALIZE("scandir", "path", 1, PATH_HAVE_FDOPENDIR); - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (!path_converter(args[0], &path)) { - goto exit; - } -skip_optional_pos: - return_value = os_scandir_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -PyDoc_STRVAR(os_fspath__doc__, -"fspath($module, /, path)\n" -"--\n" -"\n" -"Return the file system path representation of the object.\n" -"\n" -"If the object is str or bytes, then allow it to pass through as-is. If the\n" -"object defines __fspath__(), then return the result of that method. All other\n" -"types raise a TypeError."); - -#define OS_FSPATH_METHODDEF \ - {"fspath", _PyCFunction_CAST(os_fspath), METH_FASTCALL|METH_KEYWORDS, os_fspath__doc__}, - -static PyObject * -os_fspath_impl(PyObject *module, PyObject *path); - -static PyObject * -os_fspath(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "fspath", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - PyObject *path; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - path = args[0]; - return_value = os_fspath_impl(module, path); - -exit: - return return_value; -} - -#if defined(HAVE_GETRANDOM_SYSCALL) - -PyDoc_STRVAR(os_getrandom__doc__, -"getrandom($module, /, size, flags=0)\n" -"--\n" -"\n" -"Obtain a series of random bytes."); - -#define OS_GETRANDOM_METHODDEF \ - {"getrandom", _PyCFunction_CAST(os_getrandom), METH_FASTCALL|METH_KEYWORDS, os_getrandom__doc__}, - -static PyObject * -os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags); - -static PyObject * -os_getrandom(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(size), &_Py_ID(flags), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"size", "flags", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "getrandom", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - Py_ssize_t size; - int flags = 0; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); - if (!args) { - goto exit; - } - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[0]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - size = ival; - } - if (!noptargs) { - goto skip_optional_pos; - } - flags = _PyLong_AsInt(args[1]); - if (flags == -1 && PyErr_Occurred()) { - goto exit; - } -skip_optional_pos: - return_value = os_getrandom_impl(module, size, flags); - -exit: - return return_value; -} - -#endif /* defined(HAVE_GETRANDOM_SYSCALL) */ - -#if defined(MS_WINDOWS) - -PyDoc_STRVAR(os__add_dll_directory__doc__, -"_add_dll_directory($module, /, path)\n" -"--\n" -"\n" -"Add a path to the DLL search path.\n" -"\n" -"This search path is used when resolving dependencies for imported\n" -"extension modules (the module itself is resolved through sys.path),\n" -"and also by ctypes.\n" -"\n" -"Returns an opaque value that may be passed to os.remove_dll_directory\n" -"to remove this directory from the search path."); - -#define OS__ADD_DLL_DIRECTORY_METHODDEF \ - {"_add_dll_directory", _PyCFunction_CAST(os__add_dll_directory), METH_FASTCALL|METH_KEYWORDS, os__add_dll_directory__doc__}, - -static PyObject * -os__add_dll_directory_impl(PyObject *module, path_t *path); - -static PyObject * -os__add_dll_directory(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(path), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "_add_dll_directory", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - path_t path = PATH_T_INITIALIZE("_add_dll_directory", "path", 0, 0); - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - if (!path_converter(args[0], &path)) { - goto exit; - } - return_value = os__add_dll_directory_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(MS_WINDOWS) */ - -#if defined(MS_WINDOWS) - -PyDoc_STRVAR(os__remove_dll_directory__doc__, -"_remove_dll_directory($module, /, cookie)\n" -"--\n" -"\n" -"Removes a path from the DLL search path.\n" -"\n" -"The parameter is an opaque value that was returned from\n" -"os.add_dll_directory. You can only remove directories that you added\n" -"yourself."); - -#define OS__REMOVE_DLL_DIRECTORY_METHODDEF \ - {"_remove_dll_directory", _PyCFunction_CAST(os__remove_dll_directory), METH_FASTCALL|METH_KEYWORDS, os__remove_dll_directory__doc__}, - -static PyObject * -os__remove_dll_directory_impl(PyObject *module, PyObject *cookie); - -static PyObject * -os__remove_dll_directory(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(cookie), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"cookie", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "_remove_dll_directory", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - PyObject *cookie; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - cookie = args[0]; - return_value = os__remove_dll_directory_impl(module, cookie); - -exit: - return return_value; -} - -#endif /* defined(MS_WINDOWS) */ - -#if (defined(WIFEXITED) || defined(MS_WINDOWS)) - -PyDoc_STRVAR(os_waitstatus_to_exitcode__doc__, -"waitstatus_to_exitcode($module, /, status)\n" -"--\n" -"\n" -"Convert a wait status to an exit code.\n" -"\n" -"On Unix:\n" -"\n" -"* If WIFEXITED(status) is true, return WEXITSTATUS(status).\n" -"* If WIFSIGNALED(status) is true, return -WTERMSIG(status).\n" -"* Otherwise, raise a ValueError.\n" -"\n" -"On Windows, return status shifted right by 8 bits.\n" -"\n" -"On Unix, if the process is being traced or if waitpid() was called with\n" -"WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.\n" -"This function must not be called if WIFSTOPPED(status) is true."); - -#define OS_WAITSTATUS_TO_EXITCODE_METHODDEF \ - {"waitstatus_to_exitcode", _PyCFunction_CAST(os_waitstatus_to_exitcode), METH_FASTCALL|METH_KEYWORDS, os_waitstatus_to_exitcode__doc__}, - -static PyObject * -os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj); - -static PyObject * -os_waitstatus_to_exitcode(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(status), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"status", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "waitstatus_to_exitcode", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - PyObject *status_obj; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); - if (!args) { - goto exit; - } - status_obj = args[0]; - return_value = os_waitstatus_to_exitcode_impl(module, status_obj); - -exit: - return return_value; -} - -#endif /* (defined(WIFEXITED) || defined(MS_WINDOWS)) */ - -#ifndef OS_TTYNAME_METHODDEF - #define OS_TTYNAME_METHODDEF -#endif /* !defined(OS_TTYNAME_METHODDEF) */ - -#ifndef OS_CTERMID_METHODDEF - #define OS_CTERMID_METHODDEF -#endif /* !defined(OS_CTERMID_METHODDEF) */ - -#ifndef OS_FCHDIR_METHODDEF - #define OS_FCHDIR_METHODDEF -#endif /* !defined(OS_FCHDIR_METHODDEF) */ - -#ifndef OS_FCHMOD_METHODDEF - #define OS_FCHMOD_METHODDEF -#endif /* !defined(OS_FCHMOD_METHODDEF) */ - -#ifndef OS_LCHMOD_METHODDEF - #define OS_LCHMOD_METHODDEF -#endif /* !defined(OS_LCHMOD_METHODDEF) */ - -#ifndef OS_CHFLAGS_METHODDEF - #define OS_CHFLAGS_METHODDEF -#endif /* !defined(OS_CHFLAGS_METHODDEF) */ - -#ifndef OS_LCHFLAGS_METHODDEF - #define OS_LCHFLAGS_METHODDEF -#endif /* !defined(OS_LCHFLAGS_METHODDEF) */ - -#ifndef OS_CHROOT_METHODDEF - #define OS_CHROOT_METHODDEF -#endif /* !defined(OS_CHROOT_METHODDEF) */ - -#ifndef OS_FSYNC_METHODDEF - #define OS_FSYNC_METHODDEF -#endif /* !defined(OS_FSYNC_METHODDEF) */ - -#ifndef OS_SYNC_METHODDEF - #define OS_SYNC_METHODDEF -#endif /* !defined(OS_SYNC_METHODDEF) */ - -#ifndef OS_FDATASYNC_METHODDEF - #define OS_FDATASYNC_METHODDEF -#endif /* !defined(OS_FDATASYNC_METHODDEF) */ - -#ifndef OS_CHOWN_METHODDEF - #define OS_CHOWN_METHODDEF -#endif /* !defined(OS_CHOWN_METHODDEF) */ - -#ifndef OS_FCHOWN_METHODDEF - #define OS_FCHOWN_METHODDEF -#endif /* !defined(OS_FCHOWN_METHODDEF) */ - -#ifndef OS_LCHOWN_METHODDEF - #define OS_LCHOWN_METHODDEF -#endif /* !defined(OS_LCHOWN_METHODDEF) */ - -#ifndef OS_LINK_METHODDEF - #define OS_LINK_METHODDEF -#endif /* !defined(OS_LINK_METHODDEF) */ - -#ifndef OS__GETFULLPATHNAME_METHODDEF - #define OS__GETFULLPATHNAME_METHODDEF -#endif /* !defined(OS__GETFULLPATHNAME_METHODDEF) */ - -#ifndef OS__GETFINALPATHNAME_METHODDEF - #define OS__GETFINALPATHNAME_METHODDEF -#endif /* !defined(OS__GETFINALPATHNAME_METHODDEF) */ - -#ifndef OS__GETVOLUMEPATHNAME_METHODDEF - #define OS__GETVOLUMEPATHNAME_METHODDEF -#endif /* !defined(OS__GETVOLUMEPATHNAME_METHODDEF) */ - -#ifndef OS__PATH_SPLITROOT_METHODDEF - #define OS__PATH_SPLITROOT_METHODDEF -#endif /* !defined(OS__PATH_SPLITROOT_METHODDEF) */ - -#ifndef OS_NICE_METHODDEF - #define OS_NICE_METHODDEF -#endif /* !defined(OS_NICE_METHODDEF) */ - -#ifndef OS_GETPRIORITY_METHODDEF - #define OS_GETPRIORITY_METHODDEF -#endif /* !defined(OS_GETPRIORITY_METHODDEF) */ - -#ifndef OS_SETPRIORITY_METHODDEF - #define OS_SETPRIORITY_METHODDEF -#endif /* !defined(OS_SETPRIORITY_METHODDEF) */ - -#ifndef OS_SYSTEM_METHODDEF - #define OS_SYSTEM_METHODDEF -#endif /* !defined(OS_SYSTEM_METHODDEF) */ - -#ifndef OS_UMASK_METHODDEF - #define OS_UMASK_METHODDEF -#endif /* !defined(OS_UMASK_METHODDEF) */ - -#ifndef OS_UNAME_METHODDEF - #define OS_UNAME_METHODDEF -#endif /* !defined(OS_UNAME_METHODDEF) */ - -#ifndef OS_EXECV_METHODDEF - #define OS_EXECV_METHODDEF -#endif /* !defined(OS_EXECV_METHODDEF) */ - -#ifndef OS_EXECVE_METHODDEF - #define OS_EXECVE_METHODDEF -#endif /* !defined(OS_EXECVE_METHODDEF) */ - -#ifndef OS_POSIX_SPAWN_METHODDEF - #define OS_POSIX_SPAWN_METHODDEF -#endif /* !defined(OS_POSIX_SPAWN_METHODDEF) */ - -#ifndef OS_POSIX_SPAWNP_METHODDEF - #define OS_POSIX_SPAWNP_METHODDEF -#endif /* !defined(OS_POSIX_SPAWNP_METHODDEF) */ - -#ifndef OS_SPAWNV_METHODDEF - #define OS_SPAWNV_METHODDEF -#endif /* !defined(OS_SPAWNV_METHODDEF) */ - -#ifndef OS_SPAWNVE_METHODDEF - #define OS_SPAWNVE_METHODDEF -#endif /* !defined(OS_SPAWNVE_METHODDEF) */ - -#ifndef OS_REGISTER_AT_FORK_METHODDEF - #define OS_REGISTER_AT_FORK_METHODDEF -#endif /* !defined(OS_REGISTER_AT_FORK_METHODDEF) */ - -#ifndef OS_FORK1_METHODDEF - #define OS_FORK1_METHODDEF -#endif /* !defined(OS_FORK1_METHODDEF) */ - -#ifndef OS_FORK_METHODDEF - #define OS_FORK_METHODDEF -#endif /* !defined(OS_FORK_METHODDEF) */ - -#ifndef OS_SCHED_GET_PRIORITY_MAX_METHODDEF - #define OS_SCHED_GET_PRIORITY_MAX_METHODDEF -#endif /* !defined(OS_SCHED_GET_PRIORITY_MAX_METHODDEF) */ - -#ifndef OS_SCHED_GET_PRIORITY_MIN_METHODDEF - #define OS_SCHED_GET_PRIORITY_MIN_METHODDEF -#endif /* !defined(OS_SCHED_GET_PRIORITY_MIN_METHODDEF) */ - -#ifndef OS_SCHED_GETSCHEDULER_METHODDEF - #define OS_SCHED_GETSCHEDULER_METHODDEF -#endif /* !defined(OS_SCHED_GETSCHEDULER_METHODDEF) */ - -#ifndef OS_SCHED_SETSCHEDULER_METHODDEF - #define OS_SCHED_SETSCHEDULER_METHODDEF -#endif /* !defined(OS_SCHED_SETSCHEDULER_METHODDEF) */ - -#ifndef OS_SCHED_GETPARAM_METHODDEF - #define OS_SCHED_GETPARAM_METHODDEF -#endif /* !defined(OS_SCHED_GETPARAM_METHODDEF) */ - -#ifndef OS_SCHED_SETPARAM_METHODDEF - #define OS_SCHED_SETPARAM_METHODDEF -#endif /* !defined(OS_SCHED_SETPARAM_METHODDEF) */ - -#ifndef OS_SCHED_RR_GET_INTERVAL_METHODDEF - #define OS_SCHED_RR_GET_INTERVAL_METHODDEF -#endif /* !defined(OS_SCHED_RR_GET_INTERVAL_METHODDEF) */ - -#ifndef OS_SCHED_YIELD_METHODDEF - #define OS_SCHED_YIELD_METHODDEF -#endif /* !defined(OS_SCHED_YIELD_METHODDEF) */ - -#ifndef OS_SCHED_SETAFFINITY_METHODDEF - #define OS_SCHED_SETAFFINITY_METHODDEF -#endif /* !defined(OS_SCHED_SETAFFINITY_METHODDEF) */ - -#ifndef OS_SCHED_GETAFFINITY_METHODDEF - #define OS_SCHED_GETAFFINITY_METHODDEF -#endif /* !defined(OS_SCHED_GETAFFINITY_METHODDEF) */ - -#ifndef OS_OPENPTY_METHODDEF - #define OS_OPENPTY_METHODDEF -#endif /* !defined(OS_OPENPTY_METHODDEF) */ - -#ifndef OS_LOGIN_TTY_METHODDEF - #define OS_LOGIN_TTY_METHODDEF -#endif /* !defined(OS_LOGIN_TTY_METHODDEF) */ - -#ifndef OS_FORKPTY_METHODDEF - #define OS_FORKPTY_METHODDEF -#endif /* !defined(OS_FORKPTY_METHODDEF) */ - -#ifndef OS_GETEGID_METHODDEF - #define OS_GETEGID_METHODDEF -#endif /* !defined(OS_GETEGID_METHODDEF) */ - -#ifndef OS_GETEUID_METHODDEF - #define OS_GETEUID_METHODDEF -#endif /* !defined(OS_GETEUID_METHODDEF) */ - -#ifndef OS_GETGID_METHODDEF - #define OS_GETGID_METHODDEF -#endif /* !defined(OS_GETGID_METHODDEF) */ - -#ifndef OS_GETPID_METHODDEF - #define OS_GETPID_METHODDEF -#endif /* !defined(OS_GETPID_METHODDEF) */ - -#ifndef OS_GETGROUPLIST_METHODDEF - #define OS_GETGROUPLIST_METHODDEF -#endif /* !defined(OS_GETGROUPLIST_METHODDEF) */ - -#ifndef OS_GETGROUPS_METHODDEF - #define OS_GETGROUPS_METHODDEF -#endif /* !defined(OS_GETGROUPS_METHODDEF) */ - -#ifndef OS_INITGROUPS_METHODDEF - #define OS_INITGROUPS_METHODDEF -#endif /* !defined(OS_INITGROUPS_METHODDEF) */ - -#ifndef OS_GETPGID_METHODDEF - #define OS_GETPGID_METHODDEF -#endif /* !defined(OS_GETPGID_METHODDEF) */ - -#ifndef OS_GETPGRP_METHODDEF - #define OS_GETPGRP_METHODDEF -#endif /* !defined(OS_GETPGRP_METHODDEF) */ - -#ifndef OS_SETPGRP_METHODDEF - #define OS_SETPGRP_METHODDEF -#endif /* !defined(OS_SETPGRP_METHODDEF) */ - -#ifndef OS_GETPPID_METHODDEF - #define OS_GETPPID_METHODDEF -#endif /* !defined(OS_GETPPID_METHODDEF) */ - -#ifndef OS_GETLOGIN_METHODDEF - #define OS_GETLOGIN_METHODDEF -#endif /* !defined(OS_GETLOGIN_METHODDEF) */ - -#ifndef OS_GETUID_METHODDEF - #define OS_GETUID_METHODDEF -#endif /* !defined(OS_GETUID_METHODDEF) */ - -#ifndef OS_KILL_METHODDEF - #define OS_KILL_METHODDEF -#endif /* !defined(OS_KILL_METHODDEF) */ - -#ifndef OS_KILLPG_METHODDEF - #define OS_KILLPG_METHODDEF -#endif /* !defined(OS_KILLPG_METHODDEF) */ - -#ifndef OS_PLOCK_METHODDEF - #define OS_PLOCK_METHODDEF -#endif /* !defined(OS_PLOCK_METHODDEF) */ - -#ifndef OS_SETUID_METHODDEF - #define OS_SETUID_METHODDEF -#endif /* !defined(OS_SETUID_METHODDEF) */ - -#ifndef OS_SETEUID_METHODDEF - #define OS_SETEUID_METHODDEF -#endif /* !defined(OS_SETEUID_METHODDEF) */ - -#ifndef OS_SETEGID_METHODDEF - #define OS_SETEGID_METHODDEF -#endif /* !defined(OS_SETEGID_METHODDEF) */ - -#ifndef OS_SETREUID_METHODDEF - #define OS_SETREUID_METHODDEF -#endif /* !defined(OS_SETREUID_METHODDEF) */ - -#ifndef OS_SETREGID_METHODDEF - #define OS_SETREGID_METHODDEF -#endif /* !defined(OS_SETREGID_METHODDEF) */ - -#ifndef OS_SETGID_METHODDEF - #define OS_SETGID_METHODDEF -#endif /* !defined(OS_SETGID_METHODDEF) */ - -#ifndef OS_SETGROUPS_METHODDEF - #define OS_SETGROUPS_METHODDEF -#endif /* !defined(OS_SETGROUPS_METHODDEF) */ - -#ifndef OS_WAIT3_METHODDEF - #define OS_WAIT3_METHODDEF -#endif /* !defined(OS_WAIT3_METHODDEF) */ - -#ifndef OS_WAIT4_METHODDEF - #define OS_WAIT4_METHODDEF -#endif /* !defined(OS_WAIT4_METHODDEF) */ - -#ifndef OS_WAITID_METHODDEF - #define OS_WAITID_METHODDEF -#endif /* !defined(OS_WAITID_METHODDEF) */ - -#ifndef OS_WAITPID_METHODDEF - #define OS_WAITPID_METHODDEF -#endif /* !defined(OS_WAITPID_METHODDEF) */ - -#ifndef OS_WAIT_METHODDEF - #define OS_WAIT_METHODDEF -#endif /* !defined(OS_WAIT_METHODDEF) */ - -#ifndef OS_PIDFD_OPEN_METHODDEF - #define OS_PIDFD_OPEN_METHODDEF -#endif /* !defined(OS_PIDFD_OPEN_METHODDEF) */ - -#ifndef OS_SETNS_METHODDEF - #define OS_SETNS_METHODDEF -#endif /* !defined(OS_SETNS_METHODDEF) */ - -#ifndef OS_UNSHARE_METHODDEF - #define OS_UNSHARE_METHODDEF -#endif /* !defined(OS_UNSHARE_METHODDEF) */ - -#ifndef OS_READLINK_METHODDEF - #define OS_READLINK_METHODDEF -#endif /* !defined(OS_READLINK_METHODDEF) */ - -#ifndef OS_SYMLINK_METHODDEF - #define OS_SYMLINK_METHODDEF -#endif /* !defined(OS_SYMLINK_METHODDEF) */ - -#ifndef OS_TIMES_METHODDEF - #define OS_TIMES_METHODDEF -#endif /* !defined(OS_TIMES_METHODDEF) */ - -#ifndef OS_GETSID_METHODDEF - #define OS_GETSID_METHODDEF -#endif /* !defined(OS_GETSID_METHODDEF) */ - -#ifndef OS_SETSID_METHODDEF - #define OS_SETSID_METHODDEF -#endif /* !defined(OS_SETSID_METHODDEF) */ - -#ifndef OS_SETPGID_METHODDEF - #define OS_SETPGID_METHODDEF -#endif /* !defined(OS_SETPGID_METHODDEF) */ - -#ifndef OS_TCGETPGRP_METHODDEF - #define OS_TCGETPGRP_METHODDEF -#endif /* !defined(OS_TCGETPGRP_METHODDEF) */ - -#ifndef OS_TCSETPGRP_METHODDEF - #define OS_TCSETPGRP_METHODDEF -#endif /* !defined(OS_TCSETPGRP_METHODDEF) */ - -#ifndef OS_DUP2_METHODDEF - #define OS_DUP2_METHODDEF -#endif /* !defined(OS_DUP2_METHODDEF) */ - -#ifndef OS_LOCKF_METHODDEF - #define OS_LOCKF_METHODDEF -#endif /* !defined(OS_LOCKF_METHODDEF) */ - -#ifndef OS_READV_METHODDEF - #define OS_READV_METHODDEF -#endif /* !defined(OS_READV_METHODDEF) */ - -#ifndef OS_PREAD_METHODDEF - #define OS_PREAD_METHODDEF -#endif /* !defined(OS_PREAD_METHODDEF) */ - -#ifndef OS_PREADV_METHODDEF - #define OS_PREADV_METHODDEF -#endif /* !defined(OS_PREADV_METHODDEF) */ - -#ifndef OS_SENDFILE_METHODDEF - #define OS_SENDFILE_METHODDEF -#endif /* !defined(OS_SENDFILE_METHODDEF) */ - -#ifndef OS__FCOPYFILE_METHODDEF - #define OS__FCOPYFILE_METHODDEF -#endif /* !defined(OS__FCOPYFILE_METHODDEF) */ - -#ifndef OS_PIPE_METHODDEF - #define OS_PIPE_METHODDEF -#endif /* !defined(OS_PIPE_METHODDEF) */ - -#ifndef OS_PIPE2_METHODDEF - #define OS_PIPE2_METHODDEF -#endif /* !defined(OS_PIPE2_METHODDEF) */ - -#ifndef OS_WRITEV_METHODDEF - #define OS_WRITEV_METHODDEF -#endif /* !defined(OS_WRITEV_METHODDEF) */ - -#ifndef OS_PWRITE_METHODDEF - #define OS_PWRITE_METHODDEF -#endif /* !defined(OS_PWRITE_METHODDEF) */ - -#ifndef OS_PWRITEV_METHODDEF - #define OS_PWRITEV_METHODDEF -#endif /* !defined(OS_PWRITEV_METHODDEF) */ - -#ifndef OS_COPY_FILE_RANGE_METHODDEF - #define OS_COPY_FILE_RANGE_METHODDEF -#endif /* !defined(OS_COPY_FILE_RANGE_METHODDEF) */ - -#ifndef OS_SPLICE_METHODDEF - #define OS_SPLICE_METHODDEF -#endif /* !defined(OS_SPLICE_METHODDEF) */ - -#ifndef OS_MKFIFO_METHODDEF - #define OS_MKFIFO_METHODDEF -#endif /* !defined(OS_MKFIFO_METHODDEF) */ - -#ifndef OS_MKNOD_METHODDEF - #define OS_MKNOD_METHODDEF -#endif /* !defined(OS_MKNOD_METHODDEF) */ - -#ifndef OS_MAJOR_METHODDEF - #define OS_MAJOR_METHODDEF -#endif /* !defined(OS_MAJOR_METHODDEF) */ - -#ifndef OS_MINOR_METHODDEF - #define OS_MINOR_METHODDEF -#endif /* !defined(OS_MINOR_METHODDEF) */ - -#ifndef OS_MAKEDEV_METHODDEF - #define OS_MAKEDEV_METHODDEF -#endif /* !defined(OS_MAKEDEV_METHODDEF) */ - -#ifndef OS_FTRUNCATE_METHODDEF - #define OS_FTRUNCATE_METHODDEF -#endif /* !defined(OS_FTRUNCATE_METHODDEF) */ - -#ifndef OS_TRUNCATE_METHODDEF - #define OS_TRUNCATE_METHODDEF -#endif /* !defined(OS_TRUNCATE_METHODDEF) */ - -#ifndef OS_POSIX_FALLOCATE_METHODDEF - #define OS_POSIX_FALLOCATE_METHODDEF -#endif /* !defined(OS_POSIX_FALLOCATE_METHODDEF) */ - -#ifndef OS_POSIX_FADVISE_METHODDEF - #define OS_POSIX_FADVISE_METHODDEF -#endif /* !defined(OS_POSIX_FADVISE_METHODDEF) */ - -#ifndef OS_PUTENV_METHODDEF - #define OS_PUTENV_METHODDEF -#endif /* !defined(OS_PUTENV_METHODDEF) */ - -#ifndef OS_UNSETENV_METHODDEF - #define OS_UNSETENV_METHODDEF -#endif /* !defined(OS_UNSETENV_METHODDEF) */ - -#ifndef OS_WCOREDUMP_METHODDEF - #define OS_WCOREDUMP_METHODDEF -#endif /* !defined(OS_WCOREDUMP_METHODDEF) */ - -#ifndef OS_WIFCONTINUED_METHODDEF - #define OS_WIFCONTINUED_METHODDEF -#endif /* !defined(OS_WIFCONTINUED_METHODDEF) */ - -#ifndef OS_WIFSTOPPED_METHODDEF - #define OS_WIFSTOPPED_METHODDEF -#endif /* !defined(OS_WIFSTOPPED_METHODDEF) */ - -#ifndef OS_WIFSIGNALED_METHODDEF - #define OS_WIFSIGNALED_METHODDEF -#endif /* !defined(OS_WIFSIGNALED_METHODDEF) */ - -#ifndef OS_WIFEXITED_METHODDEF - #define OS_WIFEXITED_METHODDEF -#endif /* !defined(OS_WIFEXITED_METHODDEF) */ - -#ifndef OS_WEXITSTATUS_METHODDEF - #define OS_WEXITSTATUS_METHODDEF -#endif /* !defined(OS_WEXITSTATUS_METHODDEF) */ - -#ifndef OS_WTERMSIG_METHODDEF - #define OS_WTERMSIG_METHODDEF -#endif /* !defined(OS_WTERMSIG_METHODDEF) */ - -#ifndef OS_WSTOPSIG_METHODDEF - #define OS_WSTOPSIG_METHODDEF -#endif /* !defined(OS_WSTOPSIG_METHODDEF) */ - -#ifndef OS_FSTATVFS_METHODDEF - #define OS_FSTATVFS_METHODDEF -#endif /* !defined(OS_FSTATVFS_METHODDEF) */ - -#ifndef OS_STATVFS_METHODDEF - #define OS_STATVFS_METHODDEF -#endif /* !defined(OS_STATVFS_METHODDEF) */ - -#ifndef OS__GETDISKUSAGE_METHODDEF - #define OS__GETDISKUSAGE_METHODDEF -#endif /* !defined(OS__GETDISKUSAGE_METHODDEF) */ - -#ifndef OS_FPATHCONF_METHODDEF - #define OS_FPATHCONF_METHODDEF -#endif /* !defined(OS_FPATHCONF_METHODDEF) */ - -#ifndef OS_PATHCONF_METHODDEF - #define OS_PATHCONF_METHODDEF -#endif /* !defined(OS_PATHCONF_METHODDEF) */ - -#ifndef OS_CONFSTR_METHODDEF - #define OS_CONFSTR_METHODDEF -#endif /* !defined(OS_CONFSTR_METHODDEF) */ - -#ifndef OS_SYSCONF_METHODDEF - #define OS_SYSCONF_METHODDEF -#endif /* !defined(OS_SYSCONF_METHODDEF) */ - -#ifndef OS_STARTFILE_METHODDEF - #define OS_STARTFILE_METHODDEF -#endif /* !defined(OS_STARTFILE_METHODDEF) */ - -#ifndef OS_GETLOADAVG_METHODDEF - #define OS_GETLOADAVG_METHODDEF -#endif /* !defined(OS_GETLOADAVG_METHODDEF) */ - -#ifndef OS_SETRESUID_METHODDEF - #define OS_SETRESUID_METHODDEF -#endif /* !defined(OS_SETRESUID_METHODDEF) */ - -#ifndef OS_SETRESGID_METHODDEF - #define OS_SETRESGID_METHODDEF -#endif /* !defined(OS_SETRESGID_METHODDEF) */ - -#ifndef OS_GETRESUID_METHODDEF - #define OS_GETRESUID_METHODDEF -#endif /* !defined(OS_GETRESUID_METHODDEF) */ - -#ifndef OS_GETRESGID_METHODDEF - #define OS_GETRESGID_METHODDEF -#endif /* !defined(OS_GETRESGID_METHODDEF) */ - -#ifndef OS_GETXATTR_METHODDEF - #define OS_GETXATTR_METHODDEF -#endif /* !defined(OS_GETXATTR_METHODDEF) */ - -#ifndef OS_SETXATTR_METHODDEF - #define OS_SETXATTR_METHODDEF -#endif /* !defined(OS_SETXATTR_METHODDEF) */ - -#ifndef OS_REMOVEXATTR_METHODDEF - #define OS_REMOVEXATTR_METHODDEF -#endif /* !defined(OS_REMOVEXATTR_METHODDEF) */ - -#ifndef OS_LISTXATTR_METHODDEF - #define OS_LISTXATTR_METHODDEF -#endif /* !defined(OS_LISTXATTR_METHODDEF) */ - -#ifndef OS_MEMFD_CREATE_METHODDEF - #define OS_MEMFD_CREATE_METHODDEF -#endif /* !defined(OS_MEMFD_CREATE_METHODDEF) */ - -#ifndef OS_EVENTFD_METHODDEF - #define OS_EVENTFD_METHODDEF -#endif /* !defined(OS_EVENTFD_METHODDEF) */ - -#ifndef OS_EVENTFD_READ_METHODDEF - #define OS_EVENTFD_READ_METHODDEF -#endif /* !defined(OS_EVENTFD_READ_METHODDEF) */ - -#ifndef OS_EVENTFD_WRITE_METHODDEF - #define OS_EVENTFD_WRITE_METHODDEF -#endif /* !defined(OS_EVENTFD_WRITE_METHODDEF) */ - -#ifndef OS_GET_TERMINAL_SIZE_METHODDEF - #define OS_GET_TERMINAL_SIZE_METHODDEF -#endif /* !defined(OS_GET_TERMINAL_SIZE_METHODDEF) */ - -#ifndef OS_GET_HANDLE_INHERITABLE_METHODDEF - #define OS_GET_HANDLE_INHERITABLE_METHODDEF -#endif /* !defined(OS_GET_HANDLE_INHERITABLE_METHODDEF) */ - -#ifndef OS_SET_HANDLE_INHERITABLE_METHODDEF - #define OS_SET_HANDLE_INHERITABLE_METHODDEF -#endif /* !defined(OS_SET_HANDLE_INHERITABLE_METHODDEF) */ - -#ifndef OS_GET_BLOCKING_METHODDEF - #define OS_GET_BLOCKING_METHODDEF -#endif /* !defined(OS_GET_BLOCKING_METHODDEF) */ - -#ifndef OS_SET_BLOCKING_METHODDEF - #define OS_SET_BLOCKING_METHODDEF -#endif /* !defined(OS_SET_BLOCKING_METHODDEF) */ - -#ifndef OS_GETRANDOM_METHODDEF - #define OS_GETRANDOM_METHODDEF -#endif /* !defined(OS_GETRANDOM_METHODDEF) */ - -#ifndef OS__ADD_DLL_DIRECTORY_METHODDEF - #define OS__ADD_DLL_DIRECTORY_METHODDEF -#endif /* !defined(OS__ADD_DLL_DIRECTORY_METHODDEF) */ - -#ifndef OS__REMOVE_DLL_DIRECTORY_METHODDEF - #define OS__REMOVE_DLL_DIRECTORY_METHODDEF -#endif /* !defined(OS__REMOVE_DLL_DIRECTORY_METHODDEF) */ - -#ifndef OS_WAITSTATUS_TO_EXITCODE_METHODDEF - #define OS_WAITSTATUS_TO_EXITCODE_METHODDEF -#endif /* !defined(OS_WAITSTATUS_TO_EXITCODE_METHODDEF) */ -/*[clinic end generated code: output=4192d8e09e216300 input=a9049054013a1b77]*/ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() +#endif + + +PyDoc_STRVAR(os_stat__doc__, +"stat($module, /, path, *, dir_fd=None, follow_symlinks=True)\n" +"--\n" +"\n" +"Perform a stat system call on the given path.\n" +"\n" +" path\n" +" Path to be examined; can be string, bytes, a path-like object or\n" +" open-file-descriptor int.\n" +" dir_fd\n" +" If not None, it should be a file descriptor open to a directory,\n" +" and path should be a relative string; path will then be relative to\n" +" that directory.\n" +" follow_symlinks\n" +" If False, and the last element of the path is a symbolic link,\n" +" stat will examine the symbolic link itself instead of the file\n" +" the link points to.\n" +"\n" +"dir_fd and follow_symlinks may not be implemented\n" +" on your platform. If they are unavailable, using them will raise a\n" +" NotImplementedError.\n" +"\n" +"It\'s an error to use dir_fd or follow_symlinks when specifying path as\n" +" an open file descriptor."); + +#define OS_STAT_METHODDEF \ + {"stat", _PyCFunction_CAST(os_stat), METH_FASTCALL|METH_KEYWORDS, os_stat__doc__}, + +static PyObject * +os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks); + +static PyObject * +os_stat(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(dir_fd), &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "dir_fd", "follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "stat", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + path_t path = PATH_T_INITIALIZE("stat", "path", 0, 1); + int dir_fd = DEFAULT_DIR_FD; + int follow_symlinks = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[1]) { + if (!FSTATAT_DIR_FD_CONVERTER(args[1], &dir_fd)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + follow_symlinks = PyObject_IsTrue(args[2]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = os_stat_impl(module, &path, dir_fd, follow_symlinks); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +PyDoc_STRVAR(os_lstat__doc__, +"lstat($module, /, path, *, dir_fd=None)\n" +"--\n" +"\n" +"Perform a stat system call on the given path, without following symbolic links.\n" +"\n" +"Like stat(), but do not follow symbolic links.\n" +"Equivalent to stat(path, follow_symlinks=False)."); + +#define OS_LSTAT_METHODDEF \ + {"lstat", _PyCFunction_CAST(os_lstat), METH_FASTCALL|METH_KEYWORDS, os_lstat__doc__}, + +static PyObject * +os_lstat_impl(PyObject *module, path_t *path, int dir_fd); + +static PyObject * +os_lstat(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(dir_fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "dir_fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "lstat", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + path_t path = PATH_T_INITIALIZE("lstat", "path", 0, 0); + int dir_fd = DEFAULT_DIR_FD; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (!FSTATAT_DIR_FD_CONVERTER(args[1], &dir_fd)) { + goto exit; + } +skip_optional_kwonly: + return_value = os_lstat_impl(module, &path, dir_fd); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +PyDoc_STRVAR(os_access__doc__, +"access($module, /, path, mode, *, dir_fd=None, effective_ids=False,\n" +" follow_symlinks=True)\n" +"--\n" +"\n" +"Use the real uid/gid to test for access to a path.\n" +"\n" +" path\n" +" Path to be tested; can be string, bytes, or a path-like object.\n" +" mode\n" +" Operating-system mode bitfield. Can be F_OK to test existence,\n" +" or the inclusive-OR of R_OK, W_OK, and X_OK.\n" +" dir_fd\n" +" If not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that\n" +" directory.\n" +" effective_ids\n" +" If True, access will use the effective uid/gid instead of\n" +" the real uid/gid.\n" +" follow_symlinks\n" +" If False, and the last element of the path is a symbolic link,\n" +" access will examine the symbolic link itself instead of the file\n" +" the link points to.\n" +"\n" +"dir_fd, effective_ids, and follow_symlinks may not be implemented\n" +" on your platform. If they are unavailable, using them will raise a\n" +" NotImplementedError.\n" +"\n" +"Note that most operations will use the effective uid/gid, therefore this\n" +" routine can be used in a suid/sgid environment to test if the invoking user\n" +" has the specified access to the path."); + +#define OS_ACCESS_METHODDEF \ + {"access", _PyCFunction_CAST(os_access), METH_FASTCALL|METH_KEYWORDS, os_access__doc__}, + +static int +os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd, + int effective_ids, int follow_symlinks); + +static PyObject * +os_access(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 5 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(mode), &_Py_ID(dir_fd), &_Py_ID(effective_ids), &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "mode", "dir_fd", "effective_ids", "follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "access", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + path_t path = PATH_T_INITIALIZE("access", "path", 0, 0); + int mode; + int dir_fd = DEFAULT_DIR_FD; + int effective_ids = 0; + int follow_symlinks = 1; + int _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + mode = _PyLong_AsInt(args[1]); + if (mode == -1 && PyErr_Occurred()) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[2]) { + if (!FACCESSAT_DIR_FD_CONVERTER(args[2], &dir_fd)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[3]) { + effective_ids = PyObject_IsTrue(args[3]); + if (effective_ids < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + follow_symlinks = PyObject_IsTrue(args[4]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + _return_value = os_access_impl(module, &path, mode, dir_fd, effective_ids, follow_symlinks); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#if defined(HAVE_TTYNAME) + +PyDoc_STRVAR(os_ttyname__doc__, +"ttyname($module, fd, /)\n" +"--\n" +"\n" +"Return the name of the terminal device connected to \'fd\'.\n" +"\n" +" fd\n" +" Integer file descriptor handle."); + +#define OS_TTYNAME_METHODDEF \ + {"ttyname", (PyCFunction)os_ttyname, METH_O, os_ttyname__doc__}, + +static PyObject * +os_ttyname_impl(PyObject *module, int fd); + +static PyObject * +os_ttyname(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int fd; + + fd = _PyLong_AsInt(arg); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_ttyname_impl(module, fd); + +exit: + return return_value; +} + +#endif /* defined(HAVE_TTYNAME) */ + +#if defined(HAVE_CTERMID) + +PyDoc_STRVAR(os_ctermid__doc__, +"ctermid($module, /)\n" +"--\n" +"\n" +"Return the name of the controlling terminal for this process."); + +#define OS_CTERMID_METHODDEF \ + {"ctermid", (PyCFunction)os_ctermid, METH_NOARGS, os_ctermid__doc__}, + +static PyObject * +os_ctermid_impl(PyObject *module); + +static PyObject * +os_ctermid(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_ctermid_impl(module); +} + +#endif /* defined(HAVE_CTERMID) */ + +PyDoc_STRVAR(os_chdir__doc__, +"chdir($module, /, path)\n" +"--\n" +"\n" +"Change the current working directory to the specified path.\n" +"\n" +"path may always be specified as a string.\n" +"On some platforms, path may also be specified as an open file descriptor.\n" +" If this functionality is unavailable, using it raises an exception."); + +#define OS_CHDIR_METHODDEF \ + {"chdir", _PyCFunction_CAST(os_chdir), METH_FASTCALL|METH_KEYWORDS, os_chdir__doc__}, + +static PyObject * +os_chdir_impl(PyObject *module, path_t *path); + +static PyObject * +os_chdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "chdir", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + path_t path = PATH_T_INITIALIZE("chdir", "path", 0, PATH_HAVE_FCHDIR); + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + return_value = os_chdir_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#if defined(HAVE_FCHDIR) + +PyDoc_STRVAR(os_fchdir__doc__, +"fchdir($module, /, fd)\n" +"--\n" +"\n" +"Change to the directory of the given file descriptor.\n" +"\n" +"fd must be opened on a directory, not a file.\n" +"Equivalent to os.chdir(fd)."); + +#define OS_FCHDIR_METHODDEF \ + {"fchdir", _PyCFunction_CAST(os_fchdir), METH_FASTCALL|METH_KEYWORDS, os_fchdir__doc__}, + +static PyObject * +os_fchdir_impl(PyObject *module, int fd); + +static PyObject * +os_fchdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "fchdir", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int fd; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + return_value = os_fchdir_impl(module, fd); + +exit: + return return_value; +} + +#endif /* defined(HAVE_FCHDIR) */ + +PyDoc_STRVAR(os_chmod__doc__, +"chmod($module, /, path, mode, *, dir_fd=None, follow_symlinks=True)\n" +"--\n" +"\n" +"Change the access permissions of a file.\n" +"\n" +" path\n" +" Path to be modified. May always be specified as a str, bytes, or a path-like object.\n" +" On some platforms, path may also be specified as an open file descriptor.\n" +" If this functionality is unavailable, using it raises an exception.\n" +" mode\n" +" Operating-system mode bitfield.\n" +" dir_fd\n" +" If not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that\n" +" directory.\n" +" follow_symlinks\n" +" If False, and the last element of the path is a symbolic link,\n" +" chmod will modify the symbolic link itself instead of the file\n" +" the link points to.\n" +"\n" +"It is an error to use dir_fd or follow_symlinks when specifying path as\n" +" an open file descriptor.\n" +"dir_fd and follow_symlinks may not be implemented on your platform.\n" +" If they are unavailable, using them will raise a NotImplementedError."); + +#define OS_CHMOD_METHODDEF \ + {"chmod", _PyCFunction_CAST(os_chmod), METH_FASTCALL|METH_KEYWORDS, os_chmod__doc__}, + +static PyObject * +os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, + int follow_symlinks); + +static PyObject * +os_chmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(mode), &_Py_ID(dir_fd), &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "mode", "dir_fd", "follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "chmod", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + path_t path = PATH_T_INITIALIZE("chmod", "path", 0, PATH_HAVE_FCHMOD); + int mode; + int dir_fd = DEFAULT_DIR_FD; + int follow_symlinks = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + mode = _PyLong_AsInt(args[1]); + if (mode == -1 && PyErr_Occurred()) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[2]) { + if (!FCHMODAT_DIR_FD_CONVERTER(args[2], &dir_fd)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + follow_symlinks = PyObject_IsTrue(args[3]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = os_chmod_impl(module, &path, mode, dir_fd, follow_symlinks); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#if defined(HAVE_FCHMOD) + +PyDoc_STRVAR(os_fchmod__doc__, +"fchmod($module, /, fd, mode)\n" +"--\n" +"\n" +"Change the access permissions of the file given by file descriptor fd.\n" +"\n" +"Equivalent to os.chmod(fd, mode)."); + +#define OS_FCHMOD_METHODDEF \ + {"fchmod", _PyCFunction_CAST(os_fchmod), METH_FASTCALL|METH_KEYWORDS, os_fchmod__doc__}, + +static PyObject * +os_fchmod_impl(PyObject *module, int fd, int mode); + +static PyObject * +os_fchmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(fd), &_Py_ID(mode), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"fd", "mode", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "fchmod", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + int fd; + int mode; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + mode = _PyLong_AsInt(args[1]); + if (mode == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_fchmod_impl(module, fd, mode); + +exit: + return return_value; +} + +#endif /* defined(HAVE_FCHMOD) */ + +#if defined(HAVE_LCHMOD) + +PyDoc_STRVAR(os_lchmod__doc__, +"lchmod($module, /, path, mode)\n" +"--\n" +"\n" +"Change the access permissions of a file, without following symbolic links.\n" +"\n" +"If path is a symlink, this affects the link itself rather than the target.\n" +"Equivalent to chmod(path, mode, follow_symlinks=False).\""); + +#define OS_LCHMOD_METHODDEF \ + {"lchmod", _PyCFunction_CAST(os_lchmod), METH_FASTCALL|METH_KEYWORDS, os_lchmod__doc__}, + +static PyObject * +os_lchmod_impl(PyObject *module, path_t *path, int mode); + +static PyObject * +os_lchmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(mode), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "mode", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "lchmod", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + path_t path = PATH_T_INITIALIZE("lchmod", "path", 0, 0); + int mode; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + mode = _PyLong_AsInt(args[1]); + if (mode == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_lchmod_impl(module, &path, mode); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(HAVE_LCHMOD) */ + +#if defined(HAVE_CHFLAGS) + +PyDoc_STRVAR(os_chflags__doc__, +"chflags($module, /, path, flags, follow_symlinks=True)\n" +"--\n" +"\n" +"Set file flags.\n" +"\n" +"If follow_symlinks is False, and the last element of the path is a symbolic\n" +" link, chflags will change flags on the symbolic link itself instead of the\n" +" file the link points to.\n" +"follow_symlinks may not be implemented on your platform. If it is\n" +"unavailable, using it will raise a NotImplementedError."); + +#define OS_CHFLAGS_METHODDEF \ + {"chflags", _PyCFunction_CAST(os_chflags), METH_FASTCALL|METH_KEYWORDS, os_chflags__doc__}, + +static PyObject * +os_chflags_impl(PyObject *module, path_t *path, unsigned long flags, + int follow_symlinks); + +static PyObject * +os_chflags(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(flags), &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "flags", "follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "chflags", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + path_t path = PATH_T_INITIALIZE("chflags", "path", 0, 0); + unsigned long flags; + int follow_symlinks = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!PyLong_Check(args[1])) { + _PyArg_BadArgument("chflags", "argument 'flags'", "int", args[1]); + goto exit; + } + flags = PyLong_AsUnsignedLongMask(args[1]); + if (!noptargs) { + goto skip_optional_pos; + } + follow_symlinks = PyObject_IsTrue(args[2]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_pos: + return_value = os_chflags_impl(module, &path, flags, follow_symlinks); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(HAVE_CHFLAGS) */ + +#if defined(HAVE_LCHFLAGS) + +PyDoc_STRVAR(os_lchflags__doc__, +"lchflags($module, /, path, flags)\n" +"--\n" +"\n" +"Set file flags.\n" +"\n" +"This function will not follow symbolic links.\n" +"Equivalent to chflags(path, flags, follow_symlinks=False)."); + +#define OS_LCHFLAGS_METHODDEF \ + {"lchflags", _PyCFunction_CAST(os_lchflags), METH_FASTCALL|METH_KEYWORDS, os_lchflags__doc__}, + +static PyObject * +os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags); + +static PyObject * +os_lchflags(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(flags), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "flags", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "lchflags", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + path_t path = PATH_T_INITIALIZE("lchflags", "path", 0, 0); + unsigned long flags; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!PyLong_Check(args[1])) { + _PyArg_BadArgument("lchflags", "argument 'flags'", "int", args[1]); + goto exit; + } + flags = PyLong_AsUnsignedLongMask(args[1]); + return_value = os_lchflags_impl(module, &path, flags); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(HAVE_LCHFLAGS) */ + +#if defined(HAVE_CHROOT) + +PyDoc_STRVAR(os_chroot__doc__, +"chroot($module, /, path)\n" +"--\n" +"\n" +"Change root directory to path."); + +#define OS_CHROOT_METHODDEF \ + {"chroot", _PyCFunction_CAST(os_chroot), METH_FASTCALL|METH_KEYWORDS, os_chroot__doc__}, + +static PyObject * +os_chroot_impl(PyObject *module, path_t *path); + +static PyObject * +os_chroot(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "chroot", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + path_t path = PATH_T_INITIALIZE("chroot", "path", 0, 0); + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + return_value = os_chroot_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(HAVE_CHROOT) */ + +#if defined(HAVE_FSYNC) + +PyDoc_STRVAR(os_fsync__doc__, +"fsync($module, /, fd)\n" +"--\n" +"\n" +"Force write of fd to disk."); + +#define OS_FSYNC_METHODDEF \ + {"fsync", _PyCFunction_CAST(os_fsync), METH_FASTCALL|METH_KEYWORDS, os_fsync__doc__}, + +static PyObject * +os_fsync_impl(PyObject *module, int fd); + +static PyObject * +os_fsync(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "fsync", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int fd; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + return_value = os_fsync_impl(module, fd); + +exit: + return return_value; +} + +#endif /* defined(HAVE_FSYNC) */ + +#if defined(HAVE_SYNC) + +PyDoc_STRVAR(os_sync__doc__, +"sync($module, /)\n" +"--\n" +"\n" +"Force write of everything to disk."); + +#define OS_SYNC_METHODDEF \ + {"sync", (PyCFunction)os_sync, METH_NOARGS, os_sync__doc__}, + +static PyObject * +os_sync_impl(PyObject *module); + +static PyObject * +os_sync(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_sync_impl(module); +} + +#endif /* defined(HAVE_SYNC) */ + +#if defined(HAVE_FDATASYNC) + +PyDoc_STRVAR(os_fdatasync__doc__, +"fdatasync($module, /, fd)\n" +"--\n" +"\n" +"Force write of fd to disk without forcing update of metadata."); + +#define OS_FDATASYNC_METHODDEF \ + {"fdatasync", _PyCFunction_CAST(os_fdatasync), METH_FASTCALL|METH_KEYWORDS, os_fdatasync__doc__}, + +static PyObject * +os_fdatasync_impl(PyObject *module, int fd); + +static PyObject * +os_fdatasync(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "fdatasync", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int fd; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + return_value = os_fdatasync_impl(module, fd); + +exit: + return return_value; +} + +#endif /* defined(HAVE_FDATASYNC) */ + +#if defined(HAVE_CHOWN) + +PyDoc_STRVAR(os_chown__doc__, +"chown($module, /, path, uid, gid, *, dir_fd=None, follow_symlinks=True)\n" +"--\n" +"\n" +"Change the owner and group id of path to the numeric uid and gid.\\\n" +"\n" +" path\n" +" Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.\n" +" dir_fd\n" +" If not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that\n" +" directory.\n" +" follow_symlinks\n" +" If False, and the last element of the path is a symbolic link,\n" +" stat will examine the symbolic link itself instead of the file\n" +" the link points to.\n" +"\n" +"path may always be specified as a string.\n" +"On some platforms, path may also be specified as an open file descriptor.\n" +" If this functionality is unavailable, using it raises an exception.\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that directory.\n" +"If follow_symlinks is False, and the last element of the path is a symbolic\n" +" link, chown will modify the symbolic link itself instead of the file the\n" +" link points to.\n" +"It is an error to use dir_fd or follow_symlinks when specifying path as\n" +" an open file descriptor.\n" +"dir_fd and follow_symlinks may not be implemented on your platform.\n" +" If they are unavailable, using them will raise a NotImplementedError."); + +#define OS_CHOWN_METHODDEF \ + {"chown", _PyCFunction_CAST(os_chown), METH_FASTCALL|METH_KEYWORDS, os_chown__doc__}, + +static PyObject * +os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid, + int dir_fd, int follow_symlinks); + +static PyObject * +os_chown(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 5 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(uid), &_Py_ID(gid), &_Py_ID(dir_fd), &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "uid", "gid", "dir_fd", "follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "chown", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; + path_t path = PATH_T_INITIALIZE("chown", "path", 0, PATH_HAVE_FCHOWN); + uid_t uid; + gid_t gid; + int dir_fd = DEFAULT_DIR_FD; + int follow_symlinks = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!_Py_Uid_Converter(args[1], &uid)) { + goto exit; + } + if (!_Py_Gid_Converter(args[2], &gid)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[3]) { + if (!FCHOWNAT_DIR_FD_CONVERTER(args[3], &dir_fd)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + follow_symlinks = PyObject_IsTrue(args[4]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = os_chown_impl(module, &path, uid, gid, dir_fd, follow_symlinks); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(HAVE_CHOWN) */ + +#if defined(HAVE_FCHOWN) + +PyDoc_STRVAR(os_fchown__doc__, +"fchown($module, /, fd, uid, gid)\n" +"--\n" +"\n" +"Change the owner and group id of the file specified by file descriptor.\n" +"\n" +"Equivalent to os.chown(fd, uid, gid)."); + +#define OS_FCHOWN_METHODDEF \ + {"fchown", _PyCFunction_CAST(os_fchown), METH_FASTCALL|METH_KEYWORDS, os_fchown__doc__}, + +static PyObject * +os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid); + +static PyObject * +os_fchown(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(fd), &_Py_ID(uid), &_Py_ID(gid), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"fd", "uid", "gid", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "fchown", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + int fd; + uid_t uid; + gid_t gid; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); + if (!args) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + if (!_Py_Uid_Converter(args[1], &uid)) { + goto exit; + } + if (!_Py_Gid_Converter(args[2], &gid)) { + goto exit; + } + return_value = os_fchown_impl(module, fd, uid, gid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_FCHOWN) */ + +#if defined(HAVE_LCHOWN) + +PyDoc_STRVAR(os_lchown__doc__, +"lchown($module, /, path, uid, gid)\n" +"--\n" +"\n" +"Change the owner and group id of path to the numeric uid and gid.\n" +"\n" +"This function will not follow symbolic links.\n" +"Equivalent to os.chown(path, uid, gid, follow_symlinks=False)."); + +#define OS_LCHOWN_METHODDEF \ + {"lchown", _PyCFunction_CAST(os_lchown), METH_FASTCALL|METH_KEYWORDS, os_lchown__doc__}, + +static PyObject * +os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid); + +static PyObject * +os_lchown(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(uid), &_Py_ID(gid), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "uid", "gid", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "lchown", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + path_t path = PATH_T_INITIALIZE("lchown", "path", 0, 0); + uid_t uid; + gid_t gid; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!_Py_Uid_Converter(args[1], &uid)) { + goto exit; + } + if (!_Py_Gid_Converter(args[2], &gid)) { + goto exit; + } + return_value = os_lchown_impl(module, &path, uid, gid); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(HAVE_LCHOWN) */ + +PyDoc_STRVAR(os_getcwd__doc__, +"getcwd($module, /)\n" +"--\n" +"\n" +"Return a unicode string representing the current working directory."); + +#define OS_GETCWD_METHODDEF \ + {"getcwd", (PyCFunction)os_getcwd, METH_NOARGS, os_getcwd__doc__}, + +static PyObject * +os_getcwd_impl(PyObject *module); + +static PyObject * +os_getcwd(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getcwd_impl(module); +} + +PyDoc_STRVAR(os_getcwdb__doc__, +"getcwdb($module, /)\n" +"--\n" +"\n" +"Return a bytes string representing the current working directory."); + +#define OS_GETCWDB_METHODDEF \ + {"getcwdb", (PyCFunction)os_getcwdb, METH_NOARGS, os_getcwdb__doc__}, + +static PyObject * +os_getcwdb_impl(PyObject *module); + +static PyObject * +os_getcwdb(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getcwdb_impl(module); +} + +#if defined(HAVE_LINK) + +PyDoc_STRVAR(os_link__doc__, +"link($module, /, src, dst, *, src_dir_fd=None, dst_dir_fd=None,\n" +" follow_symlinks=True)\n" +"--\n" +"\n" +"Create a hard link to a file.\n" +"\n" +"If either src_dir_fd or dst_dir_fd is not None, it should be a file\n" +" descriptor open to a directory, and the respective path string (src or dst)\n" +" should be relative; the path will then be relative to that directory.\n" +"If follow_symlinks is False, and the last element of src is a symbolic\n" +" link, link will create a link to the symbolic link itself instead of the\n" +" file the link points to.\n" +"src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your\n" +" platform. If they are unavailable, using them will raise a\n" +" NotImplementedError."); + +#define OS_LINK_METHODDEF \ + {"link", _PyCFunction_CAST(os_link), METH_FASTCALL|METH_KEYWORDS, os_link__doc__}, + +static PyObject * +os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, + int dst_dir_fd, int follow_symlinks); + +static PyObject * +os_link(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 5 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(src), &_Py_ID(dst), &_Py_ID(src_dir_fd), &_Py_ID(dst_dir_fd), &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", "follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "link", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + path_t src = PATH_T_INITIALIZE("link", "src", 0, 0); + path_t dst = PATH_T_INITIALIZE("link", "dst", 0, 0); + int src_dir_fd = DEFAULT_DIR_FD; + int dst_dir_fd = DEFAULT_DIR_FD; + int follow_symlinks = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &src)) { + goto exit; + } + if (!path_converter(args[1], &dst)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[2]) { + if (!dir_fd_converter(args[2], &src_dir_fd)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[3]) { + if (!dir_fd_converter(args[3], &dst_dir_fd)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + follow_symlinks = PyObject_IsTrue(args[4]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = os_link_impl(module, &src, &dst, src_dir_fd, dst_dir_fd, follow_symlinks); + +exit: + /* Cleanup for src */ + path_cleanup(&src); + /* Cleanup for dst */ + path_cleanup(&dst); + + return return_value; +} + +#endif /* defined(HAVE_LINK) */ + +PyDoc_STRVAR(os_listdir__doc__, +"listdir($module, /, path=None)\n" +"--\n" +"\n" +"Return a list containing the names of the files in the directory.\n" +"\n" +"path can be specified as either str, bytes, or a path-like object. If path is bytes,\n" +" the filenames returned will also be bytes; in all other circumstances\n" +" the filenames returned will be str.\n" +"If path is None, uses the path=\'.\'.\n" +"On some platforms, path may also be specified as an open file descriptor;\\\n" +" the file descriptor must refer to a directory.\n" +" If this functionality is unavailable, using it raises NotImplementedError.\n" +"\n" +"The list is in arbitrary order. It does not include the special\n" +"entries \'.\' and \'..\' even if they are present in the directory."); + +#define OS_LISTDIR_METHODDEF \ + {"listdir", _PyCFunction_CAST(os_listdir), METH_FASTCALL|METH_KEYWORDS, os_listdir__doc__}, + +static PyObject * +os_listdir_impl(PyObject *module, path_t *path); + +static PyObject * +os_listdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "listdir", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + path_t path = PATH_T_INITIALIZE("listdir", "path", 1, PATH_HAVE_FDOPENDIR); + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (!path_converter(args[0], &path)) { + goto exit; + } +skip_optional_pos: + return_value = os_listdir_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(os__getfullpathname__doc__, +"_getfullpathname($module, path, /)\n" +"--\n" +"\n"); + +#define OS__GETFULLPATHNAME_METHODDEF \ + {"_getfullpathname", (PyCFunction)os__getfullpathname, METH_O, os__getfullpathname__doc__}, + +static PyObject * +os__getfullpathname_impl(PyObject *module, path_t *path); + +static PyObject * +os__getfullpathname(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + path_t path = PATH_T_INITIALIZE("_getfullpathname", "path", 0, 0); + + if (!path_converter(arg, &path)) { + goto exit; + } + return_value = os__getfullpathname_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(os__getfinalpathname__doc__, +"_getfinalpathname($module, path, /)\n" +"--\n" +"\n" +"A helper function for samepath on windows."); + +#define OS__GETFINALPATHNAME_METHODDEF \ + {"_getfinalpathname", (PyCFunction)os__getfinalpathname, METH_O, os__getfinalpathname__doc__}, + +static PyObject * +os__getfinalpathname_impl(PyObject *module, path_t *path); + +static PyObject * +os__getfinalpathname(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + path_t path = PATH_T_INITIALIZE("_getfinalpathname", "path", 0, 0); + + if (!path_converter(arg, &path)) { + goto exit; + } + return_value = os__getfinalpathname_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(os__getvolumepathname__doc__, +"_getvolumepathname($module, /, path)\n" +"--\n" +"\n" +"A helper function for ismount on Win32."); + +#define OS__GETVOLUMEPATHNAME_METHODDEF \ + {"_getvolumepathname", _PyCFunction_CAST(os__getvolumepathname), METH_FASTCALL|METH_KEYWORDS, os__getvolumepathname__doc__}, + +static PyObject * +os__getvolumepathname_impl(PyObject *module, path_t *path); + +static PyObject * +os__getvolumepathname(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "_getvolumepathname", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + path_t path = PATH_T_INITIALIZE("_getvolumepathname", "path", 0, 0); + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + return_value = os__getvolumepathname_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(os__path_splitroot__doc__, +"_path_splitroot($module, /, path)\n" +"--\n" +"\n" +"Removes everything after the root on Win32."); + +#define OS__PATH_SPLITROOT_METHODDEF \ + {"_path_splitroot", _PyCFunction_CAST(os__path_splitroot), METH_FASTCALL|METH_KEYWORDS, os__path_splitroot__doc__}, + +static PyObject * +os__path_splitroot_impl(PyObject *module, path_t *path); + +static PyObject * +os__path_splitroot(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "_path_splitroot", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + path_t path = PATH_T_INITIALIZE("_path_splitroot", "path", 0, 0); + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + return_value = os__path_splitroot_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +PyDoc_STRVAR(os__path_normpath__doc__, +"_path_normpath($module, /, path)\n" +"--\n" +"\n" +"Basic path normalization."); + +#define OS__PATH_NORMPATH_METHODDEF \ + {"_path_normpath", _PyCFunction_CAST(os__path_normpath), METH_FASTCALL|METH_KEYWORDS, os__path_normpath__doc__}, + +static PyObject * +os__path_normpath_impl(PyObject *module, PyObject *path); + +static PyObject * +os__path_normpath(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "_path_normpath", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *path; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + path = args[0]; + return_value = os__path_normpath_impl(module, path); + +exit: + return return_value; +} + +PyDoc_STRVAR(os_mkdir__doc__, +"mkdir($module, /, path, mode=511, *, dir_fd=None)\n" +"--\n" +"\n" +"Create a directory.\n" +"\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that directory.\n" +"dir_fd may not be implemented on your platform.\n" +" If it is unavailable, using it will raise a NotImplementedError.\n" +"\n" +"The mode argument is ignored on Windows. Where it is used, the current umask\n" +"value is first masked out."); + +#define OS_MKDIR_METHODDEF \ + {"mkdir", _PyCFunction_CAST(os_mkdir), METH_FASTCALL|METH_KEYWORDS, os_mkdir__doc__}, + +static PyObject * +os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd); + +static PyObject * +os_mkdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(mode), &_Py_ID(dir_fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "mode", "dir_fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "mkdir", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + path_t path = PATH_T_INITIALIZE("mkdir", "path", 0, 0); + int mode = 511; + int dir_fd = DEFAULT_DIR_FD; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[1]) { + mode = _PyLong_AsInt(args[1]); + if (mode == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + if (!MKDIRAT_DIR_FD_CONVERTER(args[2], &dir_fd)) { + goto exit; + } +skip_optional_kwonly: + return_value = os_mkdir_impl(module, &path, mode, dir_fd); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#if defined(HAVE_NICE) + +PyDoc_STRVAR(os_nice__doc__, +"nice($module, increment, /)\n" +"--\n" +"\n" +"Add increment to the priority of process and return the new priority."); + +#define OS_NICE_METHODDEF \ + {"nice", (PyCFunction)os_nice, METH_O, os_nice__doc__}, + +static PyObject * +os_nice_impl(PyObject *module, int increment); + +static PyObject * +os_nice(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int increment; + + increment = _PyLong_AsInt(arg); + if (increment == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_nice_impl(module, increment); + +exit: + return return_value; +} + +#endif /* defined(HAVE_NICE) */ + +#if defined(HAVE_GETPRIORITY) + +PyDoc_STRVAR(os_getpriority__doc__, +"getpriority($module, /, which, who)\n" +"--\n" +"\n" +"Return program scheduling priority."); + +#define OS_GETPRIORITY_METHODDEF \ + {"getpriority", _PyCFunction_CAST(os_getpriority), METH_FASTCALL|METH_KEYWORDS, os_getpriority__doc__}, + +static PyObject * +os_getpriority_impl(PyObject *module, int which, int who); + +static PyObject * +os_getpriority(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(which), &_Py_ID(who), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"which", "who", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "getpriority", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + int which; + int who; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + which = _PyLong_AsInt(args[0]); + if (which == -1 && PyErr_Occurred()) { + goto exit; + } + who = _PyLong_AsInt(args[1]); + if (who == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_getpriority_impl(module, which, who); + +exit: + return return_value; +} + +#endif /* defined(HAVE_GETPRIORITY) */ + +#if defined(HAVE_SETPRIORITY) + +PyDoc_STRVAR(os_setpriority__doc__, +"setpriority($module, /, which, who, priority)\n" +"--\n" +"\n" +"Set program scheduling priority."); + +#define OS_SETPRIORITY_METHODDEF \ + {"setpriority", _PyCFunction_CAST(os_setpriority), METH_FASTCALL|METH_KEYWORDS, os_setpriority__doc__}, + +static PyObject * +os_setpriority_impl(PyObject *module, int which, int who, int priority); + +static PyObject * +os_setpriority(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(which), &_Py_ID(who), &_Py_ID(priority), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"which", "who", "priority", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "setpriority", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + int which; + int who; + int priority; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); + if (!args) { + goto exit; + } + which = _PyLong_AsInt(args[0]); + if (which == -1 && PyErr_Occurred()) { + goto exit; + } + who = _PyLong_AsInt(args[1]); + if (who == -1 && PyErr_Occurred()) { + goto exit; + } + priority = _PyLong_AsInt(args[2]); + if (priority == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_setpriority_impl(module, which, who, priority); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SETPRIORITY) */ + +PyDoc_STRVAR(os_rename__doc__, +"rename($module, /, src, dst, *, src_dir_fd=None, dst_dir_fd=None)\n" +"--\n" +"\n" +"Rename a file or directory.\n" +"\n" +"If either src_dir_fd or dst_dir_fd is not None, it should be a file\n" +" descriptor open to a directory, and the respective path string (src or dst)\n" +" should be relative; the path will then be relative to that directory.\n" +"src_dir_fd and dst_dir_fd, may not be implemented on your platform.\n" +" If they are unavailable, using them will raise a NotImplementedError."); + +#define OS_RENAME_METHODDEF \ + {"rename", _PyCFunction_CAST(os_rename), METH_FASTCALL|METH_KEYWORDS, os_rename__doc__}, + +static PyObject * +os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, + int dst_dir_fd); + +static PyObject * +os_rename(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(src), &_Py_ID(dst), &_Py_ID(src_dir_fd), &_Py_ID(dst_dir_fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "rename", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + path_t src = PATH_T_INITIALIZE("rename", "src", 0, 0); + path_t dst = PATH_T_INITIALIZE("rename", "dst", 0, 0); + int src_dir_fd = DEFAULT_DIR_FD; + int dst_dir_fd = DEFAULT_DIR_FD; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &src)) { + goto exit; + } + if (!path_converter(args[1], &dst)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[2]) { + if (!dir_fd_converter(args[2], &src_dir_fd)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (!dir_fd_converter(args[3], &dst_dir_fd)) { + goto exit; + } +skip_optional_kwonly: + return_value = os_rename_impl(module, &src, &dst, src_dir_fd, dst_dir_fd); + +exit: + /* Cleanup for src */ + path_cleanup(&src); + /* Cleanup for dst */ + path_cleanup(&dst); + + return return_value; +} + +PyDoc_STRVAR(os_replace__doc__, +"replace($module, /, src, dst, *, src_dir_fd=None, dst_dir_fd=None)\n" +"--\n" +"\n" +"Rename a file or directory, overwriting the destination.\n" +"\n" +"If either src_dir_fd or dst_dir_fd is not None, it should be a file\n" +" descriptor open to a directory, and the respective path string (src or dst)\n" +" should be relative; the path will then be relative to that directory.\n" +"src_dir_fd and dst_dir_fd, may not be implemented on your platform.\n" +" If they are unavailable, using them will raise a NotImplementedError."); + +#define OS_REPLACE_METHODDEF \ + {"replace", _PyCFunction_CAST(os_replace), METH_FASTCALL|METH_KEYWORDS, os_replace__doc__}, + +static PyObject * +os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, + int dst_dir_fd); + +static PyObject * +os_replace(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(src), &_Py_ID(dst), &_Py_ID(src_dir_fd), &_Py_ID(dst_dir_fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "replace", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + path_t src = PATH_T_INITIALIZE("replace", "src", 0, 0); + path_t dst = PATH_T_INITIALIZE("replace", "dst", 0, 0); + int src_dir_fd = DEFAULT_DIR_FD; + int dst_dir_fd = DEFAULT_DIR_FD; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &src)) { + goto exit; + } + if (!path_converter(args[1], &dst)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[2]) { + if (!dir_fd_converter(args[2], &src_dir_fd)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (!dir_fd_converter(args[3], &dst_dir_fd)) { + goto exit; + } +skip_optional_kwonly: + return_value = os_replace_impl(module, &src, &dst, src_dir_fd, dst_dir_fd); + +exit: + /* Cleanup for src */ + path_cleanup(&src); + /* Cleanup for dst */ + path_cleanup(&dst); + + return return_value; +} + +PyDoc_STRVAR(os_rmdir__doc__, +"rmdir($module, /, path, *, dir_fd=None)\n" +"--\n" +"\n" +"Remove a directory.\n" +"\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that directory.\n" +"dir_fd may not be implemented on your platform.\n" +" If it is unavailable, using it will raise a NotImplementedError."); + +#define OS_RMDIR_METHODDEF \ + {"rmdir", _PyCFunction_CAST(os_rmdir), METH_FASTCALL|METH_KEYWORDS, os_rmdir__doc__}, + +static PyObject * +os_rmdir_impl(PyObject *module, path_t *path, int dir_fd); + +static PyObject * +os_rmdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(dir_fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "dir_fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "rmdir", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + path_t path = PATH_T_INITIALIZE("rmdir", "path", 0, 0); + int dir_fd = DEFAULT_DIR_FD; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (!UNLINKAT_DIR_FD_CONVERTER(args[1], &dir_fd)) { + goto exit; + } +skip_optional_kwonly: + return_value = os_rmdir_impl(module, &path, dir_fd); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#if defined(HAVE_SYSTEM) && defined(MS_WINDOWS) + +PyDoc_STRVAR(os_system__doc__, +"system($module, /, command)\n" +"--\n" +"\n" +"Execute the command in a subshell."); + +#define OS_SYSTEM_METHODDEF \ + {"system", _PyCFunction_CAST(os_system), METH_FASTCALL|METH_KEYWORDS, os_system__doc__}, + +static long +os_system_impl(PyObject *module, const Py_UNICODE *command); + +static PyObject * +os_system(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(command), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"command", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "system", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + const Py_UNICODE *command = NULL; + long _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("system", "argument 'command'", "str", args[0]); + goto exit; + } + command = PyUnicode_AsWideCharString(args[0], NULL); + if (command == NULL) { + goto exit; + } + _return_value = os_system_impl(module, command); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong(_return_value); + +exit: + /* Cleanup for command */ + PyMem_Free((void *)command); + + return return_value; +} + +#endif /* defined(HAVE_SYSTEM) && defined(MS_WINDOWS) */ + +#if defined(HAVE_SYSTEM) && !defined(MS_WINDOWS) + +PyDoc_STRVAR(os_system__doc__, +"system($module, /, command)\n" +"--\n" +"\n" +"Execute the command in a subshell."); + +#define OS_SYSTEM_METHODDEF \ + {"system", _PyCFunction_CAST(os_system), METH_FASTCALL|METH_KEYWORDS, os_system__doc__}, + +static long +os_system_impl(PyObject *module, PyObject *command); + +static PyObject * +os_system(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(command), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"command", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "system", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *command = NULL; + long _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!PyUnicode_FSConverter(args[0], &command)) { + goto exit; + } + _return_value = os_system_impl(module, command); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong(_return_value); + +exit: + /* Cleanup for command */ + Py_XDECREF(command); + + return return_value; +} + +#endif /* defined(HAVE_SYSTEM) && !defined(MS_WINDOWS) */ + +#if defined(HAVE_UMASK) + +PyDoc_STRVAR(os_umask__doc__, +"umask($module, mask, /)\n" +"--\n" +"\n" +"Set the current numeric umask and return the previous umask."); + +#define OS_UMASK_METHODDEF \ + {"umask", (PyCFunction)os_umask, METH_O, os_umask__doc__}, + +static PyObject * +os_umask_impl(PyObject *module, int mask); + +static PyObject * +os_umask(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int mask; + + mask = _PyLong_AsInt(arg); + if (mask == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_umask_impl(module, mask); + +exit: + return return_value; +} + +#endif /* defined(HAVE_UMASK) */ + +PyDoc_STRVAR(os_unlink__doc__, +"unlink($module, /, path, *, dir_fd=None)\n" +"--\n" +"\n" +"Remove a file (same as remove()).\n" +"\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that directory.\n" +"dir_fd may not be implemented on your platform.\n" +" If it is unavailable, using it will raise a NotImplementedError."); + +#define OS_UNLINK_METHODDEF \ + {"unlink", _PyCFunction_CAST(os_unlink), METH_FASTCALL|METH_KEYWORDS, os_unlink__doc__}, + +static PyObject * +os_unlink_impl(PyObject *module, path_t *path, int dir_fd); + +static PyObject * +os_unlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(dir_fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "dir_fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "unlink", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + path_t path = PATH_T_INITIALIZE("unlink", "path", 0, 0); + int dir_fd = DEFAULT_DIR_FD; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (!UNLINKAT_DIR_FD_CONVERTER(args[1], &dir_fd)) { + goto exit; + } +skip_optional_kwonly: + return_value = os_unlink_impl(module, &path, dir_fd); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +PyDoc_STRVAR(os_remove__doc__, +"remove($module, /, path, *, dir_fd=None)\n" +"--\n" +"\n" +"Remove a file (same as unlink()).\n" +"\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that directory.\n" +"dir_fd may not be implemented on your platform.\n" +" If it is unavailable, using it will raise a NotImplementedError."); + +#define OS_REMOVE_METHODDEF \ + {"remove", _PyCFunction_CAST(os_remove), METH_FASTCALL|METH_KEYWORDS, os_remove__doc__}, + +static PyObject * +os_remove_impl(PyObject *module, path_t *path, int dir_fd); + +static PyObject * +os_remove(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(dir_fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "dir_fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "remove", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + path_t path = PATH_T_INITIALIZE("remove", "path", 0, 0); + int dir_fd = DEFAULT_DIR_FD; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (!UNLINKAT_DIR_FD_CONVERTER(args[1], &dir_fd)) { + goto exit; + } +skip_optional_kwonly: + return_value = os_remove_impl(module, &path, dir_fd); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#if defined(HAVE_UNAME) + +PyDoc_STRVAR(os_uname__doc__, +"uname($module, /)\n" +"--\n" +"\n" +"Return an object identifying the current operating system.\n" +"\n" +"The object behaves like a named tuple with the following fields:\n" +" (sysname, nodename, release, version, machine)"); + +#define OS_UNAME_METHODDEF \ + {"uname", (PyCFunction)os_uname, METH_NOARGS, os_uname__doc__}, + +static PyObject * +os_uname_impl(PyObject *module); + +static PyObject * +os_uname(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_uname_impl(module); +} + +#endif /* defined(HAVE_UNAME) */ + +PyDoc_STRVAR(os_utime__doc__, +"utime($module, /, path, times=None, *, ns=,\n" +" dir_fd=None, follow_symlinks=True)\n" +"--\n" +"\n" +"Set the access and modified time of path.\n" +"\n" +"path may always be specified as a string.\n" +"On some platforms, path may also be specified as an open file descriptor.\n" +" If this functionality is unavailable, using it raises an exception.\n" +"\n" +"If times is not None, it must be a tuple (atime, mtime);\n" +" atime and mtime should be expressed as float seconds since the epoch.\n" +"If ns is specified, it must be a tuple (atime_ns, mtime_ns);\n" +" atime_ns and mtime_ns should be expressed as integer nanoseconds\n" +" since the epoch.\n" +"If times is None and ns is unspecified, utime uses the current time.\n" +"Specifying tuples for both times and ns is an error.\n" +"\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that directory.\n" +"If follow_symlinks is False, and the last element of the path is a symbolic\n" +" link, utime will modify the symbolic link itself instead of the file the\n" +" link points to.\n" +"It is an error to use dir_fd or follow_symlinks when specifying path\n" +" as an open file descriptor.\n" +"dir_fd and follow_symlinks may not be available on your platform.\n" +" If they are unavailable, using them will raise a NotImplementedError."); + +#define OS_UTIME_METHODDEF \ + {"utime", _PyCFunction_CAST(os_utime), METH_FASTCALL|METH_KEYWORDS, os_utime__doc__}, + +static PyObject * +os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, + int dir_fd, int follow_symlinks); + +static PyObject * +os_utime(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 5 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(times), &_Py_ID(ns), &_Py_ID(dir_fd), &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "times", "ns", "dir_fd", "follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "utime", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + path_t path = PATH_T_INITIALIZE("utime", "path", 0, PATH_UTIME_HAVE_FD); + PyObject *times = Py_None; + PyObject *ns = NULL; + int dir_fd = DEFAULT_DIR_FD; + int follow_symlinks = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[1]) { + times = args[1]; + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[2]) { + ns = args[2]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[3]) { + if (!FUTIMENSAT_DIR_FD_CONVERTER(args[3], &dir_fd)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + follow_symlinks = PyObject_IsTrue(args[4]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = os_utime_impl(module, &path, times, ns, dir_fd, follow_symlinks); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +PyDoc_STRVAR(os__exit__doc__, +"_exit($module, /, status)\n" +"--\n" +"\n" +"Exit to the system with specified status, without normal exit processing."); + +#define OS__EXIT_METHODDEF \ + {"_exit", _PyCFunction_CAST(os__exit), METH_FASTCALL|METH_KEYWORDS, os__exit__doc__}, + +static PyObject * +os__exit_impl(PyObject *module, int status); + +static PyObject * +os__exit(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(status), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"status", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "_exit", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int status; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + status = _PyLong_AsInt(args[0]); + if (status == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os__exit_impl(module, status); + +exit: + return return_value; +} + +#if defined(HAVE_EXECV) + +PyDoc_STRVAR(os_execv__doc__, +"execv($module, path, argv, /)\n" +"--\n" +"\n" +"Execute an executable path with arguments, replacing current process.\n" +"\n" +" path\n" +" Path of executable file.\n" +" argv\n" +" Tuple or list of strings."); + +#define OS_EXECV_METHODDEF \ + {"execv", _PyCFunction_CAST(os_execv), METH_FASTCALL, os_execv__doc__}, + +static PyObject * +os_execv_impl(PyObject *module, path_t *path, PyObject *argv); + +static PyObject * +os_execv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + path_t path = PATH_T_INITIALIZE("execv", "path", 0, 0); + PyObject *argv; + + if (!_PyArg_CheckPositional("execv", nargs, 2, 2)) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + argv = args[1]; + return_value = os_execv_impl(module, &path, argv); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(HAVE_EXECV) */ + +#if defined(HAVE_EXECV) + +PyDoc_STRVAR(os_execve__doc__, +"execve($module, /, path, argv, env)\n" +"--\n" +"\n" +"Execute an executable path with arguments, replacing current process.\n" +"\n" +" path\n" +" Path of executable file.\n" +" argv\n" +" Tuple or list of strings.\n" +" env\n" +" Dictionary of strings mapping to strings."); + +#define OS_EXECVE_METHODDEF \ + {"execve", _PyCFunction_CAST(os_execve), METH_FASTCALL|METH_KEYWORDS, os_execve__doc__}, + +static PyObject * +os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env); + +static PyObject * +os_execve(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(argv), &_Py_ID(env), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "argv", "env", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "execve", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + path_t path = PATH_T_INITIALIZE("execve", "path", 0, PATH_HAVE_FEXECVE); + PyObject *argv; + PyObject *env; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + argv = args[1]; + env = args[2]; + return_value = os_execve_impl(module, &path, argv, env); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(HAVE_EXECV) */ + +#if defined(HAVE_POSIX_SPAWN) + +PyDoc_STRVAR(os_posix_spawn__doc__, +"posix_spawn($module, path, argv, env, /, *, file_actions=(),\n" +" setpgroup=, resetids=False, setsid=False,\n" +" setsigmask=(), setsigdef=(), scheduler=)\n" +"--\n" +"\n" +"Execute the program specified by path in a new process.\n" +"\n" +" path\n" +" Path of executable file.\n" +" argv\n" +" Tuple or list of strings.\n" +" env\n" +" Dictionary of strings mapping to strings.\n" +" file_actions\n" +" A sequence of file action tuples.\n" +" setpgroup\n" +" The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.\n" +" resetids\n" +" If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.\n" +" setsid\n" +" If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.\n" +" setsigmask\n" +" The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.\n" +" setsigdef\n" +" The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.\n" +" scheduler\n" +" A tuple with the scheduler policy (optional) and parameters."); + +#define OS_POSIX_SPAWN_METHODDEF \ + {"posix_spawn", _PyCFunction_CAST(os_posix_spawn), METH_FASTCALL|METH_KEYWORDS, os_posix_spawn__doc__}, + +static PyObject * +os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, + PyObject *env, PyObject *file_actions, + PyObject *setpgroup, int resetids, int setsid, + PyObject *setsigmask, PyObject *setsigdef, + PyObject *scheduler); + +static PyObject * +os_posix_spawn(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 7 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(file_actions), &_Py_ID(setpgroup), &_Py_ID(resetids), &_Py_ID(setsid), &_Py_ID(setsigmask), &_Py_ID(setsigdef), &_Py_ID(scheduler), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"", "", "", "file_actions", "setpgroup", "resetids", "setsid", "setsigmask", "setsigdef", "scheduler", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "posix_spawn", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[10]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; + path_t path = PATH_T_INITIALIZE("posix_spawn", "path", 0, 0); + PyObject *argv; + PyObject *env; + PyObject *file_actions = NULL; + PyObject *setpgroup = NULL; + int resetids = 0; + int setsid = 0; + PyObject *setsigmask = NULL; + PyObject *setsigdef = NULL; + PyObject *scheduler = NULL; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + argv = args[1]; + env = args[2]; + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[3]) { + file_actions = args[3]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[4]) { + setpgroup = args[4]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[5]) { + resetids = _PyLong_AsInt(args[5]); + if (resetids == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[6]) { + setsid = _PyLong_AsInt(args[6]); + if (setsid == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[7]) { + setsigmask = args[7]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[8]) { + setsigdef = args[8]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + scheduler = args[9]; +skip_optional_kwonly: + return_value = os_posix_spawn_impl(module, &path, argv, env, file_actions, setpgroup, resetids, setsid, setsigmask, setsigdef, scheduler); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(HAVE_POSIX_SPAWN) */ + +#if defined(HAVE_POSIX_SPAWNP) + +PyDoc_STRVAR(os_posix_spawnp__doc__, +"posix_spawnp($module, path, argv, env, /, *, file_actions=(),\n" +" setpgroup=, resetids=False, setsid=False,\n" +" setsigmask=(), setsigdef=(), scheduler=)\n" +"--\n" +"\n" +"Execute the program specified by path in a new process.\n" +"\n" +" path\n" +" Path of executable file.\n" +" argv\n" +" Tuple or list of strings.\n" +" env\n" +" Dictionary of strings mapping to strings.\n" +" file_actions\n" +" A sequence of file action tuples.\n" +" setpgroup\n" +" The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.\n" +" resetids\n" +" If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.\n" +" setsid\n" +" If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.\n" +" setsigmask\n" +" The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.\n" +" setsigdef\n" +" The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.\n" +" scheduler\n" +" A tuple with the scheduler policy (optional) and parameters."); + +#define OS_POSIX_SPAWNP_METHODDEF \ + {"posix_spawnp", _PyCFunction_CAST(os_posix_spawnp), METH_FASTCALL|METH_KEYWORDS, os_posix_spawnp__doc__}, + +static PyObject * +os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv, + PyObject *env, PyObject *file_actions, + PyObject *setpgroup, int resetids, int setsid, + PyObject *setsigmask, PyObject *setsigdef, + PyObject *scheduler); + +static PyObject * +os_posix_spawnp(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 7 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(file_actions), &_Py_ID(setpgroup), &_Py_ID(resetids), &_Py_ID(setsid), &_Py_ID(setsigmask), &_Py_ID(setsigdef), &_Py_ID(scheduler), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"", "", "", "file_actions", "setpgroup", "resetids", "setsid", "setsigmask", "setsigdef", "scheduler", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "posix_spawnp", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[10]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; + path_t path = PATH_T_INITIALIZE("posix_spawnp", "path", 0, 0); + PyObject *argv; + PyObject *env; + PyObject *file_actions = NULL; + PyObject *setpgroup = NULL; + int resetids = 0; + int setsid = 0; + PyObject *setsigmask = NULL; + PyObject *setsigdef = NULL; + PyObject *scheduler = NULL; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + argv = args[1]; + env = args[2]; + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[3]) { + file_actions = args[3]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[4]) { + setpgroup = args[4]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[5]) { + resetids = _PyLong_AsInt(args[5]); + if (resetids == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[6]) { + setsid = _PyLong_AsInt(args[6]); + if (setsid == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[7]) { + setsigmask = args[7]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[8]) { + setsigdef = args[8]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + scheduler = args[9]; +skip_optional_kwonly: + return_value = os_posix_spawnp_impl(module, &path, argv, env, file_actions, setpgroup, resetids, setsid, setsigmask, setsigdef, scheduler); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(HAVE_POSIX_SPAWNP) */ + +#if (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)) + +PyDoc_STRVAR(os_spawnv__doc__, +"spawnv($module, mode, path, argv, /)\n" +"--\n" +"\n" +"Execute the program specified by path in a new process.\n" +"\n" +" mode\n" +" Mode of process creation.\n" +" path\n" +" Path of executable file.\n" +" argv\n" +" Tuple or list of strings."); + +#define OS_SPAWNV_METHODDEF \ + {"spawnv", _PyCFunction_CAST(os_spawnv), METH_FASTCALL, os_spawnv__doc__}, + +static PyObject * +os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv); + +static PyObject * +os_spawnv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int mode; + path_t path = PATH_T_INITIALIZE("spawnv", "path", 0, 0); + PyObject *argv; + + if (!_PyArg_CheckPositional("spawnv", nargs, 3, 3)) { + goto exit; + } + mode = _PyLong_AsInt(args[0]); + if (mode == -1 && PyErr_Occurred()) { + goto exit; + } + if (!path_converter(args[1], &path)) { + goto exit; + } + argv = args[2]; + return_value = os_spawnv_impl(module, mode, &path, argv); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)) */ + +#if (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)) + +PyDoc_STRVAR(os_spawnve__doc__, +"spawnve($module, mode, path, argv, env, /)\n" +"--\n" +"\n" +"Execute the program specified by path in a new process.\n" +"\n" +" mode\n" +" Mode of process creation.\n" +" path\n" +" Path of executable file.\n" +" argv\n" +" Tuple or list of strings.\n" +" env\n" +" Dictionary of strings mapping to strings."); + +#define OS_SPAWNVE_METHODDEF \ + {"spawnve", _PyCFunction_CAST(os_spawnve), METH_FASTCALL, os_spawnve__doc__}, + +static PyObject * +os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv, + PyObject *env); + +static PyObject * +os_spawnve(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int mode; + path_t path = PATH_T_INITIALIZE("spawnve", "path", 0, 0); + PyObject *argv; + PyObject *env; + + if (!_PyArg_CheckPositional("spawnve", nargs, 4, 4)) { + goto exit; + } + mode = _PyLong_AsInt(args[0]); + if (mode == -1 && PyErr_Occurred()) { + goto exit; + } + if (!path_converter(args[1], &path)) { + goto exit; + } + argv = args[2]; + env = args[3]; + return_value = os_spawnve_impl(module, mode, &path, argv, env); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)) */ + +#if defined(HAVE_FORK) + +PyDoc_STRVAR(os_register_at_fork__doc__, +"register_at_fork($module, /, *, before=,\n" +" after_in_child=,\n" +" after_in_parent=)\n" +"--\n" +"\n" +"Register callables to be called when forking a new process.\n" +"\n" +" before\n" +" A callable to be called in the parent before the fork() syscall.\n" +" after_in_child\n" +" A callable to be called in the child after fork().\n" +" after_in_parent\n" +" A callable to be called in the parent after fork().\n" +"\n" +"\'before\' callbacks are called in reverse order.\n" +"\'after_in_child\' and \'after_in_parent\' callbacks are called in order."); + +#define OS_REGISTER_AT_FORK_METHODDEF \ + {"register_at_fork", _PyCFunction_CAST(os_register_at_fork), METH_FASTCALL|METH_KEYWORDS, os_register_at_fork__doc__}, + +static PyObject * +os_register_at_fork_impl(PyObject *module, PyObject *before, + PyObject *after_in_child, PyObject *after_in_parent); + +static PyObject * +os_register_at_fork(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(before), &_Py_ID(after_in_child), &_Py_ID(after_in_parent), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"before", "after_in_child", "after_in_parent", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "register_at_fork", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + PyObject *before = NULL; + PyObject *after_in_child = NULL; + PyObject *after_in_parent = NULL; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[0]) { + before = args[0]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[1]) { + after_in_child = args[1]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + after_in_parent = args[2]; +skip_optional_kwonly: + return_value = os_register_at_fork_impl(module, before, after_in_child, after_in_parent); + +exit: + return return_value; +} + +#endif /* defined(HAVE_FORK) */ + +#if defined(HAVE_FORK1) + +PyDoc_STRVAR(os_fork1__doc__, +"fork1($module, /)\n" +"--\n" +"\n" +"Fork a child process with a single multiplexed (i.e., not bound) thread.\n" +"\n" +"Return 0 to child process and PID of child to parent process."); + +#define OS_FORK1_METHODDEF \ + {"fork1", (PyCFunction)os_fork1, METH_NOARGS, os_fork1__doc__}, + +static PyObject * +os_fork1_impl(PyObject *module); + +static PyObject * +os_fork1(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_fork1_impl(module); +} + +#endif /* defined(HAVE_FORK1) */ + +#if defined(HAVE_FORK) + +PyDoc_STRVAR(os_fork__doc__, +"fork($module, /)\n" +"--\n" +"\n" +"Fork a child process.\n" +"\n" +"Return 0 to child process and PID of child to parent process."); + +#define OS_FORK_METHODDEF \ + {"fork", (PyCFunction)os_fork, METH_NOARGS, os_fork__doc__}, + +static PyObject * +os_fork_impl(PyObject *module); + +static PyObject * +os_fork(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_fork_impl(module); +} + +#endif /* defined(HAVE_FORK) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_GET_PRIORITY_MAX) + +PyDoc_STRVAR(os_sched_get_priority_max__doc__, +"sched_get_priority_max($module, /, policy)\n" +"--\n" +"\n" +"Get the maximum scheduling priority for policy."); + +#define OS_SCHED_GET_PRIORITY_MAX_METHODDEF \ + {"sched_get_priority_max", _PyCFunction_CAST(os_sched_get_priority_max), METH_FASTCALL|METH_KEYWORDS, os_sched_get_priority_max__doc__}, + +static PyObject * +os_sched_get_priority_max_impl(PyObject *module, int policy); + +static PyObject * +os_sched_get_priority_max(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(policy), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"policy", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "sched_get_priority_max", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int policy; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + policy = _PyLong_AsInt(args[0]); + if (policy == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_sched_get_priority_max_impl(module, policy); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_GET_PRIORITY_MAX) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_GET_PRIORITY_MAX) + +PyDoc_STRVAR(os_sched_get_priority_min__doc__, +"sched_get_priority_min($module, /, policy)\n" +"--\n" +"\n" +"Get the minimum scheduling priority for policy."); + +#define OS_SCHED_GET_PRIORITY_MIN_METHODDEF \ + {"sched_get_priority_min", _PyCFunction_CAST(os_sched_get_priority_min), METH_FASTCALL|METH_KEYWORDS, os_sched_get_priority_min__doc__}, + +static PyObject * +os_sched_get_priority_min_impl(PyObject *module, int policy); + +static PyObject * +os_sched_get_priority_min(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(policy), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"policy", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "sched_get_priority_min", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int policy; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + policy = _PyLong_AsInt(args[0]); + if (policy == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_sched_get_priority_min_impl(module, policy); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_GET_PRIORITY_MAX) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETSCHEDULER) + +PyDoc_STRVAR(os_sched_getscheduler__doc__, +"sched_getscheduler($module, pid, /)\n" +"--\n" +"\n" +"Get the scheduling policy for the process identified by pid.\n" +"\n" +"Passing 0 for pid returns the scheduling policy for the calling process."); + +#define OS_SCHED_GETSCHEDULER_METHODDEF \ + {"sched_getscheduler", (PyCFunction)os_sched_getscheduler, METH_O, os_sched_getscheduler__doc__}, + +static PyObject * +os_sched_getscheduler_impl(PyObject *module, pid_t pid); + +static PyObject * +os_sched_getscheduler(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + pid_t pid; + + if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":sched_getscheduler", &pid)) { + goto exit; + } + return_value = os_sched_getscheduler_impl(module, pid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETSCHEDULER) */ + +#if defined(HAVE_SCHED_H) && (defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)) + +PyDoc_STRVAR(os_sched_param__doc__, +"sched_param(sched_priority)\n" +"--\n" +"\n" +"Currently has only one field: sched_priority\n" +"\n" +" sched_priority\n" +" A scheduling parameter."); + +static PyObject * +os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority); + +static PyObject * +os_sched_param(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(sched_priority), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"sched_priority", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "sched_param", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject * const *fastargs; + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + PyObject *sched_priority; + + fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, argsbuf); + if (!fastargs) { + goto exit; + } + sched_priority = fastargs[0]; + return_value = os_sched_param_impl(type, sched_priority); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SCHED_H) && (defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETSCHEDULER) + +PyDoc_STRVAR(os_sched_setscheduler__doc__, +"sched_setscheduler($module, pid, policy, param, /)\n" +"--\n" +"\n" +"Set the scheduling policy for the process identified by pid.\n" +"\n" +"If pid is 0, the calling process is changed.\n" +"param is an instance of sched_param."); + +#define OS_SCHED_SETSCHEDULER_METHODDEF \ + {"sched_setscheduler", _PyCFunction_CAST(os_sched_setscheduler), METH_FASTCALL, os_sched_setscheduler__doc__}, + +static PyObject * +os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy, + PyObject *param_obj); + +static PyObject * +os_sched_setscheduler(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + pid_t pid; + int policy; + PyObject *param_obj; + + if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "iO:sched_setscheduler", + &pid, &policy, ¶m_obj)) { + goto exit; + } + return_value = os_sched_setscheduler_impl(module, pid, policy, param_obj); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETSCHEDULER) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETPARAM) + +PyDoc_STRVAR(os_sched_getparam__doc__, +"sched_getparam($module, pid, /)\n" +"--\n" +"\n" +"Returns scheduling parameters for the process identified by pid.\n" +"\n" +"If pid is 0, returns parameters for the calling process.\n" +"Return value is an instance of sched_param."); + +#define OS_SCHED_GETPARAM_METHODDEF \ + {"sched_getparam", (PyCFunction)os_sched_getparam, METH_O, os_sched_getparam__doc__}, + +static PyObject * +os_sched_getparam_impl(PyObject *module, pid_t pid); + +static PyObject * +os_sched_getparam(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + pid_t pid; + + if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":sched_getparam", &pid)) { + goto exit; + } + return_value = os_sched_getparam_impl(module, pid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETPARAM) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETPARAM) + +PyDoc_STRVAR(os_sched_setparam__doc__, +"sched_setparam($module, pid, param, /)\n" +"--\n" +"\n" +"Set scheduling parameters for the process identified by pid.\n" +"\n" +"If pid is 0, sets parameters for the calling process.\n" +"param should be an instance of sched_param."); + +#define OS_SCHED_SETPARAM_METHODDEF \ + {"sched_setparam", _PyCFunction_CAST(os_sched_setparam), METH_FASTCALL, os_sched_setparam__doc__}, + +static PyObject * +os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj); + +static PyObject * +os_sched_setparam(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + pid_t pid; + PyObject *param_obj; + + if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "O:sched_setparam", + &pid, ¶m_obj)) { + goto exit; + } + return_value = os_sched_setparam_impl(module, pid, param_obj); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETPARAM) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_RR_GET_INTERVAL) + +PyDoc_STRVAR(os_sched_rr_get_interval__doc__, +"sched_rr_get_interval($module, pid, /)\n" +"--\n" +"\n" +"Return the round-robin quantum for the process identified by pid, in seconds.\n" +"\n" +"Value returned is a float."); + +#define OS_SCHED_RR_GET_INTERVAL_METHODDEF \ + {"sched_rr_get_interval", (PyCFunction)os_sched_rr_get_interval, METH_O, os_sched_rr_get_interval__doc__}, + +static double +os_sched_rr_get_interval_impl(PyObject *module, pid_t pid); + +static PyObject * +os_sched_rr_get_interval(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + pid_t pid; + double _return_value; + + if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":sched_rr_get_interval", &pid)) { + goto exit; + } + _return_value = os_sched_rr_get_interval_impl(module, pid); + if ((_return_value == -1.0) && PyErr_Occurred()) { + goto exit; + } + return_value = PyFloat_FromDouble(_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_RR_GET_INTERVAL) */ + +#if defined(HAVE_SCHED_H) + +PyDoc_STRVAR(os_sched_yield__doc__, +"sched_yield($module, /)\n" +"--\n" +"\n" +"Voluntarily relinquish the CPU."); + +#define OS_SCHED_YIELD_METHODDEF \ + {"sched_yield", (PyCFunction)os_sched_yield, METH_NOARGS, os_sched_yield__doc__}, + +static PyObject * +os_sched_yield_impl(PyObject *module); + +static PyObject * +os_sched_yield(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_sched_yield_impl(module); +} + +#endif /* defined(HAVE_SCHED_H) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETAFFINITY) + +PyDoc_STRVAR(os_sched_setaffinity__doc__, +"sched_setaffinity($module, pid, mask, /)\n" +"--\n" +"\n" +"Set the CPU affinity of the process identified by pid to mask.\n" +"\n" +"mask should be an iterable of integers identifying CPUs."); + +#define OS_SCHED_SETAFFINITY_METHODDEF \ + {"sched_setaffinity", _PyCFunction_CAST(os_sched_setaffinity), METH_FASTCALL, os_sched_setaffinity__doc__}, + +static PyObject * +os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask); + +static PyObject * +os_sched_setaffinity(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + pid_t pid; + PyObject *mask; + + if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "O:sched_setaffinity", + &pid, &mask)) { + goto exit; + } + return_value = os_sched_setaffinity_impl(module, pid, mask); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETAFFINITY) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETAFFINITY) + +PyDoc_STRVAR(os_sched_getaffinity__doc__, +"sched_getaffinity($module, pid, /)\n" +"--\n" +"\n" +"Return the affinity of the process identified by pid (or the current process if zero).\n" +"\n" +"The affinity is returned as a set of CPU identifiers."); + +#define OS_SCHED_GETAFFINITY_METHODDEF \ + {"sched_getaffinity", (PyCFunction)os_sched_getaffinity, METH_O, os_sched_getaffinity__doc__}, + +static PyObject * +os_sched_getaffinity_impl(PyObject *module, pid_t pid); + +static PyObject * +os_sched_getaffinity(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + pid_t pid; + + if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":sched_getaffinity", &pid)) { + goto exit; + } + return_value = os_sched_getaffinity_impl(module, pid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETAFFINITY) */ + +#if (defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)) + +PyDoc_STRVAR(os_openpty__doc__, +"openpty($module, /)\n" +"--\n" +"\n" +"Open a pseudo-terminal.\n" +"\n" +"Return a tuple of (master_fd, slave_fd) containing open file descriptors\n" +"for both the master and slave ends."); + +#define OS_OPENPTY_METHODDEF \ + {"openpty", (PyCFunction)os_openpty, METH_NOARGS, os_openpty__doc__}, + +static PyObject * +os_openpty_impl(PyObject *module); + +static PyObject * +os_openpty(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_openpty_impl(module); +} + +#endif /* (defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)) */ + +#if (defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)) + +PyDoc_STRVAR(os_login_tty__doc__, +"login_tty($module, fd, /)\n" +"--\n" +"\n" +"Prepare the tty of which fd is a file descriptor for a new login session.\n" +"\n" +"Make the calling process a session leader; make the tty the\n" +"controlling tty, the stdin, the stdout, and the stderr of the\n" +"calling process; close fd."); + +#define OS_LOGIN_TTY_METHODDEF \ + {"login_tty", (PyCFunction)os_login_tty, METH_O, os_login_tty__doc__}, + +static PyObject * +os_login_tty_impl(PyObject *module, int fd); + +static PyObject * +os_login_tty(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int fd; + + if (!_PyLong_FileDescriptor_Converter(arg, &fd)) { + goto exit; + } + return_value = os_login_tty_impl(module, fd); + +exit: + return return_value; +} + +#endif /* (defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)) */ + +#if defined(HAVE_FORKPTY) + +PyDoc_STRVAR(os_forkpty__doc__, +"forkpty($module, /)\n" +"--\n" +"\n" +"Fork a new process with a new pseudo-terminal as controlling tty.\n" +"\n" +"Returns a tuple of (pid, master_fd).\n" +"Like fork(), return pid of 0 to the child process,\n" +"and pid of child to the parent process.\n" +"To both, return fd of newly opened pseudo-terminal."); + +#define OS_FORKPTY_METHODDEF \ + {"forkpty", (PyCFunction)os_forkpty, METH_NOARGS, os_forkpty__doc__}, + +static PyObject * +os_forkpty_impl(PyObject *module); + +static PyObject * +os_forkpty(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_forkpty_impl(module); +} + +#endif /* defined(HAVE_FORKPTY) */ + +#if defined(HAVE_GETEGID) + +PyDoc_STRVAR(os_getegid__doc__, +"getegid($module, /)\n" +"--\n" +"\n" +"Return the current process\'s effective group id."); + +#define OS_GETEGID_METHODDEF \ + {"getegid", (PyCFunction)os_getegid, METH_NOARGS, os_getegid__doc__}, + +static PyObject * +os_getegid_impl(PyObject *module); + +static PyObject * +os_getegid(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getegid_impl(module); +} + +#endif /* defined(HAVE_GETEGID) */ + +#if defined(HAVE_GETEUID) + +PyDoc_STRVAR(os_geteuid__doc__, +"geteuid($module, /)\n" +"--\n" +"\n" +"Return the current process\'s effective user id."); + +#define OS_GETEUID_METHODDEF \ + {"geteuid", (PyCFunction)os_geteuid, METH_NOARGS, os_geteuid__doc__}, + +static PyObject * +os_geteuid_impl(PyObject *module); + +static PyObject * +os_geteuid(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_geteuid_impl(module); +} + +#endif /* defined(HAVE_GETEUID) */ + +#if defined(HAVE_GETGID) + +PyDoc_STRVAR(os_getgid__doc__, +"getgid($module, /)\n" +"--\n" +"\n" +"Return the current process\'s group id."); + +#define OS_GETGID_METHODDEF \ + {"getgid", (PyCFunction)os_getgid, METH_NOARGS, os_getgid__doc__}, + +static PyObject * +os_getgid_impl(PyObject *module); + +static PyObject * +os_getgid(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getgid_impl(module); +} + +#endif /* defined(HAVE_GETGID) */ + +#if defined(HAVE_GETPID) + +PyDoc_STRVAR(os_getpid__doc__, +"getpid($module, /)\n" +"--\n" +"\n" +"Return the current process id."); + +#define OS_GETPID_METHODDEF \ + {"getpid", (PyCFunction)os_getpid, METH_NOARGS, os_getpid__doc__}, + +static PyObject * +os_getpid_impl(PyObject *module); + +static PyObject * +os_getpid(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getpid_impl(module); +} + +#endif /* defined(HAVE_GETPID) */ + +#if defined(HAVE_GETGROUPLIST) && defined(__APPLE__) + +PyDoc_STRVAR(os_getgrouplist__doc__, +"getgrouplist($module, user, group, /)\n" +"--\n" +"\n" +"Returns a list of groups to which a user belongs.\n" +"\n" +" user\n" +" username to lookup\n" +" group\n" +" base group id of the user"); + +#define OS_GETGROUPLIST_METHODDEF \ + {"getgrouplist", _PyCFunction_CAST(os_getgrouplist), METH_FASTCALL, os_getgrouplist__doc__}, + +static PyObject * +os_getgrouplist_impl(PyObject *module, const char *user, int basegid); + +static PyObject * +os_getgrouplist(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + const char *user; + int basegid; + + if (!_PyArg_CheckPositional("getgrouplist", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("getgrouplist", "argument 1", "str", args[0]); + goto exit; + } + Py_ssize_t user_length; + user = PyUnicode_AsUTF8AndSize(args[0], &user_length); + if (user == NULL) { + goto exit; + } + if (strlen(user) != (size_t)user_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + basegid = _PyLong_AsInt(args[1]); + if (basegid == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_getgrouplist_impl(module, user, basegid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_GETGROUPLIST) && defined(__APPLE__) */ + +#if defined(HAVE_GETGROUPLIST) && !defined(__APPLE__) + +PyDoc_STRVAR(os_getgrouplist__doc__, +"getgrouplist($module, user, group, /)\n" +"--\n" +"\n" +"Returns a list of groups to which a user belongs.\n" +"\n" +" user\n" +" username to lookup\n" +" group\n" +" base group id of the user"); + +#define OS_GETGROUPLIST_METHODDEF \ + {"getgrouplist", _PyCFunction_CAST(os_getgrouplist), METH_FASTCALL, os_getgrouplist__doc__}, + +static PyObject * +os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid); + +static PyObject * +os_getgrouplist(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + const char *user; + gid_t basegid; + + if (!_PyArg_CheckPositional("getgrouplist", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("getgrouplist", "argument 1", "str", args[0]); + goto exit; + } + Py_ssize_t user_length; + user = PyUnicode_AsUTF8AndSize(args[0], &user_length); + if (user == NULL) { + goto exit; + } + if (strlen(user) != (size_t)user_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + if (!_Py_Gid_Converter(args[1], &basegid)) { + goto exit; + } + return_value = os_getgrouplist_impl(module, user, basegid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_GETGROUPLIST) && !defined(__APPLE__) */ + +#if defined(HAVE_GETGROUPS) + +PyDoc_STRVAR(os_getgroups__doc__, +"getgroups($module, /)\n" +"--\n" +"\n" +"Return list of supplemental group IDs for the process."); + +#define OS_GETGROUPS_METHODDEF \ + {"getgroups", (PyCFunction)os_getgroups, METH_NOARGS, os_getgroups__doc__}, + +static PyObject * +os_getgroups_impl(PyObject *module); + +static PyObject * +os_getgroups(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getgroups_impl(module); +} + +#endif /* defined(HAVE_GETGROUPS) */ + +#if defined(HAVE_INITGROUPS) && defined(__APPLE__) + +PyDoc_STRVAR(os_initgroups__doc__, +"initgroups($module, username, gid, /)\n" +"--\n" +"\n" +"Initialize the group access list.\n" +"\n" +"Call the system initgroups() to initialize the group access list with all of\n" +"the groups of which the specified username is a member, plus the specified\n" +"group id."); + +#define OS_INITGROUPS_METHODDEF \ + {"initgroups", _PyCFunction_CAST(os_initgroups), METH_FASTCALL, os_initgroups__doc__}, + +static PyObject * +os_initgroups_impl(PyObject *module, PyObject *oname, int gid); + +static PyObject * +os_initgroups(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *oname = NULL; + int gid; + + if (!_PyArg_CheckPositional("initgroups", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_FSConverter(args[0], &oname)) { + goto exit; + } + gid = _PyLong_AsInt(args[1]); + if (gid == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_initgroups_impl(module, oname, gid); + +exit: + /* Cleanup for oname */ + Py_XDECREF(oname); + + return return_value; +} + +#endif /* defined(HAVE_INITGROUPS) && defined(__APPLE__) */ + +#if defined(HAVE_INITGROUPS) && !defined(__APPLE__) + +PyDoc_STRVAR(os_initgroups__doc__, +"initgroups($module, username, gid, /)\n" +"--\n" +"\n" +"Initialize the group access list.\n" +"\n" +"Call the system initgroups() to initialize the group access list with all of\n" +"the groups of which the specified username is a member, plus the specified\n" +"group id."); + +#define OS_INITGROUPS_METHODDEF \ + {"initgroups", _PyCFunction_CAST(os_initgroups), METH_FASTCALL, os_initgroups__doc__}, + +static PyObject * +os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid); + +static PyObject * +os_initgroups(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *oname = NULL; + gid_t gid; + + if (!_PyArg_CheckPositional("initgroups", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_FSConverter(args[0], &oname)) { + goto exit; + } + if (!_Py_Gid_Converter(args[1], &gid)) { + goto exit; + } + return_value = os_initgroups_impl(module, oname, gid); + +exit: + /* Cleanup for oname */ + Py_XDECREF(oname); + + return return_value; +} + +#endif /* defined(HAVE_INITGROUPS) && !defined(__APPLE__) */ + +#if defined(HAVE_GETPGID) + +PyDoc_STRVAR(os_getpgid__doc__, +"getpgid($module, /, pid)\n" +"--\n" +"\n" +"Call the system call getpgid(), and return the result."); + +#define OS_GETPGID_METHODDEF \ + {"getpgid", _PyCFunction_CAST(os_getpgid), METH_FASTCALL|METH_KEYWORDS, os_getpgid__doc__}, + +static PyObject * +os_getpgid_impl(PyObject *module, pid_t pid); + +static PyObject * +os_getpgid(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(pid), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"pid", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .format = "" _Py_PARSE_PID ":getpgid", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + pid_t pid; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &pid)) { + goto exit; + } + return_value = os_getpgid_impl(module, pid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_GETPGID) */ + +#if defined(HAVE_GETPGRP) + +PyDoc_STRVAR(os_getpgrp__doc__, +"getpgrp($module, /)\n" +"--\n" +"\n" +"Return the current process group id."); + +#define OS_GETPGRP_METHODDEF \ + {"getpgrp", (PyCFunction)os_getpgrp, METH_NOARGS, os_getpgrp__doc__}, + +static PyObject * +os_getpgrp_impl(PyObject *module); + +static PyObject * +os_getpgrp(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getpgrp_impl(module); +} + +#endif /* defined(HAVE_GETPGRP) */ + +#if defined(HAVE_SETPGRP) + +PyDoc_STRVAR(os_setpgrp__doc__, +"setpgrp($module, /)\n" +"--\n" +"\n" +"Make the current process the leader of its process group."); + +#define OS_SETPGRP_METHODDEF \ + {"setpgrp", (PyCFunction)os_setpgrp, METH_NOARGS, os_setpgrp__doc__}, + +static PyObject * +os_setpgrp_impl(PyObject *module); + +static PyObject * +os_setpgrp(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_setpgrp_impl(module); +} + +#endif /* defined(HAVE_SETPGRP) */ + +#if defined(HAVE_GETPPID) + +PyDoc_STRVAR(os_getppid__doc__, +"getppid($module, /)\n" +"--\n" +"\n" +"Return the parent\'s process id.\n" +"\n" +"If the parent process has already exited, Windows machines will still\n" +"return its id; others systems will return the id of the \'init\' process (1)."); + +#define OS_GETPPID_METHODDEF \ + {"getppid", (PyCFunction)os_getppid, METH_NOARGS, os_getppid__doc__}, + +static PyObject * +os_getppid_impl(PyObject *module); + +static PyObject * +os_getppid(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getppid_impl(module); +} + +#endif /* defined(HAVE_GETPPID) */ + +#if defined(HAVE_GETLOGIN) + +PyDoc_STRVAR(os_getlogin__doc__, +"getlogin($module, /)\n" +"--\n" +"\n" +"Return the actual login name."); + +#define OS_GETLOGIN_METHODDEF \ + {"getlogin", (PyCFunction)os_getlogin, METH_NOARGS, os_getlogin__doc__}, + +static PyObject * +os_getlogin_impl(PyObject *module); + +static PyObject * +os_getlogin(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getlogin_impl(module); +} + +#endif /* defined(HAVE_GETLOGIN) */ + +#if defined(HAVE_GETUID) + +PyDoc_STRVAR(os_getuid__doc__, +"getuid($module, /)\n" +"--\n" +"\n" +"Return the current process\'s user id."); + +#define OS_GETUID_METHODDEF \ + {"getuid", (PyCFunction)os_getuid, METH_NOARGS, os_getuid__doc__}, + +static PyObject * +os_getuid_impl(PyObject *module); + +static PyObject * +os_getuid(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getuid_impl(module); +} + +#endif /* defined(HAVE_GETUID) */ + +#if defined(HAVE_KILL) + +PyDoc_STRVAR(os_kill__doc__, +"kill($module, pid, signal, /)\n" +"--\n" +"\n" +"Kill a process with a signal."); + +#define OS_KILL_METHODDEF \ + {"kill", _PyCFunction_CAST(os_kill), METH_FASTCALL, os_kill__doc__}, + +static PyObject * +os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal); + +static PyObject * +os_kill(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + pid_t pid; + Py_ssize_t signal; + + if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "n:kill", + &pid, &signal)) { + goto exit; + } + return_value = os_kill_impl(module, pid, signal); + +exit: + return return_value; +} + +#endif /* defined(HAVE_KILL) */ + +#if defined(HAVE_KILLPG) + +PyDoc_STRVAR(os_killpg__doc__, +"killpg($module, pgid, signal, /)\n" +"--\n" +"\n" +"Kill a process group with a signal."); + +#define OS_KILLPG_METHODDEF \ + {"killpg", _PyCFunction_CAST(os_killpg), METH_FASTCALL, os_killpg__doc__}, + +static PyObject * +os_killpg_impl(PyObject *module, pid_t pgid, int signal); + +static PyObject * +os_killpg(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + pid_t pgid; + int signal; + + if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "i:killpg", + &pgid, &signal)) { + goto exit; + } + return_value = os_killpg_impl(module, pgid, signal); + +exit: + return return_value; +} + +#endif /* defined(HAVE_KILLPG) */ + +#if defined(HAVE_PLOCK) + +PyDoc_STRVAR(os_plock__doc__, +"plock($module, op, /)\n" +"--\n" +"\n" +"Lock program segments into memory.\");"); + +#define OS_PLOCK_METHODDEF \ + {"plock", (PyCFunction)os_plock, METH_O, os_plock__doc__}, + +static PyObject * +os_plock_impl(PyObject *module, int op); + +static PyObject * +os_plock(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int op; + + op = _PyLong_AsInt(arg); + if (op == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_plock_impl(module, op); + +exit: + return return_value; +} + +#endif /* defined(HAVE_PLOCK) */ + +#if defined(HAVE_SETUID) + +PyDoc_STRVAR(os_setuid__doc__, +"setuid($module, uid, /)\n" +"--\n" +"\n" +"Set the current process\'s user id."); + +#define OS_SETUID_METHODDEF \ + {"setuid", (PyCFunction)os_setuid, METH_O, os_setuid__doc__}, + +static PyObject * +os_setuid_impl(PyObject *module, uid_t uid); + +static PyObject * +os_setuid(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + uid_t uid; + + if (!_Py_Uid_Converter(arg, &uid)) { + goto exit; + } + return_value = os_setuid_impl(module, uid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SETUID) */ + +#if defined(HAVE_SETEUID) + +PyDoc_STRVAR(os_seteuid__doc__, +"seteuid($module, euid, /)\n" +"--\n" +"\n" +"Set the current process\'s effective user id."); + +#define OS_SETEUID_METHODDEF \ + {"seteuid", (PyCFunction)os_seteuid, METH_O, os_seteuid__doc__}, + +static PyObject * +os_seteuid_impl(PyObject *module, uid_t euid); + +static PyObject * +os_seteuid(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + uid_t euid; + + if (!_Py_Uid_Converter(arg, &euid)) { + goto exit; + } + return_value = os_seteuid_impl(module, euid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SETEUID) */ + +#if defined(HAVE_SETEGID) + +PyDoc_STRVAR(os_setegid__doc__, +"setegid($module, egid, /)\n" +"--\n" +"\n" +"Set the current process\'s effective group id."); + +#define OS_SETEGID_METHODDEF \ + {"setegid", (PyCFunction)os_setegid, METH_O, os_setegid__doc__}, + +static PyObject * +os_setegid_impl(PyObject *module, gid_t egid); + +static PyObject * +os_setegid(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + gid_t egid; + + if (!_Py_Gid_Converter(arg, &egid)) { + goto exit; + } + return_value = os_setegid_impl(module, egid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SETEGID) */ + +#if defined(HAVE_SETREUID) + +PyDoc_STRVAR(os_setreuid__doc__, +"setreuid($module, ruid, euid, /)\n" +"--\n" +"\n" +"Set the current process\'s real and effective user ids."); + +#define OS_SETREUID_METHODDEF \ + {"setreuid", _PyCFunction_CAST(os_setreuid), METH_FASTCALL, os_setreuid__doc__}, + +static PyObject * +os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid); + +static PyObject * +os_setreuid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + uid_t ruid; + uid_t euid; + + if (!_PyArg_CheckPositional("setreuid", nargs, 2, 2)) { + goto exit; + } + if (!_Py_Uid_Converter(args[0], &ruid)) { + goto exit; + } + if (!_Py_Uid_Converter(args[1], &euid)) { + goto exit; + } + return_value = os_setreuid_impl(module, ruid, euid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SETREUID) */ + +#if defined(HAVE_SETREGID) + +PyDoc_STRVAR(os_setregid__doc__, +"setregid($module, rgid, egid, /)\n" +"--\n" +"\n" +"Set the current process\'s real and effective group ids."); + +#define OS_SETREGID_METHODDEF \ + {"setregid", _PyCFunction_CAST(os_setregid), METH_FASTCALL, os_setregid__doc__}, + +static PyObject * +os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid); + +static PyObject * +os_setregid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + gid_t rgid; + gid_t egid; + + if (!_PyArg_CheckPositional("setregid", nargs, 2, 2)) { + goto exit; + } + if (!_Py_Gid_Converter(args[0], &rgid)) { + goto exit; + } + if (!_Py_Gid_Converter(args[1], &egid)) { + goto exit; + } + return_value = os_setregid_impl(module, rgid, egid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SETREGID) */ + +#if defined(HAVE_SETGID) + +PyDoc_STRVAR(os_setgid__doc__, +"setgid($module, gid, /)\n" +"--\n" +"\n" +"Set the current process\'s group id."); + +#define OS_SETGID_METHODDEF \ + {"setgid", (PyCFunction)os_setgid, METH_O, os_setgid__doc__}, + +static PyObject * +os_setgid_impl(PyObject *module, gid_t gid); + +static PyObject * +os_setgid(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + gid_t gid; + + if (!_Py_Gid_Converter(arg, &gid)) { + goto exit; + } + return_value = os_setgid_impl(module, gid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SETGID) */ + +#if defined(HAVE_SETGROUPS) + +PyDoc_STRVAR(os_setgroups__doc__, +"setgroups($module, groups, /)\n" +"--\n" +"\n" +"Set the groups of the current process to list."); + +#define OS_SETGROUPS_METHODDEF \ + {"setgroups", (PyCFunction)os_setgroups, METH_O, os_setgroups__doc__}, + +#endif /* defined(HAVE_SETGROUPS) */ + +#if defined(HAVE_WAIT3) + +PyDoc_STRVAR(os_wait3__doc__, +"wait3($module, /, options)\n" +"--\n" +"\n" +"Wait for completion of a child process.\n" +"\n" +"Returns a tuple of information about the child process:\n" +" (pid, status, rusage)"); + +#define OS_WAIT3_METHODDEF \ + {"wait3", _PyCFunction_CAST(os_wait3), METH_FASTCALL|METH_KEYWORDS, os_wait3__doc__}, + +static PyObject * +os_wait3_impl(PyObject *module, int options); + +static PyObject * +os_wait3(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(options), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"options", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "wait3", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int options; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + options = _PyLong_AsInt(args[0]); + if (options == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_wait3_impl(module, options); + +exit: + return return_value; +} + +#endif /* defined(HAVE_WAIT3) */ + +#if defined(HAVE_WAIT4) + +PyDoc_STRVAR(os_wait4__doc__, +"wait4($module, /, pid, options)\n" +"--\n" +"\n" +"Wait for completion of a specific child process.\n" +"\n" +"Returns a tuple of information about the child process:\n" +" (pid, status, rusage)"); + +#define OS_WAIT4_METHODDEF \ + {"wait4", _PyCFunction_CAST(os_wait4), METH_FASTCALL|METH_KEYWORDS, os_wait4__doc__}, + +static PyObject * +os_wait4_impl(PyObject *module, pid_t pid, int options); + +static PyObject * +os_wait4(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(pid), &_Py_ID(options), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"pid", "options", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .format = "" _Py_PARSE_PID "i:wait4", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + pid_t pid; + int options; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &pid, &options)) { + goto exit; + } + return_value = os_wait4_impl(module, pid, options); + +exit: + return return_value; +} + +#endif /* defined(HAVE_WAIT4) */ + +#if (defined(HAVE_WAITID) && !defined(__APPLE__)) + +PyDoc_STRVAR(os_waitid__doc__, +"waitid($module, idtype, id, options, /)\n" +"--\n" +"\n" +"Returns the result of waiting for a process or processes.\n" +"\n" +" idtype\n" +" Must be one of be P_PID, P_PGID or P_ALL.\n" +" id\n" +" The id to wait on.\n" +" options\n" +" Constructed from the ORing of one or more of WEXITED, WSTOPPED\n" +" or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.\n" +"\n" +"Returns either waitid_result or None if WNOHANG is specified and there are\n" +"no children in a waitable state."); + +#define OS_WAITID_METHODDEF \ + {"waitid", _PyCFunction_CAST(os_waitid), METH_FASTCALL, os_waitid__doc__}, + +static PyObject * +os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options); + +static PyObject * +os_waitid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + idtype_t idtype; + id_t id; + int options; + + if (!_PyArg_ParseStack(args, nargs, "i" _Py_PARSE_PID "i:waitid", + &idtype, &id, &options)) { + goto exit; + } + return_value = os_waitid_impl(module, idtype, id, options); + +exit: + return return_value; +} + +#endif /* (defined(HAVE_WAITID) && !defined(__APPLE__)) */ + +#if defined(HAVE_WAITPID) + +PyDoc_STRVAR(os_waitpid__doc__, +"waitpid($module, pid, options, /)\n" +"--\n" +"\n" +"Wait for completion of a given child process.\n" +"\n" +"Returns a tuple of information regarding the child process:\n" +" (pid, status)\n" +"\n" +"The options argument is ignored on Windows."); + +#define OS_WAITPID_METHODDEF \ + {"waitpid", _PyCFunction_CAST(os_waitpid), METH_FASTCALL, os_waitpid__doc__}, + +static PyObject * +os_waitpid_impl(PyObject *module, pid_t pid, int options); + +static PyObject * +os_waitpid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + pid_t pid; + int options; + + if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "i:waitpid", + &pid, &options)) { + goto exit; + } + return_value = os_waitpid_impl(module, pid, options); + +exit: + return return_value; +} + +#endif /* defined(HAVE_WAITPID) */ + +#if !defined(HAVE_WAITPID) && defined(HAVE_CWAIT) + +PyDoc_STRVAR(os_waitpid__doc__, +"waitpid($module, pid, options, /)\n" +"--\n" +"\n" +"Wait for completion of a given process.\n" +"\n" +"Returns a tuple of information regarding the process:\n" +" (pid, status << 8)\n" +"\n" +"The options argument is ignored on Windows."); + +#define OS_WAITPID_METHODDEF \ + {"waitpid", _PyCFunction_CAST(os_waitpid), METH_FASTCALL, os_waitpid__doc__}, + +static PyObject * +os_waitpid_impl(PyObject *module, intptr_t pid, int options); + +static PyObject * +os_waitpid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + intptr_t pid; + int options; + + if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_INTPTR "i:waitpid", + &pid, &options)) { + goto exit; + } + return_value = os_waitpid_impl(module, pid, options); + +exit: + return return_value; +} + +#endif /* !defined(HAVE_WAITPID) && defined(HAVE_CWAIT) */ + +#if defined(HAVE_WAIT) + +PyDoc_STRVAR(os_wait__doc__, +"wait($module, /)\n" +"--\n" +"\n" +"Wait for completion of a child process.\n" +"\n" +"Returns a tuple of information about the child process:\n" +" (pid, status)"); + +#define OS_WAIT_METHODDEF \ + {"wait", (PyCFunction)os_wait, METH_NOARGS, os_wait__doc__}, + +static PyObject * +os_wait_impl(PyObject *module); + +static PyObject * +os_wait(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_wait_impl(module); +} + +#endif /* defined(HAVE_WAIT) */ + +#if (defined(__linux__) && defined(__NR_pidfd_open)) + +PyDoc_STRVAR(os_pidfd_open__doc__, +"pidfd_open($module, /, pid, flags=0)\n" +"--\n" +"\n" +"Return a file descriptor referring to the process *pid*.\n" +"\n" +"The descriptor can be used to perform process management without races and\n" +"signals."); + +#define OS_PIDFD_OPEN_METHODDEF \ + {"pidfd_open", _PyCFunction_CAST(os_pidfd_open), METH_FASTCALL|METH_KEYWORDS, os_pidfd_open__doc__}, + +static PyObject * +os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags); + +static PyObject * +os_pidfd_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(pid), &_Py_ID(flags), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"pid", "flags", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .format = "" _Py_PARSE_PID "|O&:pidfd_open", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + pid_t pid; + unsigned int flags = 0; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &pid, _PyLong_UnsignedInt_Converter, &flags)) { + goto exit; + } + return_value = os_pidfd_open_impl(module, pid, flags); + +exit: + return return_value; +} + +#endif /* (defined(__linux__) && defined(__NR_pidfd_open)) */ + +#if defined(HAVE_SETNS) + +PyDoc_STRVAR(os_setns__doc__, +"setns($module, /, fd, nstype=0)\n" +"--\n" +"\n" +"Move the calling thread into different namespaces.\n" +"\n" +" fd\n" +" A file descriptor to a namespace.\n" +" nstype\n" +" Type of namespace."); + +#define OS_SETNS_METHODDEF \ + {"setns", _PyCFunction_CAST(os_setns), METH_FASTCALL|METH_KEYWORDS, os_setns__doc__}, + +static PyObject * +os_setns_impl(PyObject *module, int fd, int nstype); + +static PyObject * +os_setns(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(fd), &_Py_ID(nstype), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"fd", "nstype", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "setns", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + int fd; + int nstype = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + nstype = _PyLong_AsInt(args[1]); + if (nstype == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_pos: + return_value = os_setns_impl(module, fd, nstype); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SETNS) */ + +#if defined(HAVE_UNSHARE) + +PyDoc_STRVAR(os_unshare__doc__, +"unshare($module, /, flags)\n" +"--\n" +"\n" +"Disassociate parts of a process (or thread) execution context.\n" +"\n" +" flags\n" +" Namespaces to be unshared."); + +#define OS_UNSHARE_METHODDEF \ + {"unshare", _PyCFunction_CAST(os_unshare), METH_FASTCALL|METH_KEYWORDS, os_unshare__doc__}, + +static PyObject * +os_unshare_impl(PyObject *module, int flags); + +static PyObject * +os_unshare(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(flags), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"flags", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "unshare", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int flags; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + flags = _PyLong_AsInt(args[0]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_unshare_impl(module, flags); + +exit: + return return_value; +} + +#endif /* defined(HAVE_UNSHARE) */ + +#if (defined(HAVE_READLINK) || defined(MS_WINDOWS)) + +PyDoc_STRVAR(os_readlink__doc__, +"readlink($module, /, path, *, dir_fd=None)\n" +"--\n" +"\n" +"Return a string representing the path to which the symbolic link points.\n" +"\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +"and path should be relative; path will then be relative to that directory.\n" +"\n" +"dir_fd may not be implemented on your platform. If it is unavailable,\n" +"using it will raise a NotImplementedError."); + +#define OS_READLINK_METHODDEF \ + {"readlink", _PyCFunction_CAST(os_readlink), METH_FASTCALL|METH_KEYWORDS, os_readlink__doc__}, + +static PyObject * +os_readlink_impl(PyObject *module, path_t *path, int dir_fd); + +static PyObject * +os_readlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(dir_fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "dir_fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "readlink", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + path_t path = PATH_T_INITIALIZE("readlink", "path", 0, 0); + int dir_fd = DEFAULT_DIR_FD; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (!READLINKAT_DIR_FD_CONVERTER(args[1], &dir_fd)) { + goto exit; + } +skip_optional_kwonly: + return_value = os_readlink_impl(module, &path, dir_fd); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* (defined(HAVE_READLINK) || defined(MS_WINDOWS)) */ + +#if defined(HAVE_SYMLINK) + +PyDoc_STRVAR(os_symlink__doc__, +"symlink($module, /, src, dst, target_is_directory=False, *, dir_fd=None)\n" +"--\n" +"\n" +"Create a symbolic link pointing to src named dst.\n" +"\n" +"target_is_directory is required on Windows if the target is to be\n" +" interpreted as a directory. (On Windows, symlink requires\n" +" Windows 6.0 or greater, and raises a NotImplementedError otherwise.)\n" +" target_is_directory is ignored on non-Windows platforms.\n" +"\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that directory.\n" +"dir_fd may not be implemented on your platform.\n" +" If it is unavailable, using it will raise a NotImplementedError."); + +#define OS_SYMLINK_METHODDEF \ + {"symlink", _PyCFunction_CAST(os_symlink), METH_FASTCALL|METH_KEYWORDS, os_symlink__doc__}, + +static PyObject * +os_symlink_impl(PyObject *module, path_t *src, path_t *dst, + int target_is_directory, int dir_fd); + +static PyObject * +os_symlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(src), &_Py_ID(dst), &_Py_ID(target_is_directory), &_Py_ID(dir_fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"src", "dst", "target_is_directory", "dir_fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "symlink", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + path_t src = PATH_T_INITIALIZE("symlink", "src", 0, 0); + path_t dst = PATH_T_INITIALIZE("symlink", "dst", 0, 0); + int target_is_directory = 0; + int dir_fd = DEFAULT_DIR_FD; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &src)) { + goto exit; + } + if (!path_converter(args[1], &dst)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[2]) { + target_is_directory = PyObject_IsTrue(args[2]); + if (target_is_directory < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + if (!SYMLINKAT_DIR_FD_CONVERTER(args[3], &dir_fd)) { + goto exit; + } +skip_optional_kwonly: + return_value = os_symlink_impl(module, &src, &dst, target_is_directory, dir_fd); + +exit: + /* Cleanup for src */ + path_cleanup(&src); + /* Cleanup for dst */ + path_cleanup(&dst); + + return return_value; +} + +#endif /* defined(HAVE_SYMLINK) */ + +#if defined(HAVE_TIMES) + +PyDoc_STRVAR(os_times__doc__, +"times($module, /)\n" +"--\n" +"\n" +"Return a collection containing process timing information.\n" +"\n" +"The object returned behaves like a named tuple with these fields:\n" +" (utime, stime, cutime, cstime, elapsed_time)\n" +"All fields are floating point numbers."); + +#define OS_TIMES_METHODDEF \ + {"times", (PyCFunction)os_times, METH_NOARGS, os_times__doc__}, + +static PyObject * +os_times_impl(PyObject *module); + +static PyObject * +os_times(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_times_impl(module); +} + +#endif /* defined(HAVE_TIMES) */ + +#if defined(HAVE_GETSID) + +PyDoc_STRVAR(os_getsid__doc__, +"getsid($module, pid, /)\n" +"--\n" +"\n" +"Call the system call getsid(pid) and return the result."); + +#define OS_GETSID_METHODDEF \ + {"getsid", (PyCFunction)os_getsid, METH_O, os_getsid__doc__}, + +static PyObject * +os_getsid_impl(PyObject *module, pid_t pid); + +static PyObject * +os_getsid(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + pid_t pid; + + if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":getsid", &pid)) { + goto exit; + } + return_value = os_getsid_impl(module, pid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_GETSID) */ + +#if defined(HAVE_SETSID) + +PyDoc_STRVAR(os_setsid__doc__, +"setsid($module, /)\n" +"--\n" +"\n" +"Call the system call setsid()."); + +#define OS_SETSID_METHODDEF \ + {"setsid", (PyCFunction)os_setsid, METH_NOARGS, os_setsid__doc__}, + +static PyObject * +os_setsid_impl(PyObject *module); + +static PyObject * +os_setsid(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_setsid_impl(module); +} + +#endif /* defined(HAVE_SETSID) */ + +#if defined(HAVE_SETPGID) + +PyDoc_STRVAR(os_setpgid__doc__, +"setpgid($module, pid, pgrp, /)\n" +"--\n" +"\n" +"Call the system call setpgid(pid, pgrp)."); + +#define OS_SETPGID_METHODDEF \ + {"setpgid", _PyCFunction_CAST(os_setpgid), METH_FASTCALL, os_setpgid__doc__}, + +static PyObject * +os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp); + +static PyObject * +os_setpgid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + pid_t pid; + pid_t pgrp; + + if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_PID "" _Py_PARSE_PID ":setpgid", + &pid, &pgrp)) { + goto exit; + } + return_value = os_setpgid_impl(module, pid, pgrp); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SETPGID) */ + +#if defined(HAVE_TCGETPGRP) + +PyDoc_STRVAR(os_tcgetpgrp__doc__, +"tcgetpgrp($module, fd, /)\n" +"--\n" +"\n" +"Return the process group associated with the terminal specified by fd."); + +#define OS_TCGETPGRP_METHODDEF \ + {"tcgetpgrp", (PyCFunction)os_tcgetpgrp, METH_O, os_tcgetpgrp__doc__}, + +static PyObject * +os_tcgetpgrp_impl(PyObject *module, int fd); + +static PyObject * +os_tcgetpgrp(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int fd; + + fd = _PyLong_AsInt(arg); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_tcgetpgrp_impl(module, fd); + +exit: + return return_value; +} + +#endif /* defined(HAVE_TCGETPGRP) */ + +#if defined(HAVE_TCSETPGRP) + +PyDoc_STRVAR(os_tcsetpgrp__doc__, +"tcsetpgrp($module, fd, pgid, /)\n" +"--\n" +"\n" +"Set the process group associated with the terminal specified by fd."); + +#define OS_TCSETPGRP_METHODDEF \ + {"tcsetpgrp", _PyCFunction_CAST(os_tcsetpgrp), METH_FASTCALL, os_tcsetpgrp__doc__}, + +static PyObject * +os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid); + +static PyObject * +os_tcsetpgrp(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + pid_t pgid; + + if (!_PyArg_ParseStack(args, nargs, "i" _Py_PARSE_PID ":tcsetpgrp", + &fd, &pgid)) { + goto exit; + } + return_value = os_tcsetpgrp_impl(module, fd, pgid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_TCSETPGRP) */ + +PyDoc_STRVAR(os_open__doc__, +"open($module, /, path, flags, mode=511, *, dir_fd=None)\n" +"--\n" +"\n" +"Open a file for low level IO. Returns a file descriptor (integer).\n" +"\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that directory.\n" +"dir_fd may not be implemented on your platform.\n" +" If it is unavailable, using it will raise a NotImplementedError."); + +#define OS_OPEN_METHODDEF \ + {"open", _PyCFunction_CAST(os_open), METH_FASTCALL|METH_KEYWORDS, os_open__doc__}, + +static int +os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd); + +static PyObject * +os_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(flags), &_Py_ID(mode), &_Py_ID(dir_fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "flags", "mode", "dir_fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "open", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + path_t path = PATH_T_INITIALIZE("open", "path", 0, 0); + int flags; + int mode = 511; + int dir_fd = DEFAULT_DIR_FD; + int _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + flags = _PyLong_AsInt(args[1]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[2]) { + mode = _PyLong_AsInt(args[2]); + if (mode == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + if (!OPENAT_DIR_FD_CONVERTER(args[3], &dir_fd)) { + goto exit; + } +skip_optional_kwonly: + _return_value = os_open_impl(module, &path, flags, mode, dir_fd); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong((long)_return_value); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +PyDoc_STRVAR(os_close__doc__, +"close($module, /, fd)\n" +"--\n" +"\n" +"Close a file descriptor."); + +#define OS_CLOSE_METHODDEF \ + {"close", _PyCFunction_CAST(os_close), METH_FASTCALL|METH_KEYWORDS, os_close__doc__}, + +static PyObject * +os_close_impl(PyObject *module, int fd); + +static PyObject * +os_close(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "close", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int fd; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_close_impl(module, fd); + +exit: + return return_value; +} + +PyDoc_STRVAR(os_closerange__doc__, +"closerange($module, fd_low, fd_high, /)\n" +"--\n" +"\n" +"Closes all file descriptors in [fd_low, fd_high), ignoring errors."); + +#define OS_CLOSERANGE_METHODDEF \ + {"closerange", _PyCFunction_CAST(os_closerange), METH_FASTCALL, os_closerange__doc__}, + +static PyObject * +os_closerange_impl(PyObject *module, int fd_low, int fd_high); + +static PyObject * +os_closerange(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd_low; + int fd_high; + + if (!_PyArg_CheckPositional("closerange", nargs, 2, 2)) { + goto exit; + } + fd_low = _PyLong_AsInt(args[0]); + if (fd_low == -1 && PyErr_Occurred()) { + goto exit; + } + fd_high = _PyLong_AsInt(args[1]); + if (fd_high == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_closerange_impl(module, fd_low, fd_high); + +exit: + return return_value; +} + +PyDoc_STRVAR(os_dup__doc__, +"dup($module, fd, /)\n" +"--\n" +"\n" +"Return a duplicate of a file descriptor."); + +#define OS_DUP_METHODDEF \ + {"dup", (PyCFunction)os_dup, METH_O, os_dup__doc__}, + +static int +os_dup_impl(PyObject *module, int fd); + +static PyObject * +os_dup(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int fd; + int _return_value; + + fd = _PyLong_AsInt(arg); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_dup_impl(module, fd); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + +#if ((defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))) + +PyDoc_STRVAR(os_dup2__doc__, +"dup2($module, /, fd, fd2, inheritable=True)\n" +"--\n" +"\n" +"Duplicate file descriptor."); + +#define OS_DUP2_METHODDEF \ + {"dup2", _PyCFunction_CAST(os_dup2), METH_FASTCALL|METH_KEYWORDS, os_dup2__doc__}, + +static int +os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable); + +static PyObject * +os_dup2(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(fd), &_Py_ID(fd2), &_Py_ID(inheritable), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"fd", "fd2", "inheritable", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "dup2", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + int fd; + int fd2; + int inheritable = 1; + int _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf); + if (!args) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + fd2 = _PyLong_AsInt(args[1]); + if (fd2 == -1 && PyErr_Occurred()) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + inheritable = PyObject_IsTrue(args[2]); + if (inheritable < 0) { + goto exit; + } +skip_optional_pos: + _return_value = os_dup2_impl(module, fd, fd2, inheritable); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + +#endif /* ((defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))) */ + +#if defined(HAVE_LOCKF) + +PyDoc_STRVAR(os_lockf__doc__, +"lockf($module, fd, command, length, /)\n" +"--\n" +"\n" +"Apply, test or remove a POSIX lock on an open file descriptor.\n" +"\n" +" fd\n" +" An open file descriptor.\n" +" command\n" +" One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.\n" +" length\n" +" The number of bytes to lock, starting at the current position."); + +#define OS_LOCKF_METHODDEF \ + {"lockf", _PyCFunction_CAST(os_lockf), METH_FASTCALL, os_lockf__doc__}, + +static PyObject * +os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length); + +static PyObject * +os_lockf(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + int command; + Py_off_t length; + + if (!_PyArg_CheckPositional("lockf", nargs, 3, 3)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + command = _PyLong_AsInt(args[1]); + if (command == -1 && PyErr_Occurred()) { + goto exit; + } + if (!Py_off_t_converter(args[2], &length)) { + goto exit; + } + return_value = os_lockf_impl(module, fd, command, length); + +exit: + return return_value; +} + +#endif /* defined(HAVE_LOCKF) */ + +PyDoc_STRVAR(os_lseek__doc__, +"lseek($module, fd, position, how, /)\n" +"--\n" +"\n" +"Set the position of a file descriptor. Return the new position.\n" +"\n" +"Return the new cursor position in number of bytes\n" +"relative to the beginning of the file."); + +#define OS_LSEEK_METHODDEF \ + {"lseek", _PyCFunction_CAST(os_lseek), METH_FASTCALL, os_lseek__doc__}, + +static Py_off_t +os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how); + +static PyObject * +os_lseek(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + Py_off_t position; + int how; + Py_off_t _return_value; + + if (!_PyArg_CheckPositional("lseek", nargs, 3, 3)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + if (!Py_off_t_converter(args[1], &position)) { + goto exit; + } + how = _PyLong_AsInt(args[2]); + if (how == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_lseek_impl(module, fd, position, how); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromPy_off_t(_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(os_read__doc__, +"read($module, fd, length, /)\n" +"--\n" +"\n" +"Read from a file descriptor. Returns a bytes object."); + +#define OS_READ_METHODDEF \ + {"read", _PyCFunction_CAST(os_read), METH_FASTCALL, os_read__doc__}, + +static PyObject * +os_read_impl(PyObject *module, int fd, Py_ssize_t length); + +static PyObject * +os_read(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + Py_ssize_t length; + + if (!_PyArg_CheckPositional("read", nargs, 2, 2)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[1]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + length = ival; + } + return_value = os_read_impl(module, fd, length); + +exit: + return return_value; +} + +#if defined(HAVE_READV) + +PyDoc_STRVAR(os_readv__doc__, +"readv($module, fd, buffers, /)\n" +"--\n" +"\n" +"Read from a file descriptor fd into an iterable of buffers.\n" +"\n" +"The buffers should be mutable buffers accepting bytes.\n" +"readv will transfer data into each buffer until it is full\n" +"and then move on to the next buffer in the sequence to hold\n" +"the rest of the data.\n" +"\n" +"readv returns the total number of bytes read,\n" +"which may be less than the total capacity of all the buffers."); + +#define OS_READV_METHODDEF \ + {"readv", _PyCFunction_CAST(os_readv), METH_FASTCALL, os_readv__doc__}, + +static Py_ssize_t +os_readv_impl(PyObject *module, int fd, PyObject *buffers); + +static PyObject * +os_readv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + PyObject *buffers; + Py_ssize_t _return_value; + + if (!_PyArg_CheckPositional("readv", nargs, 2, 2)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + buffers = args[1]; + _return_value = os_readv_impl(module, fd, buffers); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromSsize_t(_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_READV) */ + +#if defined(HAVE_PREAD) + +PyDoc_STRVAR(os_pread__doc__, +"pread($module, fd, length, offset, /)\n" +"--\n" +"\n" +"Read a number of bytes from a file descriptor starting at a particular offset.\n" +"\n" +"Read length bytes from file descriptor fd, starting at offset bytes from\n" +"the beginning of the file. The file offset remains unchanged."); + +#define OS_PREAD_METHODDEF \ + {"pread", _PyCFunction_CAST(os_pread), METH_FASTCALL, os_pread__doc__}, + +static PyObject * +os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset); + +static PyObject * +os_pread(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + Py_ssize_t length; + Py_off_t offset; + + if (!_PyArg_CheckPositional("pread", nargs, 3, 3)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[1]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + length = ival; + } + if (!Py_off_t_converter(args[2], &offset)) { + goto exit; + } + return_value = os_pread_impl(module, fd, length, offset); + +exit: + return return_value; +} + +#endif /* defined(HAVE_PREAD) */ + +#if (defined(HAVE_PREADV) || defined (HAVE_PREADV2)) + +PyDoc_STRVAR(os_preadv__doc__, +"preadv($module, fd, buffers, offset, flags=0, /)\n" +"--\n" +"\n" +"Reads from a file descriptor into a number of mutable bytes-like objects.\n" +"\n" +"Combines the functionality of readv() and pread(). As readv(), it will\n" +"transfer data into each buffer until it is full and then move on to the next\n" +"buffer in the sequence to hold the rest of the data. Its fourth argument,\n" +"specifies the file offset at which the input operation is to be performed. It\n" +"will return the total number of bytes read (which can be less than the total\n" +"capacity of all the objects).\n" +"\n" +"The flags argument contains a bitwise OR of zero or more of the following flags:\n" +"\n" +"- RWF_HIPRI\n" +"- RWF_NOWAIT\n" +"\n" +"Using non-zero flags requires Linux 4.6 or newer."); + +#define OS_PREADV_METHODDEF \ + {"preadv", _PyCFunction_CAST(os_preadv), METH_FASTCALL, os_preadv__doc__}, + +static Py_ssize_t +os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, + int flags); + +static PyObject * +os_preadv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + PyObject *buffers; + Py_off_t offset; + int flags = 0; + Py_ssize_t _return_value; + + if (!_PyArg_CheckPositional("preadv", nargs, 3, 4)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + buffers = args[1]; + if (!Py_off_t_converter(args[2], &offset)) { + goto exit; + } + if (nargs < 4) { + goto skip_optional; + } + flags = _PyLong_AsInt(args[3]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + _return_value = os_preadv_impl(module, fd, buffers, offset, flags); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromSsize_t(_return_value); + +exit: + return return_value; +} + +#endif /* (defined(HAVE_PREADV) || defined (HAVE_PREADV2)) */ + +PyDoc_STRVAR(os_write__doc__, +"write($module, fd, data, /)\n" +"--\n" +"\n" +"Write a bytes object to a file descriptor."); + +#define OS_WRITE_METHODDEF \ + {"write", _PyCFunction_CAST(os_write), METH_FASTCALL, os_write__doc__}, + +static Py_ssize_t +os_write_impl(PyObject *module, int fd, Py_buffer *data); + +static PyObject * +os_write(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + Py_buffer data = {NULL, NULL}; + Py_ssize_t _return_value; + + if (!_PyArg_CheckPositional("write", nargs, 2, 2)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + if (PyObject_GetBuffer(args[1], &data, PyBUF_SIMPLE) != 0) { + goto exit; + } + if (!PyBuffer_IsContiguous(&data, 'C')) { + _PyArg_BadArgument("write", "argument 2", "contiguous buffer", args[1]); + goto exit; + } + _return_value = os_write_impl(module, fd, &data); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromSsize_t(_return_value); + +exit: + /* Cleanup for data */ + if (data.obj) { + PyBuffer_Release(&data); + } + + return return_value; +} + +#if defined(HAVE_SENDFILE) && defined(__APPLE__) + +PyDoc_STRVAR(os_sendfile__doc__, +"sendfile($module, /, out_fd, in_fd, offset, count, headers=(),\n" +" trailers=(), flags=0)\n" +"--\n" +"\n" +"Copy count bytes from file descriptor in_fd to file descriptor out_fd."); + +#define OS_SENDFILE_METHODDEF \ + {"sendfile", _PyCFunction_CAST(os_sendfile), METH_FASTCALL|METH_KEYWORDS, os_sendfile__doc__}, + +static PyObject * +os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset, + Py_off_t sbytes, PyObject *headers, PyObject *trailers, + int flags); + +static PyObject * +os_sendfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 7 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(out_fd), &_Py_ID(in_fd), &_Py_ID(offset), &_Py_ID(count), &_Py_ID(headers), &_Py_ID(trailers), &_Py_ID(flags), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"out_fd", "in_fd", "offset", "count", "headers", "trailers", "flags", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "sendfile", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[7]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 4; + int out_fd; + int in_fd; + Py_off_t offset; + Py_off_t sbytes; + PyObject *headers = NULL; + PyObject *trailers = NULL; + int flags = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 4, 7, 0, argsbuf); + if (!args) { + goto exit; + } + out_fd = _PyLong_AsInt(args[0]); + if (out_fd == -1 && PyErr_Occurred()) { + goto exit; + } + in_fd = _PyLong_AsInt(args[1]); + if (in_fd == -1 && PyErr_Occurred()) { + goto exit; + } + if (!Py_off_t_converter(args[2], &offset)) { + goto exit; + } + if (!Py_off_t_converter(args[3], &sbytes)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[4]) { + headers = args[4]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[5]) { + trailers = args[5]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + flags = _PyLong_AsInt(args[6]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_pos: + return_value = os_sendfile_impl(module, out_fd, in_fd, offset, sbytes, headers, trailers, flags); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SENDFILE) && defined(__APPLE__) */ + +#if defined(HAVE_SENDFILE) && !defined(__APPLE__) && (defined(__FreeBSD__) || defined(__DragonFly__)) + +PyDoc_STRVAR(os_sendfile__doc__, +"sendfile($module, /, out_fd, in_fd, offset, count, headers=(),\n" +" trailers=(), flags=0)\n" +"--\n" +"\n" +"Copy count bytes from file descriptor in_fd to file descriptor out_fd."); + +#define OS_SENDFILE_METHODDEF \ + {"sendfile", _PyCFunction_CAST(os_sendfile), METH_FASTCALL|METH_KEYWORDS, os_sendfile__doc__}, + +static PyObject * +os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset, + Py_ssize_t count, PyObject *headers, PyObject *trailers, + int flags); + +static PyObject * +os_sendfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 7 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(out_fd), &_Py_ID(in_fd), &_Py_ID(offset), &_Py_ID(count), &_Py_ID(headers), &_Py_ID(trailers), &_Py_ID(flags), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"out_fd", "in_fd", "offset", "count", "headers", "trailers", "flags", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "sendfile", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[7]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 4; + int out_fd; + int in_fd; + Py_off_t offset; + Py_ssize_t count; + PyObject *headers = NULL; + PyObject *trailers = NULL; + int flags = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 4, 7, 0, argsbuf); + if (!args) { + goto exit; + } + out_fd = _PyLong_AsInt(args[0]); + if (out_fd == -1 && PyErr_Occurred()) { + goto exit; + } + in_fd = _PyLong_AsInt(args[1]); + if (in_fd == -1 && PyErr_Occurred()) { + goto exit; + } + if (!Py_off_t_converter(args[2], &offset)) { + goto exit; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[3]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + count = ival; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[4]) { + headers = args[4]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[5]) { + trailers = args[5]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + flags = _PyLong_AsInt(args[6]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_pos: + return_value = os_sendfile_impl(module, out_fd, in_fd, offset, count, headers, trailers, flags); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SENDFILE) && !defined(__APPLE__) && (defined(__FreeBSD__) || defined(__DragonFly__)) */ + +#if defined(HAVE_SENDFILE) && !defined(__APPLE__) && !(defined(__FreeBSD__) || defined(__DragonFly__)) + +PyDoc_STRVAR(os_sendfile__doc__, +"sendfile($module, /, out_fd, in_fd, offset, count)\n" +"--\n" +"\n" +"Copy count bytes from file descriptor in_fd to file descriptor out_fd."); + +#define OS_SENDFILE_METHODDEF \ + {"sendfile", _PyCFunction_CAST(os_sendfile), METH_FASTCALL|METH_KEYWORDS, os_sendfile__doc__}, + +static PyObject * +os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj, + Py_ssize_t count); + +static PyObject * +os_sendfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(out_fd), &_Py_ID(in_fd), &_Py_ID(offset), &_Py_ID(count), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"out_fd", "in_fd", "offset", "count", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "sendfile", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + int out_fd; + int in_fd; + PyObject *offobj; + Py_ssize_t count; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 4, 4, 0, argsbuf); + if (!args) { + goto exit; + } + out_fd = _PyLong_AsInt(args[0]); + if (out_fd == -1 && PyErr_Occurred()) { + goto exit; + } + in_fd = _PyLong_AsInt(args[1]); + if (in_fd == -1 && PyErr_Occurred()) { + goto exit; + } + offobj = args[2]; + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[3]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + count = ival; + } + return_value = os_sendfile_impl(module, out_fd, in_fd, offobj, count); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SENDFILE) && !defined(__APPLE__) && !(defined(__FreeBSD__) || defined(__DragonFly__)) */ + +#if defined(__APPLE__) + +PyDoc_STRVAR(os__fcopyfile__doc__, +"_fcopyfile($module, in_fd, out_fd, flags, /)\n" +"--\n" +"\n" +"Efficiently copy content or metadata of 2 regular file descriptors (macOS)."); + +#define OS__FCOPYFILE_METHODDEF \ + {"_fcopyfile", _PyCFunction_CAST(os__fcopyfile), METH_FASTCALL, os__fcopyfile__doc__}, + +static PyObject * +os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags); + +static PyObject * +os__fcopyfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int in_fd; + int out_fd; + int flags; + + if (!_PyArg_CheckPositional("_fcopyfile", nargs, 3, 3)) { + goto exit; + } + in_fd = _PyLong_AsInt(args[0]); + if (in_fd == -1 && PyErr_Occurred()) { + goto exit; + } + out_fd = _PyLong_AsInt(args[1]); + if (out_fd == -1 && PyErr_Occurred()) { + goto exit; + } + flags = _PyLong_AsInt(args[2]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os__fcopyfile_impl(module, in_fd, out_fd, flags); + +exit: + return return_value; +} + +#endif /* defined(__APPLE__) */ + +PyDoc_STRVAR(os_fstat__doc__, +"fstat($module, /, fd)\n" +"--\n" +"\n" +"Perform a stat system call on the given file descriptor.\n" +"\n" +"Like stat(), but for an open file descriptor.\n" +"Equivalent to os.stat(fd)."); + +#define OS_FSTAT_METHODDEF \ + {"fstat", _PyCFunction_CAST(os_fstat), METH_FASTCALL|METH_KEYWORDS, os_fstat__doc__}, + +static PyObject * +os_fstat_impl(PyObject *module, int fd); + +static PyObject * +os_fstat(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "fstat", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int fd; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_fstat_impl(module, fd); + +exit: + return return_value; +} + +PyDoc_STRVAR(os_isatty__doc__, +"isatty($module, fd, /)\n" +"--\n" +"\n" +"Return True if the fd is connected to a terminal.\n" +"\n" +"Return True if the file descriptor is an open file descriptor\n" +"connected to the slave end of a terminal."); + +#define OS_ISATTY_METHODDEF \ + {"isatty", (PyCFunction)os_isatty, METH_O, os_isatty__doc__}, + +static int +os_isatty_impl(PyObject *module, int fd); + +static PyObject * +os_isatty(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int fd; + int _return_value; + + fd = _PyLong_AsInt(arg); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_isatty_impl(module, fd); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +#if defined(HAVE_PIPE) + +PyDoc_STRVAR(os_pipe__doc__, +"pipe($module, /)\n" +"--\n" +"\n" +"Create a pipe.\n" +"\n" +"Returns a tuple of two file descriptors:\n" +" (read_fd, write_fd)"); + +#define OS_PIPE_METHODDEF \ + {"pipe", (PyCFunction)os_pipe, METH_NOARGS, os_pipe__doc__}, + +static PyObject * +os_pipe_impl(PyObject *module); + +static PyObject * +os_pipe(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_pipe_impl(module); +} + +#endif /* defined(HAVE_PIPE) */ + +#if defined(HAVE_PIPE2) + +PyDoc_STRVAR(os_pipe2__doc__, +"pipe2($module, flags, /)\n" +"--\n" +"\n" +"Create a pipe with flags set atomically.\n" +"\n" +"Returns a tuple of two file descriptors:\n" +" (read_fd, write_fd)\n" +"\n" +"flags can be constructed by ORing together one or more of these values:\n" +"O_NONBLOCK, O_CLOEXEC."); + +#define OS_PIPE2_METHODDEF \ + {"pipe2", (PyCFunction)os_pipe2, METH_O, os_pipe2__doc__}, + +static PyObject * +os_pipe2_impl(PyObject *module, int flags); + +static PyObject * +os_pipe2(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int flags; + + flags = _PyLong_AsInt(arg); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_pipe2_impl(module, flags); + +exit: + return return_value; +} + +#endif /* defined(HAVE_PIPE2) */ + +#if defined(HAVE_WRITEV) + +PyDoc_STRVAR(os_writev__doc__, +"writev($module, fd, buffers, /)\n" +"--\n" +"\n" +"Iterate over buffers, and write the contents of each to a file descriptor.\n" +"\n" +"Returns the total number of bytes written.\n" +"buffers must be a sequence of bytes-like objects."); + +#define OS_WRITEV_METHODDEF \ + {"writev", _PyCFunction_CAST(os_writev), METH_FASTCALL, os_writev__doc__}, + +static Py_ssize_t +os_writev_impl(PyObject *module, int fd, PyObject *buffers); + +static PyObject * +os_writev(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + PyObject *buffers; + Py_ssize_t _return_value; + + if (!_PyArg_CheckPositional("writev", nargs, 2, 2)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + buffers = args[1]; + _return_value = os_writev_impl(module, fd, buffers); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromSsize_t(_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_WRITEV) */ + +#if defined(HAVE_PWRITE) + +PyDoc_STRVAR(os_pwrite__doc__, +"pwrite($module, fd, buffer, offset, /)\n" +"--\n" +"\n" +"Write bytes to a file descriptor starting at a particular offset.\n" +"\n" +"Write buffer to fd, starting at offset bytes from the beginning of\n" +"the file. Returns the number of bytes writte. Does not change the\n" +"current file offset."); + +#define OS_PWRITE_METHODDEF \ + {"pwrite", _PyCFunction_CAST(os_pwrite), METH_FASTCALL, os_pwrite__doc__}, + +static Py_ssize_t +os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset); + +static PyObject * +os_pwrite(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + Py_buffer buffer = {NULL, NULL}; + Py_off_t offset; + Py_ssize_t _return_value; + + if (!_PyArg_CheckPositional("pwrite", nargs, 3, 3)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + if (PyObject_GetBuffer(args[1], &buffer, PyBUF_SIMPLE) != 0) { + goto exit; + } + if (!PyBuffer_IsContiguous(&buffer, 'C')) { + _PyArg_BadArgument("pwrite", "argument 2", "contiguous buffer", args[1]); + goto exit; + } + if (!Py_off_t_converter(args[2], &offset)) { + goto exit; + } + _return_value = os_pwrite_impl(module, fd, &buffer, offset); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromSsize_t(_return_value); + +exit: + /* Cleanup for buffer */ + if (buffer.obj) { + PyBuffer_Release(&buffer); + } + + return return_value; +} + +#endif /* defined(HAVE_PWRITE) */ + +#if (defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)) + +PyDoc_STRVAR(os_pwritev__doc__, +"pwritev($module, fd, buffers, offset, flags=0, /)\n" +"--\n" +"\n" +"Writes the contents of bytes-like objects to a file descriptor at a given offset.\n" +"\n" +"Combines the functionality of writev() and pwrite(). All buffers must be a sequence\n" +"of bytes-like objects. Buffers are processed in array order. Entire contents of first\n" +"buffer is written before proceeding to second, and so on. The operating system may\n" +"set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.\n" +"This function writes the contents of each object to the file descriptor and returns\n" +"the total number of bytes written.\n" +"\n" +"The flags argument contains a bitwise OR of zero or more of the following flags:\n" +"\n" +"- RWF_DSYNC\n" +"- RWF_SYNC\n" +"- RWF_APPEND\n" +"\n" +"Using non-zero flags requires Linux 4.7 or newer."); + +#define OS_PWRITEV_METHODDEF \ + {"pwritev", _PyCFunction_CAST(os_pwritev), METH_FASTCALL, os_pwritev__doc__}, + +static Py_ssize_t +os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, + int flags); + +static PyObject * +os_pwritev(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + PyObject *buffers; + Py_off_t offset; + int flags = 0; + Py_ssize_t _return_value; + + if (!_PyArg_CheckPositional("pwritev", nargs, 3, 4)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + buffers = args[1]; + if (!Py_off_t_converter(args[2], &offset)) { + goto exit; + } + if (nargs < 4) { + goto skip_optional; + } + flags = _PyLong_AsInt(args[3]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + _return_value = os_pwritev_impl(module, fd, buffers, offset, flags); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromSsize_t(_return_value); + +exit: + return return_value; +} + +#endif /* (defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)) */ + +#if defined(HAVE_COPY_FILE_RANGE) + +PyDoc_STRVAR(os_copy_file_range__doc__, +"copy_file_range($module, /, src, dst, count, offset_src=None,\n" +" offset_dst=None)\n" +"--\n" +"\n" +"Copy count bytes from one file descriptor to another.\n" +"\n" +" src\n" +" Source file descriptor.\n" +" dst\n" +" Destination file descriptor.\n" +" count\n" +" Number of bytes to copy.\n" +" offset_src\n" +" Starting offset in src.\n" +" offset_dst\n" +" Starting offset in dst.\n" +"\n" +"If offset_src is None, then src is read from the current position;\n" +"respectively for offset_dst."); + +#define OS_COPY_FILE_RANGE_METHODDEF \ + {"copy_file_range", _PyCFunction_CAST(os_copy_file_range), METH_FASTCALL|METH_KEYWORDS, os_copy_file_range__doc__}, + +static PyObject * +os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count, + PyObject *offset_src, PyObject *offset_dst); + +static PyObject * +os_copy_file_range(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 5 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(src), &_Py_ID(dst), &_Py_ID(count), &_Py_ID(offset_src), &_Py_ID(offset_dst), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"src", "dst", "count", "offset_src", "offset_dst", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "copy_file_range", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; + int src; + int dst; + Py_ssize_t count; + PyObject *offset_src = Py_None; + PyObject *offset_dst = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 5, 0, argsbuf); + if (!args) { + goto exit; + } + src = _PyLong_AsInt(args[0]); + if (src == -1 && PyErr_Occurred()) { + goto exit; + } + dst = _PyLong_AsInt(args[1]); + if (dst == -1 && PyErr_Occurred()) { + goto exit; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[2]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + count = ival; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[3]) { + offset_src = args[3]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + offset_dst = args[4]; +skip_optional_pos: + return_value = os_copy_file_range_impl(module, src, dst, count, offset_src, offset_dst); + +exit: + return return_value; +} + +#endif /* defined(HAVE_COPY_FILE_RANGE) */ + +#if ((defined(HAVE_SPLICE) && !defined(_AIX))) + +PyDoc_STRVAR(os_splice__doc__, +"splice($module, /, src, dst, count, offset_src=None, offset_dst=None,\n" +" flags=0)\n" +"--\n" +"\n" +"Transfer count bytes from one pipe to a descriptor or vice versa.\n" +"\n" +" src\n" +" Source file descriptor.\n" +" dst\n" +" Destination file descriptor.\n" +" count\n" +" Number of bytes to copy.\n" +" offset_src\n" +" Starting offset in src.\n" +" offset_dst\n" +" Starting offset in dst.\n" +" flags\n" +" Flags to modify the semantics of the call.\n" +"\n" +"If offset_src is None, then src is read from the current position;\n" +"respectively for offset_dst. The offset associated to the file\n" +"descriptor that refers to a pipe must be None."); + +#define OS_SPLICE_METHODDEF \ + {"splice", _PyCFunction_CAST(os_splice), METH_FASTCALL|METH_KEYWORDS, os_splice__doc__}, + +static PyObject * +os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count, + PyObject *offset_src, PyObject *offset_dst, + unsigned int flags); + +static PyObject * +os_splice(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 6 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(src), &_Py_ID(dst), &_Py_ID(count), &_Py_ID(offset_src), &_Py_ID(offset_dst), &_Py_ID(flags), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"src", "dst", "count", "offset_src", "offset_dst", "flags", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "splice", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[6]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; + int src; + int dst; + Py_ssize_t count; + PyObject *offset_src = Py_None; + PyObject *offset_dst = Py_None; + unsigned int flags = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 6, 0, argsbuf); + if (!args) { + goto exit; + } + src = _PyLong_AsInt(args[0]); + if (src == -1 && PyErr_Occurred()) { + goto exit; + } + dst = _PyLong_AsInt(args[1]); + if (dst == -1 && PyErr_Occurred()) { + goto exit; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[2]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + count = ival; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[3]) { + offset_src = args[3]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[4]) { + offset_dst = args[4]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (!_PyLong_UnsignedInt_Converter(args[5], &flags)) { + goto exit; + } +skip_optional_pos: + return_value = os_splice_impl(module, src, dst, count, offset_src, offset_dst, flags); + +exit: + return return_value; +} + +#endif /* ((defined(HAVE_SPLICE) && !defined(_AIX))) */ + +#if defined(HAVE_MKFIFO) + +PyDoc_STRVAR(os_mkfifo__doc__, +"mkfifo($module, /, path, mode=438, *, dir_fd=None)\n" +"--\n" +"\n" +"Create a \"fifo\" (a POSIX named pipe).\n" +"\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that directory.\n" +"dir_fd may not be implemented on your platform.\n" +" If it is unavailable, using it will raise a NotImplementedError."); + +#define OS_MKFIFO_METHODDEF \ + {"mkfifo", _PyCFunction_CAST(os_mkfifo), METH_FASTCALL|METH_KEYWORDS, os_mkfifo__doc__}, + +static PyObject * +os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd); + +static PyObject * +os_mkfifo(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(mode), &_Py_ID(dir_fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "mode", "dir_fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "mkfifo", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + path_t path = PATH_T_INITIALIZE("mkfifo", "path", 0, 0); + int mode = 438; + int dir_fd = DEFAULT_DIR_FD; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[1]) { + mode = _PyLong_AsInt(args[1]); + if (mode == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + if (!MKFIFOAT_DIR_FD_CONVERTER(args[2], &dir_fd)) { + goto exit; + } +skip_optional_kwonly: + return_value = os_mkfifo_impl(module, &path, mode, dir_fd); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(HAVE_MKFIFO) */ + +#if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) + +PyDoc_STRVAR(os_mknod__doc__, +"mknod($module, /, path, mode=384, device=0, *, dir_fd=None)\n" +"--\n" +"\n" +"Create a node in the file system.\n" +"\n" +"Create a node in the file system (file, device special file or named pipe)\n" +"at path. mode specifies both the permissions to use and the\n" +"type of node to be created, being combined (bitwise OR) with one of\n" +"S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode,\n" +"device defines the newly created device special file (probably using\n" +"os.makedev()). Otherwise device is ignored.\n" +"\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that directory.\n" +"dir_fd may not be implemented on your platform.\n" +" If it is unavailable, using it will raise a NotImplementedError."); + +#define OS_MKNOD_METHODDEF \ + {"mknod", _PyCFunction_CAST(os_mknod), METH_FASTCALL|METH_KEYWORDS, os_mknod__doc__}, + +static PyObject * +os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device, + int dir_fd); + +static PyObject * +os_mknod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(mode), &_Py_ID(device), &_Py_ID(dir_fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "mode", "device", "dir_fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "mknod", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + path_t path = PATH_T_INITIALIZE("mknod", "path", 0, 0); + int mode = 384; + dev_t device = 0; + int dir_fd = DEFAULT_DIR_FD; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[1]) { + mode = _PyLong_AsInt(args[1]); + if (mode == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[2]) { + if (!_Py_Dev_Converter(args[2], &device)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + if (!MKNODAT_DIR_FD_CONVERTER(args[3], &dir_fd)) { + goto exit; + } +skip_optional_kwonly: + return_value = os_mknod_impl(module, &path, mode, device, dir_fd); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) */ + +#if defined(HAVE_DEVICE_MACROS) + +PyDoc_STRVAR(os_major__doc__, +"major($module, device, /)\n" +"--\n" +"\n" +"Extracts a device major number from a raw device number."); + +#define OS_MAJOR_METHODDEF \ + {"major", (PyCFunction)os_major, METH_O, os_major__doc__}, + +static unsigned int +os_major_impl(PyObject *module, dev_t device); + +static PyObject * +os_major(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + dev_t device; + unsigned int _return_value; + + if (!_Py_Dev_Converter(arg, &device)) { + goto exit; + } + _return_value = os_major_impl(module, device); + if ((_return_value == (unsigned int)-1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromUnsignedLong((unsigned long)_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_DEVICE_MACROS) */ + +#if defined(HAVE_DEVICE_MACROS) + +PyDoc_STRVAR(os_minor__doc__, +"minor($module, device, /)\n" +"--\n" +"\n" +"Extracts a device minor number from a raw device number."); + +#define OS_MINOR_METHODDEF \ + {"minor", (PyCFunction)os_minor, METH_O, os_minor__doc__}, + +static unsigned int +os_minor_impl(PyObject *module, dev_t device); + +static PyObject * +os_minor(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + dev_t device; + unsigned int _return_value; + + if (!_Py_Dev_Converter(arg, &device)) { + goto exit; + } + _return_value = os_minor_impl(module, device); + if ((_return_value == (unsigned int)-1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromUnsignedLong((unsigned long)_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_DEVICE_MACROS) */ + +#if defined(HAVE_DEVICE_MACROS) + +PyDoc_STRVAR(os_makedev__doc__, +"makedev($module, major, minor, /)\n" +"--\n" +"\n" +"Composes a raw device number from the major and minor device numbers."); + +#define OS_MAKEDEV_METHODDEF \ + {"makedev", _PyCFunction_CAST(os_makedev), METH_FASTCALL, os_makedev__doc__}, + +static dev_t +os_makedev_impl(PyObject *module, int major, int minor); + +static PyObject * +os_makedev(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int major; + int minor; + dev_t _return_value; + + if (!_PyArg_CheckPositional("makedev", nargs, 2, 2)) { + goto exit; + } + major = _PyLong_AsInt(args[0]); + if (major == -1 && PyErr_Occurred()) { + goto exit; + } + minor = _PyLong_AsInt(args[1]); + if (minor == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_makedev_impl(module, major, minor); + if ((_return_value == (dev_t)-1) && PyErr_Occurred()) { + goto exit; + } + return_value = _PyLong_FromDev(_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_DEVICE_MACROS) */ + +#if (defined HAVE_FTRUNCATE || defined MS_WINDOWS) + +PyDoc_STRVAR(os_ftruncate__doc__, +"ftruncate($module, fd, length, /)\n" +"--\n" +"\n" +"Truncate a file, specified by file descriptor, to a specific length."); + +#define OS_FTRUNCATE_METHODDEF \ + {"ftruncate", _PyCFunction_CAST(os_ftruncate), METH_FASTCALL, os_ftruncate__doc__}, + +static PyObject * +os_ftruncate_impl(PyObject *module, int fd, Py_off_t length); + +static PyObject * +os_ftruncate(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + Py_off_t length; + + if (!_PyArg_CheckPositional("ftruncate", nargs, 2, 2)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + if (!Py_off_t_converter(args[1], &length)) { + goto exit; + } + return_value = os_ftruncate_impl(module, fd, length); + +exit: + return return_value; +} + +#endif /* (defined HAVE_FTRUNCATE || defined MS_WINDOWS) */ + +#if (defined HAVE_TRUNCATE || defined MS_WINDOWS) + +PyDoc_STRVAR(os_truncate__doc__, +"truncate($module, /, path, length)\n" +"--\n" +"\n" +"Truncate a file, specified by path, to a specific length.\n" +"\n" +"On some platforms, path may also be specified as an open file descriptor.\n" +" If this functionality is unavailable, using it raises an exception."); + +#define OS_TRUNCATE_METHODDEF \ + {"truncate", _PyCFunction_CAST(os_truncate), METH_FASTCALL|METH_KEYWORDS, os_truncate__doc__}, + +static PyObject * +os_truncate_impl(PyObject *module, path_t *path, Py_off_t length); + +static PyObject * +os_truncate(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(length), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "length", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "truncate", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + path_t path = PATH_T_INITIALIZE("truncate", "path", 0, PATH_HAVE_FTRUNCATE); + Py_off_t length; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!Py_off_t_converter(args[1], &length)) { + goto exit; + } + return_value = os_truncate_impl(module, &path, length); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* (defined HAVE_TRUNCATE || defined MS_WINDOWS) */ + +#if (defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)) + +PyDoc_STRVAR(os_posix_fallocate__doc__, +"posix_fallocate($module, fd, offset, length, /)\n" +"--\n" +"\n" +"Ensure a file has allocated at least a particular number of bytes on disk.\n" +"\n" +"Ensure that the file specified by fd encompasses a range of bytes\n" +"starting at offset bytes from the beginning and continuing for length bytes."); + +#define OS_POSIX_FALLOCATE_METHODDEF \ + {"posix_fallocate", _PyCFunction_CAST(os_posix_fallocate), METH_FASTCALL, os_posix_fallocate__doc__}, + +static PyObject * +os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset, + Py_off_t length); + +static PyObject * +os_posix_fallocate(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + Py_off_t offset; + Py_off_t length; + + if (!_PyArg_CheckPositional("posix_fallocate", nargs, 3, 3)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + if (!Py_off_t_converter(args[1], &offset)) { + goto exit; + } + if (!Py_off_t_converter(args[2], &length)) { + goto exit; + } + return_value = os_posix_fallocate_impl(module, fd, offset, length); + +exit: + return return_value; +} + +#endif /* (defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)) */ + +#if (defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)) + +PyDoc_STRVAR(os_posix_fadvise__doc__, +"posix_fadvise($module, fd, offset, length, advice, /)\n" +"--\n" +"\n" +"Announce an intention to access data in a specific pattern.\n" +"\n" +"Announce an intention to access data in a specific pattern, thus allowing\n" +"the kernel to make optimizations.\n" +"The advice applies to the region of the file specified by fd starting at\n" +"offset and continuing for length bytes.\n" +"advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,\n" +"POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or\n" +"POSIX_FADV_DONTNEED."); + +#define OS_POSIX_FADVISE_METHODDEF \ + {"posix_fadvise", _PyCFunction_CAST(os_posix_fadvise), METH_FASTCALL, os_posix_fadvise__doc__}, + +static PyObject * +os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset, + Py_off_t length, int advice); + +static PyObject * +os_posix_fadvise(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + Py_off_t offset; + Py_off_t length; + int advice; + + if (!_PyArg_CheckPositional("posix_fadvise", nargs, 4, 4)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + if (!Py_off_t_converter(args[1], &offset)) { + goto exit; + } + if (!Py_off_t_converter(args[2], &length)) { + goto exit; + } + advice = _PyLong_AsInt(args[3]); + if (advice == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_posix_fadvise_impl(module, fd, offset, length, advice); + +exit: + return return_value; +} + +#endif /* (defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)) */ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(os_putenv__doc__, +"putenv($module, name, value, /)\n" +"--\n" +"\n" +"Change or add an environment variable."); + +#define OS_PUTENV_METHODDEF \ + {"putenv", _PyCFunction_CAST(os_putenv), METH_FASTCALL, os_putenv__doc__}, + +static PyObject * +os_putenv_impl(PyObject *module, PyObject *name, PyObject *value); + +static PyObject * +os_putenv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *name; + PyObject *value; + + if (!_PyArg_CheckPositional("putenv", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("putenv", "argument 1", "str", args[0]); + goto exit; + } + if (PyUnicode_READY(args[0]) == -1) { + goto exit; + } + name = args[0]; + if (!PyUnicode_Check(args[1])) { + _PyArg_BadArgument("putenv", "argument 2", "str", args[1]); + goto exit; + } + if (PyUnicode_READY(args[1]) == -1) { + goto exit; + } + value = args[1]; + return_value = os_putenv_impl(module, name, value); + +exit: + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if !defined(MS_WINDOWS) + +PyDoc_STRVAR(os_putenv__doc__, +"putenv($module, name, value, /)\n" +"--\n" +"\n" +"Change or add an environment variable."); + +#define OS_PUTENV_METHODDEF \ + {"putenv", _PyCFunction_CAST(os_putenv), METH_FASTCALL, os_putenv__doc__}, + +static PyObject * +os_putenv_impl(PyObject *module, PyObject *name, PyObject *value); + +static PyObject * +os_putenv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *name = NULL; + PyObject *value = NULL; + + if (!_PyArg_CheckPositional("putenv", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_FSConverter(args[0], &name)) { + goto exit; + } + if (!PyUnicode_FSConverter(args[1], &value)) { + goto exit; + } + return_value = os_putenv_impl(module, name, value); + +exit: + /* Cleanup for name */ + Py_XDECREF(name); + /* Cleanup for value */ + Py_XDECREF(value); + + return return_value; +} + +#endif /* !defined(MS_WINDOWS) */ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(os_unsetenv__doc__, +"unsetenv($module, name, /)\n" +"--\n" +"\n" +"Delete an environment variable."); + +#define OS_UNSETENV_METHODDEF \ + {"unsetenv", (PyCFunction)os_unsetenv, METH_O, os_unsetenv__doc__}, + +static PyObject * +os_unsetenv_impl(PyObject *module, PyObject *name); + +static PyObject * +os_unsetenv(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyObject *name; + + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("unsetenv", "argument", "str", arg); + goto exit; + } + if (PyUnicode_READY(arg) == -1) { + goto exit; + } + name = arg; + return_value = os_unsetenv_impl(module, name); + +exit: + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if !defined(MS_WINDOWS) + +PyDoc_STRVAR(os_unsetenv__doc__, +"unsetenv($module, name, /)\n" +"--\n" +"\n" +"Delete an environment variable."); + +#define OS_UNSETENV_METHODDEF \ + {"unsetenv", (PyCFunction)os_unsetenv, METH_O, os_unsetenv__doc__}, + +static PyObject * +os_unsetenv_impl(PyObject *module, PyObject *name); + +static PyObject * +os_unsetenv(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyObject *name = NULL; + + if (!PyUnicode_FSConverter(arg, &name)) { + goto exit; + } + return_value = os_unsetenv_impl(module, name); + +exit: + /* Cleanup for name */ + Py_XDECREF(name); + + return return_value; +} + +#endif /* !defined(MS_WINDOWS) */ + +PyDoc_STRVAR(os_strerror__doc__, +"strerror($module, code, /)\n" +"--\n" +"\n" +"Translate an error code to a message string."); + +#define OS_STRERROR_METHODDEF \ + {"strerror", (PyCFunction)os_strerror, METH_O, os_strerror__doc__}, + +static PyObject * +os_strerror_impl(PyObject *module, int code); + +static PyObject * +os_strerror(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int code; + + code = _PyLong_AsInt(arg); + if (code == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_strerror_impl(module, code); + +exit: + return return_value; +} + +#if defined(HAVE_SYS_WAIT_H) && defined(WCOREDUMP) + +PyDoc_STRVAR(os_WCOREDUMP__doc__, +"WCOREDUMP($module, status, /)\n" +"--\n" +"\n" +"Return True if the process returning status was dumped to a core file."); + +#define OS_WCOREDUMP_METHODDEF \ + {"WCOREDUMP", (PyCFunction)os_WCOREDUMP, METH_O, os_WCOREDUMP__doc__}, + +static int +os_WCOREDUMP_impl(PyObject *module, int status); + +static PyObject * +os_WCOREDUMP(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int status; + int _return_value; + + status = _PyLong_AsInt(arg); + if (status == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_WCOREDUMP_impl(module, status); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SYS_WAIT_H) && defined(WCOREDUMP) */ + +#if defined(HAVE_SYS_WAIT_H) && defined(WIFCONTINUED) + +PyDoc_STRVAR(os_WIFCONTINUED__doc__, +"WIFCONTINUED($module, /, status)\n" +"--\n" +"\n" +"Return True if a particular process was continued from a job control stop.\n" +"\n" +"Return True if the process returning status was continued from a\n" +"job control stop."); + +#define OS_WIFCONTINUED_METHODDEF \ + {"WIFCONTINUED", _PyCFunction_CAST(os_WIFCONTINUED), METH_FASTCALL|METH_KEYWORDS, os_WIFCONTINUED__doc__}, + +static int +os_WIFCONTINUED_impl(PyObject *module, int status); + +static PyObject * +os_WIFCONTINUED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(status), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"status", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "WIFCONTINUED", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int status; + int _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + status = _PyLong_AsInt(args[0]); + if (status == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_WIFCONTINUED_impl(module, status); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SYS_WAIT_H) && defined(WIFCONTINUED) */ + +#if defined(HAVE_SYS_WAIT_H) && defined(WIFSTOPPED) + +PyDoc_STRVAR(os_WIFSTOPPED__doc__, +"WIFSTOPPED($module, /, status)\n" +"--\n" +"\n" +"Return True if the process returning status was stopped."); + +#define OS_WIFSTOPPED_METHODDEF \ + {"WIFSTOPPED", _PyCFunction_CAST(os_WIFSTOPPED), METH_FASTCALL|METH_KEYWORDS, os_WIFSTOPPED__doc__}, + +static int +os_WIFSTOPPED_impl(PyObject *module, int status); + +static PyObject * +os_WIFSTOPPED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(status), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"status", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "WIFSTOPPED", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int status; + int _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + status = _PyLong_AsInt(args[0]); + if (status == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_WIFSTOPPED_impl(module, status); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SYS_WAIT_H) && defined(WIFSTOPPED) */ + +#if defined(HAVE_SYS_WAIT_H) && defined(WIFSIGNALED) + +PyDoc_STRVAR(os_WIFSIGNALED__doc__, +"WIFSIGNALED($module, /, status)\n" +"--\n" +"\n" +"Return True if the process returning status was terminated by a signal."); + +#define OS_WIFSIGNALED_METHODDEF \ + {"WIFSIGNALED", _PyCFunction_CAST(os_WIFSIGNALED), METH_FASTCALL|METH_KEYWORDS, os_WIFSIGNALED__doc__}, + +static int +os_WIFSIGNALED_impl(PyObject *module, int status); + +static PyObject * +os_WIFSIGNALED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(status), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"status", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "WIFSIGNALED", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int status; + int _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + status = _PyLong_AsInt(args[0]); + if (status == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_WIFSIGNALED_impl(module, status); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SYS_WAIT_H) && defined(WIFSIGNALED) */ + +#if defined(HAVE_SYS_WAIT_H) && defined(WIFEXITED) + +PyDoc_STRVAR(os_WIFEXITED__doc__, +"WIFEXITED($module, /, status)\n" +"--\n" +"\n" +"Return True if the process returning status exited via the exit() system call."); + +#define OS_WIFEXITED_METHODDEF \ + {"WIFEXITED", _PyCFunction_CAST(os_WIFEXITED), METH_FASTCALL|METH_KEYWORDS, os_WIFEXITED__doc__}, + +static int +os_WIFEXITED_impl(PyObject *module, int status); + +static PyObject * +os_WIFEXITED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(status), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"status", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "WIFEXITED", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int status; + int _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + status = _PyLong_AsInt(args[0]); + if (status == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_WIFEXITED_impl(module, status); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SYS_WAIT_H) && defined(WIFEXITED) */ + +#if defined(HAVE_SYS_WAIT_H) && defined(WEXITSTATUS) + +PyDoc_STRVAR(os_WEXITSTATUS__doc__, +"WEXITSTATUS($module, /, status)\n" +"--\n" +"\n" +"Return the process return code from status."); + +#define OS_WEXITSTATUS_METHODDEF \ + {"WEXITSTATUS", _PyCFunction_CAST(os_WEXITSTATUS), METH_FASTCALL|METH_KEYWORDS, os_WEXITSTATUS__doc__}, + +static int +os_WEXITSTATUS_impl(PyObject *module, int status); + +static PyObject * +os_WEXITSTATUS(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(status), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"status", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "WEXITSTATUS", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int status; + int _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + status = _PyLong_AsInt(args[0]); + if (status == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_WEXITSTATUS_impl(module, status); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SYS_WAIT_H) && defined(WEXITSTATUS) */ + +#if defined(HAVE_SYS_WAIT_H) && defined(WTERMSIG) + +PyDoc_STRVAR(os_WTERMSIG__doc__, +"WTERMSIG($module, /, status)\n" +"--\n" +"\n" +"Return the signal that terminated the process that provided the status value."); + +#define OS_WTERMSIG_METHODDEF \ + {"WTERMSIG", _PyCFunction_CAST(os_WTERMSIG), METH_FASTCALL|METH_KEYWORDS, os_WTERMSIG__doc__}, + +static int +os_WTERMSIG_impl(PyObject *module, int status); + +static PyObject * +os_WTERMSIG(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(status), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"status", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "WTERMSIG", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int status; + int _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + status = _PyLong_AsInt(args[0]); + if (status == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_WTERMSIG_impl(module, status); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SYS_WAIT_H) && defined(WTERMSIG) */ + +#if defined(HAVE_SYS_WAIT_H) && defined(WSTOPSIG) + +PyDoc_STRVAR(os_WSTOPSIG__doc__, +"WSTOPSIG($module, /, status)\n" +"--\n" +"\n" +"Return the signal that stopped the process that provided the status value."); + +#define OS_WSTOPSIG_METHODDEF \ + {"WSTOPSIG", _PyCFunction_CAST(os_WSTOPSIG), METH_FASTCALL|METH_KEYWORDS, os_WSTOPSIG__doc__}, + +static int +os_WSTOPSIG_impl(PyObject *module, int status); + +static PyObject * +os_WSTOPSIG(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(status), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"status", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "WSTOPSIG", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int status; + int _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + status = _PyLong_AsInt(args[0]); + if (status == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_WSTOPSIG_impl(module, status); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SYS_WAIT_H) && defined(WSTOPSIG) */ + +#if (defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)) + +PyDoc_STRVAR(os_fstatvfs__doc__, +"fstatvfs($module, fd, /)\n" +"--\n" +"\n" +"Perform an fstatvfs system call on the given fd.\n" +"\n" +"Equivalent to statvfs(fd)."); + +#define OS_FSTATVFS_METHODDEF \ + {"fstatvfs", (PyCFunction)os_fstatvfs, METH_O, os_fstatvfs__doc__}, + +static PyObject * +os_fstatvfs_impl(PyObject *module, int fd); + +static PyObject * +os_fstatvfs(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int fd; + + fd = _PyLong_AsInt(arg); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_fstatvfs_impl(module, fd); + +exit: + return return_value; +} + +#endif /* (defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)) */ + +#if (defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)) + +PyDoc_STRVAR(os_statvfs__doc__, +"statvfs($module, /, path)\n" +"--\n" +"\n" +"Perform a statvfs system call on the given path.\n" +"\n" +"path may always be specified as a string.\n" +"On some platforms, path may also be specified as an open file descriptor.\n" +" If this functionality is unavailable, using it raises an exception."); + +#define OS_STATVFS_METHODDEF \ + {"statvfs", _PyCFunction_CAST(os_statvfs), METH_FASTCALL|METH_KEYWORDS, os_statvfs__doc__}, + +static PyObject * +os_statvfs_impl(PyObject *module, path_t *path); + +static PyObject * +os_statvfs(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "statvfs", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + path_t path = PATH_T_INITIALIZE("statvfs", "path", 0, PATH_HAVE_FSTATVFS); + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + return_value = os_statvfs_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* (defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)) */ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(os__getdiskusage__doc__, +"_getdiskusage($module, /, path)\n" +"--\n" +"\n" +"Return disk usage statistics about the given path as a (total, free) tuple."); + +#define OS__GETDISKUSAGE_METHODDEF \ + {"_getdiskusage", _PyCFunction_CAST(os__getdiskusage), METH_FASTCALL|METH_KEYWORDS, os__getdiskusage__doc__}, + +static PyObject * +os__getdiskusage_impl(PyObject *module, path_t *path); + +static PyObject * +os__getdiskusage(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "_getdiskusage", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + path_t path = PATH_T_INITIALIZE("_getdiskusage", "path", 0, 0); + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + return_value = os__getdiskusage_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if defined(HAVE_FPATHCONF) + +PyDoc_STRVAR(os_fpathconf__doc__, +"fpathconf($module, fd, name, /)\n" +"--\n" +"\n" +"Return the configuration limit name for the file descriptor fd.\n" +"\n" +"If there is no limit, return -1."); + +#define OS_FPATHCONF_METHODDEF \ + {"fpathconf", _PyCFunction_CAST(os_fpathconf), METH_FASTCALL, os_fpathconf__doc__}, + +static long +os_fpathconf_impl(PyObject *module, int fd, int name); + +static PyObject * +os_fpathconf(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + int name; + long _return_value; + + if (!_PyArg_CheckPositional("fpathconf", nargs, 2, 2)) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + if (!conv_path_confname(args[1], &name)) { + goto exit; + } + _return_value = os_fpathconf_impl(module, fd, name); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong(_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_FPATHCONF) */ + +#if defined(HAVE_PATHCONF) + +PyDoc_STRVAR(os_pathconf__doc__, +"pathconf($module, /, path, name)\n" +"--\n" +"\n" +"Return the configuration limit name for the file or directory path.\n" +"\n" +"If there is no limit, return -1.\n" +"On some platforms, path may also be specified as an open file descriptor.\n" +" If this functionality is unavailable, using it raises an exception."); + +#define OS_PATHCONF_METHODDEF \ + {"pathconf", _PyCFunction_CAST(os_pathconf), METH_FASTCALL|METH_KEYWORDS, os_pathconf__doc__}, + +static long +os_pathconf_impl(PyObject *module, path_t *path, int name); + +static PyObject * +os_pathconf(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(name), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "name", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "pathconf", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + path_t path = PATH_T_INITIALIZE("pathconf", "path", 0, PATH_HAVE_FPATHCONF); + int name; + long _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!conv_path_confname(args[1], &name)) { + goto exit; + } + _return_value = os_pathconf_impl(module, &path, name); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong(_return_value); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(HAVE_PATHCONF) */ + +#if defined(HAVE_CONFSTR) + +PyDoc_STRVAR(os_confstr__doc__, +"confstr($module, name, /)\n" +"--\n" +"\n" +"Return a string-valued system configuration variable."); + +#define OS_CONFSTR_METHODDEF \ + {"confstr", (PyCFunction)os_confstr, METH_O, os_confstr__doc__}, + +static PyObject * +os_confstr_impl(PyObject *module, int name); + +static PyObject * +os_confstr(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int name; + + if (!conv_confstr_confname(arg, &name)) { + goto exit; + } + return_value = os_confstr_impl(module, name); + +exit: + return return_value; +} + +#endif /* defined(HAVE_CONFSTR) */ + +#if defined(HAVE_SYSCONF) + +PyDoc_STRVAR(os_sysconf__doc__, +"sysconf($module, name, /)\n" +"--\n" +"\n" +"Return an integer-valued system configuration variable."); + +#define OS_SYSCONF_METHODDEF \ + {"sysconf", (PyCFunction)os_sysconf, METH_O, os_sysconf__doc__}, + +static long +os_sysconf_impl(PyObject *module, int name); + +static PyObject * +os_sysconf(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int name; + long _return_value; + + if (!conv_sysconf_confname(arg, &name)) { + goto exit; + } + _return_value = os_sysconf_impl(module, name); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong(_return_value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SYSCONF) */ + +PyDoc_STRVAR(os_abort__doc__, +"abort($module, /)\n" +"--\n" +"\n" +"Abort the interpreter immediately.\n" +"\n" +"This function \'dumps core\' or otherwise fails in the hardest way possible\n" +"on the hosting operating system. This function never returns."); + +#define OS_ABORT_METHODDEF \ + {"abort", (PyCFunction)os_abort, METH_NOARGS, os_abort__doc__}, + +static PyObject * +os_abort_impl(PyObject *module); + +static PyObject * +os_abort(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_abort_impl(module); +} + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(os_startfile__doc__, +"startfile($module, /, filepath, operation=,\n" +" arguments=, cwd=None, show_cmd=1)\n" +"--\n" +"\n" +"Start a file with its associated application.\n" +"\n" +"When \"operation\" is not specified or \"open\", this acts like\n" +"double-clicking the file in Explorer, or giving the file name as an\n" +"argument to the DOS \"start\" command: the file is opened with whatever\n" +"application (if any) its extension is associated.\n" +"When another \"operation\" is given, it specifies what should be done with\n" +"the file. A typical operation is \"print\".\n" +"\n" +"\"arguments\" is passed to the application, but should be omitted if the\n" +"file is a document.\n" +"\n" +"\"cwd\" is the working directory for the operation. If \"filepath\" is\n" +"relative, it will be resolved against this directory. This argument\n" +"should usually be an absolute path.\n" +"\n" +"\"show_cmd\" can be used to override the recommended visibility option.\n" +"See the Windows ShellExecute documentation for values.\n" +"\n" +"startfile returns as soon as the associated application is launched.\n" +"There is no option to wait for the application to close, and no way\n" +"to retrieve the application\'s exit status.\n" +"\n" +"The filepath is relative to the current directory. If you want to use\n" +"an absolute path, make sure the first character is not a slash (\"/\");\n" +"the underlying Win32 ShellExecute function doesn\'t work if it is."); + +#define OS_STARTFILE_METHODDEF \ + {"startfile", _PyCFunction_CAST(os_startfile), METH_FASTCALL|METH_KEYWORDS, os_startfile__doc__}, + +static PyObject * +os_startfile_impl(PyObject *module, path_t *filepath, + const Py_UNICODE *operation, const Py_UNICODE *arguments, + path_t *cwd, int show_cmd); + +static PyObject * +os_startfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 5 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(filepath), &_Py_ID(operation), &_Py_ID(arguments), &_Py_ID(cwd), &_Py_ID(show_cmd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"filepath", "operation", "arguments", "cwd", "show_cmd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "startfile", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + path_t filepath = PATH_T_INITIALIZE("startfile", "filepath", 0, 0); + const Py_UNICODE *operation = NULL; + const Py_UNICODE *arguments = NULL; + path_t cwd = PATH_T_INITIALIZE("startfile", "cwd", 1, 0); + int show_cmd = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 5, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &filepath)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[1]) { + if (!PyUnicode_Check(args[1])) { + _PyArg_BadArgument("startfile", "argument 'operation'", "str", args[1]); + goto exit; + } + operation = PyUnicode_AsWideCharString(args[1], NULL); + if (operation == NULL) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[2]) { + if (!PyUnicode_Check(args[2])) { + _PyArg_BadArgument("startfile", "argument 'arguments'", "str", args[2]); + goto exit; + } + arguments = PyUnicode_AsWideCharString(args[2], NULL); + if (arguments == NULL) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[3]) { + if (!path_converter(args[3], &cwd)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + show_cmd = _PyLong_AsInt(args[4]); + if (show_cmd == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_pos: + return_value = os_startfile_impl(module, &filepath, operation, arguments, &cwd, show_cmd); + +exit: + /* Cleanup for filepath */ + path_cleanup(&filepath); + /* Cleanup for operation */ + PyMem_Free((void *)operation); + /* Cleanup for arguments */ + PyMem_Free((void *)arguments); + /* Cleanup for cwd */ + path_cleanup(&cwd); + + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if defined(HAVE_GETLOADAVG) + +PyDoc_STRVAR(os_getloadavg__doc__, +"getloadavg($module, /)\n" +"--\n" +"\n" +"Return average recent system load information.\n" +"\n" +"Return the number of processes in the system run queue averaged over\n" +"the last 1, 5, and 15 minutes as a tuple of three floats.\n" +"Raises OSError if the load average was unobtainable."); + +#define OS_GETLOADAVG_METHODDEF \ + {"getloadavg", (PyCFunction)os_getloadavg, METH_NOARGS, os_getloadavg__doc__}, + +static PyObject * +os_getloadavg_impl(PyObject *module); + +static PyObject * +os_getloadavg(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getloadavg_impl(module); +} + +#endif /* defined(HAVE_GETLOADAVG) */ + +PyDoc_STRVAR(os_device_encoding__doc__, +"device_encoding($module, /, fd)\n" +"--\n" +"\n" +"Return a string describing the encoding of a terminal\'s file descriptor.\n" +"\n" +"The file descriptor must be attached to a terminal.\n" +"If the device is not a terminal, return None."); + +#define OS_DEVICE_ENCODING_METHODDEF \ + {"device_encoding", _PyCFunction_CAST(os_device_encoding), METH_FASTCALL|METH_KEYWORDS, os_device_encoding__doc__}, + +static PyObject * +os_device_encoding_impl(PyObject *module, int fd); + +static PyObject * +os_device_encoding(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "device_encoding", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int fd; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_device_encoding_impl(module, fd); + +exit: + return return_value; +} + +#if defined(HAVE_SETRESUID) + +PyDoc_STRVAR(os_setresuid__doc__, +"setresuid($module, ruid, euid, suid, /)\n" +"--\n" +"\n" +"Set the current process\'s real, effective, and saved user ids."); + +#define OS_SETRESUID_METHODDEF \ + {"setresuid", _PyCFunction_CAST(os_setresuid), METH_FASTCALL, os_setresuid__doc__}, + +static PyObject * +os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid); + +static PyObject * +os_setresuid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + uid_t ruid; + uid_t euid; + uid_t suid; + + if (!_PyArg_CheckPositional("setresuid", nargs, 3, 3)) { + goto exit; + } + if (!_Py_Uid_Converter(args[0], &ruid)) { + goto exit; + } + if (!_Py_Uid_Converter(args[1], &euid)) { + goto exit; + } + if (!_Py_Uid_Converter(args[2], &suid)) { + goto exit; + } + return_value = os_setresuid_impl(module, ruid, euid, suid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SETRESUID) */ + +#if defined(HAVE_SETRESGID) + +PyDoc_STRVAR(os_setresgid__doc__, +"setresgid($module, rgid, egid, sgid, /)\n" +"--\n" +"\n" +"Set the current process\'s real, effective, and saved group ids."); + +#define OS_SETRESGID_METHODDEF \ + {"setresgid", _PyCFunction_CAST(os_setresgid), METH_FASTCALL, os_setresgid__doc__}, + +static PyObject * +os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid); + +static PyObject * +os_setresgid(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + gid_t rgid; + gid_t egid; + gid_t sgid; + + if (!_PyArg_CheckPositional("setresgid", nargs, 3, 3)) { + goto exit; + } + if (!_Py_Gid_Converter(args[0], &rgid)) { + goto exit; + } + if (!_Py_Gid_Converter(args[1], &egid)) { + goto exit; + } + if (!_Py_Gid_Converter(args[2], &sgid)) { + goto exit; + } + return_value = os_setresgid_impl(module, rgid, egid, sgid); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SETRESGID) */ + +#if defined(HAVE_GETRESUID) + +PyDoc_STRVAR(os_getresuid__doc__, +"getresuid($module, /)\n" +"--\n" +"\n" +"Return a tuple of the current process\'s real, effective, and saved user ids."); + +#define OS_GETRESUID_METHODDEF \ + {"getresuid", (PyCFunction)os_getresuid, METH_NOARGS, os_getresuid__doc__}, + +static PyObject * +os_getresuid_impl(PyObject *module); + +static PyObject * +os_getresuid(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getresuid_impl(module); +} + +#endif /* defined(HAVE_GETRESUID) */ + +#if defined(HAVE_GETRESGID) + +PyDoc_STRVAR(os_getresgid__doc__, +"getresgid($module, /)\n" +"--\n" +"\n" +"Return a tuple of the current process\'s real, effective, and saved group ids."); + +#define OS_GETRESGID_METHODDEF \ + {"getresgid", (PyCFunction)os_getresgid, METH_NOARGS, os_getresgid__doc__}, + +static PyObject * +os_getresgid_impl(PyObject *module); + +static PyObject * +os_getresgid(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getresgid_impl(module); +} + +#endif /* defined(HAVE_GETRESGID) */ + +#if defined(USE_XATTRS) + +PyDoc_STRVAR(os_getxattr__doc__, +"getxattr($module, /, path, attribute, *, follow_symlinks=True)\n" +"--\n" +"\n" +"Return the value of extended attribute attribute on path.\n" +"\n" +"path may be either a string, a path-like object, or an open file descriptor.\n" +"If follow_symlinks is False, and the last element of the path is a symbolic\n" +" link, getxattr will examine the symbolic link itself instead of the file\n" +" the link points to."); + +#define OS_GETXATTR_METHODDEF \ + {"getxattr", _PyCFunction_CAST(os_getxattr), METH_FASTCALL|METH_KEYWORDS, os_getxattr__doc__}, + +static PyObject * +os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute, + int follow_symlinks); + +static PyObject * +os_getxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(attribute), &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "attribute", "follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "getxattr", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + path_t path = PATH_T_INITIALIZE("getxattr", "path", 0, 1); + path_t attribute = PATH_T_INITIALIZE("getxattr", "attribute", 0, 0); + int follow_symlinks = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!path_converter(args[1], &attribute)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + follow_symlinks = PyObject_IsTrue(args[2]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = os_getxattr_impl(module, &path, &attribute, follow_symlinks); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + /* Cleanup for attribute */ + path_cleanup(&attribute); + + return return_value; +} + +#endif /* defined(USE_XATTRS) */ + +#if defined(USE_XATTRS) + +PyDoc_STRVAR(os_setxattr__doc__, +"setxattr($module, /, path, attribute, value, flags=0, *,\n" +" follow_symlinks=True)\n" +"--\n" +"\n" +"Set extended attribute attribute on path to value.\n" +"\n" +"path may be either a string, a path-like object, or an open file descriptor.\n" +"If follow_symlinks is False, and the last element of the path is a symbolic\n" +" link, setxattr will modify the symbolic link itself instead of the file\n" +" the link points to."); + +#define OS_SETXATTR_METHODDEF \ + {"setxattr", _PyCFunction_CAST(os_setxattr), METH_FASTCALL|METH_KEYWORDS, os_setxattr__doc__}, + +static PyObject * +os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute, + Py_buffer *value, int flags, int follow_symlinks); + +static PyObject * +os_setxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 5 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(attribute), &_Py_ID(value), &_Py_ID(flags), &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "attribute", "value", "flags", "follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "setxattr", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; + path_t path = PATH_T_INITIALIZE("setxattr", "path", 0, 1); + path_t attribute = PATH_T_INITIALIZE("setxattr", "attribute", 0, 0); + Py_buffer value = {NULL, NULL}; + int flags = 0; + int follow_symlinks = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 4, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!path_converter(args[1], &attribute)) { + goto exit; + } + if (PyObject_GetBuffer(args[2], &value, PyBUF_SIMPLE) != 0) { + goto exit; + } + if (!PyBuffer_IsContiguous(&value, 'C')) { + _PyArg_BadArgument("setxattr", "argument 'value'", "contiguous buffer", args[2]); + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[3]) { + flags = _PyLong_AsInt(args[3]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + follow_symlinks = PyObject_IsTrue(args[4]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = os_setxattr_impl(module, &path, &attribute, &value, flags, follow_symlinks); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + /* Cleanup for attribute */ + path_cleanup(&attribute); + /* Cleanup for value */ + if (value.obj) { + PyBuffer_Release(&value); + } + + return return_value; +} + +#endif /* defined(USE_XATTRS) */ + +#if defined(USE_XATTRS) + +PyDoc_STRVAR(os_removexattr__doc__, +"removexattr($module, /, path, attribute, *, follow_symlinks=True)\n" +"--\n" +"\n" +"Remove extended attribute attribute on path.\n" +"\n" +"path may be either a string, a path-like object, or an open file descriptor.\n" +"If follow_symlinks is False, and the last element of the path is a symbolic\n" +" link, removexattr will modify the symbolic link itself instead of the file\n" +" the link points to."); + +#define OS_REMOVEXATTR_METHODDEF \ + {"removexattr", _PyCFunction_CAST(os_removexattr), METH_FASTCALL|METH_KEYWORDS, os_removexattr__doc__}, + +static PyObject * +os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute, + int follow_symlinks); + +static PyObject * +os_removexattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(attribute), &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "attribute", "follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "removexattr", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + path_t path = PATH_T_INITIALIZE("removexattr", "path", 0, 1); + path_t attribute = PATH_T_INITIALIZE("removexattr", "attribute", 0, 0); + int follow_symlinks = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!path_converter(args[1], &attribute)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + follow_symlinks = PyObject_IsTrue(args[2]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = os_removexattr_impl(module, &path, &attribute, follow_symlinks); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + /* Cleanup for attribute */ + path_cleanup(&attribute); + + return return_value; +} + +#endif /* defined(USE_XATTRS) */ + +#if defined(USE_XATTRS) + +PyDoc_STRVAR(os_listxattr__doc__, +"listxattr($module, /, path=None, *, follow_symlinks=True)\n" +"--\n" +"\n" +"Return a list of extended attributes on path.\n" +"\n" +"path may be either None, a string, a path-like object, or an open file descriptor.\n" +"if path is None, listxattr will examine the current directory.\n" +"If follow_symlinks is False, and the last element of the path is a symbolic\n" +" link, listxattr will examine the symbolic link itself instead of the file\n" +" the link points to."); + +#define OS_LISTXATTR_METHODDEF \ + {"listxattr", _PyCFunction_CAST(os_listxattr), METH_FASTCALL|METH_KEYWORDS, os_listxattr__doc__}, + +static PyObject * +os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks); + +static PyObject * +os_listxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", "follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "listxattr", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + path_t path = PATH_T_INITIALIZE("listxattr", "path", 1, 1); + int follow_symlinks = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[0]) { + if (!path_converter(args[0], &path)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + follow_symlinks = PyObject_IsTrue(args[1]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = os_listxattr_impl(module, &path, follow_symlinks); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(USE_XATTRS) */ + +PyDoc_STRVAR(os_urandom__doc__, +"urandom($module, size, /)\n" +"--\n" +"\n" +"Return a bytes object containing random bytes suitable for cryptographic use."); + +#define OS_URANDOM_METHODDEF \ + {"urandom", (PyCFunction)os_urandom, METH_O, os_urandom__doc__}, + +static PyObject * +os_urandom_impl(PyObject *module, Py_ssize_t size); + +static PyObject * +os_urandom(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + Py_ssize_t size; + + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(arg); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + size = ival; + } + return_value = os_urandom_impl(module, size); + +exit: + return return_value; +} + +#if defined(HAVE_MEMFD_CREATE) + +PyDoc_STRVAR(os_memfd_create__doc__, +"memfd_create($module, /, name, flags=MFD_CLOEXEC)\n" +"--\n" +"\n"); + +#define OS_MEMFD_CREATE_METHODDEF \ + {"memfd_create", _PyCFunction_CAST(os_memfd_create), METH_FASTCALL|METH_KEYWORDS, os_memfd_create__doc__}, + +static PyObject * +os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags); + +static PyObject * +os_memfd_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(name), &_Py_ID(flags), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"name", "flags", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "memfd_create", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *name = NULL; + unsigned int flags = MFD_CLOEXEC; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!PyUnicode_FSConverter(args[0], &name)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + flags = (unsigned int)PyLong_AsUnsignedLongMask(args[1]); + if (flags == (unsigned int)-1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_pos: + return_value = os_memfd_create_impl(module, name, flags); + +exit: + /* Cleanup for name */ + Py_XDECREF(name); + + return return_value; +} + +#endif /* defined(HAVE_MEMFD_CREATE) */ + +#if (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) + +PyDoc_STRVAR(os_eventfd__doc__, +"eventfd($module, /, initval, flags=EFD_CLOEXEC)\n" +"--\n" +"\n" +"Creates and returns an event notification file descriptor."); + +#define OS_EVENTFD_METHODDEF \ + {"eventfd", _PyCFunction_CAST(os_eventfd), METH_FASTCALL|METH_KEYWORDS, os_eventfd__doc__}, + +static PyObject * +os_eventfd_impl(PyObject *module, unsigned int initval, int flags); + +static PyObject * +os_eventfd(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(initval), &_Py_ID(flags), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"initval", "flags", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "eventfd", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + unsigned int initval; + int flags = EFD_CLOEXEC; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!_PyLong_UnsignedInt_Converter(args[0], &initval)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + flags = _PyLong_AsInt(args[1]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_pos: + return_value = os_eventfd_impl(module, initval, flags); + +exit: + return return_value; +} + +#endif /* (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) */ + +#if (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) + +PyDoc_STRVAR(os_eventfd_read__doc__, +"eventfd_read($module, /, fd)\n" +"--\n" +"\n" +"Read eventfd value"); + +#define OS_EVENTFD_READ_METHODDEF \ + {"eventfd_read", _PyCFunction_CAST(os_eventfd_read), METH_FASTCALL|METH_KEYWORDS, os_eventfd_read__doc__}, + +static PyObject * +os_eventfd_read_impl(PyObject *module, int fd); + +static PyObject * +os_eventfd_read(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(fd), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"fd", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "eventfd_read", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int fd; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + return_value = os_eventfd_read_impl(module, fd); + +exit: + return return_value; +} + +#endif /* (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) */ + +#if (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) + +PyDoc_STRVAR(os_eventfd_write__doc__, +"eventfd_write($module, /, fd, value)\n" +"--\n" +"\n" +"Write eventfd value."); + +#define OS_EVENTFD_WRITE_METHODDEF \ + {"eventfd_write", _PyCFunction_CAST(os_eventfd_write), METH_FASTCALL|METH_KEYWORDS, os_eventfd_write__doc__}, + +static PyObject * +os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value); + +static PyObject * +os_eventfd_write(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(fd), &_Py_ID(value), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"fd", "value", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "eventfd_write", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + int fd; + unsigned long long value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + if (!_PyLong_UnsignedLongLong_Converter(args[1], &value)) { + goto exit; + } + return_value = os_eventfd_write_impl(module, fd, value); + +exit: + return return_value; +} + +#endif /* (defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)) */ + +#if (defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)) + +PyDoc_STRVAR(os_get_terminal_size__doc__, +"get_terminal_size($module, fd=, /)\n" +"--\n" +"\n" +"Return the size of the terminal window as (columns, lines).\n" +"\n" +"The optional argument fd (default standard output) specifies\n" +"which file descriptor should be queried.\n" +"\n" +"If the file descriptor is not connected to a terminal, an OSError\n" +"is thrown.\n" +"\n" +"This function will only be defined if an implementation is\n" +"available for this system.\n" +"\n" +"shutil.get_terminal_size is the high-level function which should\n" +"normally be used, os.get_terminal_size is the low-level implementation."); + +#define OS_GET_TERMINAL_SIZE_METHODDEF \ + {"get_terminal_size", _PyCFunction_CAST(os_get_terminal_size), METH_FASTCALL, os_get_terminal_size__doc__}, + +static PyObject * +os_get_terminal_size_impl(PyObject *module, int fd); + +static PyObject * +os_get_terminal_size(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd = fileno(stdout); + + if (!_PyArg_CheckPositional("get_terminal_size", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = os_get_terminal_size_impl(module, fd); + +exit: + return return_value; +} + +#endif /* (defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)) */ + +PyDoc_STRVAR(os_cpu_count__doc__, +"cpu_count($module, /)\n" +"--\n" +"\n" +"Return the number of CPUs in the system; return None if indeterminable.\n" +"\n" +"This number is not equivalent to the number of CPUs the current process can\n" +"use. The number of usable CPUs can be obtained with\n" +"``len(os.sched_getaffinity(0))``"); + +#define OS_CPU_COUNT_METHODDEF \ + {"cpu_count", (PyCFunction)os_cpu_count, METH_NOARGS, os_cpu_count__doc__}, + +static PyObject * +os_cpu_count_impl(PyObject *module); + +static PyObject * +os_cpu_count(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return os_cpu_count_impl(module); +} + +PyDoc_STRVAR(os_get_inheritable__doc__, +"get_inheritable($module, fd, /)\n" +"--\n" +"\n" +"Get the close-on-exe flag of the specified file descriptor."); + +#define OS_GET_INHERITABLE_METHODDEF \ + {"get_inheritable", (PyCFunction)os_get_inheritable, METH_O, os_get_inheritable__doc__}, + +static int +os_get_inheritable_impl(PyObject *module, int fd); + +static PyObject * +os_get_inheritable(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int fd; + int _return_value; + + fd = _PyLong_AsInt(arg); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_get_inheritable_impl(module, fd); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(os_set_inheritable__doc__, +"set_inheritable($module, fd, inheritable, /)\n" +"--\n" +"\n" +"Set the inheritable flag of the specified file descriptor."); + +#define OS_SET_INHERITABLE_METHODDEF \ + {"set_inheritable", _PyCFunction_CAST(os_set_inheritable), METH_FASTCALL, os_set_inheritable__doc__}, + +static PyObject * +os_set_inheritable_impl(PyObject *module, int fd, int inheritable); + +static PyObject * +os_set_inheritable(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + int inheritable; + + if (!_PyArg_CheckPositional("set_inheritable", nargs, 2, 2)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + inheritable = _PyLong_AsInt(args[1]); + if (inheritable == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_set_inheritable_impl(module, fd, inheritable); + +exit: + return return_value; +} + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(os_get_handle_inheritable__doc__, +"get_handle_inheritable($module, handle, /)\n" +"--\n" +"\n" +"Get the close-on-exe flag of the specified file descriptor."); + +#define OS_GET_HANDLE_INHERITABLE_METHODDEF \ + {"get_handle_inheritable", (PyCFunction)os_get_handle_inheritable, METH_O, os_get_handle_inheritable__doc__}, + +static int +os_get_handle_inheritable_impl(PyObject *module, intptr_t handle); + +static PyObject * +os_get_handle_inheritable(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + intptr_t handle; + int _return_value; + + if (!PyArg_Parse(arg, "" _Py_PARSE_INTPTR ":get_handle_inheritable", &handle)) { + goto exit; + } + _return_value = os_get_handle_inheritable_impl(module, handle); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(os_set_handle_inheritable__doc__, +"set_handle_inheritable($module, handle, inheritable, /)\n" +"--\n" +"\n" +"Set the inheritable flag of the specified handle."); + +#define OS_SET_HANDLE_INHERITABLE_METHODDEF \ + {"set_handle_inheritable", _PyCFunction_CAST(os_set_handle_inheritable), METH_FASTCALL, os_set_handle_inheritable__doc__}, + +static PyObject * +os_set_handle_inheritable_impl(PyObject *module, intptr_t handle, + int inheritable); + +static PyObject * +os_set_handle_inheritable(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + intptr_t handle; + int inheritable; + + if (!_PyArg_ParseStack(args, nargs, "" _Py_PARSE_INTPTR "p:set_handle_inheritable", + &handle, &inheritable)) { + goto exit; + } + return_value = os_set_handle_inheritable_impl(module, handle, inheritable); + +exit: + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if !defined(MS_WINDOWS) + +PyDoc_STRVAR(os_get_blocking__doc__, +"get_blocking($module, fd, /)\n" +"--\n" +"\n" +"Get the blocking mode of the file descriptor.\n" +"\n" +"Return False if the O_NONBLOCK flag is set, True if the flag is cleared."); + +#define OS_GET_BLOCKING_METHODDEF \ + {"get_blocking", (PyCFunction)os_get_blocking, METH_O, os_get_blocking__doc__}, + +static int +os_get_blocking_impl(PyObject *module, int fd); + +static PyObject * +os_get_blocking(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int fd; + int _return_value; + + fd = _PyLong_AsInt(arg); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + _return_value = os_get_blocking_impl(module, fd); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +#endif /* !defined(MS_WINDOWS) */ + +#if !defined(MS_WINDOWS) + +PyDoc_STRVAR(os_set_blocking__doc__, +"set_blocking($module, fd, blocking, /)\n" +"--\n" +"\n" +"Set the blocking mode of the specified file descriptor.\n" +"\n" +"Set the O_NONBLOCK flag if blocking is False,\n" +"clear the O_NONBLOCK flag otherwise."); + +#define OS_SET_BLOCKING_METHODDEF \ + {"set_blocking", _PyCFunction_CAST(os_set_blocking), METH_FASTCALL, os_set_blocking__doc__}, + +static PyObject * +os_set_blocking_impl(PyObject *module, int fd, int blocking); + +static PyObject * +os_set_blocking(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + int blocking; + + if (!_PyArg_CheckPositional("set_blocking", nargs, 2, 2)) { + goto exit; + } + fd = _PyLong_AsInt(args[0]); + if (fd == -1 && PyErr_Occurred()) { + goto exit; + } + blocking = _PyLong_AsInt(args[1]); + if (blocking == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = os_set_blocking_impl(module, fd, blocking); + +exit: + return return_value; +} + +#endif /* !defined(MS_WINDOWS) */ + +PyDoc_STRVAR(os_DirEntry_is_symlink__doc__, +"is_symlink($self, /)\n" +"--\n" +"\n" +"Return True if the entry is a symbolic link; cached per entry."); + +#define OS_DIRENTRY_IS_SYMLINK_METHODDEF \ + {"is_symlink", _PyCFunction_CAST(os_DirEntry_is_symlink), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, os_DirEntry_is_symlink__doc__}, + +static int +os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class); + +static PyObject * +os_DirEntry_is_symlink(DirEntry *self, PyTypeObject *defining_class, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + int _return_value; + + if (nargs) { + PyErr_SetString(PyExc_TypeError, "is_symlink() takes no arguments"); + goto exit; + } + _return_value = os_DirEntry_is_symlink_impl(self, defining_class); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(os_DirEntry_is_junction__doc__, +"is_junction($self, /)\n" +"--\n" +"\n" +"Return True if the entry is a junction; cached per entry."); + +#define OS_DIRENTRY_IS_JUNCTION_METHODDEF \ + {"is_junction", _PyCFunction_CAST(os_DirEntry_is_junction), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, os_DirEntry_is_junction__doc__}, + +static int +os_DirEntry_is_junction_impl(DirEntry *self, PyTypeObject *defining_class); + +static PyObject * +os_DirEntry_is_junction(DirEntry *self, PyTypeObject *defining_class, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + int _return_value; + + if (nargs) { + PyErr_SetString(PyExc_TypeError, "is_junction() takes no arguments"); + goto exit; + } + _return_value = os_DirEntry_is_junction_impl(self, defining_class); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(os_DirEntry_stat__doc__, +"stat($self, /, *, follow_symlinks=True)\n" +"--\n" +"\n" +"Return stat_result object for the entry; cached per entry."); + +#define OS_DIRENTRY_STAT_METHODDEF \ + {"stat", _PyCFunction_CAST(os_DirEntry_stat), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, os_DirEntry_stat__doc__}, + +static PyObject * +os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class, + int follow_symlinks); + +static PyObject * +os_DirEntry_stat(DirEntry *self, PyTypeObject *defining_class, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "stat", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + int follow_symlinks = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + follow_symlinks = PyObject_IsTrue(args[0]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = os_DirEntry_stat_impl(self, defining_class, follow_symlinks); + +exit: + return return_value; +} + +PyDoc_STRVAR(os_DirEntry_is_dir__doc__, +"is_dir($self, /, *, follow_symlinks=True)\n" +"--\n" +"\n" +"Return True if the entry is a directory; cached per entry."); + +#define OS_DIRENTRY_IS_DIR_METHODDEF \ + {"is_dir", _PyCFunction_CAST(os_DirEntry_is_dir), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, os_DirEntry_is_dir__doc__}, + +static int +os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class, + int follow_symlinks); + +static PyObject * +os_DirEntry_is_dir(DirEntry *self, PyTypeObject *defining_class, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "is_dir", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + int follow_symlinks = 1; + int _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + follow_symlinks = PyObject_IsTrue(args[0]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + _return_value = os_DirEntry_is_dir_impl(self, defining_class, follow_symlinks); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(os_DirEntry_is_file__doc__, +"is_file($self, /, *, follow_symlinks=True)\n" +"--\n" +"\n" +"Return True if the entry is a file; cached per entry."); + +#define OS_DIRENTRY_IS_FILE_METHODDEF \ + {"is_file", _PyCFunction_CAST(os_DirEntry_is_file), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, os_DirEntry_is_file__doc__}, + +static int +os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class, + int follow_symlinks); + +static PyObject * +os_DirEntry_is_file(DirEntry *self, PyTypeObject *defining_class, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(follow_symlinks), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"follow_symlinks", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "is_file", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + int follow_symlinks = 1; + int _return_value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + follow_symlinks = PyObject_IsTrue(args[0]); + if (follow_symlinks < 0) { + goto exit; + } +skip_optional_kwonly: + _return_value = os_DirEntry_is_file_impl(self, defining_class, follow_symlinks); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(os_DirEntry_inode__doc__, +"inode($self, /)\n" +"--\n" +"\n" +"Return inode of the entry; cached per entry."); + +#define OS_DIRENTRY_INODE_METHODDEF \ + {"inode", (PyCFunction)os_DirEntry_inode, METH_NOARGS, os_DirEntry_inode__doc__}, + +static PyObject * +os_DirEntry_inode_impl(DirEntry *self); + +static PyObject * +os_DirEntry_inode(DirEntry *self, PyObject *Py_UNUSED(ignored)) +{ + return os_DirEntry_inode_impl(self); +} + +PyDoc_STRVAR(os_DirEntry___fspath____doc__, +"__fspath__($self, /)\n" +"--\n" +"\n" +"Returns the path for the entry."); + +#define OS_DIRENTRY___FSPATH___METHODDEF \ + {"__fspath__", (PyCFunction)os_DirEntry___fspath__, METH_NOARGS, os_DirEntry___fspath____doc__}, + +static PyObject * +os_DirEntry___fspath___impl(DirEntry *self); + +static PyObject * +os_DirEntry___fspath__(DirEntry *self, PyObject *Py_UNUSED(ignored)) +{ + return os_DirEntry___fspath___impl(self); +} + +PyDoc_STRVAR(os_scandir__doc__, +"scandir($module, /, path=None)\n" +"--\n" +"\n" +"Return an iterator of DirEntry objects for given path.\n" +"\n" +"path can be specified as either str, bytes, or a path-like object. If path\n" +"is bytes, the names of yielded DirEntry objects will also be bytes; in\n" +"all other circumstances they will be str.\n" +"\n" +"If path is None, uses the path=\'.\'."); + +#define OS_SCANDIR_METHODDEF \ + {"scandir", _PyCFunction_CAST(os_scandir), METH_FASTCALL|METH_KEYWORDS, os_scandir__doc__}, + +static PyObject * +os_scandir_impl(PyObject *module, path_t *path); + +static PyObject * +os_scandir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "scandir", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + path_t path = PATH_T_INITIALIZE("scandir", "path", 1, PATH_HAVE_FDOPENDIR); + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (!path_converter(args[0], &path)) { + goto exit; + } +skip_optional_pos: + return_value = os_scandir_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +PyDoc_STRVAR(os_fspath__doc__, +"fspath($module, /, path)\n" +"--\n" +"\n" +"Return the file system path representation of the object.\n" +"\n" +"If the object is str or bytes, then allow it to pass through as-is. If the\n" +"object defines __fspath__(), then return the result of that method. All other\n" +"types raise a TypeError."); + +#define OS_FSPATH_METHODDEF \ + {"fspath", _PyCFunction_CAST(os_fspath), METH_FASTCALL|METH_KEYWORDS, os_fspath__doc__}, + +static PyObject * +os_fspath_impl(PyObject *module, PyObject *path); + +static PyObject * +os_fspath(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "fspath", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *path; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + path = args[0]; + return_value = os_fspath_impl(module, path); + +exit: + return return_value; +} + +#if defined(HAVE_GETRANDOM_SYSCALL) + +PyDoc_STRVAR(os_getrandom__doc__, +"getrandom($module, /, size, flags=0)\n" +"--\n" +"\n" +"Obtain a series of random bytes."); + +#define OS_GETRANDOM_METHODDEF \ + {"getrandom", _PyCFunction_CAST(os_getrandom), METH_FASTCALL|METH_KEYWORDS, os_getrandom__doc__}, + +static PyObject * +os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags); + +static PyObject * +os_getrandom(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(size), &_Py_ID(flags), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"size", "flags", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "getrandom", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + Py_ssize_t size; + int flags = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[0]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + size = ival; + } + if (!noptargs) { + goto skip_optional_pos; + } + flags = _PyLong_AsInt(args[1]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_pos: + return_value = os_getrandom_impl(module, size, flags); + +exit: + return return_value; +} + +#endif /* defined(HAVE_GETRANDOM_SYSCALL) */ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(os__add_dll_directory__doc__, +"_add_dll_directory($module, /, path)\n" +"--\n" +"\n" +"Add a path to the DLL search path.\n" +"\n" +"This search path is used when resolving dependencies for imported\n" +"extension modules (the module itself is resolved through sys.path),\n" +"and also by ctypes.\n" +"\n" +"Returns an opaque value that may be passed to os.remove_dll_directory\n" +"to remove this directory from the search path."); + +#define OS__ADD_DLL_DIRECTORY_METHODDEF \ + {"_add_dll_directory", _PyCFunction_CAST(os__add_dll_directory), METH_FASTCALL|METH_KEYWORDS, os__add_dll_directory__doc__}, + +static PyObject * +os__add_dll_directory_impl(PyObject *module, path_t *path); + +static PyObject * +os__add_dll_directory(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(path), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"path", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "_add_dll_directory", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + path_t path = PATH_T_INITIALIZE("_add_dll_directory", "path", 0, 0); + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!path_converter(args[0], &path)) { + goto exit; + } + return_value = os__add_dll_directory_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(os__remove_dll_directory__doc__, +"_remove_dll_directory($module, /, cookie)\n" +"--\n" +"\n" +"Removes a path from the DLL search path.\n" +"\n" +"The parameter is an opaque value that was returned from\n" +"os.add_dll_directory. You can only remove directories that you added\n" +"yourself."); + +#define OS__REMOVE_DLL_DIRECTORY_METHODDEF \ + {"_remove_dll_directory", _PyCFunction_CAST(os__remove_dll_directory), METH_FASTCALL|METH_KEYWORDS, os__remove_dll_directory__doc__}, + +static PyObject * +os__remove_dll_directory_impl(PyObject *module, PyObject *cookie); + +static PyObject * +os__remove_dll_directory(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(cookie), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"cookie", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "_remove_dll_directory", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *cookie; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + cookie = args[0]; + return_value = os__remove_dll_directory_impl(module, cookie); + +exit: + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if (defined(WIFEXITED) || defined(MS_WINDOWS)) + +PyDoc_STRVAR(os_waitstatus_to_exitcode__doc__, +"waitstatus_to_exitcode($module, /, status)\n" +"--\n" +"\n" +"Convert a wait status to an exit code.\n" +"\n" +"On Unix:\n" +"\n" +"* If WIFEXITED(status) is true, return WEXITSTATUS(status).\n" +"* If WIFSIGNALED(status) is true, return -WTERMSIG(status).\n" +"* Otherwise, raise a ValueError.\n" +"\n" +"On Windows, return status shifted right by 8 bits.\n" +"\n" +"On Unix, if the process is being traced or if waitpid() was called with\n" +"WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.\n" +"This function must not be called if WIFSTOPPED(status) is true."); + +#define OS_WAITSTATUS_TO_EXITCODE_METHODDEF \ + {"waitstatus_to_exitcode", _PyCFunction_CAST(os_waitstatus_to_exitcode), METH_FASTCALL|METH_KEYWORDS, os_waitstatus_to_exitcode__doc__}, + +static PyObject * +os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj); + +static PyObject * +os_waitstatus_to_exitcode(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(status), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"status", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "waitstatus_to_exitcode", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *status_obj; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + status_obj = args[0]; + return_value = os_waitstatus_to_exitcode_impl(module, status_obj); + +exit: + return return_value; +} + +#endif /* (defined(WIFEXITED) || defined(MS_WINDOWS)) */ + +#ifndef OS_TTYNAME_METHODDEF + #define OS_TTYNAME_METHODDEF +#endif /* !defined(OS_TTYNAME_METHODDEF) */ + +#ifndef OS_CTERMID_METHODDEF + #define OS_CTERMID_METHODDEF +#endif /* !defined(OS_CTERMID_METHODDEF) */ + +#ifndef OS_FCHDIR_METHODDEF + #define OS_FCHDIR_METHODDEF +#endif /* !defined(OS_FCHDIR_METHODDEF) */ + +#ifndef OS_FCHMOD_METHODDEF + #define OS_FCHMOD_METHODDEF +#endif /* !defined(OS_FCHMOD_METHODDEF) */ + +#ifndef OS_LCHMOD_METHODDEF + #define OS_LCHMOD_METHODDEF +#endif /* !defined(OS_LCHMOD_METHODDEF) */ + +#ifndef OS_CHFLAGS_METHODDEF + #define OS_CHFLAGS_METHODDEF +#endif /* !defined(OS_CHFLAGS_METHODDEF) */ + +#ifndef OS_LCHFLAGS_METHODDEF + #define OS_LCHFLAGS_METHODDEF +#endif /* !defined(OS_LCHFLAGS_METHODDEF) */ + +#ifndef OS_CHROOT_METHODDEF + #define OS_CHROOT_METHODDEF +#endif /* !defined(OS_CHROOT_METHODDEF) */ + +#ifndef OS_FSYNC_METHODDEF + #define OS_FSYNC_METHODDEF +#endif /* !defined(OS_FSYNC_METHODDEF) */ + +#ifndef OS_SYNC_METHODDEF + #define OS_SYNC_METHODDEF +#endif /* !defined(OS_SYNC_METHODDEF) */ + +#ifndef OS_FDATASYNC_METHODDEF + #define OS_FDATASYNC_METHODDEF +#endif /* !defined(OS_FDATASYNC_METHODDEF) */ + +#ifndef OS_CHOWN_METHODDEF + #define OS_CHOWN_METHODDEF +#endif /* !defined(OS_CHOWN_METHODDEF) */ + +#ifndef OS_FCHOWN_METHODDEF + #define OS_FCHOWN_METHODDEF +#endif /* !defined(OS_FCHOWN_METHODDEF) */ + +#ifndef OS_LCHOWN_METHODDEF + #define OS_LCHOWN_METHODDEF +#endif /* !defined(OS_LCHOWN_METHODDEF) */ + +#ifndef OS_LINK_METHODDEF + #define OS_LINK_METHODDEF +#endif /* !defined(OS_LINK_METHODDEF) */ + +#ifndef OS__GETFULLPATHNAME_METHODDEF + #define OS__GETFULLPATHNAME_METHODDEF +#endif /* !defined(OS__GETFULLPATHNAME_METHODDEF) */ + +#ifndef OS__GETFINALPATHNAME_METHODDEF + #define OS__GETFINALPATHNAME_METHODDEF +#endif /* !defined(OS__GETFINALPATHNAME_METHODDEF) */ + +#ifndef OS__GETVOLUMEPATHNAME_METHODDEF + #define OS__GETVOLUMEPATHNAME_METHODDEF +#endif /* !defined(OS__GETVOLUMEPATHNAME_METHODDEF) */ + +#ifndef OS__PATH_SPLITROOT_METHODDEF + #define OS__PATH_SPLITROOT_METHODDEF +#endif /* !defined(OS__PATH_SPLITROOT_METHODDEF) */ + +#ifndef OS_NICE_METHODDEF + #define OS_NICE_METHODDEF +#endif /* !defined(OS_NICE_METHODDEF) */ + +#ifndef OS_GETPRIORITY_METHODDEF + #define OS_GETPRIORITY_METHODDEF +#endif /* !defined(OS_GETPRIORITY_METHODDEF) */ + +#ifndef OS_SETPRIORITY_METHODDEF + #define OS_SETPRIORITY_METHODDEF +#endif /* !defined(OS_SETPRIORITY_METHODDEF) */ + +#ifndef OS_SYSTEM_METHODDEF + #define OS_SYSTEM_METHODDEF +#endif /* !defined(OS_SYSTEM_METHODDEF) */ + +#ifndef OS_UMASK_METHODDEF + #define OS_UMASK_METHODDEF +#endif /* !defined(OS_UMASK_METHODDEF) */ + +#ifndef OS_UNAME_METHODDEF + #define OS_UNAME_METHODDEF +#endif /* !defined(OS_UNAME_METHODDEF) */ + +#ifndef OS_EXECV_METHODDEF + #define OS_EXECV_METHODDEF +#endif /* !defined(OS_EXECV_METHODDEF) */ + +#ifndef OS_EXECVE_METHODDEF + #define OS_EXECVE_METHODDEF +#endif /* !defined(OS_EXECVE_METHODDEF) */ + +#ifndef OS_POSIX_SPAWN_METHODDEF + #define OS_POSIX_SPAWN_METHODDEF +#endif /* !defined(OS_POSIX_SPAWN_METHODDEF) */ + +#ifndef OS_POSIX_SPAWNP_METHODDEF + #define OS_POSIX_SPAWNP_METHODDEF +#endif /* !defined(OS_POSIX_SPAWNP_METHODDEF) */ + +#ifndef OS_SPAWNV_METHODDEF + #define OS_SPAWNV_METHODDEF +#endif /* !defined(OS_SPAWNV_METHODDEF) */ + +#ifndef OS_SPAWNVE_METHODDEF + #define OS_SPAWNVE_METHODDEF +#endif /* !defined(OS_SPAWNVE_METHODDEF) */ + +#ifndef OS_REGISTER_AT_FORK_METHODDEF + #define OS_REGISTER_AT_FORK_METHODDEF +#endif /* !defined(OS_REGISTER_AT_FORK_METHODDEF) */ + +#ifndef OS_FORK1_METHODDEF + #define OS_FORK1_METHODDEF +#endif /* !defined(OS_FORK1_METHODDEF) */ + +#ifndef OS_FORK_METHODDEF + #define OS_FORK_METHODDEF +#endif /* !defined(OS_FORK_METHODDEF) */ + +#ifndef OS_SCHED_GET_PRIORITY_MAX_METHODDEF + #define OS_SCHED_GET_PRIORITY_MAX_METHODDEF +#endif /* !defined(OS_SCHED_GET_PRIORITY_MAX_METHODDEF) */ + +#ifndef OS_SCHED_GET_PRIORITY_MIN_METHODDEF + #define OS_SCHED_GET_PRIORITY_MIN_METHODDEF +#endif /* !defined(OS_SCHED_GET_PRIORITY_MIN_METHODDEF) */ + +#ifndef OS_SCHED_GETSCHEDULER_METHODDEF + #define OS_SCHED_GETSCHEDULER_METHODDEF +#endif /* !defined(OS_SCHED_GETSCHEDULER_METHODDEF) */ + +#ifndef OS_SCHED_SETSCHEDULER_METHODDEF + #define OS_SCHED_SETSCHEDULER_METHODDEF +#endif /* !defined(OS_SCHED_SETSCHEDULER_METHODDEF) */ + +#ifndef OS_SCHED_GETPARAM_METHODDEF + #define OS_SCHED_GETPARAM_METHODDEF +#endif /* !defined(OS_SCHED_GETPARAM_METHODDEF) */ + +#ifndef OS_SCHED_SETPARAM_METHODDEF + #define OS_SCHED_SETPARAM_METHODDEF +#endif /* !defined(OS_SCHED_SETPARAM_METHODDEF) */ + +#ifndef OS_SCHED_RR_GET_INTERVAL_METHODDEF + #define OS_SCHED_RR_GET_INTERVAL_METHODDEF +#endif /* !defined(OS_SCHED_RR_GET_INTERVAL_METHODDEF) */ + +#ifndef OS_SCHED_YIELD_METHODDEF + #define OS_SCHED_YIELD_METHODDEF +#endif /* !defined(OS_SCHED_YIELD_METHODDEF) */ + +#ifndef OS_SCHED_SETAFFINITY_METHODDEF + #define OS_SCHED_SETAFFINITY_METHODDEF +#endif /* !defined(OS_SCHED_SETAFFINITY_METHODDEF) */ + +#ifndef OS_SCHED_GETAFFINITY_METHODDEF + #define OS_SCHED_GETAFFINITY_METHODDEF +#endif /* !defined(OS_SCHED_GETAFFINITY_METHODDEF) */ + +#ifndef OS_OPENPTY_METHODDEF + #define OS_OPENPTY_METHODDEF +#endif /* !defined(OS_OPENPTY_METHODDEF) */ + +#ifndef OS_LOGIN_TTY_METHODDEF + #define OS_LOGIN_TTY_METHODDEF +#endif /* !defined(OS_LOGIN_TTY_METHODDEF) */ + +#ifndef OS_FORKPTY_METHODDEF + #define OS_FORKPTY_METHODDEF +#endif /* !defined(OS_FORKPTY_METHODDEF) */ + +#ifndef OS_GETEGID_METHODDEF + #define OS_GETEGID_METHODDEF +#endif /* !defined(OS_GETEGID_METHODDEF) */ + +#ifndef OS_GETEUID_METHODDEF + #define OS_GETEUID_METHODDEF +#endif /* !defined(OS_GETEUID_METHODDEF) */ + +#ifndef OS_GETGID_METHODDEF + #define OS_GETGID_METHODDEF +#endif /* !defined(OS_GETGID_METHODDEF) */ + +#ifndef OS_GETPID_METHODDEF + #define OS_GETPID_METHODDEF +#endif /* !defined(OS_GETPID_METHODDEF) */ + +#ifndef OS_GETGROUPLIST_METHODDEF + #define OS_GETGROUPLIST_METHODDEF +#endif /* !defined(OS_GETGROUPLIST_METHODDEF) */ + +#ifndef OS_GETGROUPS_METHODDEF + #define OS_GETGROUPS_METHODDEF +#endif /* !defined(OS_GETGROUPS_METHODDEF) */ + +#ifndef OS_INITGROUPS_METHODDEF + #define OS_INITGROUPS_METHODDEF +#endif /* !defined(OS_INITGROUPS_METHODDEF) */ + +#ifndef OS_GETPGID_METHODDEF + #define OS_GETPGID_METHODDEF +#endif /* !defined(OS_GETPGID_METHODDEF) */ + +#ifndef OS_GETPGRP_METHODDEF + #define OS_GETPGRP_METHODDEF +#endif /* !defined(OS_GETPGRP_METHODDEF) */ + +#ifndef OS_SETPGRP_METHODDEF + #define OS_SETPGRP_METHODDEF +#endif /* !defined(OS_SETPGRP_METHODDEF) */ + +#ifndef OS_GETPPID_METHODDEF + #define OS_GETPPID_METHODDEF +#endif /* !defined(OS_GETPPID_METHODDEF) */ + +#ifndef OS_GETLOGIN_METHODDEF + #define OS_GETLOGIN_METHODDEF +#endif /* !defined(OS_GETLOGIN_METHODDEF) */ + +#ifndef OS_GETUID_METHODDEF + #define OS_GETUID_METHODDEF +#endif /* !defined(OS_GETUID_METHODDEF) */ + +#ifndef OS_KILL_METHODDEF + #define OS_KILL_METHODDEF +#endif /* !defined(OS_KILL_METHODDEF) */ + +#ifndef OS_KILLPG_METHODDEF + #define OS_KILLPG_METHODDEF +#endif /* !defined(OS_KILLPG_METHODDEF) */ + +#ifndef OS_PLOCK_METHODDEF + #define OS_PLOCK_METHODDEF +#endif /* !defined(OS_PLOCK_METHODDEF) */ + +#ifndef OS_SETUID_METHODDEF + #define OS_SETUID_METHODDEF +#endif /* !defined(OS_SETUID_METHODDEF) */ + +#ifndef OS_SETEUID_METHODDEF + #define OS_SETEUID_METHODDEF +#endif /* !defined(OS_SETEUID_METHODDEF) */ + +#ifndef OS_SETEGID_METHODDEF + #define OS_SETEGID_METHODDEF +#endif /* !defined(OS_SETEGID_METHODDEF) */ + +#ifndef OS_SETREUID_METHODDEF + #define OS_SETREUID_METHODDEF +#endif /* !defined(OS_SETREUID_METHODDEF) */ + +#ifndef OS_SETREGID_METHODDEF + #define OS_SETREGID_METHODDEF +#endif /* !defined(OS_SETREGID_METHODDEF) */ + +#ifndef OS_SETGID_METHODDEF + #define OS_SETGID_METHODDEF +#endif /* !defined(OS_SETGID_METHODDEF) */ + +#ifndef OS_SETGROUPS_METHODDEF + #define OS_SETGROUPS_METHODDEF +#endif /* !defined(OS_SETGROUPS_METHODDEF) */ + +#ifndef OS_WAIT3_METHODDEF + #define OS_WAIT3_METHODDEF +#endif /* !defined(OS_WAIT3_METHODDEF) */ + +#ifndef OS_WAIT4_METHODDEF + #define OS_WAIT4_METHODDEF +#endif /* !defined(OS_WAIT4_METHODDEF) */ + +#ifndef OS_WAITID_METHODDEF + #define OS_WAITID_METHODDEF +#endif /* !defined(OS_WAITID_METHODDEF) */ + +#ifndef OS_WAITPID_METHODDEF + #define OS_WAITPID_METHODDEF +#endif /* !defined(OS_WAITPID_METHODDEF) */ + +#ifndef OS_WAIT_METHODDEF + #define OS_WAIT_METHODDEF +#endif /* !defined(OS_WAIT_METHODDEF) */ + +#ifndef OS_PIDFD_OPEN_METHODDEF + #define OS_PIDFD_OPEN_METHODDEF +#endif /* !defined(OS_PIDFD_OPEN_METHODDEF) */ + +#ifndef OS_SETNS_METHODDEF + #define OS_SETNS_METHODDEF +#endif /* !defined(OS_SETNS_METHODDEF) */ + +#ifndef OS_UNSHARE_METHODDEF + #define OS_UNSHARE_METHODDEF +#endif /* !defined(OS_UNSHARE_METHODDEF) */ + +#ifndef OS_READLINK_METHODDEF + #define OS_READLINK_METHODDEF +#endif /* !defined(OS_READLINK_METHODDEF) */ + +#ifndef OS_SYMLINK_METHODDEF + #define OS_SYMLINK_METHODDEF +#endif /* !defined(OS_SYMLINK_METHODDEF) */ + +#ifndef OS_TIMES_METHODDEF + #define OS_TIMES_METHODDEF +#endif /* !defined(OS_TIMES_METHODDEF) */ + +#ifndef OS_GETSID_METHODDEF + #define OS_GETSID_METHODDEF +#endif /* !defined(OS_GETSID_METHODDEF) */ + +#ifndef OS_SETSID_METHODDEF + #define OS_SETSID_METHODDEF +#endif /* !defined(OS_SETSID_METHODDEF) */ + +#ifndef OS_SETPGID_METHODDEF + #define OS_SETPGID_METHODDEF +#endif /* !defined(OS_SETPGID_METHODDEF) */ + +#ifndef OS_TCGETPGRP_METHODDEF + #define OS_TCGETPGRP_METHODDEF +#endif /* !defined(OS_TCGETPGRP_METHODDEF) */ + +#ifndef OS_TCSETPGRP_METHODDEF + #define OS_TCSETPGRP_METHODDEF +#endif /* !defined(OS_TCSETPGRP_METHODDEF) */ + +#ifndef OS_DUP2_METHODDEF + #define OS_DUP2_METHODDEF +#endif /* !defined(OS_DUP2_METHODDEF) */ + +#ifndef OS_LOCKF_METHODDEF + #define OS_LOCKF_METHODDEF +#endif /* !defined(OS_LOCKF_METHODDEF) */ + +#ifndef OS_READV_METHODDEF + #define OS_READV_METHODDEF +#endif /* !defined(OS_READV_METHODDEF) */ + +#ifndef OS_PREAD_METHODDEF + #define OS_PREAD_METHODDEF +#endif /* !defined(OS_PREAD_METHODDEF) */ + +#ifndef OS_PREADV_METHODDEF + #define OS_PREADV_METHODDEF +#endif /* !defined(OS_PREADV_METHODDEF) */ + +#ifndef OS_SENDFILE_METHODDEF + #define OS_SENDFILE_METHODDEF +#endif /* !defined(OS_SENDFILE_METHODDEF) */ + +#ifndef OS__FCOPYFILE_METHODDEF + #define OS__FCOPYFILE_METHODDEF +#endif /* !defined(OS__FCOPYFILE_METHODDEF) */ + +#ifndef OS_PIPE_METHODDEF + #define OS_PIPE_METHODDEF +#endif /* !defined(OS_PIPE_METHODDEF) */ + +#ifndef OS_PIPE2_METHODDEF + #define OS_PIPE2_METHODDEF +#endif /* !defined(OS_PIPE2_METHODDEF) */ + +#ifndef OS_WRITEV_METHODDEF + #define OS_WRITEV_METHODDEF +#endif /* !defined(OS_WRITEV_METHODDEF) */ + +#ifndef OS_PWRITE_METHODDEF + #define OS_PWRITE_METHODDEF +#endif /* !defined(OS_PWRITE_METHODDEF) */ + +#ifndef OS_PWRITEV_METHODDEF + #define OS_PWRITEV_METHODDEF +#endif /* !defined(OS_PWRITEV_METHODDEF) */ + +#ifndef OS_COPY_FILE_RANGE_METHODDEF + #define OS_COPY_FILE_RANGE_METHODDEF +#endif /* !defined(OS_COPY_FILE_RANGE_METHODDEF) */ + +#ifndef OS_SPLICE_METHODDEF + #define OS_SPLICE_METHODDEF +#endif /* !defined(OS_SPLICE_METHODDEF) */ + +#ifndef OS_MKFIFO_METHODDEF + #define OS_MKFIFO_METHODDEF +#endif /* !defined(OS_MKFIFO_METHODDEF) */ + +#ifndef OS_MKNOD_METHODDEF + #define OS_MKNOD_METHODDEF +#endif /* !defined(OS_MKNOD_METHODDEF) */ + +#ifndef OS_MAJOR_METHODDEF + #define OS_MAJOR_METHODDEF +#endif /* !defined(OS_MAJOR_METHODDEF) */ + +#ifndef OS_MINOR_METHODDEF + #define OS_MINOR_METHODDEF +#endif /* !defined(OS_MINOR_METHODDEF) */ + +#ifndef OS_MAKEDEV_METHODDEF + #define OS_MAKEDEV_METHODDEF +#endif /* !defined(OS_MAKEDEV_METHODDEF) */ + +#ifndef OS_FTRUNCATE_METHODDEF + #define OS_FTRUNCATE_METHODDEF +#endif /* !defined(OS_FTRUNCATE_METHODDEF) */ + +#ifndef OS_TRUNCATE_METHODDEF + #define OS_TRUNCATE_METHODDEF +#endif /* !defined(OS_TRUNCATE_METHODDEF) */ + +#ifndef OS_POSIX_FALLOCATE_METHODDEF + #define OS_POSIX_FALLOCATE_METHODDEF +#endif /* !defined(OS_POSIX_FALLOCATE_METHODDEF) */ + +#ifndef OS_POSIX_FADVISE_METHODDEF + #define OS_POSIX_FADVISE_METHODDEF +#endif /* !defined(OS_POSIX_FADVISE_METHODDEF) */ + +#ifndef OS_PUTENV_METHODDEF + #define OS_PUTENV_METHODDEF +#endif /* !defined(OS_PUTENV_METHODDEF) */ + +#ifndef OS_UNSETENV_METHODDEF + #define OS_UNSETENV_METHODDEF +#endif /* !defined(OS_UNSETENV_METHODDEF) */ + +#ifndef OS_WCOREDUMP_METHODDEF + #define OS_WCOREDUMP_METHODDEF +#endif /* !defined(OS_WCOREDUMP_METHODDEF) */ + +#ifndef OS_WIFCONTINUED_METHODDEF + #define OS_WIFCONTINUED_METHODDEF +#endif /* !defined(OS_WIFCONTINUED_METHODDEF) */ + +#ifndef OS_WIFSTOPPED_METHODDEF + #define OS_WIFSTOPPED_METHODDEF +#endif /* !defined(OS_WIFSTOPPED_METHODDEF) */ + +#ifndef OS_WIFSIGNALED_METHODDEF + #define OS_WIFSIGNALED_METHODDEF +#endif /* !defined(OS_WIFSIGNALED_METHODDEF) */ + +#ifndef OS_WIFEXITED_METHODDEF + #define OS_WIFEXITED_METHODDEF +#endif /* !defined(OS_WIFEXITED_METHODDEF) */ + +#ifndef OS_WEXITSTATUS_METHODDEF + #define OS_WEXITSTATUS_METHODDEF +#endif /* !defined(OS_WEXITSTATUS_METHODDEF) */ + +#ifndef OS_WTERMSIG_METHODDEF + #define OS_WTERMSIG_METHODDEF +#endif /* !defined(OS_WTERMSIG_METHODDEF) */ + +#ifndef OS_WSTOPSIG_METHODDEF + #define OS_WSTOPSIG_METHODDEF +#endif /* !defined(OS_WSTOPSIG_METHODDEF) */ + +#ifndef OS_FSTATVFS_METHODDEF + #define OS_FSTATVFS_METHODDEF +#endif /* !defined(OS_FSTATVFS_METHODDEF) */ + +#ifndef OS_STATVFS_METHODDEF + #define OS_STATVFS_METHODDEF +#endif /* !defined(OS_STATVFS_METHODDEF) */ + +#ifndef OS__GETDISKUSAGE_METHODDEF + #define OS__GETDISKUSAGE_METHODDEF +#endif /* !defined(OS__GETDISKUSAGE_METHODDEF) */ + +#ifndef OS_FPATHCONF_METHODDEF + #define OS_FPATHCONF_METHODDEF +#endif /* !defined(OS_FPATHCONF_METHODDEF) */ + +#ifndef OS_PATHCONF_METHODDEF + #define OS_PATHCONF_METHODDEF +#endif /* !defined(OS_PATHCONF_METHODDEF) */ + +#ifndef OS_CONFSTR_METHODDEF + #define OS_CONFSTR_METHODDEF +#endif /* !defined(OS_CONFSTR_METHODDEF) */ + +#ifndef OS_SYSCONF_METHODDEF + #define OS_SYSCONF_METHODDEF +#endif /* !defined(OS_SYSCONF_METHODDEF) */ + +#ifndef OS_STARTFILE_METHODDEF + #define OS_STARTFILE_METHODDEF +#endif /* !defined(OS_STARTFILE_METHODDEF) */ + +#ifndef OS_GETLOADAVG_METHODDEF + #define OS_GETLOADAVG_METHODDEF +#endif /* !defined(OS_GETLOADAVG_METHODDEF) */ + +#ifndef OS_SETRESUID_METHODDEF + #define OS_SETRESUID_METHODDEF +#endif /* !defined(OS_SETRESUID_METHODDEF) */ + +#ifndef OS_SETRESGID_METHODDEF + #define OS_SETRESGID_METHODDEF +#endif /* !defined(OS_SETRESGID_METHODDEF) */ + +#ifndef OS_GETRESUID_METHODDEF + #define OS_GETRESUID_METHODDEF +#endif /* !defined(OS_GETRESUID_METHODDEF) */ + +#ifndef OS_GETRESGID_METHODDEF + #define OS_GETRESGID_METHODDEF +#endif /* !defined(OS_GETRESGID_METHODDEF) */ + +#ifndef OS_GETXATTR_METHODDEF + #define OS_GETXATTR_METHODDEF +#endif /* !defined(OS_GETXATTR_METHODDEF) */ + +#ifndef OS_SETXATTR_METHODDEF + #define OS_SETXATTR_METHODDEF +#endif /* !defined(OS_SETXATTR_METHODDEF) */ + +#ifndef OS_REMOVEXATTR_METHODDEF + #define OS_REMOVEXATTR_METHODDEF +#endif /* !defined(OS_REMOVEXATTR_METHODDEF) */ + +#ifndef OS_LISTXATTR_METHODDEF + #define OS_LISTXATTR_METHODDEF +#endif /* !defined(OS_LISTXATTR_METHODDEF) */ + +#ifndef OS_MEMFD_CREATE_METHODDEF + #define OS_MEMFD_CREATE_METHODDEF +#endif /* !defined(OS_MEMFD_CREATE_METHODDEF) */ + +#ifndef OS_EVENTFD_METHODDEF + #define OS_EVENTFD_METHODDEF +#endif /* !defined(OS_EVENTFD_METHODDEF) */ + +#ifndef OS_EVENTFD_READ_METHODDEF + #define OS_EVENTFD_READ_METHODDEF +#endif /* !defined(OS_EVENTFD_READ_METHODDEF) */ + +#ifndef OS_EVENTFD_WRITE_METHODDEF + #define OS_EVENTFD_WRITE_METHODDEF +#endif /* !defined(OS_EVENTFD_WRITE_METHODDEF) */ + +#ifndef OS_GET_TERMINAL_SIZE_METHODDEF + #define OS_GET_TERMINAL_SIZE_METHODDEF +#endif /* !defined(OS_GET_TERMINAL_SIZE_METHODDEF) */ + +#ifndef OS_GET_HANDLE_INHERITABLE_METHODDEF + #define OS_GET_HANDLE_INHERITABLE_METHODDEF +#endif /* !defined(OS_GET_HANDLE_INHERITABLE_METHODDEF) */ + +#ifndef OS_SET_HANDLE_INHERITABLE_METHODDEF + #define OS_SET_HANDLE_INHERITABLE_METHODDEF +#endif /* !defined(OS_SET_HANDLE_INHERITABLE_METHODDEF) */ + +#ifndef OS_GET_BLOCKING_METHODDEF + #define OS_GET_BLOCKING_METHODDEF +#endif /* !defined(OS_GET_BLOCKING_METHODDEF) */ + +#ifndef OS_SET_BLOCKING_METHODDEF + #define OS_SET_BLOCKING_METHODDEF +#endif /* !defined(OS_SET_BLOCKING_METHODDEF) */ + +#ifndef OS_GETRANDOM_METHODDEF + #define OS_GETRANDOM_METHODDEF +#endif /* !defined(OS_GETRANDOM_METHODDEF) */ + +#ifndef OS__ADD_DLL_DIRECTORY_METHODDEF + #define OS__ADD_DLL_DIRECTORY_METHODDEF +#endif /* !defined(OS__ADD_DLL_DIRECTORY_METHODDEF) */ + +#ifndef OS__REMOVE_DLL_DIRECTORY_METHODDEF + #define OS__REMOVE_DLL_DIRECTORY_METHODDEF +#endif /* !defined(OS__REMOVE_DLL_DIRECTORY_METHODDEF) */ + +#ifndef OS_WAITSTATUS_TO_EXITCODE_METHODDEF + #define OS_WAITSTATUS_TO_EXITCODE_METHODDEF +#endif /* !defined(OS_WAITSTATUS_TO_EXITCODE_METHODDEF) */ +/*[clinic end generated code: output=4192d8e09e216300 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 39c2ca1a9b4bc4..c8aa556080c5ff 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1,16056 +1,16056 @@ -/* POSIX module implementation */ - -/* This file is also used for Windows NT/MS-Win. In that case the - module actually calls itself 'nt', not 'posix', and a few - functions are either unimplemented or implemented differently. The source - assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent - of the compiler used. Different compilers define their own feature - test macro, e.g. '_MSC_VER'. */ - -#define PY_SSIZE_T_CLEAN - -#include "Python.h" -// Include before pycore internal headers. FSCTL_GET_REPARSE_POINT -// is not exported by if the WIN32_LEAN_AND_MEAN macro is defined, -// whereas pycore_condvar.h defines the WIN32_LEAN_AND_MEAN macro. -#ifdef MS_WINDOWS -# include -# include -#endif - -#ifdef __VXWORKS__ -# include "pycore_bitutils.h" // _Py_popcount32() -#endif -#include "pycore_call.h" // _PyObject_CallNoArgs() -#include "pycore_ceval.h" // _PyEval_ReInitThreads() -#include "pycore_fileutils.h" // _Py_closerange() -#include "pycore_import.h" // _PyImport_ReInitLock() -#include "pycore_initconfig.h" // _PyStatus_EXCEPTION() -#include "pycore_moduleobject.h" // _PyModule_GetState() -#include "pycore_object.h" // _PyObject_LookupSpecial() -#include "pycore_pystate.h" // _PyInterpreterState_GET() -#include "pycore_signal.h" // Py_NSIG - -#include "structmember.h" // PyMemberDef -#ifndef MS_WINDOWS -# include "posixmodule.h" -#else -# include "winreparse.h" -#endif - -#if !defined(EX_OK) && defined(EXIT_SUCCESS) -# define EX_OK EXIT_SUCCESS -#endif - -/* On android API level 21, 'AT_EACCESS' is not declared although - * HAVE_FACCESSAT is defined. */ -#ifdef __ANDROID__ -# undef HAVE_FACCESSAT -#endif - -#include // ctermid() -#include // system() - -/* - * A number of APIs are available on macOS from a certain macOS version. - * To support building with a new SDK while deploying to older versions - * the availability test is split into two: - * - HAVE_: The configure check for compile time availability - * - HAVE__RUNTIME: Runtime check for availability - * - * The latter is always true when not on macOS, or when using a compiler - * that does not support __has_builtin (older versions of Xcode). - * - * Due to compiler restrictions there is one valid use of HAVE__RUNTIME: - * if (HAVE__RUNTIME) { ... } - * - * In mixing the test with other tests or using negations will result in compile - * errors. - */ -#if defined(__APPLE__) - -#if defined(__has_builtin) -#if __has_builtin(__builtin_available) -#define HAVE_BUILTIN_AVAILABLE 1 -#endif -#endif - -#ifdef HAVE_BUILTIN_AVAILABLE -# define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) -# define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) -# define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) -# define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) -# define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) -# define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) -# define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) -# define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) -# define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) -# define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) -# define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) -# define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) -# define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *) -# define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *) -# define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *) -# define HAVE_MKFIFOAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *) -# define HAVE_MKNODAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *) - -# define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *) - -#else /* Xcode 8 or earlier */ - - /* __builtin_available is not present in these compilers, but - * some of the symbols might be weak linked (10.10 SDK or later - * deploying on 10.9. - * - * Fall back to the older style of availability checking for - * symbols introduced in macOS 10.10. - */ - -# ifdef HAVE_FSTATAT -# define HAVE_FSTATAT_RUNTIME (fstatat != NULL) -# endif - -# ifdef HAVE_FACCESSAT -# define HAVE_FACCESSAT_RUNTIME (faccessat != NULL) -# endif - -# ifdef HAVE_FCHMODAT -# define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL) -# endif - -# ifdef HAVE_FCHOWNAT -# define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL) -# endif - -# ifdef HAVE_LINKAT -# define HAVE_LINKAT_RUNTIME (linkat != NULL) -# endif - -# ifdef HAVE_FDOPENDIR -# define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL) -# endif - -# ifdef HAVE_MKDIRAT -# define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL) -# endif - -# ifdef HAVE_RENAMEAT -# define HAVE_RENAMEAT_RUNTIME (renameat != NULL) -# endif - -# ifdef HAVE_UNLINKAT -# define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL) -# endif - -# ifdef HAVE_OPENAT -# define HAVE_OPENAT_RUNTIME (openat != NULL) -# endif - -# ifdef HAVE_READLINKAT -# define HAVE_READLINKAT_RUNTIME (readlinkat != NULL) -# endif - -# ifdef HAVE_SYMLINKAT -# define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL) -# endif - -#endif - -#ifdef HAVE_FUTIMESAT -/* Some of the logic for weak linking depends on this assertion */ -# error "HAVE_FUTIMESAT unexpectedly defined" -#endif - -#else -# define HAVE_FSTATAT_RUNTIME 1 -# define HAVE_FACCESSAT_RUNTIME 1 -# define HAVE_FCHMODAT_RUNTIME 1 -# define HAVE_FCHOWNAT_RUNTIME 1 -# define HAVE_LINKAT_RUNTIME 1 -# define HAVE_FDOPENDIR_RUNTIME 1 -# define HAVE_MKDIRAT_RUNTIME 1 -# define HAVE_RENAMEAT_RUNTIME 1 -# define HAVE_UNLINKAT_RUNTIME 1 -# define HAVE_OPENAT_RUNTIME 1 -# define HAVE_READLINKAT_RUNTIME 1 -# define HAVE_SYMLINKAT_RUNTIME 1 -# define HAVE_FUTIMENS_RUNTIME 1 -# define HAVE_UTIMENSAT_RUNTIME 1 -# define HAVE_PWRITEV_RUNTIME 1 -# define HAVE_MKFIFOAT_RUNTIME 1 -# define HAVE_MKNODAT_RUNTIME 1 -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - -PyDoc_STRVAR(posix__doc__, -"This module provides access to operating system functionality that is\n\ -standardized by the C Standard and the POSIX standard (a thinly\n\ -disguised Unix interface). Refer to the library manual and\n\ -corresponding Unix manual entries for more information on calls."); - - -#ifdef HAVE_SYS_UIO_H -# include -#endif - -#ifdef HAVE_SYS_SYSMACROS_H -/* GNU C Library: major(), minor(), makedev() */ -# include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif /* HAVE_SYS_TYPES_H */ - -#ifdef HAVE_SYS_STAT_H -# include -#endif /* HAVE_SYS_STAT_H */ - -#ifdef HAVE_SYS_WAIT_H -# include // WNOHANG -#endif -#ifdef HAVE_LINUX_WAIT_H -# include // P_PIDFD -#endif - -#ifdef HAVE_SIGNAL_H -# include -#endif - -#ifdef HAVE_FCNTL_H -# include -#endif - -#ifdef HAVE_GRP_H -# include -#endif - -#ifdef HAVE_SYSEXITS_H -# include -#endif - -#ifdef HAVE_SYS_LOADAVG_H -# include -#endif - -#ifdef HAVE_SYS_SENDFILE_H -# include -#endif - -#if defined(__APPLE__) -# include -#endif - -#ifdef HAVE_SCHED_H -# include -#endif - -#ifdef HAVE_COPY_FILE_RANGE -# include -#endif - -#if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY) -# undef HAVE_SCHED_SETAFFINITY -#endif - -#if defined(HAVE_SYS_XATTR_H) && defined(__GLIBC__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__) -# define USE_XATTRS -#endif - -#ifdef USE_XATTRS -# include -#endif - -#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) -# ifdef HAVE_SYS_SOCKET_H -# include -# endif -#endif - -#ifdef HAVE_DLFCN_H -# include -#endif - -#ifdef __hpux -# include -#endif - -#if defined(__DragonFly__) || \ - defined(__OpenBSD__) || \ - defined(__FreeBSD__) || \ - defined(__NetBSD__) || \ - defined(__APPLE__) -# include -#endif - -#ifdef HAVE_LINUX_RANDOM_H -# include -#endif -#ifdef HAVE_GETRANDOM_SYSCALL -# include -#endif - -#if defined(MS_WINDOWS) -# define TERMSIZE_USE_CONIO -#elif defined(HAVE_SYS_IOCTL_H) -# include -# if defined(HAVE_TERMIOS_H) -# include -# endif -# if defined(TIOCGWINSZ) -# define TERMSIZE_USE_IOCTL -# endif -#endif /* MS_WINDOWS */ - -/* Various compilers have only certain posix functions */ -/* XXX Gosh I wish these were all moved into pyconfig.h */ -#if defined(__WATCOMC__) && !defined(__QNX__) /* Watcom compiler */ -# define HAVE_OPENDIR 1 -# define HAVE_SYSTEM 1 -# include -#else -# ifdef _MSC_VER - /* Microsoft compiler */ -# define HAVE_GETPPID 1 -# define HAVE_GETLOGIN 1 -# define HAVE_SPAWNV 1 -# define HAVE_EXECV 1 -# define HAVE_WSPAWNV 1 -# define HAVE_WEXECV 1 -# define HAVE_PIPE 1 -# define HAVE_SYSTEM 1 -# define HAVE_CWAIT 1 -# define HAVE_FSYNC 1 -# define fsync _commit -# endif /* _MSC_VER */ -#endif /* ! __WATCOMC__ || __QNX__ */ - -/*[clinic input] -# one of the few times we lie about this name! -module os -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/ - -#ifndef _MSC_VER - -#if defined(__sgi)&&_COMPILER_VERSION>=700 -/* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode - (default) */ -extern char *ctermid_r(char *); -#endif - -#endif /* !_MSC_VER */ - -#if defined(__VXWORKS__) -# include -# include -# include -# include -# ifndef _P_WAIT -# define _P_WAIT 0 -# define _P_NOWAIT 1 -# define _P_NOWAITO 1 -# endif -#endif /* __VXWORKS__ */ - -#ifdef HAVE_POSIX_SPAWN -# include -#endif - -#ifdef HAVE_UTIME_H -# include -#endif /* HAVE_UTIME_H */ - -#ifdef HAVE_SYS_UTIME_H -# include -# define HAVE_UTIME_H /* pretend we do for the rest of this file */ -#endif /* HAVE_SYS_UTIME_H */ - -#ifdef HAVE_SYS_TIMES_H -# include -#endif /* HAVE_SYS_TIMES_H */ - -#ifdef HAVE_SYS_PARAM_H -# include -#endif /* HAVE_SYS_PARAM_H */ - -#ifdef HAVE_SYS_UTSNAME_H -# include -#endif /* HAVE_SYS_UTSNAME_H */ - -#ifdef HAVE_DIRENT_H -# include -# define NAMLEN(dirent) strlen((dirent)->d_name) -#else -# if defined(__WATCOMC__) && !defined(__QNX__) -# include -# define NAMLEN(dirent) strlen((dirent)->d_name) -# else -# define dirent direct -# define NAMLEN(dirent) (dirent)->d_namlen -# endif -# ifdef HAVE_SYS_NDIR_H -# include -# endif -# ifdef HAVE_SYS_DIR_H -# include -# endif -# ifdef HAVE_NDIR_H -# include -# endif -#endif - -#ifdef _MSC_VER -# ifdef HAVE_DIRECT_H -# include -# endif -# ifdef HAVE_IO_H -# include -# endif -# ifdef HAVE_PROCESS_H -# include -# endif -# ifndef IO_REPARSE_TAG_SYMLINK -# define IO_REPARSE_TAG_SYMLINK (0xA000000CL) -# endif -# ifndef IO_REPARSE_TAG_MOUNT_POINT -# define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) -# endif -# include "osdefs.h" // SEP -# include -# include -# include // ShellExecute() -# include // UNLEN -# define HAVE_SYMLINK -#endif /* _MSC_VER */ - -#ifndef MAXPATHLEN -# if defined(PATH_MAX) && PATH_MAX > 1024 -# define MAXPATHLEN PATH_MAX -# else -# define MAXPATHLEN 1024 -# endif -#endif /* MAXPATHLEN */ - -#ifdef UNION_WAIT - /* Emulate some macros on systems that have a union instead of macros */ -# ifndef WIFEXITED -# define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump) -# endif -# ifndef WEXITSTATUS -# define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1) -# endif -# ifndef WTERMSIG -# define WTERMSIG(u_wait) ((u_wait).w_termsig) -# endif -# define WAIT_TYPE union wait -# define WAIT_STATUS_INT(s) (s.w_status) -#else - /* !UNION_WAIT */ -# define WAIT_TYPE int -# define WAIT_STATUS_INT(s) (s) -#endif /* UNION_WAIT */ - -/* Don't use the "_r" form if we don't need it (also, won't have a - prototype for it, at least on Solaris -- maybe others as well?). */ -#if defined(HAVE_CTERMID_R) -# define USE_CTERMID_R -#endif - -/* choose the appropriate stat and fstat functions and return structs */ -#undef STAT -#undef FSTAT -#undef STRUCT_STAT -#ifdef MS_WINDOWS -# define STAT win32_stat -# define LSTAT win32_lstat -# define FSTAT _Py_fstat_noraise -# define STRUCT_STAT struct _Py_stat_struct -#else -# define STAT stat -# define LSTAT lstat -# define FSTAT fstat -# define STRUCT_STAT struct stat -#endif - -#if defined(MAJOR_IN_MKDEV) -# include -#else -# if defined(MAJOR_IN_SYSMACROS) -# include -# endif -# if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H) -# include -# endif -#endif - -#ifdef MS_WINDOWS -# define INITFUNC PyInit_nt -# define MODNAME "nt" -#else -# define INITFUNC PyInit_posix -# define MODNAME "posix" -#endif - -#if defined(__sun) -/* Something to implement in autoconf, not present in autoconf 2.69 */ -# define HAVE_STRUCT_STAT_ST_FSTYPE 1 -#endif - -/* memfd_create is either defined in sys/mman.h or sys/memfd.h - * linux/memfd.h defines additional flags - */ -#ifdef HAVE_SYS_MMAN_H -# include -#endif -#ifdef HAVE_SYS_MEMFD_H -# include -#endif -#ifdef HAVE_LINUX_MEMFD_H -# include -#endif - -/* eventfd() */ -#ifdef HAVE_SYS_EVENTFD_H -# include -#endif - -#ifdef _Py_MEMORY_SANITIZER -# include -#endif - -#ifdef HAVE_FORK -static void -run_at_forkers(PyObject *lst, int reverse) -{ - Py_ssize_t i; - PyObject *cpy; - - if (lst != NULL) { - assert(PyList_CheckExact(lst)); - - /* Use a list copy in case register_at_fork() is called from - * one of the callbacks. - */ - cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst)); - if (cpy == NULL) - PyErr_WriteUnraisable(lst); - else { - if (reverse) - PyList_Reverse(cpy); - for (i = 0; i < PyList_GET_SIZE(cpy); i++) { - PyObject *func, *res; - func = PyList_GET_ITEM(cpy, i); - res = _PyObject_CallNoArgs(func); - if (res == NULL) - PyErr_WriteUnraisable(func); - else - Py_DECREF(res); - } - Py_DECREF(cpy); - } - } -} - -void -PyOS_BeforeFork(void) -{ - run_at_forkers(_PyInterpreterState_GET()->before_forkers, 1); - - _PyImport_AcquireLock(); -} - -void -PyOS_AfterFork_Parent(void) -{ - if (_PyImport_ReleaseLock() <= 0) - Py_FatalError("failed releasing import lock after fork"); - - run_at_forkers(_PyInterpreterState_GET()->after_forkers_parent, 0); -} - -void -PyOS_AfterFork_Child(void) -{ - PyStatus status; - _PyRuntimeState *runtime = &_PyRuntime; - - status = _PyGILState_Reinit(runtime); - if (_PyStatus_EXCEPTION(status)) { - goto fatal_error; - } - - PyThreadState *tstate = _PyThreadState_GET(); - _Py_EnsureTstateNotNULL(tstate); - - status = _PyEval_ReInitThreads(tstate); - if (_PyStatus_EXCEPTION(status)) { - goto fatal_error; - } - - status = _PyImport_ReInitLock(); - if (_PyStatus_EXCEPTION(status)) { - goto fatal_error; - } - - _PySignal_AfterFork(); - - status = _PyRuntimeState_ReInitThreads(runtime); - if (_PyStatus_EXCEPTION(status)) { - goto fatal_error; - } - - status = _PyInterpreterState_DeleteExceptMain(runtime); - if (_PyStatus_EXCEPTION(status)) { - goto fatal_error; - } - assert(_PyThreadState_GET() == tstate); - - status = _PyPerfTrampoline_AfterFork_Child(); - if (_PyStatus_EXCEPTION(status)) { - goto fatal_error; - } - - run_at_forkers(tstate->interp->after_forkers_child, 0); - return; - -fatal_error: - Py_ExitStatusException(status); -} - -static int -register_at_forker(PyObject **lst, PyObject *func) -{ - if (func == NULL) /* nothing to register? do nothing. */ - return 0; - if (*lst == NULL) { - *lst = PyList_New(0); - if (*lst == NULL) - return -1; - } - return PyList_Append(*lst, func); -} -#endif /* HAVE_FORK */ - - -/* Legacy wrapper */ -void -PyOS_AfterFork(void) -{ -#ifdef HAVE_FORK - PyOS_AfterFork_Child(); -#endif -} - - -#ifdef MS_WINDOWS -/* defined in fileutils.c */ -void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *); -void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *, - ULONG, struct _Py_stat_struct *); -#endif - - -#ifndef MS_WINDOWS -PyObject * -_PyLong_FromUid(uid_t uid) -{ - if (uid == (uid_t)-1) - return PyLong_FromLong(-1); - return PyLong_FromUnsignedLong(uid); -} - -PyObject * -_PyLong_FromGid(gid_t gid) -{ - if (gid == (gid_t)-1) - return PyLong_FromLong(-1); - return PyLong_FromUnsignedLong(gid); -} - -int -_Py_Uid_Converter(PyObject *obj, uid_t *p) -{ - uid_t uid; - PyObject *index; - int overflow; - long result; - unsigned long uresult; - - index = _PyNumber_Index(obj); - if (index == NULL) { - PyErr_Format(PyExc_TypeError, - "uid should be integer, not %.200s", - _PyType_Name(Py_TYPE(obj))); - return 0; - } - - /* - * Handling uid_t is complicated for two reasons: - * * Although uid_t is (always?) unsigned, it still - * accepts -1. - * * We don't know its size in advance--it may be - * bigger than an int, or it may be smaller than - * a long. - * - * So a bit of defensive programming is in order. - * Start with interpreting the value passed - * in as a signed long and see if it works. - */ - - result = PyLong_AsLongAndOverflow(index, &overflow); - - if (!overflow) { - uid = (uid_t)result; - - if (result == -1) { - if (PyErr_Occurred()) - goto fail; - /* It's a legitimate -1, we're done. */ - goto success; - } - - /* Any other negative number is disallowed. */ - if (result < 0) - goto underflow; - - /* Ensure the value wasn't truncated. */ - if (sizeof(uid_t) < sizeof(long) && - (long)uid != result) - goto underflow; - goto success; - } - - if (overflow < 0) - goto underflow; - - /* - * Okay, the value overflowed a signed long. If it - * fits in an *unsigned* long, it may still be okay, - * as uid_t may be unsigned long on this platform. - */ - uresult = PyLong_AsUnsignedLong(index); - if (PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) - goto overflow; - goto fail; - } - - uid = (uid_t)uresult; - - /* - * If uid == (uid_t)-1, the user actually passed in ULONG_MAX, - * but this value would get interpreted as (uid_t)-1 by chown - * and its siblings. That's not what the user meant! So we - * throw an overflow exception instead. (We already - * handled a real -1 with PyLong_AsLongAndOverflow() above.) - */ - if (uid == (uid_t)-1) - goto overflow; - - /* Ensure the value wasn't truncated. */ - if (sizeof(uid_t) < sizeof(long) && - (unsigned long)uid != uresult) - goto overflow; - /* fallthrough */ - -success: - Py_DECREF(index); - *p = uid; - return 1; - -underflow: - PyErr_SetString(PyExc_OverflowError, - "uid is less than minimum"); - goto fail; - -overflow: - PyErr_SetString(PyExc_OverflowError, - "uid is greater than maximum"); - /* fallthrough */ - -fail: - Py_DECREF(index); - return 0; -} - -int -_Py_Gid_Converter(PyObject *obj, gid_t *p) -{ - gid_t gid; - PyObject *index; - int overflow; - long result; - unsigned long uresult; - - index = _PyNumber_Index(obj); - if (index == NULL) { - PyErr_Format(PyExc_TypeError, - "gid should be integer, not %.200s", - _PyType_Name(Py_TYPE(obj))); - return 0; - } - - /* - * Handling gid_t is complicated for two reasons: - * * Although gid_t is (always?) unsigned, it still - * accepts -1. - * * We don't know its size in advance--it may be - * bigger than an int, or it may be smaller than - * a long. - * - * So a bit of defensive programming is in order. - * Start with interpreting the value passed - * in as a signed long and see if it works. - */ - - result = PyLong_AsLongAndOverflow(index, &overflow); - - if (!overflow) { - gid = (gid_t)result; - - if (result == -1) { - if (PyErr_Occurred()) - goto fail; - /* It's a legitimate -1, we're done. */ - goto success; - } - - /* Any other negative number is disallowed. */ - if (result < 0) { - goto underflow; - } - - /* Ensure the value wasn't truncated. */ - if (sizeof(gid_t) < sizeof(long) && - (long)gid != result) - goto underflow; - goto success; - } - - if (overflow < 0) - goto underflow; - - /* - * Okay, the value overflowed a signed long. If it - * fits in an *unsigned* long, it may still be okay, - * as gid_t may be unsigned long on this platform. - */ - uresult = PyLong_AsUnsignedLong(index); - if (PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) - goto overflow; - goto fail; - } - - gid = (gid_t)uresult; - - /* - * If gid == (gid_t)-1, the user actually passed in ULONG_MAX, - * but this value would get interpreted as (gid_t)-1 by chown - * and its siblings. That's not what the user meant! So we - * throw an overflow exception instead. (We already - * handled a real -1 with PyLong_AsLongAndOverflow() above.) - */ - if (gid == (gid_t)-1) - goto overflow; - - /* Ensure the value wasn't truncated. */ - if (sizeof(gid_t) < sizeof(long) && - (unsigned long)gid != uresult) - goto overflow; - /* fallthrough */ - -success: - Py_DECREF(index); - *p = gid; - return 1; - -underflow: - PyErr_SetString(PyExc_OverflowError, - "gid is less than minimum"); - goto fail; - -overflow: - PyErr_SetString(PyExc_OverflowError, - "gid is greater than maximum"); - /* fallthrough */ - -fail: - Py_DECREF(index); - return 0; -} -#endif /* MS_WINDOWS */ - - -#define _PyLong_FromDev PyLong_FromLongLong - - -#if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) || defined(HAVE_DEVICE_MACROS) -static int -_Py_Dev_Converter(PyObject *obj, void *p) -{ - *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj); - if (PyErr_Occurred()) - return 0; - return 1; -} -#endif /* (HAVE_MKNOD && HAVE_MAKEDEV) || HAVE_DEVICE_MACROS */ - - -#ifdef AT_FDCWD -/* - * Why the (int) cast? Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965); - * without the int cast, the value gets interpreted as uint (4291925331), - * which doesn't play nicely with all the initializer lines in this file that - * look like this: - * int dir_fd = DEFAULT_DIR_FD; - */ -#define DEFAULT_DIR_FD (int)AT_FDCWD -#else -#define DEFAULT_DIR_FD (-100) -#endif - -static int -_fd_converter(PyObject *o, int *p) -{ - int overflow; - long long_value; - - PyObject *index = _PyNumber_Index(o); - if (index == NULL) { - return 0; - } - - assert(PyLong_Check(index)); - long_value = PyLong_AsLongAndOverflow(index, &overflow); - Py_DECREF(index); - assert(!PyErr_Occurred()); - if (overflow > 0 || long_value > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "fd is greater than maximum"); - return 0; - } - if (overflow < 0 || long_value < INT_MIN) { - PyErr_SetString(PyExc_OverflowError, - "fd is less than minimum"); - return 0; - } - - *p = (int)long_value; - return 1; -} - -static int -dir_fd_converter(PyObject *o, void *p) -{ - if (o == Py_None) { - *(int *)p = DEFAULT_DIR_FD; - return 1; - } - else if (PyIndex_Check(o)) { - return _fd_converter(o, (int *)p); - } - else { - PyErr_Format(PyExc_TypeError, - "argument should be integer or None, not %.200s", - _PyType_Name(Py_TYPE(o))); - return 0; - } -} - -typedef struct { - PyObject *billion; - PyObject *DirEntryType; - PyObject *ScandirIteratorType; -#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) - PyObject *SchedParamType; -#endif - PyObject *StatResultType; - PyObject *StatVFSResultType; - PyObject *TerminalSizeType; - PyObject *TimesResultType; - PyObject *UnameResultType; -#if defined(HAVE_WAITID) && !defined(__APPLE__) - PyObject *WaitidResultType; -#endif -#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) - PyObject *struct_rusage; -#endif - PyObject *st_mode; -} _posixstate; - - -static inline _posixstate* -get_posix_state(PyObject *module) -{ - void *state = _PyModule_GetState(module); - assert(state != NULL); - return (_posixstate *)state; -} - -/* - * A PyArg_ParseTuple "converter" function - * that handles filesystem paths in the manner - * preferred by the os module. - * - * path_converter accepts (Unicode) strings and their - * subclasses, and bytes and their subclasses. What - * it does with the argument depends on the platform: - * - * * On Windows, if we get a (Unicode) string we - * extract the wchar_t * and return it; if we get - * bytes we decode to wchar_t * and return that. - * - * * On all other platforms, strings are encoded - * to bytes using PyUnicode_FSConverter, then we - * extract the char * from the bytes object and - * return that. - * - * path_converter also optionally accepts signed - * integers (representing open file descriptors) instead - * of path strings. - * - * Input fields: - * path.nullable - * If nonzero, the path is permitted to be None. - * path.allow_fd - * If nonzero, the path is permitted to be a file handle - * (a signed int) instead of a string. - * path.function_name - * If non-NULL, path_converter will use that as the name - * of the function in error messages. - * (If path.function_name is NULL it omits the function name.) - * path.argument_name - * If non-NULL, path_converter will use that as the name - * of the parameter in error messages. - * (If path.argument_name is NULL it uses "path".) - * - * Output fields: - * path.wide - * Points to the path if it was expressed as Unicode - * and was not encoded. (Only used on Windows.) - * path.narrow - * Points to the path if it was expressed as bytes, - * or it was Unicode and was encoded to bytes. (On Windows, - * is a non-zero integer if the path was expressed as bytes. - * The type is deliberately incompatible to prevent misuse.) - * path.fd - * Contains a file descriptor if path.accept_fd was true - * and the caller provided a signed integer instead of any - * sort of string. - * - * WARNING: if your "path" parameter is optional, and is - * unspecified, path_converter will never get called. - * So if you set allow_fd, you *MUST* initialize path.fd = -1 - * yourself! - * path.length - * The length of the path in characters, if specified as - * a string. - * path.object - * The original object passed in (if get a PathLike object, - * the result of PyOS_FSPath() is treated as the original object). - * Own a reference to the object. - * path.cleanup - * For internal use only. May point to a temporary object. - * (Pay no attention to the man behind the curtain.) - * - * At most one of path.wide or path.narrow will be non-NULL. - * If path was None and path.nullable was set, - * or if path was an integer and path.allow_fd was set, - * both path.wide and path.narrow will be NULL - * and path.length will be 0. - * - * path_converter takes care to not write to the path_t - * unless it's successful. However it must reset the - * "cleanup" field each time it's called. - * - * Use as follows: - * path_t path; - * memset(&path, 0, sizeof(path)); - * PyArg_ParseTuple(args, "O&", path_converter, &path); - * // ... use values from path ... - * path_cleanup(&path); - * - * (Note that if PyArg_Parse fails you don't need to call - * path_cleanup(). However it is safe to do so.) - */ -typedef struct { - const char *function_name; - const char *argument_name; - int nullable; - int allow_fd; - const wchar_t *wide; -#ifdef MS_WINDOWS - BOOL narrow; -#else - const char *narrow; -#endif - int fd; - Py_ssize_t length; - PyObject *object; - PyObject *cleanup; -} path_t; - -#ifdef MS_WINDOWS -#define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \ - {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL} -#else -#define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \ - {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL} -#endif - -static void -path_cleanup(path_t *path) -{ - wchar_t *wide = (wchar_t *)path->wide; - path->wide = NULL; - PyMem_Free(wide); - Py_CLEAR(path->object); - Py_CLEAR(path->cleanup); -} - -static int -path_converter(PyObject *o, void *p) -{ - path_t *path = (path_t *)p; - PyObject *bytes = NULL; - Py_ssize_t length = 0; - int is_index, is_bytes, is_unicode; - const char *narrow; -#ifdef MS_WINDOWS - PyObject *wo = NULL; - wchar_t *wide = NULL; -#endif - -#define FORMAT_EXCEPTION(exc, fmt) \ - PyErr_Format(exc, "%s%s" fmt, \ - path->function_name ? path->function_name : "", \ - path->function_name ? ": " : "", \ - path->argument_name ? path->argument_name : "path") - - /* Py_CLEANUP_SUPPORTED support */ - if (o == NULL) { - path_cleanup(path); - return 1; - } - - /* Ensure it's always safe to call path_cleanup(). */ - path->object = path->cleanup = NULL; - /* path->object owns a reference to the original object */ - Py_INCREF(o); - - if ((o == Py_None) && path->nullable) { - path->wide = NULL; -#ifdef MS_WINDOWS - path->narrow = FALSE; -#else - path->narrow = NULL; -#endif - path->fd = -1; - goto success_exit; - } - - /* Only call this here so that we don't treat the return value of - os.fspath() as an fd or buffer. */ - is_index = path->allow_fd && PyIndex_Check(o); - is_bytes = PyBytes_Check(o); - is_unicode = PyUnicode_Check(o); - - if (!is_index && !is_unicode && !is_bytes) { - /* Inline PyOS_FSPath() for better error messages. */ - PyObject *func, *res; - - func = _PyObject_LookupSpecial(o, &_Py_ID(__fspath__)); - if (NULL == func) { - goto error_format; - } - res = _PyObject_CallNoArgs(func); - Py_DECREF(func); - if (NULL == res) { - goto error_exit; - } - else if (PyUnicode_Check(res)) { - is_unicode = 1; - } - else if (PyBytes_Check(res)) { - is_bytes = 1; - } - else { - PyErr_Format(PyExc_TypeError, - "expected %.200s.__fspath__() to return str or bytes, " - "not %.200s", _PyType_Name(Py_TYPE(o)), - _PyType_Name(Py_TYPE(res))); - Py_DECREF(res); - goto error_exit; - } - - /* still owns a reference to the original object */ - Py_DECREF(o); - o = res; - } - - if (is_unicode) { -#ifdef MS_WINDOWS - wide = PyUnicode_AsWideCharString(o, &length); - if (!wide) { - goto error_exit; - } - if (length > 32767) { - FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); - goto error_exit; - } - if (wcslen(wide) != length) { - FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); - goto error_exit; - } - - path->wide = wide; - path->narrow = FALSE; - path->fd = -1; - wide = NULL; - goto success_exit; -#else - if (!PyUnicode_FSConverter(o, &bytes)) { - goto error_exit; - } -#endif - } - else if (is_bytes) { - bytes = Py_NewRef(o); - } - else if (is_index) { - if (!_fd_converter(o, &path->fd)) { - goto error_exit; - } - path->wide = NULL; -#ifdef MS_WINDOWS - path->narrow = FALSE; -#else - path->narrow = NULL; -#endif - goto success_exit; - } - else { - error_format: - PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s", - path->function_name ? path->function_name : "", - path->function_name ? ": " : "", - path->argument_name ? path->argument_name : "path", - path->allow_fd && path->nullable ? "string, bytes, os.PathLike, " - "integer or None" : - path->allow_fd ? "string, bytes, os.PathLike or integer" : - path->nullable ? "string, bytes, os.PathLike or None" : - "string, bytes or os.PathLike", - _PyType_Name(Py_TYPE(o))); - goto error_exit; - } - - length = PyBytes_GET_SIZE(bytes); - narrow = PyBytes_AS_STRING(bytes); - if ((size_t)length != strlen(narrow)) { - FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); - goto error_exit; - } - -#ifdef MS_WINDOWS - wo = PyUnicode_DecodeFSDefaultAndSize( - narrow, - length - ); - if (!wo) { - goto error_exit; - } - - wide = PyUnicode_AsWideCharString(wo, &length); - Py_DECREF(wo); - if (!wide) { - goto error_exit; - } - if (length > 32767) { - FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); - goto error_exit; - } - if (wcslen(wide) != length) { - FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); - goto error_exit; - } - path->wide = wide; - path->narrow = TRUE; - Py_DECREF(bytes); - wide = NULL; -#else - path->wide = NULL; - path->narrow = narrow; - if (bytes == o) { - /* Still a reference owned by path->object, don't have to - worry about path->narrow is used after free. */ - Py_DECREF(bytes); - } - else { - path->cleanup = bytes; - } -#endif - path->fd = -1; - - success_exit: - path->length = length; - path->object = o; - return Py_CLEANUP_SUPPORTED; - - error_exit: - Py_XDECREF(o); - Py_XDECREF(bytes); -#ifdef MS_WINDOWS - PyMem_Free(wide); -#endif - return 0; -} - -static void -argument_unavailable_error(const char *function_name, const char *argument_name) -{ - PyErr_Format(PyExc_NotImplementedError, - "%s%s%s unavailable on this platform", - (function_name != NULL) ? function_name : "", - (function_name != NULL) ? ": ": "", - argument_name); -} - -static int -dir_fd_unavailable(PyObject *o, void *p) -{ - int dir_fd; - if (!dir_fd_converter(o, &dir_fd)) - return 0; - if (dir_fd != DEFAULT_DIR_FD) { - argument_unavailable_error(NULL, "dir_fd"); - return 0; - } - *(int *)p = dir_fd; - return 1; -} - -static int -fd_specified(const char *function_name, int fd) -{ - if (fd == -1) - return 0; - - argument_unavailable_error(function_name, "fd"); - return 1; -} - -static int -follow_symlinks_specified(const char *function_name, int follow_symlinks) -{ - if (follow_symlinks) - return 0; - - argument_unavailable_error(function_name, "follow_symlinks"); - return 1; -} - -static int -path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd) -{ - if (!path->wide && (dir_fd != DEFAULT_DIR_FD) -#ifndef MS_WINDOWS - && !path->narrow -#endif - ) { - PyErr_Format(PyExc_ValueError, - "%s: can't specify dir_fd without matching path", - function_name); - return 1; - } - return 0; -} - -static int -dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd) -{ - if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) { - PyErr_Format(PyExc_ValueError, - "%s: can't specify both dir_fd and fd", - function_name); - return 1; - } - return 0; -} - -static int -fd_and_follow_symlinks_invalid(const char *function_name, int fd, - int follow_symlinks) -{ - if ((fd > 0) && (!follow_symlinks)) { - PyErr_Format(PyExc_ValueError, - "%s: cannot use fd and follow_symlinks together", - function_name); - return 1; - } - return 0; -} - -static int -dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd, - int follow_symlinks) -{ - if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) { - PyErr_Format(PyExc_ValueError, - "%s: cannot use dir_fd and follow_symlinks together", - function_name); - return 1; - } - return 0; -} - -#ifdef MS_WINDOWS - typedef long long Py_off_t; -#else - typedef off_t Py_off_t; -#endif - -static int -Py_off_t_converter(PyObject *arg, void *addr) -{ -#ifdef HAVE_LARGEFILE_SUPPORT - *((Py_off_t *)addr) = PyLong_AsLongLong(arg); -#else - *((Py_off_t *)addr) = PyLong_AsLong(arg); -#endif - if (PyErr_Occurred()) - return 0; - return 1; -} - -static PyObject * -PyLong_FromPy_off_t(Py_off_t offset) -{ -#ifdef HAVE_LARGEFILE_SUPPORT - return PyLong_FromLongLong(offset); -#else - return PyLong_FromLong(offset); -#endif -} - -#ifdef HAVE_SIGSET_T -/* Convert an iterable of integers to a sigset. - Return 1 on success, return 0 and raise an exception on error. */ -int -_Py_Sigset_Converter(PyObject *obj, void *addr) -{ - sigset_t *mask = (sigset_t *)addr; - PyObject *iterator, *item; - long signum; - int overflow; - - // The extra parens suppress the unreachable-code warning with clang on MacOS - if (sigemptyset(mask) < (0)) { - /* Probably only if mask == NULL. */ - PyErr_SetFromErrno(PyExc_OSError); - return 0; - } - - iterator = PyObject_GetIter(obj); - if (iterator == NULL) { - return 0; - } - - while ((item = PyIter_Next(iterator)) != NULL) { - signum = PyLong_AsLongAndOverflow(item, &overflow); - Py_DECREF(item); - if (signum <= 0 || signum >= Py_NSIG) { - if (overflow || signum != -1 || !PyErr_Occurred()) { - PyErr_Format(PyExc_ValueError, - "signal number %ld out of range [1; %i]", - signum, Py_NSIG - 1); - } - goto error; - } - if (sigaddset(mask, (int)signum)) { - if (errno != EINVAL) { - /* Probably impossible */ - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - /* For backwards compatibility, allow idioms such as - * `range(1, NSIG)` but warn about invalid signal numbers - */ - const char msg[] = - "invalid signal number %ld, please use valid_signals()"; - if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) { - goto error; - } - } - } - if (!PyErr_Occurred()) { - Py_DECREF(iterator); - return 1; - } - -error: - Py_DECREF(iterator); - return 0; -} -#endif /* HAVE_SIGSET_T */ - -#ifdef MS_WINDOWS - -static int -win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag) -{ - char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; - _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer; - DWORD n_bytes_returned; - - if (0 == DeviceIoControl( - reparse_point_handle, - FSCTL_GET_REPARSE_POINT, - NULL, 0, /* in buffer */ - target_buffer, sizeof(target_buffer), - &n_bytes_returned, - NULL)) /* we're not using OVERLAPPED_IO */ - return FALSE; - - if (reparse_tag) - *reparse_tag = rdb->ReparseTag; - - return TRUE; -} - -#endif /* MS_WINDOWS */ - -/* Return a dictionary corresponding to the POSIX environment table */ -#if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED)) -/* On Darwin/MacOSX a shared library or framework has no access to -** environ directly, we must obtain it with _NSGetEnviron(). See also -** man environ(7). -*/ -#include -#elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__)) -extern char **environ; -#endif /* !_MSC_VER */ - -static PyObject * -convertenviron(void) -{ - PyObject *d; -#ifdef MS_WINDOWS - wchar_t **e; -#else - char **e; -#endif - - d = PyDict_New(); - if (d == NULL) - return NULL; -#ifdef MS_WINDOWS - /* _wenviron must be initialized in this way if the program is started - through main() instead of wmain(). */ - _wgetenv(L""); - e = _wenviron; -#elif defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED)) - /* environ is not accessible as an extern in a shared object on OSX; use - _NSGetEnviron to resolve it. The value changes if you add environment - variables between calls to Py_Initialize, so don't cache the value. */ - e = *_NSGetEnviron(); -#else - e = environ; -#endif - if (e == NULL) - return d; - for (; *e != NULL; e++) { - PyObject *k; - PyObject *v; -#ifdef MS_WINDOWS - const wchar_t *p = wcschr(*e, L'='); -#else - const char *p = strchr(*e, '='); -#endif - if (p == NULL) - continue; -#ifdef MS_WINDOWS - k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e)); -#else - k = PyBytes_FromStringAndSize(*e, (int)(p-*e)); -#endif - if (k == NULL) { - Py_DECREF(d); - return NULL; - } -#ifdef MS_WINDOWS - v = PyUnicode_FromWideChar(p+1, wcslen(p+1)); -#else - v = PyBytes_FromStringAndSize(p+1, strlen(p+1)); -#endif - if (v == NULL) { - Py_DECREF(k); - Py_DECREF(d); - return NULL; - } - if (PyDict_SetDefault(d, k, v) == NULL) { - Py_DECREF(v); - Py_DECREF(k); - Py_DECREF(d); - return NULL; - } - Py_DECREF(k); - Py_DECREF(v); - } - return d; -} - -/* Set a POSIX-specific error from errno, and return NULL */ - -static PyObject * -posix_error(void) -{ - return PyErr_SetFromErrno(PyExc_OSError); -} - -#ifdef MS_WINDOWS -static PyObject * -win32_error(const char* function, const char* filename) -{ - /* XXX We should pass the function name along in the future. - (winreg.c also wants to pass the function name.) - This would however require an additional param to the - Windows error object, which is non-trivial. - */ - errno = GetLastError(); - if (filename) - return PyErr_SetFromWindowsErrWithFilename(errno, filename); - else - return PyErr_SetFromWindowsErr(errno); -} - -static PyObject * -win32_error_object_err(const char* function, PyObject* filename, DWORD err) -{ - /* XXX - see win32_error for comments on 'function' */ - if (filename) - return PyErr_SetExcFromWindowsErrWithFilenameObject( - PyExc_OSError, - err, - filename); - else - return PyErr_SetFromWindowsErr(err); -} - -static PyObject * -win32_error_object(const char* function, PyObject* filename) -{ - errno = GetLastError(); - return win32_error_object_err(function, filename, errno); -} - -#endif /* MS_WINDOWS */ - -static PyObject * -posix_path_object_error(PyObject *path) -{ - return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path); -} - -static PyObject * -path_object_error(PyObject *path) -{ -#ifdef MS_WINDOWS - return PyErr_SetExcFromWindowsErrWithFilenameObject( - PyExc_OSError, 0, path); -#else - return posix_path_object_error(path); -#endif -} - -static PyObject * -path_object_error2(PyObject *path, PyObject *path2) -{ -#ifdef MS_WINDOWS - return PyErr_SetExcFromWindowsErrWithFilenameObjects( - PyExc_OSError, 0, path, path2); -#else - return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2); -#endif -} - -static PyObject * -path_error(path_t *path) -{ - return path_object_error(path->object); -} - -static PyObject * -posix_path_error(path_t *path) -{ - return posix_path_object_error(path->object); -} - -static PyObject * -path_error2(path_t *path, path_t *path2) -{ - return path_object_error2(path->object, path2->object); -} - - -/* POSIX generic methods */ - -static PyObject * -posix_fildes_fd(int fd, int (*func)(int)) -{ - int res; - int async_err = 0; - - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - res = (*func)(fd); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (res != 0) - return (!async_err) ? posix_error() : NULL; - Py_RETURN_NONE; -} - - -#ifdef MS_WINDOWS -/* This is a reimplementation of the C library's chdir function, - but one that produces Win32 errors instead of DOS error codes. - chdir is essentially a wrapper around SetCurrentDirectory; however, - it also needs to set "magic" environment variables indicating - the per-drive current directory, which are of the form =: */ -static BOOL __stdcall -win32_wchdir(LPCWSTR path) -{ - wchar_t path_buf[MAX_PATH], *new_path = path_buf; - int result; - wchar_t env[4] = L"=x:"; - - if(!SetCurrentDirectoryW(path)) - return FALSE; - result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path); - if (!result) - return FALSE; - if (result > Py_ARRAY_LENGTH(path_buf)) { - new_path = PyMem_RawMalloc(result * sizeof(wchar_t)); - if (!new_path) { - SetLastError(ERROR_OUTOFMEMORY); - return FALSE; - } - result = GetCurrentDirectoryW(result, new_path); - if (!result) { - PyMem_RawFree(new_path); - return FALSE; - } - } - int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 || - wcsncmp(new_path, L"//", 2) == 0); - if (!is_unc_like_path) { - env[1] = new_path[0]; - result = SetEnvironmentVariableW(env, new_path); - } - if (new_path != path_buf) - PyMem_RawFree(new_path); - return result ? TRUE : FALSE; -} -#endif - -#ifdef MS_WINDOWS -/* The CRT of Windows has a number of flaws wrt. its stat() implementation: - - time stamps are restricted to second resolution - - file modification times suffer from forth-and-back conversions between - UTC and local time - Therefore, we implement our own stat, based on the Win32 API directly. -*/ -#define HAVE_STAT_NSEC 1 -#define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1 -#define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1 - -static void -find_data_to_file_info(WIN32_FIND_DATAW *pFileData, - BY_HANDLE_FILE_INFORMATION *info, - ULONG *reparse_tag) -{ - memset(info, 0, sizeof(*info)); - info->dwFileAttributes = pFileData->dwFileAttributes; - info->ftCreationTime = pFileData->ftCreationTime; - info->ftLastAccessTime = pFileData->ftLastAccessTime; - info->ftLastWriteTime = pFileData->ftLastWriteTime; - info->nFileSizeHigh = pFileData->nFileSizeHigh; - info->nFileSizeLow = pFileData->nFileSizeLow; -/* info->nNumberOfLinks = 1; */ - if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) - *reparse_tag = pFileData->dwReserved0; - else - *reparse_tag = 0; -} - -static BOOL -attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag) -{ - HANDLE hFindFile; - WIN32_FIND_DATAW FileData; - LPCWSTR filename = pszFile; - size_t n = wcslen(pszFile); - if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) { - // cannot use PyMem_Malloc here because we do not hold the GIL - filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0])); - wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n); - while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) { - ((LPWSTR)filename)[n] = L'\0'; - } - if (!n || (n == 1 && filename[1] == L':')) { - // Nothing left to query - free((void *)filename); - return FALSE; - } - } - hFindFile = FindFirstFileW(filename, &FileData); - if (pszFile != filename) { - free((void *)filename); - } - if (hFindFile == INVALID_HANDLE_VALUE) { - return FALSE; - } - FindClose(hFindFile); - find_data_to_file_info(&FileData, info, reparse_tag); - return TRUE; -} - -static int -win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result, - BOOL traverse) -{ - HANDLE hFile; - BY_HANDLE_FILE_INFORMATION fileInfo; - FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 }; - DWORD fileType, error; - BOOL isUnhandledTag = FALSE; - int retval = 0; - - DWORD access = FILE_READ_ATTRIBUTES; - DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */ - if (!traverse) { - flags |= FILE_FLAG_OPEN_REPARSE_POINT; - } - - hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL); - if (hFile == INVALID_HANDLE_VALUE) { - /* Either the path doesn't exist, or the caller lacks access. */ - error = GetLastError(); - switch (error) { - case ERROR_ACCESS_DENIED: /* Cannot sync or read attributes. */ - case ERROR_SHARING_VIOLATION: /* It's a paging file. */ - /* Try reading the parent directory. */ - if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) { - /* Cannot read the parent directory. */ - switch (GetLastError()) { - case ERROR_FILE_NOT_FOUND: /* File cannot be found */ - case ERROR_PATH_NOT_FOUND: /* File parent directory cannot be found */ - case ERROR_NOT_READY: /* Drive exists but unavailable */ - case ERROR_BAD_NET_NAME: /* Remote drive unavailable */ - break; - /* Restore the error from CreateFileW(). */ - default: - SetLastError(error); - } - - return -1; - } - if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - if (traverse || - !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) { - /* The stat call has to traverse but cannot, so fail. */ - SetLastError(error); - return -1; - } - } - break; - - case ERROR_INVALID_PARAMETER: - /* \\.\con requires read or write access. */ - hFile = CreateFileW(path, access | GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, - OPEN_EXISTING, flags, NULL); - if (hFile == INVALID_HANDLE_VALUE) { - SetLastError(error); - return -1; - } - break; - - case ERROR_CANT_ACCESS_FILE: - /* bpo37834: open unhandled reparse points if traverse fails. */ - if (traverse) { - traverse = FALSE; - isUnhandledTag = TRUE; - hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, - flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL); - } - if (hFile == INVALID_HANDLE_VALUE) { - SetLastError(error); - return -1; - } - break; - - default: - return -1; - } - } - - if (hFile != INVALID_HANDLE_VALUE) { - /* Handle types other than files on disk. */ - fileType = GetFileType(hFile); - if (fileType != FILE_TYPE_DISK) { - if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) { - retval = -1; - goto cleanup; - } - DWORD fileAttributes = GetFileAttributesW(path); - memset(result, 0, sizeof(*result)); - if (fileAttributes != INVALID_FILE_ATTRIBUTES && - fileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - /* \\.\pipe\ or \\.\mailslot\ */ - result->st_mode = _S_IFDIR; - } else if (fileType == FILE_TYPE_CHAR) { - /* \\.\nul */ - result->st_mode = _S_IFCHR; - } else if (fileType == FILE_TYPE_PIPE) { - /* \\.\pipe\spam */ - result->st_mode = _S_IFIFO; - } - /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */ - goto cleanup; - } - - /* Query the reparse tag, and traverse a non-link. */ - if (!traverse) { - if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo, - &tagInfo, sizeof(tagInfo))) { - /* Allow devices that do not support FileAttributeTagInfo. */ - switch (GetLastError()) { - case ERROR_INVALID_PARAMETER: - case ERROR_INVALID_FUNCTION: - case ERROR_NOT_SUPPORTED: - tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL; - tagInfo.ReparseTag = 0; - break; - default: - retval = -1; - goto cleanup; - } - } else if (tagInfo.FileAttributes & - FILE_ATTRIBUTE_REPARSE_POINT) { - if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) { - if (isUnhandledTag) { - /* Traversing previously failed for either this link - or its target. */ - SetLastError(ERROR_CANT_ACCESS_FILE); - retval = -1; - goto cleanup; - } - /* Traverse a non-link, but not if traversing already failed - for an unhandled tag. */ - } else if (!isUnhandledTag) { - CloseHandle(hFile); - return win32_xstat_impl(path, result, TRUE); - } - } - } - - if (!GetFileInformationByHandle(hFile, &fileInfo)) { - switch (GetLastError()) { - case ERROR_INVALID_PARAMETER: - case ERROR_INVALID_FUNCTION: - case ERROR_NOT_SUPPORTED: - /* Volumes and physical disks are block devices, e.g. - \\.\C: and \\.\PhysicalDrive0. */ - memset(result, 0, sizeof(*result)); - result->st_mode = 0x6000; /* S_IFBLK */ - goto cleanup; - } - retval = -1; - goto cleanup; - } - } - - _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, result); - - if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { - /* Fix the file execute permissions. This hack sets S_IEXEC if - the filename has an extension that is commonly used by files - that CreateProcessW can execute. A real implementation calls - GetSecurityInfo, OpenThreadToken/OpenProcessToken, and - AccessCheck to check for generic read, write, and execute - access. */ - const wchar_t *fileExtension = wcsrchr(path, '.'); - if (fileExtension) { - if (_wcsicmp(fileExtension, L".exe") == 0 || - _wcsicmp(fileExtension, L".bat") == 0 || - _wcsicmp(fileExtension, L".cmd") == 0 || - _wcsicmp(fileExtension, L".com") == 0) { - result->st_mode |= 0111; - } - } - } - -cleanup: - if (hFile != INVALID_HANDLE_VALUE) { - /* Preserve last error if we are failing */ - error = retval ? GetLastError() : 0; - if (!CloseHandle(hFile)) { - retval = -1; - } else if (retval) { - /* Restore last error */ - SetLastError(error); - } - } - - return retval; -} - -static int -win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse) -{ - /* Protocol violation: we explicitly clear errno, instead of - setting it to a POSIX error. Callers should use GetLastError. */ - int code = win32_xstat_impl(path, result, traverse); - errno = 0; - return code; -} -/* About the following functions: win32_lstat_w, win32_stat, win32_stat_w - - In Posix, stat automatically traverses symlinks and returns the stat - structure for the target. In Windows, the equivalent GetFileAttributes by - default does not traverse symlinks and instead returns attributes for - the symlink. - - Instead, we will open the file (which *does* traverse symlinks by default) - and GetFileInformationByHandle(). */ - -static int -win32_lstat(const wchar_t* path, struct _Py_stat_struct *result) -{ - return win32_xstat(path, result, FALSE); -} - -static int -win32_stat(const wchar_t* path, struct _Py_stat_struct *result) -{ - return win32_xstat(path, result, TRUE); -} - -#endif /* MS_WINDOWS */ - -PyDoc_STRVAR(stat_result__doc__, -"stat_result: Result from stat, fstat, or lstat.\n\n\ -This object may be accessed either as a tuple of\n\ - (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\ -or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\ -\n\ -Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\ -or st_flags, they are available as attributes only.\n\ -\n\ -See os.stat for more information."); - -static PyStructSequence_Field stat_result_fields[] = { - {"st_mode", "protection bits"}, - {"st_ino", "inode"}, - {"st_dev", "device"}, - {"st_nlink", "number of hard links"}, - {"st_uid", "user ID of owner"}, - {"st_gid", "group ID of owner"}, - {"st_size", "total size, in bytes"}, - /* The NULL is replaced with PyStructSequence_UnnamedField later. */ - {NULL, "integer time of last access"}, - {NULL, "integer time of last modification"}, - {NULL, "integer time of last change"}, - {"st_atime", "time of last access"}, - {"st_mtime", "time of last modification"}, - {"st_ctime", "time of last change"}, - {"st_atime_ns", "time of last access in nanoseconds"}, - {"st_mtime_ns", "time of last modification in nanoseconds"}, - {"st_ctime_ns", "time of last change in nanoseconds"}, -#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE - {"st_blksize", "blocksize for filesystem I/O"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_BLOCKS - {"st_blocks", "number of blocks allocated"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_RDEV - {"st_rdev", "device type (if inode device)"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_FLAGS - {"st_flags", "user defined flags for file"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_GEN - {"st_gen", "generation number"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME - {"st_birthtime", "time of creation"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES - {"st_file_attributes", "Windows file attribute bits"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_FSTYPE - {"st_fstype", "Type of filesystem"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG - {"st_reparse_tag", "Windows reparse tag"}, -#endif - {0} -}; - -#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE -#define ST_BLKSIZE_IDX 16 -#else -#define ST_BLKSIZE_IDX 15 -#endif - -#ifdef HAVE_STRUCT_STAT_ST_BLOCKS -#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1) -#else -#define ST_BLOCKS_IDX ST_BLKSIZE_IDX -#endif - -#ifdef HAVE_STRUCT_STAT_ST_RDEV -#define ST_RDEV_IDX (ST_BLOCKS_IDX+1) -#else -#define ST_RDEV_IDX ST_BLOCKS_IDX -#endif - -#ifdef HAVE_STRUCT_STAT_ST_FLAGS -#define ST_FLAGS_IDX (ST_RDEV_IDX+1) -#else -#define ST_FLAGS_IDX ST_RDEV_IDX -#endif - -#ifdef HAVE_STRUCT_STAT_ST_GEN -#define ST_GEN_IDX (ST_FLAGS_IDX+1) -#else -#define ST_GEN_IDX ST_FLAGS_IDX -#endif - -#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME -#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1) -#else -#define ST_BIRTHTIME_IDX ST_GEN_IDX -#endif - -#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES -#define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1) -#else -#define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX -#endif - -#ifdef HAVE_STRUCT_STAT_ST_FSTYPE -#define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1) -#else -#define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX -#endif - -#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG -#define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1) -#else -#define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX -#endif - -static PyStructSequence_Desc stat_result_desc = { - "stat_result", /* name */ - stat_result__doc__, /* doc */ - stat_result_fields, - 10 -}; - -PyDoc_STRVAR(statvfs_result__doc__, -"statvfs_result: Result from statvfs or fstatvfs.\n\n\ -This object may be accessed either as a tuple of\n\ - (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\ -or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\ -\n\ -See os.statvfs for more information."); - -static PyStructSequence_Field statvfs_result_fields[] = { - {"f_bsize", }, - {"f_frsize", }, - {"f_blocks", }, - {"f_bfree", }, - {"f_bavail", }, - {"f_files", }, - {"f_ffree", }, - {"f_favail", }, - {"f_flag", }, - {"f_namemax",}, - {"f_fsid", }, - {0} -}; - -static PyStructSequence_Desc statvfs_result_desc = { - "statvfs_result", /* name */ - statvfs_result__doc__, /* doc */ - statvfs_result_fields, - 10 -}; - -#if defined(HAVE_WAITID) && !defined(__APPLE__) -PyDoc_STRVAR(waitid_result__doc__, -"waitid_result: Result from waitid.\n\n\ -This object may be accessed either as a tuple of\n\ - (si_pid, si_uid, si_signo, si_status, si_code),\n\ -or via the attributes si_pid, si_uid, and so on.\n\ -\n\ -See os.waitid for more information."); - -static PyStructSequence_Field waitid_result_fields[] = { - {"si_pid", }, - {"si_uid", }, - {"si_signo", }, - {"si_status", }, - {"si_code", }, - {0} -}; - -static PyStructSequence_Desc waitid_result_desc = { - "waitid_result", /* name */ - waitid_result__doc__, /* doc */ - waitid_result_fields, - 5 -}; -#endif -static newfunc structseq_new; - -static PyObject * -statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyStructSequence *result; - int i; - - result = (PyStructSequence*)structseq_new(type, args, kwds); - if (!result) - return NULL; - /* If we have been initialized from a tuple, - st_?time might be set to None. Initialize it - from the int slots. */ - for (i = 7; i <= 9; i++) { - if (result->ob_item[i+3] == Py_None) { - Py_DECREF(Py_None); - result->ob_item[i+3] = Py_NewRef(result->ob_item[i]); - } - } - return (PyObject*)result; -} - -static int -_posix_clear(PyObject *module) -{ - _posixstate *state = get_posix_state(module); - Py_CLEAR(state->billion); - Py_CLEAR(state->DirEntryType); - Py_CLEAR(state->ScandirIteratorType); -#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) - Py_CLEAR(state->SchedParamType); -#endif - Py_CLEAR(state->StatResultType); - Py_CLEAR(state->StatVFSResultType); - Py_CLEAR(state->TerminalSizeType); - Py_CLEAR(state->TimesResultType); - Py_CLEAR(state->UnameResultType); -#if defined(HAVE_WAITID) && !defined(__APPLE__) - Py_CLEAR(state->WaitidResultType); -#endif -#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) - Py_CLEAR(state->struct_rusage); -#endif - Py_CLEAR(state->st_mode); - return 0; -} - -static int -_posix_traverse(PyObject *module, visitproc visit, void *arg) -{ - _posixstate *state = get_posix_state(module); - Py_VISIT(state->billion); - Py_VISIT(state->DirEntryType); - Py_VISIT(state->ScandirIteratorType); -#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) - Py_VISIT(state->SchedParamType); -#endif - Py_VISIT(state->StatResultType); - Py_VISIT(state->StatVFSResultType); - Py_VISIT(state->TerminalSizeType); - Py_VISIT(state->TimesResultType); - Py_VISIT(state->UnameResultType); -#if defined(HAVE_WAITID) && !defined(__APPLE__) - Py_VISIT(state->WaitidResultType); -#endif -#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) - Py_VISIT(state->struct_rusage); -#endif - Py_VISIT(state->st_mode); - return 0; -} - -static void -_posix_free(void *module) -{ - _posix_clear((PyObject *)module); -} - -static void -fill_time(PyObject *module, PyObject *v, int index, time_t sec, unsigned long nsec) -{ - PyObject *s = _PyLong_FromTime_t(sec); - PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec); - PyObject *s_in_ns = NULL; - PyObject *ns_total = NULL; - PyObject *float_s = NULL; - - if (!(s && ns_fractional)) - goto exit; - - s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion); - if (!s_in_ns) - goto exit; - - ns_total = PyNumber_Add(s_in_ns, ns_fractional); - if (!ns_total) - goto exit; - - float_s = PyFloat_FromDouble(sec + 1e-9*nsec); - if (!float_s) { - goto exit; - } - - PyStructSequence_SET_ITEM(v, index, s); - PyStructSequence_SET_ITEM(v, index+3, float_s); - PyStructSequence_SET_ITEM(v, index+6, ns_total); - s = NULL; - float_s = NULL; - ns_total = NULL; -exit: - Py_XDECREF(s); - Py_XDECREF(ns_fractional); - Py_XDECREF(s_in_ns); - Py_XDECREF(ns_total); - Py_XDECREF(float_s); -} - -/* pack a system stat C structure into the Python stat tuple - (used by posix_stat() and posix_fstat()) */ -static PyObject* -_pystat_fromstructstat(PyObject *module, STRUCT_STAT *st) -{ - unsigned long ansec, mnsec, cnsec; - PyObject *StatResultType = get_posix_state(module)->StatResultType; - PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType); - if (v == NULL) - return NULL; - - PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode)); - static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino), - "stat.st_ino is larger than unsigned long long"); - PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLongLong(st->st_ino)); -#ifdef MS_WINDOWS - PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev)); -#else - PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev)); -#endif - PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink)); -#if defined(MS_WINDOWS) - PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0)); - PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0)); -#else - PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid)); - PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid)); -#endif - static_assert(sizeof(long long) >= sizeof(st->st_size), - "stat.st_size is larger than long long"); - PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size)); - -#if defined(HAVE_STAT_TV_NSEC) - ansec = st->st_atim.tv_nsec; - mnsec = st->st_mtim.tv_nsec; - cnsec = st->st_ctim.tv_nsec; -#elif defined(HAVE_STAT_TV_NSEC2) - ansec = st->st_atimespec.tv_nsec; - mnsec = st->st_mtimespec.tv_nsec; - cnsec = st->st_ctimespec.tv_nsec; -#elif defined(HAVE_STAT_NSEC) - ansec = st->st_atime_nsec; - mnsec = st->st_mtime_nsec; - cnsec = st->st_ctime_nsec; -#else - ansec = mnsec = cnsec = 0; -#endif - fill_time(module, v, 7, st->st_atime, ansec); - fill_time(module, v, 8, st->st_mtime, mnsec); - fill_time(module, v, 9, st->st_ctime, cnsec); - -#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE - PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX, - PyLong_FromLong((long)st->st_blksize)); -#endif -#ifdef HAVE_STRUCT_STAT_ST_BLOCKS - PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX, - PyLong_FromLong((long)st->st_blocks)); -#endif -#ifdef HAVE_STRUCT_STAT_ST_RDEV - PyStructSequence_SET_ITEM(v, ST_RDEV_IDX, - PyLong_FromLong((long)st->st_rdev)); -#endif -#ifdef HAVE_STRUCT_STAT_ST_GEN - PyStructSequence_SET_ITEM(v, ST_GEN_IDX, - PyLong_FromLong((long)st->st_gen)); -#endif -#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME - { - PyObject *val; - unsigned long bsec,bnsec; - bsec = (long)st->st_birthtime; -#ifdef HAVE_STAT_TV_NSEC2 - bnsec = st->st_birthtimespec.tv_nsec; -#else - bnsec = 0; -#endif - val = PyFloat_FromDouble(bsec + 1e-9*bnsec); - PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX, - val); - } -#endif -#ifdef HAVE_STRUCT_STAT_ST_FLAGS - PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX, - PyLong_FromLong((long)st->st_flags)); -#endif -#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES - PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX, - PyLong_FromUnsignedLong(st->st_file_attributes)); -#endif -#ifdef HAVE_STRUCT_STAT_ST_FSTYPE - PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX, - PyUnicode_FromString(st->st_fstype)); -#endif -#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG - PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX, - PyLong_FromUnsignedLong(st->st_reparse_tag)); -#endif - - if (PyErr_Occurred()) { - Py_DECREF(v); - return NULL; - } - - return v; -} - -/* POSIX methods */ - - -static PyObject * -posix_do_stat(PyObject *module, const char *function_name, path_t *path, - int dir_fd, int follow_symlinks) -{ - STRUCT_STAT st; - int result; - -#ifdef HAVE_FSTATAT - int fstatat_unavailable = 0; -#endif - -#if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT) - if (follow_symlinks_specified(function_name, follow_symlinks)) - return NULL; -#endif - - if (path_and_dir_fd_invalid("stat", path, dir_fd) || - dir_fd_and_fd_invalid("stat", dir_fd, path->fd) || - fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - if (path->fd != -1) - result = FSTAT(path->fd, &st); -#ifdef MS_WINDOWS - else if (follow_symlinks) - result = win32_stat(path->wide, &st); - else - result = win32_lstat(path->wide, &st); -#else - else -#if defined(HAVE_LSTAT) - if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) - result = LSTAT(path->narrow, &st); - else -#endif /* HAVE_LSTAT */ -#ifdef HAVE_FSTATAT - if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) { - if (HAVE_FSTATAT_RUNTIME) { - result = fstatat(dir_fd, path->narrow, &st, - follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); - - } else { - fstatat_unavailable = 1; - } - } else -#endif /* HAVE_FSTATAT */ - result = STAT(path->narrow, &st); -#endif /* MS_WINDOWS */ - Py_END_ALLOW_THREADS - -#ifdef HAVE_FSTATAT - if (fstatat_unavailable) { - argument_unavailable_error("stat", "dir_fd"); - return NULL; - } -#endif - - if (result != 0) { - return path_error(path); - } - - return _pystat_fromstructstat(module, &st); -} - -/*[python input] - -for s in """ - -FACCESSAT -FCHMODAT -FCHOWNAT -FSTATAT -LINKAT -MKDIRAT -MKFIFOAT -MKNODAT -OPENAT -READLINKAT -SYMLINKAT -UNLINKAT - -""".strip().split(): - s = s.strip() - print(""" -#ifdef HAVE_{s} - #define {s}_DIR_FD_CONVERTER dir_fd_converter -#else - #define {s}_DIR_FD_CONVERTER dir_fd_unavailable -#endif -""".rstrip().format(s=s)) - -for s in """ - -FCHDIR -FCHMOD -FCHOWN -FDOPENDIR -FEXECVE -FPATHCONF -FSTATVFS -FTRUNCATE - -""".strip().split(): - s = s.strip() - print(""" -#ifdef HAVE_{s} - #define PATH_HAVE_{s} 1 -#else - #define PATH_HAVE_{s} 0 -#endif - -""".rstrip().format(s=s)) -[python start generated code]*/ - -#ifdef HAVE_FACCESSAT - #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_FCHMODAT - #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_FCHOWNAT - #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_FSTATAT - #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_LINKAT - #define LINKAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_MKDIRAT - #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_MKFIFOAT - #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_MKNODAT - #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_OPENAT - #define OPENAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_READLINKAT - #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_SYMLINKAT - #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_UNLINKAT - #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_FCHDIR - #define PATH_HAVE_FCHDIR 1 -#else - #define PATH_HAVE_FCHDIR 0 -#endif - -#ifdef HAVE_FCHMOD - #define PATH_HAVE_FCHMOD 1 -#else - #define PATH_HAVE_FCHMOD 0 -#endif - -#ifdef HAVE_FCHOWN - #define PATH_HAVE_FCHOWN 1 -#else - #define PATH_HAVE_FCHOWN 0 -#endif - -#ifdef HAVE_FDOPENDIR - #define PATH_HAVE_FDOPENDIR 1 -#else - #define PATH_HAVE_FDOPENDIR 0 -#endif - -#ifdef HAVE_FEXECVE - #define PATH_HAVE_FEXECVE 1 -#else - #define PATH_HAVE_FEXECVE 0 -#endif - -#ifdef HAVE_FPATHCONF - #define PATH_HAVE_FPATHCONF 1 -#else - #define PATH_HAVE_FPATHCONF 0 -#endif - -#ifdef HAVE_FSTATVFS - #define PATH_HAVE_FSTATVFS 1 -#else - #define PATH_HAVE_FSTATVFS 0 -#endif - -#ifdef HAVE_FTRUNCATE - #define PATH_HAVE_FTRUNCATE 1 -#else - #define PATH_HAVE_FTRUNCATE 0 -#endif -/*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/ - -#ifdef MS_WINDOWS - #undef PATH_HAVE_FTRUNCATE - #define PATH_HAVE_FTRUNCATE 1 -#endif - -/*[python input] - -class path_t_converter(CConverter): - - type = "path_t" - impl_by_reference = True - parse_by_reference = True - - converter = 'path_converter' - - def converter_init(self, *, allow_fd=False, nullable=False): - # right now path_t doesn't support default values. - # to support a default value, you'll need to override initialize(). - if self.default not in (unspecified, None): - fail("Can't specify a default to the path_t converter!") - - if self.c_default not in (None, 'Py_None'): - raise RuntimeError("Can't specify a c_default to the path_t converter!") - - self.nullable = nullable - self.allow_fd = allow_fd - - def pre_render(self): - def strify(value): - if isinstance(value, str): - return value - return str(int(bool(value))) - - # add self.py_name here when merging with posixmodule conversion - self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format( - self.function.name, - self.name, - strify(self.nullable), - strify(self.allow_fd), - ) - - def cleanup(self): - return "path_cleanup(&" + self.name + ");\n" - - -class dir_fd_converter(CConverter): - type = 'int' - - def converter_init(self, requires=None): - if self.default in (unspecified, None): - self.c_default = 'DEFAULT_DIR_FD' - if isinstance(requires, str): - self.converter = requires.upper() + '_DIR_FD_CONVERTER' - else: - self.converter = 'dir_fd_converter' - -class uid_t_converter(CConverter): - type = "uid_t" - converter = '_Py_Uid_Converter' - -class gid_t_converter(CConverter): - type = "gid_t" - converter = '_Py_Gid_Converter' - -class dev_t_converter(CConverter): - type = 'dev_t' - converter = '_Py_Dev_Converter' - -class dev_t_return_converter(unsigned_long_return_converter): - type = 'dev_t' - conversion_fn = '_PyLong_FromDev' - unsigned_cast = '(dev_t)' - -class FSConverter_converter(CConverter): - type = 'PyObject *' - converter = 'PyUnicode_FSConverter' - def converter_init(self): - if self.default is not unspecified: - fail("FSConverter_converter does not support default values") - self.c_default = 'NULL' - - def cleanup(self): - return "Py_XDECREF(" + self.name + ");\n" - -class pid_t_converter(CConverter): - type = 'pid_t' - format_unit = '" _Py_PARSE_PID "' - -class idtype_t_converter(int_converter): - type = 'idtype_t' - -class id_t_converter(CConverter): - type = 'id_t' - format_unit = '" _Py_PARSE_PID "' - -class intptr_t_converter(CConverter): - type = 'intptr_t' - format_unit = '" _Py_PARSE_INTPTR "' - -class Py_off_t_converter(CConverter): - type = 'Py_off_t' - converter = 'Py_off_t_converter' - -class Py_off_t_return_converter(long_return_converter): - type = 'Py_off_t' - conversion_fn = 'PyLong_FromPy_off_t' - -class path_confname_converter(CConverter): - type="int" - converter="conv_path_confname" - -class confstr_confname_converter(path_confname_converter): - converter='conv_confstr_confname' - -class sysconf_confname_converter(path_confname_converter): - converter="conv_sysconf_confname" - -[python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=3338733161aa7879]*/ - -/*[clinic input] - -os.stat - - path : path_t(allow_fd=True) - Path to be examined; can be string, bytes, a path-like object or - open-file-descriptor int. - - * - - dir_fd : dir_fd(requires='fstatat') = None - If not None, it should be a file descriptor open to a directory, - and path should be a relative string; path will then be relative to - that directory. - - follow_symlinks: bool = True - If False, and the last element of the path is a symbolic link, - stat will examine the symbolic link itself instead of the file - the link points to. - -Perform a stat system call on the given path. - -dir_fd and follow_symlinks may not be implemented - on your platform. If they are unavailable, using them will raise a - NotImplementedError. - -It's an error to use dir_fd or follow_symlinks when specifying path as - an open file descriptor. - -[clinic start generated code]*/ - -static PyObject * -os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks) -/*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/ -{ - return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks); -} - - -/*[clinic input] -os.lstat - - path : path_t - - * - - dir_fd : dir_fd(requires='fstatat') = None - -Perform a stat system call on the given path, without following symbolic links. - -Like stat(), but do not follow symbolic links. -Equivalent to stat(path, follow_symlinks=False). -[clinic start generated code]*/ - -static PyObject * -os_lstat_impl(PyObject *module, path_t *path, int dir_fd) -/*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/ -{ - int follow_symlinks = 0; - return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks); -} - - -/*[clinic input] -os.access -> bool - - path: path_t - Path to be tested; can be string, bytes, or a path-like object. - - mode: int - Operating-system mode bitfield. Can be F_OK to test existence, - or the inclusive-OR of R_OK, W_OK, and X_OK. - - * - - dir_fd : dir_fd(requires='faccessat') = None - If not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that - directory. - - effective_ids: bool = False - If True, access will use the effective uid/gid instead of - the real uid/gid. - - follow_symlinks: bool = True - If False, and the last element of the path is a symbolic link, - access will examine the symbolic link itself instead of the file - the link points to. - -Use the real uid/gid to test for access to a path. - -{parameters} -dir_fd, effective_ids, and follow_symlinks may not be implemented - on your platform. If they are unavailable, using them will raise a - NotImplementedError. - -Note that most operations will use the effective uid/gid, therefore this - routine can be used in a suid/sgid environment to test if the invoking user - has the specified access to the path. - -[clinic start generated code]*/ - -static int -os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd, - int effective_ids, int follow_symlinks) -/*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/ -{ - int return_value; - -#ifdef MS_WINDOWS - DWORD attr; -#else - int result; -#endif - -#ifdef HAVE_FACCESSAT - int faccessat_unavailable = 0; -#endif - -#ifndef HAVE_FACCESSAT - if (follow_symlinks_specified("access", follow_symlinks)) - return -1; - - if (effective_ids) { - argument_unavailable_error("access", "effective_ids"); - return -1; - } -#endif - -#ifdef MS_WINDOWS - Py_BEGIN_ALLOW_THREADS - attr = GetFileAttributesW(path->wide); - Py_END_ALLOW_THREADS - - /* - * Access is possible if - * * we didn't get a -1, and - * * write access wasn't requested, - * * or the file isn't read-only, - * * or it's a directory. - * (Directories cannot be read-only on Windows.) - */ - return_value = (attr != INVALID_FILE_ATTRIBUTES) && - (!(mode & 2) || - !(attr & FILE_ATTRIBUTE_READONLY) || - (attr & FILE_ATTRIBUTE_DIRECTORY)); -#else - - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_FACCESSAT - if ((dir_fd != DEFAULT_DIR_FD) || - effective_ids || - !follow_symlinks) { - - if (HAVE_FACCESSAT_RUNTIME) { - int flags = 0; - if (!follow_symlinks) - flags |= AT_SYMLINK_NOFOLLOW; - if (effective_ids) - flags |= AT_EACCESS; - result = faccessat(dir_fd, path->narrow, mode, flags); - } else { - faccessat_unavailable = 1; - } - } - else -#endif - result = access(path->narrow, mode); - Py_END_ALLOW_THREADS - -#ifdef HAVE_FACCESSAT - if (faccessat_unavailable) { - if (dir_fd != DEFAULT_DIR_FD) { - argument_unavailable_error("access", "dir_fd"); - return -1; - } - if (follow_symlinks_specified("access", follow_symlinks)) - return -1; - - if (effective_ids) { - argument_unavailable_error("access", "effective_ids"); - return -1; - } - /* should be unreachable */ - return -1; - } -#endif - return_value = !result; -#endif - - return return_value; -} - -#ifndef F_OK -#define F_OK 0 -#endif -#ifndef R_OK -#define R_OK 4 -#endif -#ifndef W_OK -#define W_OK 2 -#endif -#ifndef X_OK -#define X_OK 1 -#endif - - -#ifdef HAVE_TTYNAME -/*[clinic input] -os.ttyname - - fd: int - Integer file descriptor handle. - - / - -Return the name of the terminal device connected to 'fd'. -[clinic start generated code]*/ - -static PyObject * -os_ttyname_impl(PyObject *module, int fd) -/*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/ -{ - - long size = sysconf(_SC_TTY_NAME_MAX); - if (size == -1) { - return posix_error(); - } - char *buffer = (char *)PyMem_RawMalloc(size); - if (buffer == NULL) { - return PyErr_NoMemory(); - } - int ret = ttyname_r(fd, buffer, size); - if (ret != 0) { - PyMem_RawFree(buffer); - errno = ret; - return posix_error(); - } - PyObject *res = PyUnicode_DecodeFSDefault(buffer); - PyMem_RawFree(buffer); - return res; -} -#endif - -#ifdef HAVE_CTERMID -/*[clinic input] -os.ctermid - -Return the name of the controlling terminal for this process. -[clinic start generated code]*/ - -static PyObject * -os_ctermid_impl(PyObject *module) -/*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/ -{ - char *ret; - char buffer[L_ctermid]; - -#ifdef USE_CTERMID_R - ret = ctermid_r(buffer); -#else - ret = ctermid(buffer); -#endif - if (ret == NULL) - return posix_error(); - return PyUnicode_DecodeFSDefault(buffer); -} -#endif /* HAVE_CTERMID */ - - -/*[clinic input] -os.chdir - - path: path_t(allow_fd='PATH_HAVE_FCHDIR') - -Change the current working directory to the specified path. - -path may always be specified as a string. -On some platforms, path may also be specified as an open file descriptor. - If this functionality is unavailable, using it raises an exception. -[clinic start generated code]*/ - -static PyObject * -os_chdir_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/ -{ - int result; - - if (PySys_Audit("os.chdir", "(O)", path->object) < 0) { - return NULL; - } - - Py_BEGIN_ALLOW_THREADS -#ifdef MS_WINDOWS - /* on unix, success = 0, on windows, success = !0 */ - result = !win32_wchdir(path->wide); -#else -#ifdef HAVE_FCHDIR - if (path->fd != -1) - result = fchdir(path->fd); - else -#endif - result = chdir(path->narrow); -#endif - Py_END_ALLOW_THREADS - - if (result) { - return path_error(path); - } - - Py_RETURN_NONE; -} - - -#ifdef HAVE_FCHDIR -/*[clinic input] -os.fchdir - - fd: fildes - -Change to the directory of the given file descriptor. - -fd must be opened on a directory, not a file. -Equivalent to os.chdir(fd). - -[clinic start generated code]*/ - -static PyObject * -os_fchdir_impl(PyObject *module, int fd) -/*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/ -{ - if (PySys_Audit("os.chdir", "(i)", fd) < 0) { - return NULL; - } - return posix_fildes_fd(fd, fchdir); -} -#endif /* HAVE_FCHDIR */ - - -/*[clinic input] -os.chmod - - path: path_t(allow_fd='PATH_HAVE_FCHMOD') - Path to be modified. May always be specified as a str, bytes, or a path-like object. - On some platforms, path may also be specified as an open file descriptor. - If this functionality is unavailable, using it raises an exception. - - mode: int - Operating-system mode bitfield. - - * - - dir_fd : dir_fd(requires='fchmodat') = None - If not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that - directory. - - follow_symlinks: bool = True - If False, and the last element of the path is a symbolic link, - chmod will modify the symbolic link itself instead of the file - the link points to. - -Change the access permissions of a file. - -It is an error to use dir_fd or follow_symlinks when specifying path as - an open file descriptor. -dir_fd and follow_symlinks may not be implemented on your platform. - If they are unavailable, using them will raise a NotImplementedError. - -[clinic start generated code]*/ - -static PyObject * -os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, - int follow_symlinks) -/*[clinic end generated code: output=5cf6a94915cc7bff input=989081551c00293b]*/ -{ - int result; - -#ifdef MS_WINDOWS - DWORD attr; -#endif - -#ifdef HAVE_FCHMODAT - int fchmodat_nofollow_unsupported = 0; - int fchmodat_unsupported = 0; -#endif - -#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD)) - if (follow_symlinks_specified("chmod", follow_symlinks)) - return NULL; -#endif - - if (PySys_Audit("os.chmod", "Oii", path->object, mode, - dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { - return NULL; - } - -#ifdef MS_WINDOWS - Py_BEGIN_ALLOW_THREADS - attr = GetFileAttributesW(path->wide); - if (attr == INVALID_FILE_ATTRIBUTES) - result = 0; - else { - if (mode & _S_IWRITE) - attr &= ~FILE_ATTRIBUTE_READONLY; - else - attr |= FILE_ATTRIBUTE_READONLY; - result = SetFileAttributesW(path->wide, attr); - } - Py_END_ALLOW_THREADS - - if (!result) { - return path_error(path); - } -#else /* MS_WINDOWS */ - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_FCHMOD - if (path->fd != -1) - result = fchmod(path->fd, mode); - else -#endif /* HAVE_CHMOD */ -#ifdef HAVE_LCHMOD - if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) - result = lchmod(path->narrow, mode); - else -#endif /* HAVE_LCHMOD */ -#ifdef HAVE_FCHMODAT - if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) { - if (HAVE_FCHMODAT_RUNTIME) { - /* - * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW! - * The documentation specifically shows how to use it, - * and then says it isn't implemented yet. - * (true on linux with glibc 2.15, and openindiana 3.x) - * - * Once it is supported, os.chmod will automatically - * support dir_fd and follow_symlinks=False. (Hopefully.) - * Until then, we need to be careful what exception we raise. - */ - result = fchmodat(dir_fd, path->narrow, mode, - follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); - /* - * But wait! We can't throw the exception without allowing threads, - * and we can't do that in this nested scope. (Macro trickery, sigh.) - */ - fchmodat_nofollow_unsupported = - result && - ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) && - !follow_symlinks; - } else { - fchmodat_unsupported = 1; - fchmodat_nofollow_unsupported = 1; - - result = -1; - } - } - else -#endif /* HAVE_FHCMODAT */ - { -#ifdef HAVE_CHMOD - result = chmod(path->narrow, mode); -#elif defined(__wasi__) - // WASI SDK 15.0 does not support chmod. - // Ignore missing syscall for now. - result = 0; -#else - result = -1; - errno = ENOSYS; -#endif - } - Py_END_ALLOW_THREADS - - if (result) { -#ifdef HAVE_FCHMODAT - if (fchmodat_unsupported) { - if (dir_fd != DEFAULT_DIR_FD) { - argument_unavailable_error("chmod", "dir_fd"); - return NULL; - } - } - - if (fchmodat_nofollow_unsupported) { - if (dir_fd != DEFAULT_DIR_FD) - dir_fd_and_follow_symlinks_invalid("chmod", - dir_fd, follow_symlinks); - else - follow_symlinks_specified("chmod", follow_symlinks); - return NULL; - } - else -#endif /* HAVE_FCHMODAT */ - return path_error(path); - } -#endif /* MS_WINDOWS */ - - Py_RETURN_NONE; -} - - -#ifdef HAVE_FCHMOD -/*[clinic input] -os.fchmod - - fd: int - mode: int - -Change the access permissions of the file given by file descriptor fd. - -Equivalent to os.chmod(fd, mode). -[clinic start generated code]*/ - -static PyObject * -os_fchmod_impl(PyObject *module, int fd, int mode) -/*[clinic end generated code: output=afd9bc05b4e426b3 input=8ab11975ca01ee5b]*/ -{ - int res; - int async_err = 0; - - if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) { - return NULL; - } - - do { - Py_BEGIN_ALLOW_THREADS - res = fchmod(fd, mode); - Py_END_ALLOW_THREADS - } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (res != 0) - return (!async_err) ? posix_error() : NULL; - - Py_RETURN_NONE; -} -#endif /* HAVE_FCHMOD */ - - -#ifdef HAVE_LCHMOD -/*[clinic input] -os.lchmod - - path: path_t - mode: int - -Change the access permissions of a file, without following symbolic links. - -If path is a symlink, this affects the link itself rather than the target. -Equivalent to chmod(path, mode, follow_symlinks=False)." -[clinic start generated code]*/ - -static PyObject * -os_lchmod_impl(PyObject *module, path_t *path, int mode) -/*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/ -{ - int res; - if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) { - return NULL; - } - Py_BEGIN_ALLOW_THREADS - res = lchmod(path->narrow, mode); - Py_END_ALLOW_THREADS - if (res < 0) { - path_error(path); - return NULL; - } - Py_RETURN_NONE; -} -#endif /* HAVE_LCHMOD */ - - -#ifdef HAVE_CHFLAGS -/*[clinic input] -os.chflags - - path: path_t - flags: unsigned_long(bitwise=True) - follow_symlinks: bool=True - -Set file flags. - -If follow_symlinks is False, and the last element of the path is a symbolic - link, chflags will change flags on the symbolic link itself instead of the - file the link points to. -follow_symlinks may not be implemented on your platform. If it is -unavailable, using it will raise a NotImplementedError. - -[clinic start generated code]*/ - -static PyObject * -os_chflags_impl(PyObject *module, path_t *path, unsigned long flags, - int follow_symlinks) -/*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/ -{ - int result; - -#ifndef HAVE_LCHFLAGS - if (follow_symlinks_specified("chflags", follow_symlinks)) - return NULL; -#endif - - if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) { - return NULL; - } - - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_LCHFLAGS - if (!follow_symlinks) - result = lchflags(path->narrow, flags); - else -#endif - result = chflags(path->narrow, flags); - Py_END_ALLOW_THREADS - - if (result) - return path_error(path); - - Py_RETURN_NONE; -} -#endif /* HAVE_CHFLAGS */ - - -#ifdef HAVE_LCHFLAGS -/*[clinic input] -os.lchflags - - path: path_t - flags: unsigned_long(bitwise=True) - -Set file flags. - -This function will not follow symbolic links. -Equivalent to chflags(path, flags, follow_symlinks=False). -[clinic start generated code]*/ - -static PyObject * -os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags) -/*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/ -{ - int res; - if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) { - return NULL; - } - Py_BEGIN_ALLOW_THREADS - res = lchflags(path->narrow, flags); - Py_END_ALLOW_THREADS - if (res < 0) { - return path_error(path); - } - Py_RETURN_NONE; -} -#endif /* HAVE_LCHFLAGS */ - - -#ifdef HAVE_CHROOT -/*[clinic input] -os.chroot - path: path_t - -Change root directory to path. - -[clinic start generated code]*/ - -static PyObject * -os_chroot_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/ -{ - int res; - Py_BEGIN_ALLOW_THREADS - res = chroot(path->narrow); - Py_END_ALLOW_THREADS - if (res < 0) - return path_error(path); - Py_RETURN_NONE; -} -#endif /* HAVE_CHROOT */ - - -#ifdef HAVE_FSYNC -/*[clinic input] -os.fsync - - fd: fildes - -Force write of fd to disk. -[clinic start generated code]*/ - -static PyObject * -os_fsync_impl(PyObject *module, int fd) -/*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/ -{ - return posix_fildes_fd(fd, fsync); -} -#endif /* HAVE_FSYNC */ - - -#ifdef HAVE_SYNC -/*[clinic input] -os.sync - -Force write of everything to disk. -[clinic start generated code]*/ - -static PyObject * -os_sync_impl(PyObject *module) -/*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/ -{ - Py_BEGIN_ALLOW_THREADS - sync(); - Py_END_ALLOW_THREADS - Py_RETURN_NONE; -} -#endif /* HAVE_SYNC */ - - -#ifdef HAVE_FDATASYNC -#ifdef __hpux -extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */ -#endif - -/*[clinic input] -os.fdatasync - - fd: fildes - -Force write of fd to disk without forcing update of metadata. -[clinic start generated code]*/ - -static PyObject * -os_fdatasync_impl(PyObject *module, int fd) -/*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/ -{ - return posix_fildes_fd(fd, fdatasync); -} -#endif /* HAVE_FDATASYNC */ - - -#ifdef HAVE_CHOWN -/*[clinic input] -os.chown - - path : path_t(allow_fd='PATH_HAVE_FCHOWN') - Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int. - - uid: uid_t - - gid: gid_t - - * - - dir_fd : dir_fd(requires='fchownat') = None - If not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that - directory. - - follow_symlinks: bool = True - If False, and the last element of the path is a symbolic link, - stat will examine the symbolic link itself instead of the file - the link points to. - -Change the owner and group id of path to the numeric uid and gid.\ - -path may always be specified as a string. -On some platforms, path may also be specified as an open file descriptor. - If this functionality is unavailable, using it raises an exception. -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -If follow_symlinks is False, and the last element of the path is a symbolic - link, chown will modify the symbolic link itself instead of the file the - link points to. -It is an error to use dir_fd or follow_symlinks when specifying path as - an open file descriptor. -dir_fd and follow_symlinks may not be implemented on your platform. - If they are unavailable, using them will raise a NotImplementedError. - -[clinic start generated code]*/ - -static PyObject * -os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid, - int dir_fd, int follow_symlinks) -/*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/ -{ - int result; - -#if defined(HAVE_FCHOWNAT) - int fchownat_unsupported = 0; -#endif - -#if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT)) - if (follow_symlinks_specified("chown", follow_symlinks)) - return NULL; -#endif - if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) || - fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks)) - return NULL; - - if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, - dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { - return NULL; - } - - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_FCHOWN - if (path->fd != -1) - result = fchown(path->fd, uid, gid); - else -#endif -#ifdef HAVE_LCHOWN - if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) - result = lchown(path->narrow, uid, gid); - else -#endif -#ifdef HAVE_FCHOWNAT - if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) { - if (HAVE_FCHOWNAT_RUNTIME) { - result = fchownat(dir_fd, path->narrow, uid, gid, - follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); - } else { - fchownat_unsupported = 1; - } - } else -#endif - result = chown(path->narrow, uid, gid); - Py_END_ALLOW_THREADS - -#ifdef HAVE_FCHOWNAT - if (fchownat_unsupported) { - /* This would be incorrect if the current platform - * doesn't support lchown. - */ - argument_unavailable_error(NULL, "dir_fd"); - return NULL; - } -#endif - - if (result) - return path_error(path); - - Py_RETURN_NONE; -} -#endif /* HAVE_CHOWN */ - - -#ifdef HAVE_FCHOWN -/*[clinic input] -os.fchown - - fd: int - uid: uid_t - gid: gid_t - -Change the owner and group id of the file specified by file descriptor. - -Equivalent to os.chown(fd, uid, gid). - -[clinic start generated code]*/ - -static PyObject * -os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid) -/*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/ -{ - int res; - int async_err = 0; - - if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) { - return NULL; - } - - do { - Py_BEGIN_ALLOW_THREADS - res = fchown(fd, uid, gid); - Py_END_ALLOW_THREADS - } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (res != 0) - return (!async_err) ? posix_error() : NULL; - - Py_RETURN_NONE; -} -#endif /* HAVE_FCHOWN */ - - -#ifdef HAVE_LCHOWN -/*[clinic input] -os.lchown - - path : path_t - uid: uid_t - gid: gid_t - -Change the owner and group id of path to the numeric uid and gid. - -This function will not follow symbolic links. -Equivalent to os.chown(path, uid, gid, follow_symlinks=False). -[clinic start generated code]*/ - -static PyObject * -os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid) -/*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/ -{ - int res; - if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) { - return NULL; - } - Py_BEGIN_ALLOW_THREADS - res = lchown(path->narrow, uid, gid); - Py_END_ALLOW_THREADS - if (res < 0) { - return path_error(path); - } - Py_RETURN_NONE; -} -#endif /* HAVE_LCHOWN */ - - -static PyObject * -posix_getcwd(int use_bytes) -{ -#ifdef MS_WINDOWS - wchar_t wbuf[MAXPATHLEN]; - wchar_t *wbuf2 = wbuf; - DWORD len; - - Py_BEGIN_ALLOW_THREADS - len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf); - /* If the buffer is large enough, len does not include the - terminating \0. If the buffer is too small, len includes - the space needed for the terminator. */ - if (len >= Py_ARRAY_LENGTH(wbuf)) { - if (len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) { - wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t)); - } - else { - wbuf2 = NULL; - } - if (wbuf2) { - len = GetCurrentDirectoryW(len, wbuf2); - } - } - Py_END_ALLOW_THREADS - - if (!wbuf2) { - PyErr_NoMemory(); - return NULL; - } - if (!len) { - if (wbuf2 != wbuf) - PyMem_RawFree(wbuf2); - return PyErr_SetFromWindowsErr(0); - } - - PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len); - if (wbuf2 != wbuf) { - PyMem_RawFree(wbuf2); - } - - if (use_bytes) { - if (resobj == NULL) { - return NULL; - } - Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj)); - } - - return resobj; -#else - const size_t chunk = 1024; - - char *buf = NULL; - char *cwd = NULL; - size_t buflen = 0; - - Py_BEGIN_ALLOW_THREADS - do { - char *newbuf; - if (buflen <= PY_SSIZE_T_MAX - chunk) { - buflen += chunk; - newbuf = PyMem_RawRealloc(buf, buflen); - } - else { - newbuf = NULL; - } - if (newbuf == NULL) { - PyMem_RawFree(buf); - buf = NULL; - break; - } - buf = newbuf; - - cwd = getcwd(buf, buflen); - } while (cwd == NULL && errno == ERANGE); - Py_END_ALLOW_THREADS - - if (buf == NULL) { - return PyErr_NoMemory(); - } - if (cwd == NULL) { - PyMem_RawFree(buf); - return posix_error(); - } - - PyObject *obj; - if (use_bytes) { - obj = PyBytes_FromStringAndSize(buf, strlen(buf)); - } - else { - obj = PyUnicode_DecodeFSDefault(buf); - } - PyMem_RawFree(buf); - - return obj; -#endif /* !MS_WINDOWS */ -} - - -/*[clinic input] -os.getcwd - -Return a unicode string representing the current working directory. -[clinic start generated code]*/ - -static PyObject * -os_getcwd_impl(PyObject *module) -/*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/ -{ - return posix_getcwd(0); -} - - -/*[clinic input] -os.getcwdb - -Return a bytes string representing the current working directory. -[clinic start generated code]*/ - -static PyObject * -os_getcwdb_impl(PyObject *module) -/*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/ -{ - return posix_getcwd(1); -} - - -#if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS)) -#define HAVE_LINK 1 -#endif - -#ifdef HAVE_LINK -/*[clinic input] - -os.link - - src : path_t - dst : path_t - * - src_dir_fd : dir_fd = None - dst_dir_fd : dir_fd = None - follow_symlinks: bool = True - -Create a hard link to a file. - -If either src_dir_fd or dst_dir_fd is not None, it should be a file - descriptor open to a directory, and the respective path string (src or dst) - should be relative; the path will then be relative to that directory. -If follow_symlinks is False, and the last element of src is a symbolic - link, link will create a link to the symbolic link itself instead of the - file the link points to. -src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your - platform. If they are unavailable, using them will raise a - NotImplementedError. -[clinic start generated code]*/ - -static PyObject * -os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, - int dst_dir_fd, int follow_symlinks) -/*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/ -{ -#ifdef MS_WINDOWS - BOOL result = FALSE; -#else - int result; -#endif -#if defined(HAVE_LINKAT) - int linkat_unavailable = 0; -#endif - -#ifndef HAVE_LINKAT - if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) { - argument_unavailable_error("link", "src_dir_fd and dst_dir_fd"); - return NULL; - } -#endif - -#ifndef MS_WINDOWS - if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { - PyErr_SetString(PyExc_NotImplementedError, - "link: src and dst must be the same type"); - return NULL; - } -#endif - - if (PySys_Audit("os.link", "OOii", src->object, dst->object, - src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd, - dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) { - return NULL; - } - -#ifdef MS_WINDOWS - Py_BEGIN_ALLOW_THREADS - result = CreateHardLinkW(dst->wide, src->wide, NULL); - Py_END_ALLOW_THREADS - - if (!result) - return path_error2(src, dst); -#else - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_LINKAT - if ((src_dir_fd != DEFAULT_DIR_FD) || - (dst_dir_fd != DEFAULT_DIR_FD) || - (!follow_symlinks)) { - - if (HAVE_LINKAT_RUNTIME) { - - result = linkat(src_dir_fd, src->narrow, - dst_dir_fd, dst->narrow, - follow_symlinks ? AT_SYMLINK_FOLLOW : 0); - - } -#ifdef __APPLE__ - else { - if (src_dir_fd == DEFAULT_DIR_FD && dst_dir_fd == DEFAULT_DIR_FD) { - /* See issue 41355: This matches the behaviour of !HAVE_LINKAT */ - result = link(src->narrow, dst->narrow); - } else { - linkat_unavailable = 1; - } - } -#endif - } - else -#endif /* HAVE_LINKAT */ - result = link(src->narrow, dst->narrow); - Py_END_ALLOW_THREADS - -#ifdef HAVE_LINKAT - if (linkat_unavailable) { - /* Either or both dir_fd arguments were specified */ - if (src_dir_fd != DEFAULT_DIR_FD) { - argument_unavailable_error("link", "src_dir_fd"); - } else { - argument_unavailable_error("link", "dst_dir_fd"); - } - return NULL; - } -#endif - - if (result) - return path_error2(src, dst); -#endif /* MS_WINDOWS */ - - Py_RETURN_NONE; -} -#endif - - -#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR) -static PyObject * -_listdir_windows_no_opendir(path_t *path, PyObject *list) -{ - PyObject *v; - HANDLE hFindFile = INVALID_HANDLE_VALUE; - BOOL result; - wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */ - /* only claim to have space for MAX_PATH */ - Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4; - wchar_t *wnamebuf = NULL; - - WIN32_FIND_DATAW wFileData; - const wchar_t *po_wchars; - - if (!path->wide) { /* Default arg: "." */ - po_wchars = L"."; - len = 1; - } else { - po_wchars = path->wide; - len = wcslen(path->wide); - } - /* The +5 is so we can append "\\*.*\0" */ - wnamebuf = PyMem_New(wchar_t, len + 5); - if (!wnamebuf) { - PyErr_NoMemory(); - goto exit; - } - wcscpy(wnamebuf, po_wchars); - if (len > 0) { - wchar_t wch = wnamebuf[len-1]; - if (wch != SEP && wch != ALTSEP && wch != L':') - wnamebuf[len++] = SEP; - wcscpy(wnamebuf + len, L"*.*"); - } - if ((list = PyList_New(0)) == NULL) { - goto exit; - } - Py_BEGIN_ALLOW_THREADS - hFindFile = FindFirstFileW(wnamebuf, &wFileData); - Py_END_ALLOW_THREADS - if (hFindFile == INVALID_HANDLE_VALUE) { - int error = GetLastError(); - if (error == ERROR_FILE_NOT_FOUND) - goto exit; - Py_DECREF(list); - list = path_error(path); - goto exit; - } - do { - /* Skip over . and .. */ - if (wcscmp(wFileData.cFileName, L".") != 0 && - wcscmp(wFileData.cFileName, L"..") != 0) { - v = PyUnicode_FromWideChar(wFileData.cFileName, - wcslen(wFileData.cFileName)); - if (path->narrow && v) { - Py_SETREF(v, PyUnicode_EncodeFSDefault(v)); - } - if (v == NULL) { - Py_DECREF(list); - list = NULL; - break; - } - if (PyList_Append(list, v) != 0) { - Py_DECREF(v); - Py_DECREF(list); - list = NULL; - break; - } - Py_DECREF(v); - } - Py_BEGIN_ALLOW_THREADS - result = FindNextFileW(hFindFile, &wFileData); - Py_END_ALLOW_THREADS - /* FindNextFile sets error to ERROR_NO_MORE_FILES if - it got to the end of the directory. */ - if (!result && GetLastError() != ERROR_NO_MORE_FILES) { - Py_DECREF(list); - list = path_error(path); - goto exit; - } - } while (result == TRUE); - -exit: - if (hFindFile != INVALID_HANDLE_VALUE) { - if (FindClose(hFindFile) == FALSE) { - if (list != NULL) { - Py_DECREF(list); - list = path_error(path); - } - } - } - PyMem_Free(wnamebuf); - - return list; -} /* end of _listdir_windows_no_opendir */ - -#else /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */ - -static PyObject * -_posix_listdir(path_t *path, PyObject *list) -{ - PyObject *v; - DIR *dirp = NULL; - struct dirent *ep; - int return_str; /* if false, return bytes */ -#ifdef HAVE_FDOPENDIR - int fd = -1; -#endif - - errno = 0; -#ifdef HAVE_FDOPENDIR - if (path->fd != -1) { - if (HAVE_FDOPENDIR_RUNTIME) { - /* closedir() closes the FD, so we duplicate it */ - fd = _Py_dup(path->fd); - if (fd == -1) - return NULL; - - return_str = 1; - - Py_BEGIN_ALLOW_THREADS - dirp = fdopendir(fd); - Py_END_ALLOW_THREADS - } else { - PyErr_SetString(PyExc_TypeError, - "listdir: path should be string, bytes, os.PathLike or None, not int"); - return NULL; - } - } - else -#endif - { - const char *name; - if (path->narrow) { - name = path->narrow; - /* only return bytes if they specified a bytes object */ - return_str = !PyBytes_Check(path->object); - } - else { - name = "."; - return_str = 1; - } - - Py_BEGIN_ALLOW_THREADS - dirp = opendir(name); - Py_END_ALLOW_THREADS - } - - if (dirp == NULL) { - list = path_error(path); -#ifdef HAVE_FDOPENDIR - if (fd != -1) { - Py_BEGIN_ALLOW_THREADS - close(fd); - Py_END_ALLOW_THREADS - } -#endif - goto exit; - } - if ((list = PyList_New(0)) == NULL) { - goto exit; - } - for (;;) { - errno = 0; - Py_BEGIN_ALLOW_THREADS - ep = readdir(dirp); - Py_END_ALLOW_THREADS - if (ep == NULL) { - if (errno == 0) { - break; - } else { - Py_DECREF(list); - list = path_error(path); - goto exit; - } - } - if (ep->d_name[0] == '.' && - (NAMLEN(ep) == 1 || - (ep->d_name[1] == '.' && NAMLEN(ep) == 2))) - continue; - if (return_str) - v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep)); - else - v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep)); - if (v == NULL) { - Py_CLEAR(list); - break; - } - if (PyList_Append(list, v) != 0) { - Py_DECREF(v); - Py_CLEAR(list); - break; - } - Py_DECREF(v); - } - -exit: - if (dirp != NULL) { - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_FDOPENDIR - if (fd > -1) - rewinddir(dirp); -#endif - closedir(dirp); - Py_END_ALLOW_THREADS - } - - return list; -} /* end of _posix_listdir */ -#endif /* which OS */ - - -/*[clinic input] -os.listdir - - path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None - -Return a list containing the names of the files in the directory. - -path can be specified as either str, bytes, or a path-like object. If path is bytes, - the filenames returned will also be bytes; in all other circumstances - the filenames returned will be str. -If path is None, uses the path='.'. -On some platforms, path may also be specified as an open file descriptor;\ - the file descriptor must refer to a directory. - If this functionality is unavailable, using it raises NotImplementedError. - -The list is in arbitrary order. It does not include the special -entries '.' and '..' even if they are present in the directory. - - -[clinic start generated code]*/ - -static PyObject * -os_listdir_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/ -{ - if (PySys_Audit("os.listdir", "O", - path->object ? path->object : Py_None) < 0) { - return NULL; - } -#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR) - return _listdir_windows_no_opendir(path, NULL); -#else - return _posix_listdir(path, NULL); -#endif -} - -#ifdef MS_WINDOWS -int -_PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p) -{ - wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf; - DWORD result; - - result = GetFullPathNameW(path, - Py_ARRAY_LENGTH(woutbuf), woutbuf, - NULL); - if (!result) { - return -1; - } - - if (result >= Py_ARRAY_LENGTH(woutbuf)) { - if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) { - woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t)); - } - else { - woutbufp = NULL; - } - if (!woutbufp) { - *abspath_p = NULL; - return 0; - } - - result = GetFullPathNameW(path, result, woutbufp, NULL); - if (!result) { - PyMem_RawFree(woutbufp); - return -1; - } - } - - if (woutbufp != woutbuf) { - *abspath_p = woutbufp; - return 0; - } - - *abspath_p = _PyMem_RawWcsdup(woutbufp); - return 0; -} - - -/* A helper function for abspath on win32 */ -/*[clinic input] -os._getfullpathname - - path: path_t - / - -[clinic start generated code]*/ - -static PyObject * -os__getfullpathname_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/ -{ - wchar_t *abspath; - - if (_PyOS_getfullpathname(path->wide, &abspath) < 0) { - return win32_error_object("GetFullPathNameW", path->object); - } - if (abspath == NULL) { - return PyErr_NoMemory(); - } - - PyObject *str = PyUnicode_FromWideChar(abspath, wcslen(abspath)); - PyMem_RawFree(abspath); - if (str == NULL) { - return NULL; - } - if (path->narrow) { - Py_SETREF(str, PyUnicode_EncodeFSDefault(str)); - } - return str; -} - - -/*[clinic input] -os._getfinalpathname - - path: path_t - / - -A helper function for samepath on windows. -[clinic start generated code]*/ - -static PyObject * -os__getfinalpathname_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/ -{ - HANDLE hFile; - wchar_t buf[MAXPATHLEN], *target_path = buf; - int buf_size = Py_ARRAY_LENGTH(buf); - int result_length; - PyObject *result; - - Py_BEGIN_ALLOW_THREADS - hFile = CreateFileW( - path->wide, - 0, /* desired access */ - 0, /* share mode */ - NULL, /* security attributes */ - OPEN_EXISTING, - /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ - FILE_FLAG_BACKUP_SEMANTICS, - NULL); - Py_END_ALLOW_THREADS - - if (hFile == INVALID_HANDLE_VALUE) { - return win32_error_object("CreateFileW", path->object); - } - - /* We have a good handle to the target, use it to determine the - target path name. */ - while (1) { - Py_BEGIN_ALLOW_THREADS - result_length = GetFinalPathNameByHandleW(hFile, target_path, - buf_size, VOLUME_NAME_DOS); - Py_END_ALLOW_THREADS - - if (!result_length) { - result = win32_error_object("GetFinalPathNameByHandleW", - path->object); - goto cleanup; - } - - if (result_length < buf_size) { - break; - } - - wchar_t *tmp; - tmp = PyMem_Realloc(target_path != buf ? target_path : NULL, - result_length * sizeof(*tmp)); - if (!tmp) { - result = PyErr_NoMemory(); - goto cleanup; - } - - buf_size = result_length; - target_path = tmp; - } - - result = PyUnicode_FromWideChar(target_path, result_length); - if (result && path->narrow) { - Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); - } - -cleanup: - if (target_path != buf) { - PyMem_Free(target_path); - } - CloseHandle(hFile); - return result; -} - - -/*[clinic input] -os._getvolumepathname - - path: path_t - -A helper function for ismount on Win32. -[clinic start generated code]*/ - -static PyObject * -os__getvolumepathname_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/ -{ - PyObject *result; - wchar_t *mountpath=NULL; - size_t buflen; - BOOL ret; - - /* Volume path should be shorter than entire path */ - buflen = Py_MAX(path->length, MAX_PATH); - - if (buflen > PY_DWORD_MAX) { - PyErr_SetString(PyExc_OverflowError, "path too long"); - return NULL; - } - - mountpath = PyMem_New(wchar_t, buflen); - if (mountpath == NULL) - return PyErr_NoMemory(); - - Py_BEGIN_ALLOW_THREADS - ret = GetVolumePathNameW(path->wide, mountpath, - Py_SAFE_DOWNCAST(buflen, size_t, DWORD)); - Py_END_ALLOW_THREADS - - if (!ret) { - result = win32_error_object("_getvolumepathname", path->object); - goto exit; - } - result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath)); - if (path->narrow) - Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); - -exit: - PyMem_Free(mountpath); - return result; -} - - -/*[clinic input] -os._path_splitroot - - path: path_t - -Removes everything after the root on Win32. -[clinic start generated code]*/ - -static PyObject * -os__path_splitroot_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=ab7f1a88b654581c input=dc93b1d3984cffb6]*/ -{ - wchar_t *buffer; - wchar_t *end; - PyObject *result = NULL; - HRESULT ret; - - buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1)); - if (!buffer) { - return NULL; - } - wcscpy(buffer, path->wide); - for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) { - *p = L'\\'; - } - - Py_BEGIN_ALLOW_THREADS - ret = PathCchSkipRoot(buffer, &end); - Py_END_ALLOW_THREADS - if (FAILED(ret)) { - result = Py_BuildValue("sO", "", path->object); - } else if (end != buffer) { - size_t rootLen = (size_t)(end - buffer); - result = Py_BuildValue("NN", - PyUnicode_FromWideChar(path->wide, rootLen), - PyUnicode_FromWideChar(path->wide + rootLen, -1) - ); - } else { - result = Py_BuildValue("Os", path->object, ""); - } - PyMem_Free(buffer); - - return result; -} - - -#endif /* MS_WINDOWS */ - - -/*[clinic input] -os._path_normpath - - path: object - -Basic path normalization. -[clinic start generated code]*/ - -static PyObject * -os__path_normpath_impl(PyObject *module, PyObject *path) -/*[clinic end generated code: output=b94d696d828019da input=5e90c39e12549dc0]*/ -{ - if (!PyUnicode_Check(path)) { - PyErr_Format(PyExc_TypeError, "expected 'str', not '%.200s'", - Py_TYPE(path)->tp_name); - return NULL; - } - Py_ssize_t len; - wchar_t *buffer = PyUnicode_AsWideCharString(path, &len); - if (!buffer) { - return NULL; - } - PyObject *result = PyUnicode_FromWideChar(_Py_normpath(buffer, len), -1); - PyMem_Free(buffer); - return result; -} - -/*[clinic input] -os.mkdir - - path : path_t - - mode: int = 0o777 - - * - - dir_fd : dir_fd(requires='mkdirat') = None - -# "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\ - -Create a directory. - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -dir_fd may not be implemented on your platform. - If it is unavailable, using it will raise a NotImplementedError. - -The mode argument is ignored on Windows. Where it is used, the current umask -value is first masked out. -[clinic start generated code]*/ - -static PyObject * -os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd) -/*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/ -{ - int result; -#ifdef HAVE_MKDIRAT - int mkdirat_unavailable = 0; -#endif - - if (PySys_Audit("os.mkdir", "Oii", path->object, mode, - dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { - return NULL; - } - -#ifdef MS_WINDOWS - Py_BEGIN_ALLOW_THREADS - result = CreateDirectoryW(path->wide, NULL); - Py_END_ALLOW_THREADS - - if (!result) - return path_error(path); -#else - Py_BEGIN_ALLOW_THREADS -#if HAVE_MKDIRAT - if (dir_fd != DEFAULT_DIR_FD) { - if (HAVE_MKDIRAT_RUNTIME) { - result = mkdirat(dir_fd, path->narrow, mode); - - } else { - mkdirat_unavailable = 1; - } - } else -#endif -#if defined(__WATCOMC__) && !defined(__QNX__) - result = mkdir(path->narrow); -#else - result = mkdir(path->narrow, mode); -#endif - Py_END_ALLOW_THREADS - -#if HAVE_MKDIRAT - if (mkdirat_unavailable) { - argument_unavailable_error(NULL, "dir_fd"); - return NULL; - } -#endif - - if (result < 0) - return path_error(path); -#endif /* MS_WINDOWS */ - Py_RETURN_NONE; -} - - -/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */ -#if defined(HAVE_SYS_RESOURCE_H) -#include -#endif - - -#ifdef HAVE_NICE -/*[clinic input] -os.nice - - increment: int - / - -Add increment to the priority of process and return the new priority. -[clinic start generated code]*/ - -static PyObject * -os_nice_impl(PyObject *module, int increment) -/*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/ -{ - int value; - - /* There are two flavours of 'nice': one that returns the new - priority (as required by almost all standards out there) and the - Linux/FreeBSD one, which returns '0' on success and advices - the use of getpriority() to get the new priority. - - If we are of the nice family that returns the new priority, we - need to clear errno before the call, and check if errno is filled - before calling posix_error() on a returnvalue of -1, because the - -1 may be the actual new priority! */ - - errno = 0; - value = nice(increment); -#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY) - if (value == 0) - value = getpriority(PRIO_PROCESS, 0); -#endif - if (value == -1 && errno != 0) - /* either nice() or getpriority() returned an error */ - return posix_error(); - return PyLong_FromLong((long) value); -} -#endif /* HAVE_NICE */ - - -#ifdef HAVE_GETPRIORITY -/*[clinic input] -os.getpriority - - which: int - who: int - -Return program scheduling priority. -[clinic start generated code]*/ - -static PyObject * -os_getpriority_impl(PyObject *module, int which, int who) -/*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/ -{ - int retval; - - errno = 0; - retval = getpriority(which, who); - if (errno != 0) - return posix_error(); - return PyLong_FromLong((long)retval); -} -#endif /* HAVE_GETPRIORITY */ - - -#ifdef HAVE_SETPRIORITY -/*[clinic input] -os.setpriority - - which: int - who: int - priority: int - -Set program scheduling priority. -[clinic start generated code]*/ - -static PyObject * -os_setpriority_impl(PyObject *module, int which, int who, int priority) -/*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/ -{ - int retval; - - retval = setpriority(which, who, priority); - if (retval == -1) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETPRIORITY */ - - -static PyObject * -internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace) -{ - const char *function_name = is_replace ? "replace" : "rename"; - int dir_fd_specified; - -#ifdef HAVE_RENAMEAT - int renameat_unavailable = 0; -#endif - -#ifdef MS_WINDOWS - BOOL result; - int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0; -#else - int result; -#endif - - dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) || - (dst_dir_fd != DEFAULT_DIR_FD); -#ifndef HAVE_RENAMEAT - if (dir_fd_specified) { - argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd"); - return NULL; - } -#endif - - if (PySys_Audit("os.rename", "OOii", src->object, dst->object, - src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd, - dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) { - return NULL; - } - -#ifdef MS_WINDOWS - Py_BEGIN_ALLOW_THREADS - result = MoveFileExW(src->wide, dst->wide, flags); - Py_END_ALLOW_THREADS - - if (!result) - return path_error2(src, dst); - -#else - if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { - PyErr_Format(PyExc_ValueError, - "%s: src and dst must be the same type", function_name); - return NULL; - } - - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_RENAMEAT - if (dir_fd_specified) { - if (HAVE_RENAMEAT_RUNTIME) { - result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow); - } else { - renameat_unavailable = 1; - } - } else -#endif - result = rename(src->narrow, dst->narrow); - Py_END_ALLOW_THREADS - - -#ifdef HAVE_RENAMEAT - if (renameat_unavailable) { - argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd"); - return NULL; - } -#endif - - if (result) - return path_error2(src, dst); -#endif - Py_RETURN_NONE; -} - - -/*[clinic input] -os.rename - - src : path_t - dst : path_t - * - src_dir_fd : dir_fd = None - dst_dir_fd : dir_fd = None - -Rename a file or directory. - -If either src_dir_fd or dst_dir_fd is not None, it should be a file - descriptor open to a directory, and the respective path string (src or dst) - should be relative; the path will then be relative to that directory. -src_dir_fd and dst_dir_fd, may not be implemented on your platform. - If they are unavailable, using them will raise a NotImplementedError. -[clinic start generated code]*/ - -static PyObject * -os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, - int dst_dir_fd) -/*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/ -{ - return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0); -} - - -/*[clinic input] -os.replace = os.rename - -Rename a file or directory, overwriting the destination. - -If either src_dir_fd or dst_dir_fd is not None, it should be a file - descriptor open to a directory, and the respective path string (src or dst) - should be relative; the path will then be relative to that directory. -src_dir_fd and dst_dir_fd, may not be implemented on your platform. - If they are unavailable, using them will raise a NotImplementedError. -[clinic start generated code]*/ - -static PyObject * -os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, - int dst_dir_fd) -/*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/ -{ - return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1); -} - - -/*[clinic input] -os.rmdir - - path: path_t - * - dir_fd: dir_fd(requires='unlinkat') = None - -Remove a directory. - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -dir_fd may not be implemented on your platform. - If it is unavailable, using it will raise a NotImplementedError. -[clinic start generated code]*/ - -static PyObject * -os_rmdir_impl(PyObject *module, path_t *path, int dir_fd) -/*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/ -{ - int result; -#ifdef HAVE_UNLINKAT - int unlinkat_unavailable = 0; -#endif - - if (PySys_Audit("os.rmdir", "Oi", path->object, - dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { - return NULL; - } - - Py_BEGIN_ALLOW_THREADS -#ifdef MS_WINDOWS - /* Windows, success=1, UNIX, success=0 */ - result = !RemoveDirectoryW(path->wide); -#else -#ifdef HAVE_UNLINKAT - if (dir_fd != DEFAULT_DIR_FD) { - if (HAVE_UNLINKAT_RUNTIME) { - result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR); - } else { - unlinkat_unavailable = 1; - result = -1; - } - } else -#endif - result = rmdir(path->narrow); -#endif - Py_END_ALLOW_THREADS - -#ifdef HAVE_UNLINKAT - if (unlinkat_unavailable) { - argument_unavailable_error("rmdir", "dir_fd"); - return NULL; - } -#endif - - if (result) - return path_error(path); - - Py_RETURN_NONE; -} - - -#ifdef HAVE_SYSTEM -#ifdef MS_WINDOWS -/*[clinic input] -os.system -> long - - command: Py_UNICODE - -Execute the command in a subshell. -[clinic start generated code]*/ - -static long -os_system_impl(PyObject *module, const Py_UNICODE *command) -/*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/ -{ - long result; - - if (PySys_Audit("os.system", "(u)", command) < 0) { - return -1; - } - - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - result = _wsystem(command); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - return result; -} -#else /* MS_WINDOWS */ -/*[clinic input] -os.system -> long - - command: FSConverter - -Execute the command in a subshell. -[clinic start generated code]*/ - -static long -os_system_impl(PyObject *module, PyObject *command) -/*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/ -{ - long result; - const char *bytes = PyBytes_AsString(command); - - if (PySys_Audit("os.system", "(O)", command) < 0) { - return -1; - } - - Py_BEGIN_ALLOW_THREADS - result = system(bytes); - Py_END_ALLOW_THREADS - return result; -} -#endif -#endif /* HAVE_SYSTEM */ - - -#ifdef HAVE_UMASK -/*[clinic input] -os.umask - - mask: int - / - -Set the current numeric umask and return the previous umask. -[clinic start generated code]*/ - -static PyObject * -os_umask_impl(PyObject *module, int mask) -/*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/ -{ - int i = (int)umask(mask); - if (i < 0) - return posix_error(); - return PyLong_FromLong((long)i); -} -#endif - -#ifdef MS_WINDOWS - -/* override the default DeleteFileW behavior so that directory -symlinks can be removed with this function, the same as with -Unix symlinks */ -BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName) -{ - WIN32_FILE_ATTRIBUTE_DATA info; - WIN32_FIND_DATAW find_data; - HANDLE find_data_handle; - int is_directory = 0; - int is_link = 0; - - if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) { - is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; - - /* Get WIN32_FIND_DATA structure for the path to determine if - it is a symlink */ - if(is_directory && - info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - find_data_handle = FindFirstFileW(lpFileName, &find_data); - - if(find_data_handle != INVALID_HANDLE_VALUE) { - /* IO_REPARSE_TAG_SYMLINK if it is a symlink and - IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */ - is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK || - find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT; - FindClose(find_data_handle); - } - } - } - - if (is_directory && is_link) - return RemoveDirectoryW(lpFileName); - - return DeleteFileW(lpFileName); -} -#endif /* MS_WINDOWS */ - - -/*[clinic input] -os.unlink - - path: path_t - * - dir_fd: dir_fd(requires='unlinkat')=None - -Remove a file (same as remove()). - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -dir_fd may not be implemented on your platform. - If it is unavailable, using it will raise a NotImplementedError. - -[clinic start generated code]*/ - -static PyObject * -os_unlink_impl(PyObject *module, path_t *path, int dir_fd) -/*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/ -{ - int result; -#ifdef HAVE_UNLINKAT - int unlinkat_unavailable = 0; -#endif - - if (PySys_Audit("os.remove", "Oi", path->object, - dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH -#ifdef MS_WINDOWS - /* Windows, success=1, UNIX, success=0 */ - result = !Py_DeleteFileW(path->wide); -#else -#ifdef HAVE_UNLINKAT - if (dir_fd != DEFAULT_DIR_FD) { - if (HAVE_UNLINKAT_RUNTIME) { - - result = unlinkat(dir_fd, path->narrow, 0); - } else { - unlinkat_unavailable = 1; - } - } else -#endif /* HAVE_UNLINKAT */ - result = unlink(path->narrow); -#endif - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - -#ifdef HAVE_UNLINKAT - if (unlinkat_unavailable) { - argument_unavailable_error(NULL, "dir_fd"); - return NULL; - } -#endif - - if (result) - return path_error(path); - - Py_RETURN_NONE; -} - - -/*[clinic input] -os.remove = os.unlink - -Remove a file (same as unlink()). - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -dir_fd may not be implemented on your platform. - If it is unavailable, using it will raise a NotImplementedError. -[clinic start generated code]*/ - -static PyObject * -os_remove_impl(PyObject *module, path_t *path, int dir_fd) -/*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/ -{ - return os_unlink_impl(module, path, dir_fd); -} - - -static PyStructSequence_Field uname_result_fields[] = { - {"sysname", "operating system name"}, - {"nodename", "name of machine on network (implementation-defined)"}, - {"release", "operating system release"}, - {"version", "operating system version"}, - {"machine", "hardware identifier"}, - {NULL} -}; - -PyDoc_STRVAR(uname_result__doc__, -"uname_result: Result from os.uname().\n\n\ -This object may be accessed either as a tuple of\n\ - (sysname, nodename, release, version, machine),\n\ -or via the attributes sysname, nodename, release, version, and machine.\n\ -\n\ -See os.uname for more information."); - -static PyStructSequence_Desc uname_result_desc = { - MODNAME ".uname_result", /* name */ - uname_result__doc__, /* doc */ - uname_result_fields, - 5 -}; - -#ifdef HAVE_UNAME -/*[clinic input] -os.uname - -Return an object identifying the current operating system. - -The object behaves like a named tuple with the following fields: - (sysname, nodename, release, version, machine) - -[clinic start generated code]*/ - -static PyObject * -os_uname_impl(PyObject *module) -/*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/ -{ - struct utsname u; - int res; - PyObject *value; - - Py_BEGIN_ALLOW_THREADS - res = uname(&u); - Py_END_ALLOW_THREADS - if (res < 0) - return posix_error(); - - PyObject *UnameResultType = get_posix_state(module)->UnameResultType; - value = PyStructSequence_New((PyTypeObject *)UnameResultType); - if (value == NULL) - return NULL; - -#define SET(i, field) \ - { \ - PyObject *o = PyUnicode_DecodeFSDefault(field); \ - if (!o) { \ - Py_DECREF(value); \ - return NULL; \ - } \ - PyStructSequence_SET_ITEM(value, i, o); \ - } \ - - SET(0, u.sysname); - SET(1, u.nodename); - SET(2, u.release); - SET(3, u.version); - SET(4, u.machine); - -#undef SET - - return value; -} -#endif /* HAVE_UNAME */ - - - -typedef struct { - int now; - time_t atime_s; - long atime_ns; - time_t mtime_s; - long mtime_ns; -} utime_t; - -/* - * these macros assume that "ut" is a pointer to a utime_t - * they also intentionally leak the declaration of a pointer named "time" - */ -#define UTIME_TO_TIMESPEC \ - struct timespec ts[2]; \ - struct timespec *time; \ - if (ut->now) \ - time = NULL; \ - else { \ - ts[0].tv_sec = ut->atime_s; \ - ts[0].tv_nsec = ut->atime_ns; \ - ts[1].tv_sec = ut->mtime_s; \ - ts[1].tv_nsec = ut->mtime_ns; \ - time = ts; \ - } \ - -#define UTIME_TO_TIMEVAL \ - struct timeval tv[2]; \ - struct timeval *time; \ - if (ut->now) \ - time = NULL; \ - else { \ - tv[0].tv_sec = ut->atime_s; \ - tv[0].tv_usec = ut->atime_ns / 1000; \ - tv[1].tv_sec = ut->mtime_s; \ - tv[1].tv_usec = ut->mtime_ns / 1000; \ - time = tv; \ - } \ - -#define UTIME_TO_UTIMBUF \ - struct utimbuf u; \ - struct utimbuf *time; \ - if (ut->now) \ - time = NULL; \ - else { \ - u.actime = ut->atime_s; \ - u.modtime = ut->mtime_s; \ - time = &u; \ - } - -#define UTIME_TO_TIME_T \ - time_t timet[2]; \ - time_t *time; \ - if (ut->now) \ - time = NULL; \ - else { \ - timet[0] = ut->atime_s; \ - timet[1] = ut->mtime_s; \ - time = timet; \ - } \ - - -#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT) - -static int -utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks) -{ -#if defined(__APPLE__) && defined(HAVE_UTIMENSAT) - if (HAVE_UTIMENSAT_RUNTIME) { - int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW; - UTIME_TO_TIMESPEC; - return utimensat(dir_fd, path, time, flags); - } else { - errno = ENOSYS; - return -1; - } -#elif defined(HAVE_UTIMENSAT) - int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW; - UTIME_TO_TIMESPEC; - return utimensat(dir_fd, path, time, flags); -#elif defined(HAVE_FUTIMESAT) - UTIME_TO_TIMEVAL; - /* - * follow_symlinks will never be false here; - * we only allow !follow_symlinks and dir_fd together - * if we have utimensat() - */ - assert(follow_symlinks); - return futimesat(dir_fd, path, time); -#endif -} - - #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS) - -static int -utime_fd(utime_t *ut, int fd) -{ -#ifdef HAVE_FUTIMENS - - if (HAVE_FUTIMENS_RUNTIME) { - - UTIME_TO_TIMESPEC; - return futimens(fd, time); - - } else -#ifndef HAVE_FUTIMES - { - /* Not sure if this can happen */ - PyErr_SetString( - PyExc_RuntimeError, - "neither futimens nor futimes are supported" - " on this system"); - return -1; - } -#endif - -#endif -#ifdef HAVE_FUTIMES - { - UTIME_TO_TIMEVAL; - return futimes(fd, time); - } -#endif -} - - #define PATH_UTIME_HAVE_FD 1 -#else - #define PATH_UTIME_HAVE_FD 0 -#endif - -#if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES) -# define UTIME_HAVE_NOFOLLOW_SYMLINKS -#endif - -#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS - -static int -utime_nofollow_symlinks(utime_t *ut, const char *path) -{ -#ifdef HAVE_UTIMENSAT - if (HAVE_UTIMENSAT_RUNTIME) { - UTIME_TO_TIMESPEC; - return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW); - } else -#ifndef HAVE_LUTIMES - { - /* Not sure if this can happen */ - PyErr_SetString( - PyExc_RuntimeError, - "neither utimensat nor lutimes are supported" - " on this system"); - return -1; - } -#endif -#endif - -#ifdef HAVE_LUTIMES - { - UTIME_TO_TIMEVAL; - return lutimes(path, time); - } -#endif -} - -#endif - -#ifndef MS_WINDOWS - -static int -utime_default(utime_t *ut, const char *path) -{ -#if defined(__APPLE__) && defined(HAVE_UTIMENSAT) - if (HAVE_UTIMENSAT_RUNTIME) { - UTIME_TO_TIMESPEC; - return utimensat(DEFAULT_DIR_FD, path, time, 0); - } else { - UTIME_TO_TIMEVAL; - return utimes(path, time); - } -#elif defined(HAVE_UTIMENSAT) - UTIME_TO_TIMESPEC; - return utimensat(DEFAULT_DIR_FD, path, time, 0); -#elif defined(HAVE_UTIMES) - UTIME_TO_TIMEVAL; - return utimes(path, time); -#elif defined(HAVE_UTIME_H) - UTIME_TO_UTIMBUF; - return utime(path, time); -#else - UTIME_TO_TIME_T; - return utime(path, time); -#endif -} - -#endif - -static int -split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns) -{ - int result = 0; - PyObject *divmod; - divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion); - if (!divmod) - goto exit; - if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) { - PyErr_Format(PyExc_TypeError, - "%.200s.__divmod__() must return a 2-tuple, not %.200s", - _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod))); - goto exit; - } - *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0)); - if ((*s == -1) && PyErr_Occurred()) - goto exit; - *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1)); - if ((*ns == -1) && PyErr_Occurred()) - goto exit; - - result = 1; -exit: - Py_XDECREF(divmod); - return result; -} - - -/*[clinic input] -os.utime - - path: path_t(allow_fd='PATH_UTIME_HAVE_FD') - times: object = None - * - ns: object = NULL - dir_fd: dir_fd(requires='futimensat') = None - follow_symlinks: bool=True - -# "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\ - -Set the access and modified time of path. - -path may always be specified as a string. -On some platforms, path may also be specified as an open file descriptor. - If this functionality is unavailable, using it raises an exception. - -If times is not None, it must be a tuple (atime, mtime); - atime and mtime should be expressed as float seconds since the epoch. -If ns is specified, it must be a tuple (atime_ns, mtime_ns); - atime_ns and mtime_ns should be expressed as integer nanoseconds - since the epoch. -If times is None and ns is unspecified, utime uses the current time. -Specifying tuples for both times and ns is an error. - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -If follow_symlinks is False, and the last element of the path is a symbolic - link, utime will modify the symbolic link itself instead of the file the - link points to. -It is an error to use dir_fd or follow_symlinks when specifying path - as an open file descriptor. -dir_fd and follow_symlinks may not be available on your platform. - If they are unavailable, using them will raise a NotImplementedError. - -[clinic start generated code]*/ - -static PyObject * -os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, - int dir_fd, int follow_symlinks) -/*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/ -{ -#ifdef MS_WINDOWS - HANDLE hFile; - FILETIME atime, mtime; -#else - int result; -#endif - - utime_t utime; - - memset(&utime, 0, sizeof(utime_t)); - - if (times != Py_None && ns) { - PyErr_SetString(PyExc_ValueError, - "utime: you may specify either 'times'" - " or 'ns' but not both"); - return NULL; - } - - if (times != Py_None) { - time_t a_sec, m_sec; - long a_nsec, m_nsec; - if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) { - PyErr_SetString(PyExc_TypeError, - "utime: 'times' must be either" - " a tuple of two ints or None"); - return NULL; - } - utime.now = 0; - if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0), - &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 || - _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1), - &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) { - return NULL; - } - utime.atime_s = a_sec; - utime.atime_ns = a_nsec; - utime.mtime_s = m_sec; - utime.mtime_ns = m_nsec; - } - else if (ns) { - if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) { - PyErr_SetString(PyExc_TypeError, - "utime: 'ns' must be a tuple of two ints"); - return NULL; - } - utime.now = 0; - if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0), - &utime.atime_s, &utime.atime_ns) || - !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1), - &utime.mtime_s, &utime.mtime_ns)) { - return NULL; - } - } - else { - /* times and ns are both None/unspecified. use "now". */ - utime.now = 1; - } - -#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS) - if (follow_symlinks_specified("utime", follow_symlinks)) - return NULL; -#endif - - if (path_and_dir_fd_invalid("utime", path, dir_fd) || - dir_fd_and_fd_invalid("utime", dir_fd, path->fd) || - fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks)) - return NULL; - -#if !defined(HAVE_UTIMENSAT) - if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) { - PyErr_SetString(PyExc_ValueError, - "utime: cannot use dir_fd and follow_symlinks " - "together on this platform"); - return NULL; - } -#endif - - if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None, - dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { - return NULL; - } - -#ifdef MS_WINDOWS - Py_BEGIN_ALLOW_THREADS - hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0, - NULL, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, NULL); - Py_END_ALLOW_THREADS - if (hFile == INVALID_HANDLE_VALUE) { - path_error(path); - return NULL; - } - - if (utime.now) { - GetSystemTimeAsFileTime(&mtime); - atime = mtime; - } - else { - _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime); - _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime); - } - if (!SetFileTime(hFile, NULL, &atime, &mtime)) { - /* Avoid putting the file name into the error here, - as that may confuse the user into believing that - something is wrong with the file, when it also - could be the time stamp that gives a problem. */ - PyErr_SetFromWindowsErr(0); - CloseHandle(hFile); - return NULL; - } - CloseHandle(hFile); -#else /* MS_WINDOWS */ - Py_BEGIN_ALLOW_THREADS - -#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS - if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) - result = utime_nofollow_symlinks(&utime, path->narrow); - else -#endif - -#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT) - if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) { - result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks); - - } else -#endif - -#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS) - if (path->fd != -1) - result = utime_fd(&utime, path->fd); - else -#endif - - result = utime_default(&utime, path->narrow); - - Py_END_ALLOW_THREADS - -#if defined(__APPLE__) && defined(HAVE_UTIMENSAT) - /* See utime_dir_fd implementation */ - if (result == -1 && errno == ENOSYS) { - argument_unavailable_error(NULL, "dir_fd"); - return NULL; - } -#endif - - if (result < 0) { - /* see previous comment about not putting filename in error here */ - posix_error(); - return NULL; - } - -#endif /* MS_WINDOWS */ - - Py_RETURN_NONE; -} - -/* Process operations */ - - -/*[clinic input] -os._exit - - status: int - -Exit to the system with specified status, without normal exit processing. -[clinic start generated code]*/ - -static PyObject * -os__exit_impl(PyObject *module, int status) -/*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/ -{ - _exit(status); - return NULL; /* Make gcc -Wall happy */ -} - -#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV) -#define EXECV_CHAR wchar_t -#else -#define EXECV_CHAR char -#endif - -#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN) -static void -free_string_array(EXECV_CHAR **array, Py_ssize_t count) -{ - Py_ssize_t i; - for (i = 0; i < count; i++) - PyMem_Free(array[i]); - PyMem_Free(array); -} - -static int -fsconvert_strdup(PyObject *o, EXECV_CHAR **out) -{ - Py_ssize_t size; - PyObject *ub; - int result = 0; -#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV) - if (!PyUnicode_FSDecoder(o, &ub)) - return 0; - *out = PyUnicode_AsWideCharString(ub, &size); - if (*out) - result = 1; -#else - if (!PyUnicode_FSConverter(o, &ub)) - return 0; - size = PyBytes_GET_SIZE(ub); - *out = PyMem_Malloc(size + 1); - if (*out) { - memcpy(*out, PyBytes_AS_STRING(ub), size + 1); - result = 1; - } else - PyErr_NoMemory(); -#endif - Py_DECREF(ub); - return result; -} -#endif - -#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN) -static EXECV_CHAR** -parse_envlist(PyObject* env, Py_ssize_t *envc_ptr) -{ - Py_ssize_t i, pos, envc; - PyObject *keys=NULL, *vals=NULL; - PyObject *key, *val, *key2, *val2, *keyval; - EXECV_CHAR **envlist; - - i = PyMapping_Size(env); - if (i < 0) - return NULL; - envlist = PyMem_NEW(EXECV_CHAR *, i + 1); - if (envlist == NULL) { - PyErr_NoMemory(); - return NULL; - } - envc = 0; - keys = PyMapping_Keys(env); - if (!keys) - goto error; - vals = PyMapping_Values(env); - if (!vals) - goto error; - if (!PyList_Check(keys) || !PyList_Check(vals)) { - PyErr_Format(PyExc_TypeError, - "env.keys() or env.values() is not a list"); - goto error; - } - - for (pos = 0; pos < i; pos++) { - key = PyList_GetItem(keys, pos); - val = PyList_GetItem(vals, pos); - if (!key || !val) - goto error; - -#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV) - if (!PyUnicode_FSDecoder(key, &key2)) - goto error; - if (!PyUnicode_FSDecoder(val, &val2)) { - Py_DECREF(key2); - goto error; - } - /* Search from index 1 because on Windows starting '=' is allowed for - defining hidden environment variables. */ - if (PyUnicode_GET_LENGTH(key2) == 0 || - PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1) - { - PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); - Py_DECREF(key2); - Py_DECREF(val2); - goto error; - } - keyval = PyUnicode_FromFormat("%U=%U", key2, val2); -#else - if (!PyUnicode_FSConverter(key, &key2)) - goto error; - if (!PyUnicode_FSConverter(val, &val2)) { - Py_DECREF(key2); - goto error; - } - if (PyBytes_GET_SIZE(key2) == 0 || - strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL) - { - PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); - Py_DECREF(key2); - Py_DECREF(val2); - goto error; - } - keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2), - PyBytes_AS_STRING(val2)); -#endif - Py_DECREF(key2); - Py_DECREF(val2); - if (!keyval) - goto error; - - if (!fsconvert_strdup(keyval, &envlist[envc++])) { - Py_DECREF(keyval); - goto error; - } - - Py_DECREF(keyval); - } - Py_DECREF(vals); - Py_DECREF(keys); - - envlist[envc] = 0; - *envc_ptr = envc; - return envlist; - -error: - Py_XDECREF(keys); - Py_XDECREF(vals); - free_string_array(envlist, envc); - return NULL; -} - -static EXECV_CHAR** -parse_arglist(PyObject* argv, Py_ssize_t *argc) -{ - int i; - EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1); - if (argvlist == NULL) { - PyErr_NoMemory(); - return NULL; - } - for (i = 0; i < *argc; i++) { - PyObject* item = PySequence_ITEM(argv, i); - if (item == NULL) - goto fail; - if (!fsconvert_strdup(item, &argvlist[i])) { - Py_DECREF(item); - goto fail; - } - Py_DECREF(item); - } - argvlist[*argc] = NULL; - return argvlist; -fail: - *argc = i; - free_string_array(argvlist, *argc); - return NULL; -} - -#endif - - -#ifdef HAVE_EXECV -/*[clinic input] -os.execv - - path: path_t - Path of executable file. - argv: object - Tuple or list of strings. - / - -Execute an executable path with arguments, replacing current process. -[clinic start generated code]*/ - -static PyObject * -os_execv_impl(PyObject *module, path_t *path, PyObject *argv) -/*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/ -{ - EXECV_CHAR **argvlist; - Py_ssize_t argc; - - PyInterpreterState *interp = _PyInterpreterState_GET(); - if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) { - PyErr_SetString(PyExc_RuntimeError, - "exec not supported for isolated subinterpreters"); - return NULL; - } - - /* execv has two arguments: (path, argv), where - argv is a list or tuple of strings. */ - - if (!PyList_Check(argv) && !PyTuple_Check(argv)) { - PyErr_SetString(PyExc_TypeError, - "execv() arg 2 must be a tuple or list"); - return NULL; - } - argc = PySequence_Size(argv); - if (argc < 1) { - PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty"); - return NULL; - } - - argvlist = parse_arglist(argv, &argc); - if (argvlist == NULL) { - return NULL; - } - if (!argvlist[0][0]) { - PyErr_SetString(PyExc_ValueError, - "execv() arg 2 first element cannot be empty"); - free_string_array(argvlist, argc); - return NULL; - } - - if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) { - free_string_array(argvlist, argc); - return NULL; - } - - _Py_BEGIN_SUPPRESS_IPH -#ifdef HAVE_WEXECV - _wexecv(path->wide, argvlist); -#else - execv(path->narrow, argvlist); -#endif - _Py_END_SUPPRESS_IPH - - /* If we get here it's definitely an error */ - - free_string_array(argvlist, argc); - return posix_error(); -} - - -/*[clinic input] -os.execve - - path: path_t(allow_fd='PATH_HAVE_FEXECVE') - Path of executable file. - argv: object - Tuple or list of strings. - env: object - Dictionary of strings mapping to strings. - -Execute an executable path with arguments, replacing current process. -[clinic start generated code]*/ - -static PyObject * -os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env) -/*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/ -{ - EXECV_CHAR **argvlist = NULL; - EXECV_CHAR **envlist; - Py_ssize_t argc, envc; - - PyInterpreterState *interp = _PyInterpreterState_GET(); - if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) { - PyErr_SetString(PyExc_RuntimeError, - "exec not supported for isolated subinterpreters"); - return NULL; - } - - /* execve has three arguments: (path, argv, env), where - argv is a list or tuple of strings and env is a dictionary - like posix.environ. */ - - if (!PyList_Check(argv) && !PyTuple_Check(argv)) { - PyErr_SetString(PyExc_TypeError, - "execve: argv must be a tuple or list"); - goto fail_0; - } - argc = PySequence_Size(argv); - if (argc < 1) { - PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty"); - return NULL; - } - - if (!PyMapping_Check(env)) { - PyErr_SetString(PyExc_TypeError, - "execve: environment must be a mapping object"); - goto fail_0; - } - - argvlist = parse_arglist(argv, &argc); - if (argvlist == NULL) { - goto fail_0; - } - if (!argvlist[0][0]) { - PyErr_SetString(PyExc_ValueError, - "execve: argv first element cannot be empty"); - goto fail_0; - } - - envlist = parse_envlist(env, &envc); - if (envlist == NULL) - goto fail_0; - - if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) { - goto fail_1; - } - - _Py_BEGIN_SUPPRESS_IPH -#ifdef HAVE_FEXECVE - if (path->fd > -1) - fexecve(path->fd, argvlist, envlist); - else -#endif -#ifdef HAVE_WEXECV - _wexecve(path->wide, argvlist, envlist); -#else - execve(path->narrow, argvlist, envlist); -#endif - _Py_END_SUPPRESS_IPH - - /* If we get here it's definitely an error */ - - posix_path_error(path); - fail_1: - free_string_array(envlist, envc); - fail_0: - if (argvlist) - free_string_array(argvlist, argc); - return NULL; -} - -#endif /* HAVE_EXECV */ - -#ifdef HAVE_POSIX_SPAWN - -enum posix_spawn_file_actions_identifier { - POSIX_SPAWN_OPEN, - POSIX_SPAWN_CLOSE, - POSIX_SPAWN_DUP2 -}; - -#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) -static int -convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res); -#endif - -static int -parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup, - int resetids, int setsid, PyObject *setsigmask, - PyObject *setsigdef, PyObject *scheduler, - posix_spawnattr_t *attrp) -{ - long all_flags = 0; - - errno = posix_spawnattr_init(attrp); - if (errno) { - posix_error(); - return -1; - } - - if (setpgroup) { - pid_t pgid = PyLong_AsPid(setpgroup); - if (pgid == (pid_t)-1 && PyErr_Occurred()) { - goto fail; - } - errno = posix_spawnattr_setpgroup(attrp, pgid); - if (errno) { - posix_error(); - goto fail; - } - all_flags |= POSIX_SPAWN_SETPGROUP; - } - - if (resetids) { - all_flags |= POSIX_SPAWN_RESETIDS; - } - - if (setsid) { -#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME - if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) { -#endif -#ifdef POSIX_SPAWN_SETSID - all_flags |= POSIX_SPAWN_SETSID; -#elif defined(POSIX_SPAWN_SETSID_NP) - all_flags |= POSIX_SPAWN_SETSID_NP; -#else - argument_unavailable_error(func_name, "setsid"); - return -1; -#endif - -#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME - } else { - argument_unavailable_error(func_name, "setsid"); - return -1; - } -#endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */ - - } - -#ifdef HAVE_SIGSET_T - if (setsigmask) { - sigset_t set; - if (!_Py_Sigset_Converter(setsigmask, &set)) { - goto fail; - } - errno = posix_spawnattr_setsigmask(attrp, &set); - if (errno) { - posix_error(); - goto fail; - } - all_flags |= POSIX_SPAWN_SETSIGMASK; - } - - if (setsigdef) { - sigset_t set; - if (!_Py_Sigset_Converter(setsigdef, &set)) { - goto fail; - } - errno = posix_spawnattr_setsigdefault(attrp, &set); - if (errno) { - posix_error(); - goto fail; - } - all_flags |= POSIX_SPAWN_SETSIGDEF; - } -#else - if (setsigmask || setsigdef) { - PyErr_SetString(PyExc_NotImplementedError, - "sigset is not supported on this platform"); - goto fail; - } -#endif - - if (scheduler) { -#ifdef POSIX_SPAWN_SETSCHEDULER - PyObject *py_schedpolicy; - PyObject *schedparam_obj; - struct sched_param schedparam; - - if (!PyArg_ParseTuple(scheduler, "OO" - ";A scheduler tuple must have two elements", - &py_schedpolicy, &schedparam_obj)) { - goto fail; - } - if (!convert_sched_param(module, schedparam_obj, &schedparam)) { - goto fail; - } - if (py_schedpolicy != Py_None) { - int schedpolicy = _PyLong_AsInt(py_schedpolicy); - - if (schedpolicy == -1 && PyErr_Occurred()) { - goto fail; - } - errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy); - if (errno) { - posix_error(); - goto fail; - } - all_flags |= POSIX_SPAWN_SETSCHEDULER; - } - errno = posix_spawnattr_setschedparam(attrp, &schedparam); - if (errno) { - posix_error(); - goto fail; - } - all_flags |= POSIX_SPAWN_SETSCHEDPARAM; -#else - PyErr_SetString(PyExc_NotImplementedError, - "The scheduler option is not supported in this system."); - goto fail; -#endif - } - - errno = posix_spawnattr_setflags(attrp, all_flags); - if (errno) { - posix_error(); - goto fail; - } - - return 0; - -fail: - (void)posix_spawnattr_destroy(attrp); - return -1; -} - -static int -parse_file_actions(PyObject *file_actions, - posix_spawn_file_actions_t *file_actionsp, - PyObject *temp_buffer) -{ - PyObject *seq; - PyObject *file_action = NULL; - PyObject *tag_obj; - - seq = PySequence_Fast(file_actions, - "file_actions must be a sequence or None"); - if (seq == NULL) { - return -1; - } - - errno = posix_spawn_file_actions_init(file_actionsp); - if (errno) { - posix_error(); - Py_DECREF(seq); - return -1; - } - - for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) { - file_action = PySequence_Fast_GET_ITEM(seq, i); - Py_INCREF(file_action); - if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) { - PyErr_SetString(PyExc_TypeError, - "Each file_actions element must be a non-empty tuple"); - goto fail; - } - long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0)); - if (tag == -1 && PyErr_Occurred()) { - goto fail; - } - - /* Populate the file_actions object */ - switch (tag) { - case POSIX_SPAWN_OPEN: { - int fd, oflag; - PyObject *path; - unsigned long mode; - if (!PyArg_ParseTuple(file_action, "OiO&ik" - ";A open file_action tuple must have 5 elements", - &tag_obj, &fd, PyUnicode_FSConverter, &path, - &oflag, &mode)) - { - goto fail; - } - if (PyList_Append(temp_buffer, path)) { - Py_DECREF(path); - goto fail; - } - errno = posix_spawn_file_actions_addopen(file_actionsp, - fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode); - Py_DECREF(path); - if (errno) { - posix_error(); - goto fail; - } - break; - } - case POSIX_SPAWN_CLOSE: { - int fd; - if (!PyArg_ParseTuple(file_action, "Oi" - ";A close file_action tuple must have 2 elements", - &tag_obj, &fd)) - { - goto fail; - } - errno = posix_spawn_file_actions_addclose(file_actionsp, fd); - if (errno) { - posix_error(); - goto fail; - } - break; - } - case POSIX_SPAWN_DUP2: { - int fd1, fd2; - if (!PyArg_ParseTuple(file_action, "Oii" - ";A dup2 file_action tuple must have 3 elements", - &tag_obj, &fd1, &fd2)) - { - goto fail; - } - errno = posix_spawn_file_actions_adddup2(file_actionsp, - fd1, fd2); - if (errno) { - posix_error(); - goto fail; - } - break; - } - default: { - PyErr_SetString(PyExc_TypeError, - "Unknown file_actions identifier"); - goto fail; - } - } - Py_DECREF(file_action); - } - - Py_DECREF(seq); - return 0; - -fail: - Py_DECREF(seq); - Py_DECREF(file_action); - (void)posix_spawn_file_actions_destroy(file_actionsp); - return -1; -} - - -static PyObject * -py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv, - PyObject *env, PyObject *file_actions, - PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask, - PyObject *setsigdef, PyObject *scheduler) -{ - const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn"; - EXECV_CHAR **argvlist = NULL; - EXECV_CHAR **envlist = NULL; - posix_spawn_file_actions_t file_actions_buf; - posix_spawn_file_actions_t *file_actionsp = NULL; - posix_spawnattr_t attr; - posix_spawnattr_t *attrp = NULL; - Py_ssize_t argc, envc; - PyObject *result = NULL; - PyObject *temp_buffer = NULL; - pid_t pid; - int err_code; - - /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where - argv is a list or tuple of strings and env is a dictionary - like posix.environ. */ - - if (!PyList_Check(argv) && !PyTuple_Check(argv)) { - PyErr_Format(PyExc_TypeError, - "%s: argv must be a tuple or list", func_name); - goto exit; - } - argc = PySequence_Size(argv); - if (argc < 1) { - PyErr_Format(PyExc_ValueError, - "%s: argv must not be empty", func_name); - return NULL; - } - - if (!PyMapping_Check(env)) { - PyErr_Format(PyExc_TypeError, - "%s: environment must be a mapping object", func_name); - goto exit; - } - - argvlist = parse_arglist(argv, &argc); - if (argvlist == NULL) { - goto exit; - } - if (!argvlist[0][0]) { - PyErr_Format(PyExc_ValueError, - "%s: argv first element cannot be empty", func_name); - goto exit; - } - - envlist = parse_envlist(env, &envc); - if (envlist == NULL) { - goto exit; - } - - if (file_actions != NULL && file_actions != Py_None) { - /* There is a bug in old versions of glibc that makes some of the - * helper functions for manipulating file actions not copy the provided - * buffers. The problem is that posix_spawn_file_actions_addopen does not - * copy the value of path for some old versions of glibc (<2.20). - * The use of temp_buffer here is a workaround that keeps the - * python objects that own the buffers alive until posix_spawn gets called. - * Check https://bugs.python.org/issue33630 and - * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/ - temp_buffer = PyList_New(0); - if (!temp_buffer) { - goto exit; - } - if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) { - goto exit; - } - file_actionsp = &file_actions_buf; - } - - if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid, - setsigmask, setsigdef, scheduler, &attr)) { - goto exit; - } - attrp = &attr; - - if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) { - goto exit; - } - - _Py_BEGIN_SUPPRESS_IPH -#ifdef HAVE_POSIX_SPAWNP - if (use_posix_spawnp) { - err_code = posix_spawnp(&pid, path->narrow, - file_actionsp, attrp, argvlist, envlist); - } - else -#endif /* HAVE_POSIX_SPAWNP */ - { - err_code = posix_spawn(&pid, path->narrow, - file_actionsp, attrp, argvlist, envlist); - } - _Py_END_SUPPRESS_IPH - - if (err_code) { - errno = err_code; - PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object); - goto exit; - } -#ifdef _Py_MEMORY_SANITIZER - __msan_unpoison(&pid, sizeof(pid)); -#endif - result = PyLong_FromPid(pid); - -exit: - if (file_actionsp) { - (void)posix_spawn_file_actions_destroy(file_actionsp); - } - if (attrp) { - (void)posix_spawnattr_destroy(attrp); - } - if (envlist) { - free_string_array(envlist, envc); - } - if (argvlist) { - free_string_array(argvlist, argc); - } - Py_XDECREF(temp_buffer); - return result; -} - - -/*[clinic input] - -os.posix_spawn - path: path_t - Path of executable file. - argv: object - Tuple or list of strings. - env: object - Dictionary of strings mapping to strings. - / - * - file_actions: object(c_default='NULL') = () - A sequence of file action tuples. - setpgroup: object = NULL - The pgroup to use with the POSIX_SPAWN_SETPGROUP flag. - resetids: bool(accept={int}) = False - If the value is `true` the POSIX_SPAWN_RESETIDS will be activated. - setsid: bool(accept={int}) = False - If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated. - setsigmask: object(c_default='NULL') = () - The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag. - setsigdef: object(c_default='NULL') = () - The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag. - scheduler: object = NULL - A tuple with the scheduler policy (optional) and parameters. - -Execute the program specified by path in a new process. -[clinic start generated code]*/ - -static PyObject * -os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, - PyObject *env, PyObject *file_actions, - PyObject *setpgroup, int resetids, int setsid, - PyObject *setsigmask, PyObject *setsigdef, - PyObject *scheduler) -/*[clinic end generated code: output=14a1098c566bc675 input=8c6305619a00ad04]*/ -{ - return py_posix_spawn(0, module, path, argv, env, file_actions, - setpgroup, resetids, setsid, setsigmask, setsigdef, - scheduler); -} - #endif /* HAVE_POSIX_SPAWN */ - - - -#ifdef HAVE_POSIX_SPAWNP -/*[clinic input] - -os.posix_spawnp - path: path_t - Path of executable file. - argv: object - Tuple or list of strings. - env: object - Dictionary of strings mapping to strings. - / - * - file_actions: object(c_default='NULL') = () - A sequence of file action tuples. - setpgroup: object = NULL - The pgroup to use with the POSIX_SPAWN_SETPGROUP flag. - resetids: bool(accept={int}) = False - If the value is `True` the POSIX_SPAWN_RESETIDS will be activated. - setsid: bool(accept={int}) = False - If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated. - setsigmask: object(c_default='NULL') = () - The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag. - setsigdef: object(c_default='NULL') = () - The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag. - scheduler: object = NULL - A tuple with the scheduler policy (optional) and parameters. - -Execute the program specified by path in a new process. -[clinic start generated code]*/ - -static PyObject * -os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv, - PyObject *env, PyObject *file_actions, - PyObject *setpgroup, int resetids, int setsid, - PyObject *setsigmask, PyObject *setsigdef, - PyObject *scheduler) -/*[clinic end generated code: output=7b9aaefe3031238d input=c1911043a22028da]*/ -{ - return py_posix_spawn(1, module, path, argv, env, file_actions, - setpgroup, resetids, setsid, setsigmask, setsigdef, - scheduler); -} -#endif /* HAVE_POSIX_SPAWNP */ - -#ifdef HAVE_RTPSPAWN -static intptr_t -_rtp_spawn(int mode, const char *rtpFileName, const char *argv[], - const char *envp[]) -{ - RTP_ID rtpid; - int status; - pid_t res; - int async_err = 0; - - /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes. - uStackSize=0 cannot be used, the default stack size is too small for - Python. */ - if (envp) { - rtpid = rtpSpawn(rtpFileName, argv, envp, - 100, 0x1000000, 0, VX_FP_TASK); - } - else { - rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ, - 100, 0x1000000, 0, VX_FP_TASK); - } - if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) { - do { - res = waitpid((pid_t)rtpid, &status, 0); - } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - - if (res < 0) - return RTP_ID_ERROR; - return ((intptr_t)status); - } - return ((intptr_t)rtpid); -} -#endif - -#if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN) -/*[clinic input] -os.spawnv - - mode: int - Mode of process creation. - path: path_t - Path of executable file. - argv: object - Tuple or list of strings. - / - -Execute the program specified by path in a new process. -[clinic start generated code]*/ - -static PyObject * -os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv) -/*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/ -{ - EXECV_CHAR **argvlist; - int i; - Py_ssize_t argc; - intptr_t spawnval; - PyObject *(*getitem)(PyObject *, Py_ssize_t); - - /* spawnv has three arguments: (mode, path, argv), where - argv is a list or tuple of strings. */ - - if (PyList_Check(argv)) { - argc = PyList_Size(argv); - getitem = PyList_GetItem; - } - else if (PyTuple_Check(argv)) { - argc = PyTuple_Size(argv); - getitem = PyTuple_GetItem; - } - else { - PyErr_SetString(PyExc_TypeError, - "spawnv() arg 2 must be a tuple or list"); - return NULL; - } - if (argc == 0) { - PyErr_SetString(PyExc_ValueError, - "spawnv() arg 2 cannot be empty"); - return NULL; - } - - argvlist = PyMem_NEW(EXECV_CHAR *, argc+1); - if (argvlist == NULL) { - return PyErr_NoMemory(); - } - for (i = 0; i < argc; i++) { - if (!fsconvert_strdup((*getitem)(argv, i), - &argvlist[i])) { - free_string_array(argvlist, i); - PyErr_SetString( - PyExc_TypeError, - "spawnv() arg 2 must contain only strings"); - return NULL; - } - if (i == 0 && !argvlist[0][0]) { - free_string_array(argvlist, i + 1); - PyErr_SetString( - PyExc_ValueError, - "spawnv() arg 2 first element cannot be empty"); - return NULL; - } - } - argvlist[argc] = NULL; - -#if !defined(HAVE_RTPSPAWN) - if (mode == _OLD_P_OVERLAY) - mode = _P_OVERLAY; -#endif - - if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, - Py_None) < 0) { - free_string_array(argvlist, argc); - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH -#ifdef HAVE_WSPAWNV - spawnval = _wspawnv(mode, path->wide, argvlist); -#elif defined(HAVE_RTPSPAWN) - spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL); -#else - spawnval = _spawnv(mode, path->narrow, argvlist); -#endif - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - - free_string_array(argvlist, argc); - - if (spawnval == -1) - return posix_error(); - else - return Py_BuildValue(_Py_PARSE_INTPTR, spawnval); -} - -/*[clinic input] -os.spawnve - - mode: int - Mode of process creation. - path: path_t - Path of executable file. - argv: object - Tuple or list of strings. - env: object - Dictionary of strings mapping to strings. - / - -Execute the program specified by path in a new process. -[clinic start generated code]*/ - -static PyObject * -os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv, - PyObject *env) -/*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/ -{ - EXECV_CHAR **argvlist; - EXECV_CHAR **envlist; - PyObject *res = NULL; - Py_ssize_t argc, i, envc; - intptr_t spawnval; - PyObject *(*getitem)(PyObject *, Py_ssize_t); - Py_ssize_t lastarg = 0; - - /* spawnve has four arguments: (mode, path, argv, env), where - argv is a list or tuple of strings and env is a dictionary - like posix.environ. */ - - if (PyList_Check(argv)) { - argc = PyList_Size(argv); - getitem = PyList_GetItem; - } - else if (PyTuple_Check(argv)) { - argc = PyTuple_Size(argv); - getitem = PyTuple_GetItem; - } - else { - PyErr_SetString(PyExc_TypeError, - "spawnve() arg 2 must be a tuple or list"); - goto fail_0; - } - if (argc == 0) { - PyErr_SetString(PyExc_ValueError, - "spawnve() arg 2 cannot be empty"); - goto fail_0; - } - if (!PyMapping_Check(env)) { - PyErr_SetString(PyExc_TypeError, - "spawnve() arg 3 must be a mapping object"); - goto fail_0; - } - - argvlist = PyMem_NEW(EXECV_CHAR *, argc+1); - if (argvlist == NULL) { - PyErr_NoMemory(); - goto fail_0; - } - for (i = 0; i < argc; i++) { - if (!fsconvert_strdup((*getitem)(argv, i), - &argvlist[i])) - { - lastarg = i; - goto fail_1; - } - if (i == 0 && !argvlist[0][0]) { - lastarg = i + 1; - PyErr_SetString( - PyExc_ValueError, - "spawnv() arg 2 first element cannot be empty"); - goto fail_1; - } - } - lastarg = argc; - argvlist[argc] = NULL; - - envlist = parse_envlist(env, &envc); - if (envlist == NULL) - goto fail_1; - -#if !defined(HAVE_RTPSPAWN) - if (mode == _OLD_P_OVERLAY) - mode = _P_OVERLAY; -#endif - - if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) { - goto fail_2; - } - - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH -#ifdef HAVE_WSPAWNV - spawnval = _wspawnve(mode, path->wide, argvlist, envlist); -#elif defined(HAVE_RTPSPAWN) - spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, - (const char **)envlist); -#else - spawnval = _spawnve(mode, path->narrow, argvlist, envlist); -#endif - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - - if (spawnval == -1) - (void) posix_error(); - else - res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval); - - fail_2: - while (--envc >= 0) { - PyMem_Free(envlist[envc]); - } - PyMem_Free(envlist); - fail_1: - free_string_array(argvlist, lastarg); - fail_0: - return res; -} - -#endif /* HAVE_SPAWNV */ - -#ifdef HAVE_FORK - -/* Helper function to validate arguments. - Returns 0 on success. non-zero on failure with a TypeError raised. - If obj is non-NULL it must be callable. */ -static int -check_null_or_callable(PyObject *obj, const char* obj_name) -{ - if (obj && !PyCallable_Check(obj)) { - PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s", - obj_name, _PyType_Name(Py_TYPE(obj))); - return -1; - } - return 0; -} - -/*[clinic input] -os.register_at_fork - - * - before: object=NULL - A callable to be called in the parent before the fork() syscall. - after_in_child: object=NULL - A callable to be called in the child after fork(). - after_in_parent: object=NULL - A callable to be called in the parent after fork(). - -Register callables to be called when forking a new process. - -'before' callbacks are called in reverse order. -'after_in_child' and 'after_in_parent' callbacks are called in order. - -[clinic start generated code]*/ - -static PyObject * -os_register_at_fork_impl(PyObject *module, PyObject *before, - PyObject *after_in_child, PyObject *after_in_parent) -/*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/ -{ - PyInterpreterState *interp; - - if (!before && !after_in_child && !after_in_parent) { - PyErr_SetString(PyExc_TypeError, "At least one argument is required."); - return NULL; - } - if (check_null_or_callable(before, "before") || - check_null_or_callable(after_in_child, "after_in_child") || - check_null_or_callable(after_in_parent, "after_in_parent")) { - return NULL; - } - interp = _PyInterpreterState_GET(); - - if (register_at_forker(&interp->before_forkers, before)) { - return NULL; - } - if (register_at_forker(&interp->after_forkers_child, after_in_child)) { - return NULL; - } - if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) { - return NULL; - } - Py_RETURN_NONE; -} -#endif /* HAVE_FORK */ - - -#ifdef HAVE_FORK1 -/*[clinic input] -os.fork1 - -Fork a child process with a single multiplexed (i.e., not bound) thread. - -Return 0 to child process and PID of child to parent process. -[clinic start generated code]*/ - -static PyObject * -os_fork1_impl(PyObject *module) -/*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/ -{ - pid_t pid; - - if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) { - PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters"); - return NULL; - } - PyOS_BeforeFork(); - pid = fork1(); - if (pid == 0) { - /* child: this clobbers and resets the import lock. */ - PyOS_AfterFork_Child(); - } else { - /* parent: release the import lock. */ - PyOS_AfterFork_Parent(); - } - if (pid == -1) - return posix_error(); - return PyLong_FromPid(pid); -} -#endif /* HAVE_FORK1 */ - - -#ifdef HAVE_FORK -/*[clinic input] -os.fork - -Fork a child process. - -Return 0 to child process and PID of child to parent process. -[clinic start generated code]*/ - -static PyObject * -os_fork_impl(PyObject *module) -/*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/ -{ - pid_t pid; - PyInterpreterState *interp = _PyInterpreterState_GET(); - if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_FORK)) { - PyErr_SetString(PyExc_RuntimeError, - "fork not supported for isolated subinterpreters"); - return NULL; - } - if (PySys_Audit("os.fork", NULL) < 0) { - return NULL; - } - PyOS_BeforeFork(); - pid = fork(); - if (pid == 0) { - /* child: this clobbers and resets the import lock. */ - PyOS_AfterFork_Child(); - } else { - /* parent: release the import lock. */ - PyOS_AfterFork_Parent(); - } - if (pid == -1) - return posix_error(); - return PyLong_FromPid(pid); -} -#endif /* HAVE_FORK */ - - -#ifdef HAVE_SCHED_H -#ifdef HAVE_SCHED_GET_PRIORITY_MAX -/*[clinic input] -os.sched_get_priority_max - - policy: int - -Get the maximum scheduling priority for policy. -[clinic start generated code]*/ - -static PyObject * -os_sched_get_priority_max_impl(PyObject *module, int policy) -/*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/ -{ - int max; - - max = sched_get_priority_max(policy); - if (max < 0) - return posix_error(); - return PyLong_FromLong(max); -} - - -/*[clinic input] -os.sched_get_priority_min - - policy: int - -Get the minimum scheduling priority for policy. -[clinic start generated code]*/ - -static PyObject * -os_sched_get_priority_min_impl(PyObject *module, int policy) -/*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/ -{ - int min = sched_get_priority_min(policy); - if (min < 0) - return posix_error(); - return PyLong_FromLong(min); -} -#endif /* HAVE_SCHED_GET_PRIORITY_MAX */ - - -#ifdef HAVE_SCHED_SETSCHEDULER -/*[clinic input] -os.sched_getscheduler - pid: pid_t - / - -Get the scheduling policy for the process identified by pid. - -Passing 0 for pid returns the scheduling policy for the calling process. -[clinic start generated code]*/ - -static PyObject * -os_sched_getscheduler_impl(PyObject *module, pid_t pid) -/*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/ -{ - int policy; - - policy = sched_getscheduler(pid); - if (policy < 0) - return posix_error(); - return PyLong_FromLong(policy); -} -#endif /* HAVE_SCHED_SETSCHEDULER */ - - -#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) -/*[clinic input] -class os.sched_param "PyObject *" "SchedParamType" - -@classmethod -os.sched_param.__new__ - - sched_priority: object - A scheduling parameter. - -Currently has only one field: sched_priority -[clinic start generated code]*/ - -static PyObject * -os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority) -/*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/ -{ - PyObject *res; - - res = PyStructSequence_New(type); - if (!res) - return NULL; - PyStructSequence_SET_ITEM(res, 0, Py_NewRef(sched_priority)); - return res; -} - -PyDoc_VAR(os_sched_param__doc__); - -static PyStructSequence_Field sched_param_fields[] = { - {"sched_priority", "the scheduling priority"}, - {0} -}; - -static PyStructSequence_Desc sched_param_desc = { - "sched_param", /* name */ - os_sched_param__doc__, /* doc */ - sched_param_fields, - 1 -}; - -static int -convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res) -{ - long priority; - - if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) { - PyErr_SetString(PyExc_TypeError, "must have a sched_param object"); - return 0; - } - priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0)); - if (priority == -1 && PyErr_Occurred()) - return 0; - if (priority > INT_MAX || priority < INT_MIN) { - PyErr_SetString(PyExc_OverflowError, "sched_priority out of range"); - return 0; - } - res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int); - return 1; -} -#endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */ - - -#ifdef HAVE_SCHED_SETSCHEDULER -/*[clinic input] -os.sched_setscheduler - - pid: pid_t - policy: int - param as param_obj: object - / - -Set the scheduling policy for the process identified by pid. - -If pid is 0, the calling process is changed. -param is an instance of sched_param. -[clinic start generated code]*/ - -static PyObject * -os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy, - PyObject *param_obj) -/*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/ -{ - struct sched_param param; - if (!convert_sched_param(module, param_obj, ¶m)) { - return NULL; - } - - /* - ** sched_setscheduler() returns 0 in Linux, but the previous - ** scheduling policy under Solaris/Illumos, and others. - ** On error, -1 is returned in all Operating Systems. - */ - if (sched_setscheduler(pid, policy, ¶m) == -1) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SCHED_SETSCHEDULER*/ - - -#ifdef HAVE_SCHED_SETPARAM -/*[clinic input] -os.sched_getparam - pid: pid_t - / - -Returns scheduling parameters for the process identified by pid. - -If pid is 0, returns parameters for the calling process. -Return value is an instance of sched_param. -[clinic start generated code]*/ - -static PyObject * -os_sched_getparam_impl(PyObject *module, pid_t pid) -/*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/ -{ - struct sched_param param; - PyObject *result; - PyObject *priority; - - if (sched_getparam(pid, ¶m)) - return posix_error(); - PyObject *SchedParamType = get_posix_state(module)->SchedParamType; - result = PyStructSequence_New((PyTypeObject *)SchedParamType); - if (!result) - return NULL; - priority = PyLong_FromLong(param.sched_priority); - if (!priority) { - Py_DECREF(result); - return NULL; - } - PyStructSequence_SET_ITEM(result, 0, priority); - return result; -} - - -/*[clinic input] -os.sched_setparam - pid: pid_t - param as param_obj: object - / - -Set scheduling parameters for the process identified by pid. - -If pid is 0, sets parameters for the calling process. -param should be an instance of sched_param. -[clinic start generated code]*/ - -static PyObject * -os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj) -/*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/ -{ - struct sched_param param; - if (!convert_sched_param(module, param_obj, ¶m)) { - return NULL; - } - - if (sched_setparam(pid, ¶m)) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SCHED_SETPARAM */ - - -#ifdef HAVE_SCHED_RR_GET_INTERVAL -/*[clinic input] -os.sched_rr_get_interval -> double - pid: pid_t - / - -Return the round-robin quantum for the process identified by pid, in seconds. - -Value returned is a float. -[clinic start generated code]*/ - -static double -os_sched_rr_get_interval_impl(PyObject *module, pid_t pid) -/*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/ -{ - struct timespec interval; - if (sched_rr_get_interval(pid, &interval)) { - posix_error(); - return -1.0; - } -#ifdef _Py_MEMORY_SANITIZER - __msan_unpoison(&interval, sizeof(interval)); -#endif - return (double)interval.tv_sec + 1e-9*interval.tv_nsec; -} -#endif /* HAVE_SCHED_RR_GET_INTERVAL */ - - -/*[clinic input] -os.sched_yield - -Voluntarily relinquish the CPU. -[clinic start generated code]*/ - -static PyObject * -os_sched_yield_impl(PyObject *module) -/*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/ -{ - int result; - Py_BEGIN_ALLOW_THREADS - result = sched_yield(); - Py_END_ALLOW_THREADS - if (result < 0) { - return posix_error(); - } - Py_RETURN_NONE; -} - -#ifdef HAVE_SCHED_SETAFFINITY -/* The minimum number of CPUs allocated in a cpu_set_t */ -static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT; - -/*[clinic input] -os.sched_setaffinity - pid: pid_t - mask : object - / - -Set the CPU affinity of the process identified by pid to mask. - -mask should be an iterable of integers identifying CPUs. -[clinic start generated code]*/ - -static PyObject * -os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask) -/*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/ -{ - int ncpus; - size_t setsize; - cpu_set_t *cpu_set = NULL; - PyObject *iterator = NULL, *item; - - iterator = PyObject_GetIter(mask); - if (iterator == NULL) - return NULL; - - ncpus = NCPUS_START; - setsize = CPU_ALLOC_SIZE(ncpus); - cpu_set = CPU_ALLOC(ncpus); - if (cpu_set == NULL) { - PyErr_NoMemory(); - goto error; - } - CPU_ZERO_S(setsize, cpu_set); - - while ((item = PyIter_Next(iterator))) { - long cpu; - if (!PyLong_Check(item)) { - PyErr_Format(PyExc_TypeError, - "expected an iterator of ints, " - "but iterator yielded %R", - Py_TYPE(item)); - Py_DECREF(item); - goto error; - } - cpu = PyLong_AsLong(item); - Py_DECREF(item); - if (cpu < 0) { - if (!PyErr_Occurred()) - PyErr_SetString(PyExc_ValueError, "negative CPU number"); - goto error; - } - if (cpu > INT_MAX - 1) { - PyErr_SetString(PyExc_OverflowError, "CPU number too large"); - goto error; - } - if (cpu >= ncpus) { - /* Grow CPU mask to fit the CPU number */ - int newncpus = ncpus; - cpu_set_t *newmask; - size_t newsetsize; - while (newncpus <= cpu) { - if (newncpus > INT_MAX / 2) - newncpus = cpu + 1; - else - newncpus = newncpus * 2; - } - newmask = CPU_ALLOC(newncpus); - if (newmask == NULL) { - PyErr_NoMemory(); - goto error; - } - newsetsize = CPU_ALLOC_SIZE(newncpus); - CPU_ZERO_S(newsetsize, newmask); - memcpy(newmask, cpu_set, setsize); - CPU_FREE(cpu_set); - setsize = newsetsize; - cpu_set = newmask; - ncpus = newncpus; - } - CPU_SET_S(cpu, setsize, cpu_set); - } - if (PyErr_Occurred()) { - goto error; - } - Py_CLEAR(iterator); - - if (sched_setaffinity(pid, setsize, cpu_set)) { - posix_error(); - goto error; - } - CPU_FREE(cpu_set); - Py_RETURN_NONE; - -error: - if (cpu_set) - CPU_FREE(cpu_set); - Py_XDECREF(iterator); - return NULL; -} - - -/*[clinic input] -os.sched_getaffinity - pid: pid_t - / - -Return the affinity of the process identified by pid (or the current process if zero). - -The affinity is returned as a set of CPU identifiers. -[clinic start generated code]*/ - -static PyObject * -os_sched_getaffinity_impl(PyObject *module, pid_t pid) -/*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/ -{ - int cpu, ncpus, count; - size_t setsize; - cpu_set_t *mask = NULL; - PyObject *res = NULL; - - ncpus = NCPUS_START; - while (1) { - setsize = CPU_ALLOC_SIZE(ncpus); - mask = CPU_ALLOC(ncpus); - if (mask == NULL) - return PyErr_NoMemory(); - if (sched_getaffinity(pid, setsize, mask) == 0) - break; - CPU_FREE(mask); - if (errno != EINVAL) - return posix_error(); - if (ncpus > INT_MAX / 2) { - PyErr_SetString(PyExc_OverflowError, "could not allocate " - "a large enough CPU set"); - return NULL; - } - ncpus = ncpus * 2; - } - - res = PySet_New(NULL); - if (res == NULL) - goto error; - for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) { - if (CPU_ISSET_S(cpu, setsize, mask)) { - PyObject *cpu_num = PyLong_FromLong(cpu); - --count; - if (cpu_num == NULL) - goto error; - if (PySet_Add(res, cpu_num)) { - Py_DECREF(cpu_num); - goto error; - } - Py_DECREF(cpu_num); - } - } - CPU_FREE(mask); - return res; - -error: - if (mask) - CPU_FREE(mask); - Py_XDECREF(res); - return NULL; -} - -#endif /* HAVE_SCHED_SETAFFINITY */ - -#endif /* HAVE_SCHED_H */ - - -/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */ -#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX) -# define DEV_PTY_FILE "/dev/ptc" -# define HAVE_DEV_PTMX -#else -# define DEV_PTY_FILE "/dev/ptmx" -#endif - -#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) -#ifdef HAVE_PTY_H -#include -#ifdef HAVE_UTMP_H -#include -#endif /* HAVE_UTMP_H */ -#elif defined(HAVE_LIBUTIL_H) -#include -#elif defined(HAVE_UTIL_H) -#include -#endif /* HAVE_PTY_H */ -#ifdef HAVE_STROPTS_H -#include -#endif -#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */ - - -#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) -/*[clinic input] -os.openpty - -Open a pseudo-terminal. - -Return a tuple of (master_fd, slave_fd) containing open file descriptors -for both the master and slave ends. -[clinic start generated code]*/ - -static PyObject * -os_openpty_impl(PyObject *module) -/*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/ -{ - int master_fd = -1, slave_fd = -1; -#ifndef HAVE_OPENPTY - char * slave_name; -#endif -#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY) - PyOS_sighandler_t sig_saved; -#if defined(__sun) && defined(__SVR4) - extern char *ptsname(int fildes); -#endif -#endif - -#ifdef HAVE_OPENPTY - if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0) - goto posix_error; - - if (_Py_set_inheritable(master_fd, 0, NULL) < 0) - goto error; - if (_Py_set_inheritable(slave_fd, 0, NULL) < 0) - goto error; - -#elif defined(HAVE__GETPTY) - slave_name = _getpty(&master_fd, O_RDWR, 0666, 0); - if (slave_name == NULL) - goto posix_error; - if (_Py_set_inheritable(master_fd, 0, NULL) < 0) - goto error; - - slave_fd = _Py_open(slave_name, O_RDWR); - if (slave_fd < 0) - goto error; - -#else - master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */ - if (master_fd < 0) - goto posix_error; - - sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL); - - /* change permission of slave */ - if (grantpt(master_fd) < 0) { - PyOS_setsig(SIGCHLD, sig_saved); - goto posix_error; - } - - /* unlock slave */ - if (unlockpt(master_fd) < 0) { - PyOS_setsig(SIGCHLD, sig_saved); - goto posix_error; - } - - PyOS_setsig(SIGCHLD, sig_saved); - - slave_name = ptsname(master_fd); /* get name of slave */ - if (slave_name == NULL) - goto posix_error; - - slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */ - if (slave_fd == -1) - goto error; - - if (_Py_set_inheritable(master_fd, 0, NULL) < 0) - goto posix_error; - -#if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC) - ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */ - ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */ -#ifndef __hpux - ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */ -#endif /* __hpux */ -#endif /* HAVE_CYGWIN */ -#endif /* HAVE_OPENPTY */ - - return Py_BuildValue("(ii)", master_fd, slave_fd); - -posix_error: - posix_error(); -error: - if (master_fd != -1) - close(master_fd); - if (slave_fd != -1) - close(slave_fd); - return NULL; -} -#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */ - - -#if defined(HAVE_SETSID) && defined(TIOCSCTTY) -#define HAVE_FALLBACK_LOGIN_TTY 1 -#endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */ - -#if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) -/*[clinic input] -os.login_tty - - fd: fildes - / - -Prepare the tty of which fd is a file descriptor for a new login session. - -Make the calling process a session leader; make the tty the -controlling tty, the stdin, the stdout, and the stderr of the -calling process; close fd. -[clinic start generated code]*/ - -static PyObject * -os_login_tty_impl(PyObject *module, int fd) -/*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/ -{ -#ifdef HAVE_LOGIN_TTY - if (login_tty(fd) == -1) { - return posix_error(); - } -#else /* defined(HAVE_FALLBACK_LOGIN_TTY) */ - /* Establish a new session. */ - if (setsid() == -1) { - return posix_error(); - } - - /* The tty becomes the controlling terminal. */ - if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) { - return posix_error(); - } - - /* The tty becomes stdin/stdout/stderr */ - if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) { - return posix_error(); - } - if (fd > 2) { - close(fd); - } -#endif /* HAVE_LOGIN_TTY */ - Py_RETURN_NONE; -} -#endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */ - - -#ifdef HAVE_FORKPTY -/*[clinic input] -os.forkpty - -Fork a new process with a new pseudo-terminal as controlling tty. - -Returns a tuple of (pid, master_fd). -Like fork(), return pid of 0 to the child process, -and pid of child to the parent process. -To both, return fd of newly opened pseudo-terminal. -[clinic start generated code]*/ - -static PyObject * -os_forkpty_impl(PyObject *module) -/*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/ -{ - int master_fd = -1; - pid_t pid; - - if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) { - PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters"); - return NULL; - } - if (PySys_Audit("os.forkpty", NULL) < 0) { - return NULL; - } - PyOS_BeforeFork(); - pid = forkpty(&master_fd, NULL, NULL, NULL); - if (pid == 0) { - /* child: this clobbers and resets the import lock. */ - PyOS_AfterFork_Child(); - } else { - /* parent: release the import lock. */ - PyOS_AfterFork_Parent(); - } - if (pid == -1) { - return posix_error(); - } - return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd); -} -#endif /* HAVE_FORKPTY */ - - -#ifdef HAVE_GETEGID -/*[clinic input] -os.getegid - -Return the current process's effective group id. -[clinic start generated code]*/ - -static PyObject * -os_getegid_impl(PyObject *module) -/*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/ -{ - return _PyLong_FromGid(getegid()); -} -#endif /* HAVE_GETEGID */ - - -#ifdef HAVE_GETEUID -/*[clinic input] -os.geteuid - -Return the current process's effective user id. -[clinic start generated code]*/ - -static PyObject * -os_geteuid_impl(PyObject *module) -/*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/ -{ - return _PyLong_FromUid(geteuid()); -} -#endif /* HAVE_GETEUID */ - - -#ifdef HAVE_GETGID -/*[clinic input] -os.getgid - -Return the current process's group id. -[clinic start generated code]*/ - -static PyObject * -os_getgid_impl(PyObject *module) -/*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/ -{ - return _PyLong_FromGid(getgid()); -} -#endif /* HAVE_GETGID */ - - -#ifdef HAVE_GETPID -/*[clinic input] -os.getpid - -Return the current process id. -[clinic start generated code]*/ - -static PyObject * -os_getpid_impl(PyObject *module) -/*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/ -{ - return PyLong_FromPid(getpid()); -} -#endif /* HAVE_GETPID */ - -#ifdef NGROUPS_MAX -#define MAX_GROUPS NGROUPS_MAX -#else - /* defined to be 16 on Solaris7, so this should be a small number */ -#define MAX_GROUPS 64 -#endif - -#ifdef HAVE_GETGROUPLIST - -#ifdef __APPLE__ -/*[clinic input] -os.getgrouplist - - user: str - username to lookup - group as basegid: int - base group id of the user - / - -Returns a list of groups to which a user belongs. -[clinic start generated code]*/ - -static PyObject * -os_getgrouplist_impl(PyObject *module, const char *user, int basegid) -/*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/ -#else -/*[clinic input] -os.getgrouplist - - user: str - username to lookup - group as basegid: gid_t - base group id of the user - / - -Returns a list of groups to which a user belongs. -[clinic start generated code]*/ - -static PyObject * -os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid) -/*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/ -#endif -{ - int i, ngroups; - PyObject *list; -#ifdef __APPLE__ - int *groups; -#else - gid_t *groups; -#endif - - /* - * NGROUPS_MAX is defined by POSIX.1 as the maximum - * number of supplimental groups a users can belong to. - * We have to increment it by one because - * getgrouplist() returns both the supplemental groups - * and the primary group, i.e. all of the groups the - * user belongs to. - */ - ngroups = 1 + MAX_GROUPS; - - while (1) { -#ifdef __APPLE__ - groups = PyMem_New(int, ngroups); -#else - groups = PyMem_New(gid_t, ngroups); -#endif - if (groups == NULL) { - return PyErr_NoMemory(); - } - - int old_ngroups = ngroups; - if (getgrouplist(user, basegid, groups, &ngroups) != -1) { - /* Success */ - break; - } - - /* getgrouplist() fails if the group list is too small */ - PyMem_Free(groups); - - if (ngroups > old_ngroups) { - /* If the group list is too small, the glibc implementation of - getgrouplist() sets ngroups to the total number of groups and - returns -1. */ - } - else { - /* Double the group list size */ - if (ngroups > INT_MAX / 2) { - return PyErr_NoMemory(); - } - ngroups *= 2; - } - - /* Retry getgrouplist() with a larger group list */ - } - -#ifdef _Py_MEMORY_SANITIZER - /* Clang memory sanitizer libc intercepts don't know getgrouplist. */ - __msan_unpoison(&ngroups, sizeof(ngroups)); - __msan_unpoison(groups, ngroups*sizeof(*groups)); -#endif - - list = PyList_New(ngroups); - if (list == NULL) { - PyMem_Free(groups); - return NULL; - } - - for (i = 0; i < ngroups; i++) { -#ifdef __APPLE__ - PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]); -#else - PyObject *o = _PyLong_FromGid(groups[i]); -#endif - if (o == NULL) { - Py_DECREF(list); - PyMem_Free(groups); - return NULL; - } - PyList_SET_ITEM(list, i, o); - } - - PyMem_Free(groups); - - return list; -} -#endif /* HAVE_GETGROUPLIST */ - - -#ifdef HAVE_GETGROUPS -/*[clinic input] -os.getgroups - -Return list of supplemental group IDs for the process. -[clinic start generated code]*/ - -static PyObject * -os_getgroups_impl(PyObject *module) -/*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/ -{ - // Call getgroups with length 0 to get the actual number of groups - int n = getgroups(0, NULL); - if (n < 0) { - return posix_error(); - } - - if (n == 0) { - return PyList_New(0); - } - - gid_t *grouplist = PyMem_New(gid_t, n); - if (grouplist == NULL) { - return PyErr_NoMemory(); - } - - n = getgroups(n, grouplist); - if (n == -1) { - PyMem_Free(grouplist); - return posix_error(); - } - - PyObject *result = PyList_New(n); - if (result == NULL) { - goto error; - } - - for (int i = 0; i < n; ++i) { - PyObject *group = _PyLong_FromGid(grouplist[i]); - if (group == NULL) { - goto error; - } - PyList_SET_ITEM(result, i, group); - } - PyMem_Free(grouplist); - - return result; - -error: - PyMem_Free(grouplist); - Py_XDECREF(result); - return NULL; -} -#endif /* HAVE_GETGROUPS */ - -#ifdef HAVE_INITGROUPS -#ifdef __APPLE__ -/*[clinic input] -os.initgroups - - username as oname: FSConverter - gid: int - / - -Initialize the group access list. - -Call the system initgroups() to initialize the group access list with all of -the groups of which the specified username is a member, plus the specified -group id. -[clinic start generated code]*/ - -static PyObject * -os_initgroups_impl(PyObject *module, PyObject *oname, int gid) -/*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/ -#else -/*[clinic input] -os.initgroups - - username as oname: FSConverter - gid: gid_t - / - -Initialize the group access list. - -Call the system initgroups() to initialize the group access list with all of -the groups of which the specified username is a member, plus the specified -group id. -[clinic start generated code]*/ - -static PyObject * -os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid) -/*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/ -#endif -{ - const char *username = PyBytes_AS_STRING(oname); - - if (initgroups(username, gid) == -1) - return PyErr_SetFromErrno(PyExc_OSError); - - Py_RETURN_NONE; -} -#endif /* HAVE_INITGROUPS */ - - -#ifdef HAVE_GETPGID -/*[clinic input] -os.getpgid - - pid: pid_t - -Call the system call getpgid(), and return the result. -[clinic start generated code]*/ - -static PyObject * -os_getpgid_impl(PyObject *module, pid_t pid) -/*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/ -{ - pid_t pgid = getpgid(pid); - if (pgid < 0) - return posix_error(); - return PyLong_FromPid(pgid); -} -#endif /* HAVE_GETPGID */ - - -#ifdef HAVE_GETPGRP -/*[clinic input] -os.getpgrp - -Return the current process group id. -[clinic start generated code]*/ - -static PyObject * -os_getpgrp_impl(PyObject *module) -/*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/ -{ -#ifdef GETPGRP_HAVE_ARG - return PyLong_FromPid(getpgrp(0)); -#else /* GETPGRP_HAVE_ARG */ - return PyLong_FromPid(getpgrp()); -#endif /* GETPGRP_HAVE_ARG */ -} -#endif /* HAVE_GETPGRP */ - - -#ifdef HAVE_SETPGRP -/*[clinic input] -os.setpgrp - -Make the current process the leader of its process group. -[clinic start generated code]*/ - -static PyObject * -os_setpgrp_impl(PyObject *module) -/*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/ -{ -#ifdef SETPGRP_HAVE_ARG - if (setpgrp(0, 0) < 0) -#else /* SETPGRP_HAVE_ARG */ - if (setpgrp() < 0) -#endif /* SETPGRP_HAVE_ARG */ - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETPGRP */ - -#ifdef HAVE_GETPPID - -#ifdef MS_WINDOWS -#include - -static PyObject* -win32_getppid() -{ - HANDLE snapshot; - pid_t mypid; - PyObject* result = NULL; - BOOL have_record; - PROCESSENTRY32 pe; - - mypid = getpid(); /* This function never fails */ - - snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (snapshot == INVALID_HANDLE_VALUE) - return PyErr_SetFromWindowsErr(GetLastError()); - - pe.dwSize = sizeof(pe); - have_record = Process32First(snapshot, &pe); - while (have_record) { - if (mypid == (pid_t)pe.th32ProcessID) { - /* We could cache the ulong value in a static variable. */ - result = PyLong_FromPid((pid_t)pe.th32ParentProcessID); - break; - } - - have_record = Process32Next(snapshot, &pe); - } - - /* If our loop exits and our pid was not found (result will be NULL) - * then GetLastError will return ERROR_NO_MORE_FILES. This is an - * error anyway, so let's raise it. */ - if (!result) - result = PyErr_SetFromWindowsErr(GetLastError()); - - CloseHandle(snapshot); - - return result; -} -#endif /*MS_WINDOWS*/ - - -/*[clinic input] -os.getppid - -Return the parent's process id. - -If the parent process has already exited, Windows machines will still -return its id; others systems will return the id of the 'init' process (1). -[clinic start generated code]*/ - -static PyObject * -os_getppid_impl(PyObject *module) -/*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/ -{ -#ifdef MS_WINDOWS - return win32_getppid(); -#else - return PyLong_FromPid(getppid()); -#endif -} -#endif /* HAVE_GETPPID */ - - -#ifdef HAVE_GETLOGIN -/*[clinic input] -os.getlogin - -Return the actual login name. -[clinic start generated code]*/ - -static PyObject * -os_getlogin_impl(PyObject *module) -/*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/ -{ - PyObject *result = NULL; -#ifdef MS_WINDOWS - wchar_t user_name[UNLEN + 1]; - DWORD num_chars = Py_ARRAY_LENGTH(user_name); - - if (GetUserNameW(user_name, &num_chars)) { - /* num_chars is the number of unicode chars plus null terminator */ - result = PyUnicode_FromWideChar(user_name, num_chars - 1); - } - else - result = PyErr_SetFromWindowsErr(GetLastError()); -#else - char *name; - int old_errno = errno; - - errno = 0; - name = getlogin(); - if (name == NULL) { - if (errno) - posix_error(); - else - PyErr_SetString(PyExc_OSError, "unable to determine login name"); - } - else - result = PyUnicode_DecodeFSDefault(name); - errno = old_errno; -#endif - return result; -} -#endif /* HAVE_GETLOGIN */ - - -#ifdef HAVE_GETUID -/*[clinic input] -os.getuid - -Return the current process's user id. -[clinic start generated code]*/ - -static PyObject * -os_getuid_impl(PyObject *module) -/*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/ -{ - return _PyLong_FromUid(getuid()); -} -#endif /* HAVE_GETUID */ - - -#ifdef MS_WINDOWS -#define HAVE_KILL -#endif /* MS_WINDOWS */ - -#ifdef HAVE_KILL -/*[clinic input] -os.kill - - pid: pid_t - signal: Py_ssize_t - / - -Kill a process with a signal. -[clinic start generated code]*/ - -static PyObject * -os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal) -/*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/ -{ - if (PySys_Audit("os.kill", "in", pid, signal) < 0) { - return NULL; - } -#ifndef MS_WINDOWS - if (kill(pid, (int)signal) == -1) { - return posix_error(); - } - - // Check immediately if the signal was sent to the current process. - // Don't micro-optimize pid == getpid(), since PyErr_SetString() check - // is cheap. - if (PyErr_CheckSignals()) { - return NULL; - } - - Py_RETURN_NONE; -#else /* !MS_WINDOWS */ - PyObject *result; - DWORD sig = (DWORD)signal; - DWORD err; - HANDLE handle; - - /* Console processes which share a common console can be sent CTRL+C or - CTRL+BREAK events, provided they handle said events. */ - if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) { - if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) { - err = GetLastError(); - PyErr_SetFromWindowsErr(err); - } - else - Py_RETURN_NONE; - } - - /* If the signal is outside of what GenerateConsoleCtrlEvent can use, - attempt to open and terminate the process. */ - handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid); - if (handle == NULL) { - err = GetLastError(); - return PyErr_SetFromWindowsErr(err); - } - - if (TerminateProcess(handle, sig) == 0) { - err = GetLastError(); - result = PyErr_SetFromWindowsErr(err); - } else { - result = Py_NewRef(Py_None); - } - - CloseHandle(handle); - return result; -#endif /* !MS_WINDOWS */ -} -#endif /* HAVE_KILL */ - - -#ifdef HAVE_KILLPG -/*[clinic input] -os.killpg - - pgid: pid_t - signal: int - / - -Kill a process group with a signal. -[clinic start generated code]*/ - -static PyObject * -os_killpg_impl(PyObject *module, pid_t pgid, int signal) -/*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/ -{ - if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) { - return NULL; - } - /* XXX some man pages make the `pgid` parameter an int, others - a pid_t. Since getpgrp() returns a pid_t, we assume killpg should - take the same type. Moreover, pid_t is always at least as wide as - int (else compilation of this module fails), which is safe. */ - if (killpg(pgid, signal) == -1) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_KILLPG */ - - -#ifdef HAVE_PLOCK -#ifdef HAVE_SYS_LOCK_H -#include -#endif - -/*[clinic input] -os.plock - op: int - / - -Lock program segments into memory."); -[clinic start generated code]*/ - -static PyObject * -os_plock_impl(PyObject *module, int op) -/*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/ -{ - if (plock(op) == -1) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_PLOCK */ - - -#ifdef HAVE_SETUID -/*[clinic input] -os.setuid - - uid: uid_t - / - -Set the current process's user id. -[clinic start generated code]*/ - -static PyObject * -os_setuid_impl(PyObject *module, uid_t uid) -/*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/ -{ - if (setuid(uid) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETUID */ - - -#ifdef HAVE_SETEUID -/*[clinic input] -os.seteuid - - euid: uid_t - / - -Set the current process's effective user id. -[clinic start generated code]*/ - -static PyObject * -os_seteuid_impl(PyObject *module, uid_t euid) -/*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/ -{ - if (seteuid(euid) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETEUID */ - - -#ifdef HAVE_SETEGID -/*[clinic input] -os.setegid - - egid: gid_t - / - -Set the current process's effective group id. -[clinic start generated code]*/ - -static PyObject * -os_setegid_impl(PyObject *module, gid_t egid) -/*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/ -{ - if (setegid(egid) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETEGID */ - - -#ifdef HAVE_SETREUID -/*[clinic input] -os.setreuid - - ruid: uid_t - euid: uid_t - / - -Set the current process's real and effective user ids. -[clinic start generated code]*/ - -static PyObject * -os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid) -/*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/ -{ - if (setreuid(ruid, euid) < 0) { - return posix_error(); - } else { - Py_RETURN_NONE; - } -} -#endif /* HAVE_SETREUID */ - - -#ifdef HAVE_SETREGID -/*[clinic input] -os.setregid - - rgid: gid_t - egid: gid_t - / - -Set the current process's real and effective group ids. -[clinic start generated code]*/ - -static PyObject * -os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid) -/*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/ -{ - if (setregid(rgid, egid) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETREGID */ - - -#ifdef HAVE_SETGID -/*[clinic input] -os.setgid - gid: gid_t - / - -Set the current process's group id. -[clinic start generated code]*/ - -static PyObject * -os_setgid_impl(PyObject *module, gid_t gid) -/*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/ -{ - if (setgid(gid) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETGID */ - - -#ifdef HAVE_SETGROUPS -/*[clinic input] -os.setgroups - - groups: object - / - -Set the groups of the current process to list. -[clinic start generated code]*/ - -static PyObject * -os_setgroups(PyObject *module, PyObject *groups) -/*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/ -{ - if (!PySequence_Check(groups)) { - PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence"); - return NULL; - } - Py_ssize_t len = PySequence_Size(groups); - if (len < 0) { - return NULL; - } - if (len > MAX_GROUPS) { - PyErr_SetString(PyExc_ValueError, "too many groups"); - return NULL; - } - - gid_t *grouplist = PyMem_New(gid_t, len); - for (Py_ssize_t i = 0; i < len; i++) { - PyObject *elem; - elem = PySequence_GetItem(groups, i); - if (!elem) { - PyMem_Free(grouplist); - return NULL; - } - if (!PyLong_Check(elem)) { - PyErr_SetString(PyExc_TypeError, - "groups must be integers"); - Py_DECREF(elem); - PyMem_Free(grouplist); - return NULL; - } else { - if (!_Py_Gid_Converter(elem, &grouplist[i])) { - Py_DECREF(elem); - PyMem_Free(grouplist); - return NULL; - } - } - Py_DECREF(elem); - } - - if (setgroups(len, grouplist) < 0) { - PyMem_Free(grouplist); - return posix_error(); - } - PyMem_Free(grouplist); - Py_RETURN_NONE; -} -#endif /* HAVE_SETGROUPS */ - -#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) -static PyObject * -wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru) -{ - PyObject *result; - PyObject *struct_rusage; - - if (pid == -1) - return posix_error(); - - // If wait succeeded but no child was ready to report status, ru will not - // have been populated. - if (pid == 0) { - memset(ru, 0, sizeof(*ru)); - } - - struct_rusage = _PyImport_GetModuleAttrString("resource", "struct_rusage"); - if (struct_rusage == NULL) - return NULL; - - /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */ - result = PyStructSequence_New((PyTypeObject*) struct_rusage); - Py_DECREF(struct_rusage); - if (!result) - return NULL; - -#ifndef doubletime -#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001) -#endif - - PyStructSequence_SET_ITEM(result, 0, - PyFloat_FromDouble(doubletime(ru->ru_utime))); - PyStructSequence_SET_ITEM(result, 1, - PyFloat_FromDouble(doubletime(ru->ru_stime))); -#define SET_INT(result, index, value)\ - PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value)) - SET_INT(result, 2, ru->ru_maxrss); - SET_INT(result, 3, ru->ru_ixrss); - SET_INT(result, 4, ru->ru_idrss); - SET_INT(result, 5, ru->ru_isrss); - SET_INT(result, 6, ru->ru_minflt); - SET_INT(result, 7, ru->ru_majflt); - SET_INT(result, 8, ru->ru_nswap); - SET_INT(result, 9, ru->ru_inblock); - SET_INT(result, 10, ru->ru_oublock); - SET_INT(result, 11, ru->ru_msgsnd); - SET_INT(result, 12, ru->ru_msgrcv); - SET_INT(result, 13, ru->ru_nsignals); - SET_INT(result, 14, ru->ru_nvcsw); - SET_INT(result, 15, ru->ru_nivcsw); -#undef SET_INT - - if (PyErr_Occurred()) { - Py_DECREF(result); - return NULL; - } - - return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result); -} -#endif /* HAVE_WAIT3 || HAVE_WAIT4 */ - - -#ifdef HAVE_WAIT3 -/*[clinic input] -os.wait3 - - options: int -Wait for completion of a child process. - -Returns a tuple of information about the child process: - (pid, status, rusage) -[clinic start generated code]*/ - -static PyObject * -os_wait3_impl(PyObject *module, int options) -/*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/ -{ - pid_t pid; - struct rusage ru; - int async_err = 0; - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; - - do { - Py_BEGIN_ALLOW_THREADS - pid = wait3(&status, options, &ru); - Py_END_ALLOW_THREADS - } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (pid < 0) - return (!async_err) ? posix_error() : NULL; - - return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru); -} -#endif /* HAVE_WAIT3 */ - - -#ifdef HAVE_WAIT4 -/*[clinic input] - -os.wait4 - - pid: pid_t - options: int - -Wait for completion of a specific child process. - -Returns a tuple of information about the child process: - (pid, status, rusage) -[clinic start generated code]*/ - -static PyObject * -os_wait4_impl(PyObject *module, pid_t pid, int options) -/*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/ -{ - pid_t res; - struct rusage ru; - int async_err = 0; - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; - - do { - Py_BEGIN_ALLOW_THREADS - res = wait4(pid, &status, options, &ru); - Py_END_ALLOW_THREADS - } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (res < 0) - return (!async_err) ? posix_error() : NULL; - - return wait_helper(module, res, WAIT_STATUS_INT(status), &ru); -} -#endif /* HAVE_WAIT4 */ - - -#if defined(HAVE_WAITID) && !defined(__APPLE__) -/*[clinic input] -os.waitid - - idtype: idtype_t - Must be one of be P_PID, P_PGID or P_ALL. - id: id_t - The id to wait on. - options: int - Constructed from the ORing of one or more of WEXITED, WSTOPPED - or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT. - / - -Returns the result of waiting for a process or processes. - -Returns either waitid_result or None if WNOHANG is specified and there are -no children in a waitable state. -[clinic start generated code]*/ - -static PyObject * -os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options) -/*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/ -{ - PyObject *result; - int res; - int async_err = 0; - siginfo_t si; - si.si_pid = 0; - - do { - Py_BEGIN_ALLOW_THREADS - res = waitid(idtype, id, &si, options); - Py_END_ALLOW_THREADS - } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (res < 0) - return (!async_err) ? posix_error() : NULL; - - if (si.si_pid == 0) - Py_RETURN_NONE; - - PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType; - result = PyStructSequence_New((PyTypeObject *)WaitidResultType); - if (!result) - return NULL; - - PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid)); - PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid)); - PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo))); - PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status))); - PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code))); - if (PyErr_Occurred()) { - Py_DECREF(result); - return NULL; - } - - return result; -} -#endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */ - - -#if defined(HAVE_WAITPID) -/*[clinic input] -os.waitpid - pid: pid_t - options: int - / - -Wait for completion of a given child process. - -Returns a tuple of information regarding the child process: - (pid, status) - -The options argument is ignored on Windows. -[clinic start generated code]*/ - -static PyObject * -os_waitpid_impl(PyObject *module, pid_t pid, int options) -/*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/ -{ - pid_t res; - int async_err = 0; - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; - - do { - Py_BEGIN_ALLOW_THREADS - res = waitpid(pid, &status, options); - Py_END_ALLOW_THREADS - } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (res < 0) - return (!async_err) ? posix_error() : NULL; - - return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status)); -} -#elif defined(HAVE_CWAIT) -/* MS C has a variant of waitpid() that's usable for most purposes. */ -/*[clinic input] -os.waitpid - pid: intptr_t - options: int - / - -Wait for completion of a given process. - -Returns a tuple of information regarding the process: - (pid, status << 8) - -The options argument is ignored on Windows. -[clinic start generated code]*/ - -static PyObject * -os_waitpid_impl(PyObject *module, intptr_t pid, int options) -/*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/ -{ - int status; - intptr_t res; - int async_err = 0; - - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - res = _cwait(&status, pid, options); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (res < 0) - return (!async_err) ? posix_error() : NULL; - - unsigned long long ustatus = (unsigned int)status; - - /* shift the status left a byte so this is more like the POSIX waitpid */ - return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8); -} -#endif - - -#ifdef HAVE_WAIT -/*[clinic input] -os.wait - -Wait for completion of a child process. - -Returns a tuple of information about the child process: - (pid, status) -[clinic start generated code]*/ - -static PyObject * -os_wait_impl(PyObject *module) -/*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/ -{ - pid_t pid; - int async_err = 0; - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; - - do { - Py_BEGIN_ALLOW_THREADS - pid = wait(&status); - Py_END_ALLOW_THREADS - } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (pid < 0) - return (!async_err) ? posix_error() : NULL; - - return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status)); -} -#endif /* HAVE_WAIT */ - -#if defined(__linux__) && defined(__NR_pidfd_open) -/*[clinic input] -os.pidfd_open - pid: pid_t - flags: unsigned_int = 0 - -Return a file descriptor referring to the process *pid*. - -The descriptor can be used to perform process management without races and -signals. -[clinic start generated code]*/ - -static PyObject * -os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags) -/*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/ -{ - int fd = syscall(__NR_pidfd_open, pid, flags); - if (fd < 0) { - return posix_error(); - } - return PyLong_FromLong(fd); -} -#endif - - -#ifdef HAVE_SETNS -/*[clinic input] -os.setns - fd: fildes - A file descriptor to a namespace. - nstype: int = 0 - Type of namespace. - -Move the calling thread into different namespaces. -[clinic start generated code]*/ - -static PyObject * -os_setns_impl(PyObject *module, int fd, int nstype) -/*[clinic end generated code: output=5dbd055bfb66ecd0 input=42787871226bf3ee]*/ -{ - int res; - - Py_BEGIN_ALLOW_THREADS - res = setns(fd, nstype); - Py_END_ALLOW_THREADS - - if (res != 0) { - return posix_error(); - } - - Py_RETURN_NONE; -} -#endif - - -#ifdef HAVE_UNSHARE -/*[clinic input] -os.unshare - flags: int - Namespaces to be unshared. - -Disassociate parts of a process (or thread) execution context. -[clinic start generated code]*/ - -static PyObject * -os_unshare_impl(PyObject *module, int flags) -/*[clinic end generated code: output=1b3177906dd237ee input=9e065db3232b8b1b]*/ -{ - int res; - - Py_BEGIN_ALLOW_THREADS - res = unshare(flags); - Py_END_ALLOW_THREADS - - if (res != 0) { - return posix_error(); - } - - Py_RETURN_NONE; -} -#endif - - -#if defined(HAVE_READLINK) || defined(MS_WINDOWS) -/*[clinic input] -os.readlink - - path: path_t - * - dir_fd: dir_fd(requires='readlinkat') = None - -Return a string representing the path to which the symbolic link points. - -If dir_fd is not None, it should be a file descriptor open to a directory, -and path should be relative; path will then be relative to that directory. - -dir_fd may not be implemented on your platform. If it is unavailable, -using it will raise a NotImplementedError. -[clinic start generated code]*/ - -static PyObject * -os_readlink_impl(PyObject *module, path_t *path, int dir_fd) -/*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/ -{ -#if defined(HAVE_READLINK) - char buffer[MAXPATHLEN+1]; - ssize_t length; -#ifdef HAVE_READLINKAT - int readlinkat_unavailable = 0; -#endif - - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_READLINKAT - if (dir_fd != DEFAULT_DIR_FD) { - if (HAVE_READLINKAT_RUNTIME) { - length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN); - } else { - readlinkat_unavailable = 1; - } - } else -#endif - length = readlink(path->narrow, buffer, MAXPATHLEN); - Py_END_ALLOW_THREADS - -#ifdef HAVE_READLINKAT - if (readlinkat_unavailable) { - argument_unavailable_error(NULL, "dir_fd"); - return NULL; - } -#endif - - if (length < 0) { - return path_error(path); - } - buffer[length] = '\0'; - - if (PyUnicode_Check(path->object)) - return PyUnicode_DecodeFSDefaultAndSize(buffer, length); - else - return PyBytes_FromStringAndSize(buffer, length); -#elif defined(MS_WINDOWS) - DWORD n_bytes_returned; - DWORD io_result = 0; - HANDLE reparse_point_handle; - char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; - _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer; - PyObject *result = NULL; - - /* First get a handle to the reparse point */ - Py_BEGIN_ALLOW_THREADS - reparse_point_handle = CreateFileW( - path->wide, - 0, - 0, - 0, - OPEN_EXISTING, - FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, - 0); - if (reparse_point_handle != INVALID_HANDLE_VALUE) { - /* New call DeviceIoControl to read the reparse point */ - io_result = DeviceIoControl( - reparse_point_handle, - FSCTL_GET_REPARSE_POINT, - 0, 0, /* in buffer */ - target_buffer, sizeof(target_buffer), - &n_bytes_returned, - 0 /* we're not using OVERLAPPED_IO */ - ); - CloseHandle(reparse_point_handle); - } - Py_END_ALLOW_THREADS - - if (io_result == 0) { - return path_error(path); - } - - wchar_t *name = NULL; - Py_ssize_t nameLen = 0; - if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK) - { - name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer + - rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset); - nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t); - } - else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) - { - name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer + - rdb->MountPointReparseBuffer.SubstituteNameOffset); - nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t); - } - else - { - PyErr_SetString(PyExc_ValueError, "not a symbolic link"); - } - if (name) { - if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) { - /* Our buffer is mutable, so this is okay */ - name[1] = L'\\'; - } - result = PyUnicode_FromWideChar(name, nameLen); - if (result && path->narrow) { - Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); - } - } - return result; -#endif -} -#endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */ - -#if defined(MS_WINDOWS) - -/* Remove the last portion of the path - return 0 on success */ -static int -_dirnameW(WCHAR *path) -{ - WCHAR *ptr; - size_t length = wcsnlen_s(path, MAX_PATH); - if (length == MAX_PATH) { - return -1; - } - - /* walk the path from the end until a backslash is encountered */ - for(ptr = path + length; ptr != path; ptr--) { - if (*ptr == L'\\' || *ptr == L'/') { - break; - } - } - *ptr = 0; - return 0; -} - -#endif - -#ifdef HAVE_SYMLINK - -#if defined(MS_WINDOWS) - -/* Is this path absolute? */ -static int -_is_absW(const WCHAR *path) -{ - return path[0] == L'\\' || path[0] == L'/' || - (path[0] && path[1] == L':'); -} - -/* join root and rest with a backslash - return 0 on success */ -static int -_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest) -{ - if (_is_absW(rest)) { - return wcscpy_s(dest_path, MAX_PATH, rest); - } - - if (wcscpy_s(dest_path, MAX_PATH, root)) { - return -1; - } - - if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) { - return -1; - } - - return wcscat_s(dest_path, MAX_PATH, rest); -} - -/* Return True if the path at src relative to dest is a directory */ -static int -_check_dirW(LPCWSTR src, LPCWSTR dest) -{ - WIN32_FILE_ATTRIBUTE_DATA src_info; - WCHAR dest_parent[MAX_PATH]; - WCHAR src_resolved[MAX_PATH] = L""; - - /* dest_parent = os.path.dirname(dest) */ - if (wcscpy_s(dest_parent, MAX_PATH, dest) || - _dirnameW(dest_parent)) { - return 0; - } - /* src_resolved = os.path.join(dest_parent, src) */ - if (_joinW(src_resolved, dest_parent, src)) { - return 0; - } - return ( - GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info) - && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY - ); -} -#endif - - -/*[clinic input] -os.symlink - src: path_t - dst: path_t - target_is_directory: bool = False - * - dir_fd: dir_fd(requires='symlinkat')=None - -# "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\ - -Create a symbolic link pointing to src named dst. - -target_is_directory is required on Windows if the target is to be - interpreted as a directory. (On Windows, symlink requires - Windows 6.0 or greater, and raises a NotImplementedError otherwise.) - target_is_directory is ignored on non-Windows platforms. - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -dir_fd may not be implemented on your platform. - If it is unavailable, using it will raise a NotImplementedError. - -[clinic start generated code]*/ - -static PyObject * -os_symlink_impl(PyObject *module, path_t *src, path_t *dst, - int target_is_directory, int dir_fd) -/*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/ -{ -#ifdef MS_WINDOWS - DWORD result; - DWORD flags = 0; - - /* Assumed true, set to false if detected to not be available. */ - static int windows_has_symlink_unprivileged_flag = TRUE; -#else - int result; -#ifdef HAVE_SYMLINKAT - int symlinkat_unavailable = 0; -#endif -#endif - - if (PySys_Audit("os.symlink", "OOi", src->object, dst->object, - dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { - return NULL; - } - -#ifdef MS_WINDOWS - - if (windows_has_symlink_unprivileged_flag) { - /* Allow non-admin symlinks if system allows it. */ - flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE; - } - - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - /* if src is a directory, ensure flags==1 (target_is_directory bit) */ - if (target_is_directory || _check_dirW(src->wide, dst->wide)) { - flags |= SYMBOLIC_LINK_FLAG_DIRECTORY; - } - - result = CreateSymbolicLinkW(dst->wide, src->wide, flags); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - - if (windows_has_symlink_unprivileged_flag && !result && - ERROR_INVALID_PARAMETER == GetLastError()) { - - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - /* This error might be caused by - SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported. - Try again, and update windows_has_symlink_unprivileged_flag if we - are successful this time. - - NOTE: There is a risk of a race condition here if there are other - conditions than the flag causing ERROR_INVALID_PARAMETER, and - another process (or thread) changes that condition in between our - calls to CreateSymbolicLink. - */ - flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE); - result = CreateSymbolicLinkW(dst->wide, src->wide, flags); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - - if (result || ERROR_INVALID_PARAMETER != GetLastError()) { - windows_has_symlink_unprivileged_flag = FALSE; - } - } - - if (!result) - return path_error2(src, dst); - -#else - - if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { - PyErr_SetString(PyExc_ValueError, - "symlink: src and dst must be the same type"); - return NULL; - } - - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_SYMLINKAT - if (dir_fd != DEFAULT_DIR_FD) { - if (HAVE_SYMLINKAT_RUNTIME) { - result = symlinkat(src->narrow, dir_fd, dst->narrow); - } else { - symlinkat_unavailable = 1; - } - } else -#endif - result = symlink(src->narrow, dst->narrow); - Py_END_ALLOW_THREADS - -#ifdef HAVE_SYMLINKAT - if (symlinkat_unavailable) { - argument_unavailable_error(NULL, "dir_fd"); - return NULL; - } -#endif - - if (result) - return path_error2(src, dst); -#endif - - Py_RETURN_NONE; -} -#endif /* HAVE_SYMLINK */ - - - - -static PyStructSequence_Field times_result_fields[] = { - {"user", "user time"}, - {"system", "system time"}, - {"children_user", "user time of children"}, - {"children_system", "system time of children"}, - {"elapsed", "elapsed time since an arbitrary point in the past"}, - {NULL} -}; - -PyDoc_STRVAR(times_result__doc__, -"times_result: Result from os.times().\n\n\ -This object may be accessed either as a tuple of\n\ - (user, system, children_user, children_system, elapsed),\n\ -or via the attributes user, system, children_user, children_system,\n\ -and elapsed.\n\ -\n\ -See os.times for more information."); - -static PyStructSequence_Desc times_result_desc = { - "times_result", /* name */ - times_result__doc__, /* doc */ - times_result_fields, - 5 -}; - -#ifdef MS_WINDOWS -#define HAVE_TIMES /* mandatory, for the method table */ -#endif - -#ifdef HAVE_TIMES - -static PyObject * -build_times_result(PyObject *module, double user, double system, - double children_user, double children_system, - double elapsed) -{ - PyObject *TimesResultType = get_posix_state(module)->TimesResultType; - PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType); - if (value == NULL) - return NULL; - -#define SET(i, field) \ - { \ - PyObject *o = PyFloat_FromDouble(field); \ - if (!o) { \ - Py_DECREF(value); \ - return NULL; \ - } \ - PyStructSequence_SET_ITEM(value, i, o); \ - } \ - - SET(0, user); - SET(1, system); - SET(2, children_user); - SET(3, children_system); - SET(4, elapsed); - -#undef SET - - return value; -} - - -#ifndef MS_WINDOWS -#define NEED_TICKS_PER_SECOND -static long ticks_per_second = -1; -#endif /* MS_WINDOWS */ - -/*[clinic input] -os.times - -Return a collection containing process timing information. - -The object returned behaves like a named tuple with these fields: - (utime, stime, cutime, cstime, elapsed_time) -All fields are floating point numbers. -[clinic start generated code]*/ - -static PyObject * -os_times_impl(PyObject *module) -/*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/ -#ifdef MS_WINDOWS -{ - FILETIME create, exit, kernel, user; - HANDLE hProc; - hProc = GetCurrentProcess(); - GetProcessTimes(hProc, &create, &exit, &kernel, &user); - /* The fields of a FILETIME structure are the hi and lo part - of a 64-bit value expressed in 100 nanosecond units. - 1e7 is one second in such units; 1e-7 the inverse. - 429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7. - */ - return build_times_result(module, - (double)(user.dwHighDateTime*429.4967296 + - user.dwLowDateTime*1e-7), - (double)(kernel.dwHighDateTime*429.4967296 + - kernel.dwLowDateTime*1e-7), - (double)0, - (double)0, - (double)0); -} -#else /* MS_WINDOWS */ -{ - - - struct tms t; - clock_t c; - errno = 0; - c = times(&t); - if (c == (clock_t) -1) - return posix_error(); - return build_times_result(module, - (double)t.tms_utime / ticks_per_second, - (double)t.tms_stime / ticks_per_second, - (double)t.tms_cutime / ticks_per_second, - (double)t.tms_cstime / ticks_per_second, - (double)c / ticks_per_second); -} -#endif /* MS_WINDOWS */ -#endif /* HAVE_TIMES */ - - -#ifdef HAVE_GETSID -/*[clinic input] -os.getsid - - pid: pid_t - / - -Call the system call getsid(pid) and return the result. -[clinic start generated code]*/ - -static PyObject * -os_getsid_impl(PyObject *module, pid_t pid) -/*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/ -{ - int sid; - sid = getsid(pid); - if (sid < 0) - return posix_error(); - return PyLong_FromLong((long)sid); -} -#endif /* HAVE_GETSID */ - - -#ifdef HAVE_SETSID -/*[clinic input] -os.setsid - -Call the system call setsid(). -[clinic start generated code]*/ - -static PyObject * -os_setsid_impl(PyObject *module) -/*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/ -{ - if (setsid() < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETSID */ - - -#ifdef HAVE_SETPGID -/*[clinic input] -os.setpgid - - pid: pid_t - pgrp: pid_t - / - -Call the system call setpgid(pid, pgrp). -[clinic start generated code]*/ - -static PyObject * -os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp) -/*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/ -{ - if (setpgid(pid, pgrp) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETPGID */ - - -#ifdef HAVE_TCGETPGRP -/*[clinic input] -os.tcgetpgrp - - fd: int - / - -Return the process group associated with the terminal specified by fd. -[clinic start generated code]*/ - -static PyObject * -os_tcgetpgrp_impl(PyObject *module, int fd) -/*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/ -{ - pid_t pgid = tcgetpgrp(fd); - if (pgid < 0) - return posix_error(); - return PyLong_FromPid(pgid); -} -#endif /* HAVE_TCGETPGRP */ - - -#ifdef HAVE_TCSETPGRP -/*[clinic input] -os.tcsetpgrp - - fd: int - pgid: pid_t - / - -Set the process group associated with the terminal specified by fd. -[clinic start generated code]*/ - -static PyObject * -os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid) -/*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/ -{ - if (tcsetpgrp(fd, pgid) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_TCSETPGRP */ - -/* Functions acting on file descriptors */ - -#ifdef O_CLOEXEC -extern int _Py_open_cloexec_works; -#endif - - -/*[clinic input] -os.open -> int - path: path_t - flags: int - mode: int = 0o777 - * - dir_fd: dir_fd(requires='openat') = None - -# "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\ - -Open a file for low level IO. Returns a file descriptor (integer). - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -dir_fd may not be implemented on your platform. - If it is unavailable, using it will raise a NotImplementedError. -[clinic start generated code]*/ - -static int -os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd) -/*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/ -{ - int fd; - int async_err = 0; -#ifdef HAVE_OPENAT - int openat_unavailable = 0; -#endif - -#ifdef O_CLOEXEC - int *atomic_flag_works = &_Py_open_cloexec_works; -#elif !defined(MS_WINDOWS) - int *atomic_flag_works = NULL; -#endif - -#ifdef MS_WINDOWS - flags |= O_NOINHERIT; -#elif defined(O_CLOEXEC) - flags |= O_CLOEXEC; -#endif - - if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) { - return -1; - } - - _Py_BEGIN_SUPPRESS_IPH - do { - Py_BEGIN_ALLOW_THREADS -#ifdef MS_WINDOWS - fd = _wopen(path->wide, flags, mode); -#else -#ifdef HAVE_OPENAT - if (dir_fd != DEFAULT_DIR_FD) { - if (HAVE_OPENAT_RUNTIME) { - fd = openat(dir_fd, path->narrow, flags, mode); - - } else { - openat_unavailable = 1; - fd = -1; - } - } else -#endif /* HAVE_OPENAT */ - fd = open(path->narrow, flags, mode); -#endif /* !MS_WINDOWS */ - Py_END_ALLOW_THREADS - } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - _Py_END_SUPPRESS_IPH - -#ifdef HAVE_OPENAT - if (openat_unavailable) { - argument_unavailable_error(NULL, "dir_fd"); - return -1; - } -#endif - - if (fd < 0) { - if (!async_err) - PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object); - return -1; - } - -#ifndef MS_WINDOWS - if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) { - close(fd); - return -1; - } -#endif - - return fd; -} - - -/*[clinic input] -os.close - - fd: int - -Close a file descriptor. -[clinic start generated code]*/ - -static PyObject * -os_close_impl(PyObject *module, int fd) -/*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/ -{ - int res; - /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/ - * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html - * for more details. - */ - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - res = close(fd); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - if (res < 0) - return posix_error(); - Py_RETURN_NONE; -} - -/*[clinic input] -os.closerange - - fd_low: int - fd_high: int - / - -Closes all file descriptors in [fd_low, fd_high), ignoring errors. -[clinic start generated code]*/ - -static PyObject * -os_closerange_impl(PyObject *module, int fd_low, int fd_high) -/*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/ -{ - Py_BEGIN_ALLOW_THREADS - _Py_closerange(fd_low, fd_high - 1); - Py_END_ALLOW_THREADS - Py_RETURN_NONE; -} - - -/*[clinic input] -os.dup -> int - - fd: int - / - -Return a duplicate of a file descriptor. -[clinic start generated code]*/ - -static int -os_dup_impl(PyObject *module, int fd) -/*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/ -{ - return _Py_dup(fd); -} - -// dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS(). -// dup2.c provides working dup2() if and only if F_DUPFD is available. -#if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS)) -/*[clinic input] -os.dup2 -> int - fd: int - fd2: int - inheritable: bool=True - -Duplicate file descriptor. -[clinic start generated code]*/ - -static int -os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable) -/*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/ -{ - int res = 0; -#if defined(HAVE_DUP3) && \ - !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)) - /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */ - static int dup3_works = -1; -#endif - - if (fd < 0 || fd2 < 0) { - posix_error(); - return -1; - } - - /* dup2() can fail with EINTR if the target FD is already open, because it - * then has to be closed. See os_close_impl() for why we don't handle EINTR - * upon close(), and therefore below. - */ -#ifdef MS_WINDOWS - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - res = dup2(fd, fd2); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - if (res < 0) { - posix_error(); - return -1; - } - res = fd2; // msvcrt dup2 returns 0 on success. - - /* Character files like console cannot be make non-inheritable */ - if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) { - close(fd2); - return -1; - } - -#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC) - Py_BEGIN_ALLOW_THREADS - if (!inheritable) - res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2); - else - res = dup2(fd, fd2); - Py_END_ALLOW_THREADS - if (res < 0) { - posix_error(); - return -1; - } - -#else - -#ifdef HAVE_DUP3 - if (!inheritable && dup3_works != 0) { - Py_BEGIN_ALLOW_THREADS - res = dup3(fd, fd2, O_CLOEXEC); - Py_END_ALLOW_THREADS - if (res < 0) { - if (dup3_works == -1) - dup3_works = (errno != ENOSYS); - if (dup3_works) { - posix_error(); - return -1; - } - } - } - - if (inheritable || dup3_works == 0) - { -#endif - Py_BEGIN_ALLOW_THREADS - res = dup2(fd, fd2); - Py_END_ALLOW_THREADS - if (res < 0) { - posix_error(); - return -1; - } - - if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) { - close(fd2); - return -1; - } -#ifdef HAVE_DUP3 - } -#endif - -#endif - - return res; -} -#endif - - -#ifdef HAVE_LOCKF -/*[clinic input] -os.lockf - - fd: int - An open file descriptor. - command: int - One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST. - length: Py_off_t - The number of bytes to lock, starting at the current position. - / - -Apply, test or remove a POSIX lock on an open file descriptor. - -[clinic start generated code]*/ - -static PyObject * -os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length) -/*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/ -{ - int res; - - if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) { - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - res = lockf(fd, command, length); - Py_END_ALLOW_THREADS - - if (res < 0) - return posix_error(); - - Py_RETURN_NONE; -} -#endif /* HAVE_LOCKF */ - - -/*[clinic input] -os.lseek -> Py_off_t - - fd: int - position: Py_off_t - how: int - / - -Set the position of a file descriptor. Return the new position. - -Return the new cursor position in number of bytes -relative to the beginning of the file. -[clinic start generated code]*/ - -static Py_off_t -os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how) -/*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/ -{ - Py_off_t result; - -#ifdef SEEK_SET - /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ - switch (how) { - case 0: how = SEEK_SET; break; - case 1: how = SEEK_CUR; break; - case 2: how = SEEK_END; break; - } -#endif /* SEEK_END */ - - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH -#ifdef MS_WINDOWS - result = _lseeki64(fd, position, how); -#else - result = lseek(fd, position, how); -#endif - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - if (result < 0) - posix_error(); - - return result; -} - - -/*[clinic input] -os.read - fd: int - length: Py_ssize_t - / - -Read from a file descriptor. Returns a bytes object. -[clinic start generated code]*/ - -static PyObject * -os_read_impl(PyObject *module, int fd, Py_ssize_t length) -/*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/ -{ - Py_ssize_t n; - PyObject *buffer; - - if (length < 0) { - errno = EINVAL; - return posix_error(); - } - - length = Py_MIN(length, _PY_READ_MAX); - - buffer = PyBytes_FromStringAndSize((char *)NULL, length); - if (buffer == NULL) - return NULL; - - n = _Py_read(fd, PyBytes_AS_STRING(buffer), length); - if (n == -1) { - Py_DECREF(buffer); - return NULL; - } - - if (n != length) - _PyBytes_Resize(&buffer, n); - - return buffer; -} - -#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \ - || defined(__APPLE__))) \ - || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \ - || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2) -static int -iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type) -{ - Py_ssize_t i, j; - - *iov = PyMem_New(struct iovec, cnt); - if (*iov == NULL) { - PyErr_NoMemory(); - return -1; - } - - *buf = PyMem_New(Py_buffer, cnt); - if (*buf == NULL) { - PyMem_Free(*iov); - PyErr_NoMemory(); - return -1; - } - - for (i = 0; i < cnt; i++) { - PyObject *item = PySequence_GetItem(seq, i); - if (item == NULL) - goto fail; - if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) { - Py_DECREF(item); - goto fail; - } - Py_DECREF(item); - (*iov)[i].iov_base = (*buf)[i].buf; - (*iov)[i].iov_len = (*buf)[i].len; - } - return 0; - -fail: - PyMem_Free(*iov); - for (j = 0; j < i; j++) { - PyBuffer_Release(&(*buf)[j]); - } - PyMem_Free(*buf); - return -1; -} - -static void -iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt) -{ - int i; - PyMem_Free(iov); - for (i = 0; i < cnt; i++) { - PyBuffer_Release(&buf[i]); - } - PyMem_Free(buf); -} -#endif - - -#ifdef HAVE_READV -/*[clinic input] -os.readv -> Py_ssize_t - - fd: int - buffers: object - / - -Read from a file descriptor fd into an iterable of buffers. - -The buffers should be mutable buffers accepting bytes. -readv will transfer data into each buffer until it is full -and then move on to the next buffer in the sequence to hold -the rest of the data. - -readv returns the total number of bytes read, -which may be less than the total capacity of all the buffers. -[clinic start generated code]*/ - -static Py_ssize_t -os_readv_impl(PyObject *module, int fd, PyObject *buffers) -/*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/ -{ - Py_ssize_t cnt, n; - int async_err = 0; - struct iovec *iov; - Py_buffer *buf; - - if (!PySequence_Check(buffers)) { - PyErr_SetString(PyExc_TypeError, - "readv() arg 2 must be a sequence"); - return -1; - } - - cnt = PySequence_Size(buffers); - if (cnt < 0) - return -1; - - if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) - return -1; - - do { - Py_BEGIN_ALLOW_THREADS - n = readv(fd, iov, cnt); - Py_END_ALLOW_THREADS - } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - - iov_cleanup(iov, buf, cnt); - if (n < 0) { - if (!async_err) - posix_error(); - return -1; - } - - return n; -} -#endif /* HAVE_READV */ - - -#ifdef HAVE_PREAD -/*[clinic input] -os.pread - - fd: int - length: Py_ssize_t - offset: Py_off_t - / - -Read a number of bytes from a file descriptor starting at a particular offset. - -Read length bytes from file descriptor fd, starting at offset bytes from -the beginning of the file. The file offset remains unchanged. -[clinic start generated code]*/ - -static PyObject * -os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset) -/*[clinic end generated code: output=3f875c1eef82e32f input=85cb4a5589627144]*/ -{ - Py_ssize_t n; - int async_err = 0; - PyObject *buffer; - - if (length < 0) { - errno = EINVAL; - return posix_error(); - } - buffer = PyBytes_FromStringAndSize((char *)NULL, length); - if (buffer == NULL) - return NULL; - - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - n = pread(fd, PyBytes_AS_STRING(buffer), length, offset); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - - if (n < 0) { - Py_DECREF(buffer); - return (!async_err) ? posix_error() : NULL; - } - if (n != length) - _PyBytes_Resize(&buffer, n); - return buffer; -} -#endif /* HAVE_PREAD */ - -#if defined(HAVE_PREADV) || defined (HAVE_PREADV2) -/*[clinic input] -os.preadv -> Py_ssize_t - - fd: int - buffers: object - offset: Py_off_t - flags: int = 0 - / - -Reads from a file descriptor into a number of mutable bytes-like objects. - -Combines the functionality of readv() and pread(). As readv(), it will -transfer data into each buffer until it is full and then move on to the next -buffer in the sequence to hold the rest of the data. Its fourth argument, -specifies the file offset at which the input operation is to be performed. It -will return the total number of bytes read (which can be less than the total -capacity of all the objects). - -The flags argument contains a bitwise OR of zero or more of the following flags: - -- RWF_HIPRI -- RWF_NOWAIT - -Using non-zero flags requires Linux 4.6 or newer. -[clinic start generated code]*/ - -static Py_ssize_t -os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, - int flags) -/*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/ -{ - Py_ssize_t cnt, n; - int async_err = 0; - struct iovec *iov; - Py_buffer *buf; - - if (!PySequence_Check(buffers)) { - PyErr_SetString(PyExc_TypeError, - "preadv2() arg 2 must be a sequence"); - return -1; - } - - cnt = PySequence_Size(buffers); - if (cnt < 0) { - return -1; - } - -#ifndef HAVE_PREADV2 - if(flags != 0) { - argument_unavailable_error("preadv2", "flags"); - return -1; - } -#endif - - if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) { - return -1; - } -#ifdef HAVE_PREADV2 - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - n = preadv2(fd, iov, cnt, offset, flags); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); -#else - do { -#ifdef __APPLE__ -/* This entire function will be removed from the module dict when the API - * is not available. - */ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability" -#pragma clang diagnostic ignored "-Wunguarded-availability-new" -#endif - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - n = preadv(fd, iov, cnt, offset); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - -#ifdef __APPLE__ -#pragma clang diagnostic pop -#endif - -#endif - - iov_cleanup(iov, buf, cnt); - if (n < 0) { - if (!async_err) { - posix_error(); - } - return -1; - } - - return n; -} -#endif /* HAVE_PREADV */ - - -/*[clinic input] -os.write -> Py_ssize_t - - fd: int - data: Py_buffer - / - -Write a bytes object to a file descriptor. -[clinic start generated code]*/ - -static Py_ssize_t -os_write_impl(PyObject *module, int fd, Py_buffer *data) -/*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/ -{ - return _Py_write(fd, data->buf, data->len); -} - -#ifdef HAVE_SENDFILE -#ifdef __APPLE__ -/*[clinic input] -os.sendfile - - out_fd: int - in_fd: int - offset: Py_off_t - count as sbytes: Py_off_t - headers: object(c_default="NULL") = () - trailers: object(c_default="NULL") = () - flags: int = 0 - -Copy count bytes from file descriptor in_fd to file descriptor out_fd. -[clinic start generated code]*/ - -static PyObject * -os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset, - Py_off_t sbytes, PyObject *headers, PyObject *trailers, - int flags) -/*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/ -#elif defined(__FreeBSD__) || defined(__DragonFly__) -/*[clinic input] -os.sendfile - - out_fd: int - in_fd: int - offset: Py_off_t - count: Py_ssize_t - headers: object(c_default="NULL") = () - trailers: object(c_default="NULL") = () - flags: int = 0 - -Copy count bytes from file descriptor in_fd to file descriptor out_fd. -[clinic start generated code]*/ - -static PyObject * -os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset, - Py_ssize_t count, PyObject *headers, PyObject *trailers, - int flags) -/*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/ -#else -/*[clinic input] -os.sendfile - - out_fd: int - in_fd: int - offset as offobj: object - count: Py_ssize_t - -Copy count bytes from file descriptor in_fd to file descriptor out_fd. -[clinic start generated code]*/ - -static PyObject * -os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj, - Py_ssize_t count) -/*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/ -#endif -{ - Py_ssize_t ret; - int async_err = 0; - -#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) -#ifndef __APPLE__ - off_t sbytes; -#endif - Py_buffer *hbuf, *tbuf; - struct sf_hdtr sf; - - sf.headers = NULL; - sf.trailers = NULL; - - if (headers != NULL) { - if (!PySequence_Check(headers)) { - PyErr_SetString(PyExc_TypeError, - "sendfile() headers must be a sequence"); - return NULL; - } else { - Py_ssize_t i = PySequence_Size(headers); - if (i < 0) - return NULL; - if (i > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "sendfile() header is too large"); - return NULL; - } - if (i > 0) { - sf.hdr_cnt = (int)i; - if (iov_setup(&(sf.headers), &hbuf, - headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0) - return NULL; -#ifdef __APPLE__ - for (i = 0; i < sf.hdr_cnt; i++) { - Py_ssize_t blen = sf.headers[i].iov_len; -# define OFF_T_MAX 0x7fffffffffffffff - if (sbytes >= OFF_T_MAX - blen) { - PyErr_SetString(PyExc_OverflowError, - "sendfile() header is too large"); - return NULL; - } - sbytes += blen; - } -#endif - } - } - } - if (trailers != NULL) { - if (!PySequence_Check(trailers)) { - PyErr_SetString(PyExc_TypeError, - "sendfile() trailers must be a sequence"); - return NULL; - } else { - Py_ssize_t i = PySequence_Size(trailers); - if (i < 0) - return NULL; - if (i > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "sendfile() trailer is too large"); - return NULL; - } - if (i > 0) { - sf.trl_cnt = (int)i; - if (iov_setup(&(sf.trailers), &tbuf, - trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0) - return NULL; - } - } - } - - _Py_BEGIN_SUPPRESS_IPH - do { - Py_BEGIN_ALLOW_THREADS -#ifdef __APPLE__ - ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags); -#else - ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags); -#endif - Py_END_ALLOW_THREADS - } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - _Py_END_SUPPRESS_IPH - - if (sf.headers != NULL) - iov_cleanup(sf.headers, hbuf, sf.hdr_cnt); - if (sf.trailers != NULL) - iov_cleanup(sf.trailers, tbuf, sf.trl_cnt); - - if (ret < 0) { - if ((errno == EAGAIN) || (errno == EBUSY)) { - if (sbytes != 0) { - // some data has been sent - goto done; - } - else { - // no data has been sent; upper application is supposed - // to retry on EAGAIN or EBUSY - return posix_error(); - } - } - return (!async_err) ? posix_error() : NULL; - } - goto done; - -done: - #if !defined(HAVE_LARGEFILE_SUPPORT) - return Py_BuildValue("l", sbytes); - #else - return Py_BuildValue("L", sbytes); - #endif - -#else -#ifdef __linux__ - if (offobj == Py_None) { - do { - Py_BEGIN_ALLOW_THREADS - ret = sendfile(out_fd, in_fd, NULL, count); - Py_END_ALLOW_THREADS - } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (ret < 0) - return (!async_err) ? posix_error() : NULL; - return Py_BuildValue("n", ret); - } -#endif - off_t offset; - if (!Py_off_t_converter(offobj, &offset)) - return NULL; - -#if defined(__sun) && defined(__SVR4) - // On Solaris, sendfile raises EINVAL rather than returning 0 - // when the offset is equal or bigger than the in_fd size. - struct stat st; - - do { - Py_BEGIN_ALLOW_THREADS - ret = fstat(in_fd, &st); - Py_END_ALLOW_THREADS - } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (ret < 0) - return (!async_err) ? posix_error() : NULL; - - if (offset >= st.st_size) { - return Py_BuildValue("i", 0); - } - - // On illumos specifically sendfile() may perform a partial write but - // return -1/an error (in one confirmed case the destination socket - // had a 5 second timeout set and errno was EAGAIN) and it's on the client - // code to check if the offset parameter was modified by sendfile(). - // - // We need this variable to track said change. - off_t original_offset = offset; -#endif - - do { - Py_BEGIN_ALLOW_THREADS - ret = sendfile(out_fd, in_fd, &offset, count); -#if defined(__sun) && defined(__SVR4) - // This handles illumos-specific sendfile() partial write behavior, - // see a comment above for more details. - if (ret < 0 && offset != original_offset) { - ret = offset - original_offset; - } -#endif - Py_END_ALLOW_THREADS - } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (ret < 0) - return (!async_err) ? posix_error() : NULL; - return Py_BuildValue("n", ret); -#endif -} -#endif /* HAVE_SENDFILE */ - - -#if defined(__APPLE__) -/*[clinic input] -os._fcopyfile - - in_fd: int - out_fd: int - flags: int - / - -Efficiently copy content or metadata of 2 regular file descriptors (macOS). -[clinic start generated code]*/ - -static PyObject * -os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags) -/*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/ -{ - int ret; - - Py_BEGIN_ALLOW_THREADS - ret = fcopyfile(in_fd, out_fd, NULL, flags); - Py_END_ALLOW_THREADS - if (ret < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif - - -/*[clinic input] -os.fstat - - fd : int - -Perform a stat system call on the given file descriptor. - -Like stat(), but for an open file descriptor. -Equivalent to os.stat(fd). -[clinic start generated code]*/ - -static PyObject * -os_fstat_impl(PyObject *module, int fd) -/*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/ -{ - STRUCT_STAT st; - int res; - int async_err = 0; - - do { - Py_BEGIN_ALLOW_THREADS - res = FSTAT(fd, &st); - Py_END_ALLOW_THREADS - } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (res != 0) { -#ifdef MS_WINDOWS - return PyErr_SetFromWindowsErr(0); -#else - return (!async_err) ? posix_error() : NULL; -#endif - } - - return _pystat_fromstructstat(module, &st); -} - - -/*[clinic input] -os.isatty -> bool - fd: int - / - -Return True if the fd is connected to a terminal. - -Return True if the file descriptor is an open file descriptor -connected to the slave end of a terminal. -[clinic start generated code]*/ - -static int -os_isatty_impl(PyObject *module, int fd) -/*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/ -{ - int return_value; - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - return_value = isatty(fd); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - return return_value; -} - - -#ifdef HAVE_PIPE -/*[clinic input] -os.pipe - -Create a pipe. - -Returns a tuple of two file descriptors: - (read_fd, write_fd) -[clinic start generated code]*/ - -static PyObject * -os_pipe_impl(PyObject *module) -/*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/ -{ - int fds[2]; -#ifdef MS_WINDOWS - HANDLE read, write; - SECURITY_ATTRIBUTES attr; - BOOL ok; -#else - int res; -#endif - -#ifdef MS_WINDOWS - attr.nLength = sizeof(attr); - attr.lpSecurityDescriptor = NULL; - attr.bInheritHandle = FALSE; - - Py_BEGIN_ALLOW_THREADS - ok = CreatePipe(&read, &write, &attr, 0); - if (ok) { - fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY); - fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY); - if (fds[0] == -1 || fds[1] == -1) { - CloseHandle(read); - CloseHandle(write); - ok = 0; - } - } - Py_END_ALLOW_THREADS - - if (!ok) - return PyErr_SetFromWindowsErr(0); -#else - -#ifdef HAVE_PIPE2 - Py_BEGIN_ALLOW_THREADS - res = pipe2(fds, O_CLOEXEC); - Py_END_ALLOW_THREADS - - if (res != 0 && errno == ENOSYS) - { -#endif - Py_BEGIN_ALLOW_THREADS - res = pipe(fds); - Py_END_ALLOW_THREADS - - if (res == 0) { - if (_Py_set_inheritable(fds[0], 0, NULL) < 0) { - close(fds[0]); - close(fds[1]); - return NULL; - } - if (_Py_set_inheritable(fds[1], 0, NULL) < 0) { - close(fds[0]); - close(fds[1]); - return NULL; - } - } -#ifdef HAVE_PIPE2 - } -#endif - - if (res != 0) - return PyErr_SetFromErrno(PyExc_OSError); -#endif /* !MS_WINDOWS */ - return Py_BuildValue("(ii)", fds[0], fds[1]); -} -#endif /* HAVE_PIPE */ - - -#ifdef HAVE_PIPE2 -/*[clinic input] -os.pipe2 - - flags: int - / - -Create a pipe with flags set atomically. - -Returns a tuple of two file descriptors: - (read_fd, write_fd) - -flags can be constructed by ORing together one or more of these values: -O_NONBLOCK, O_CLOEXEC. -[clinic start generated code]*/ - -static PyObject * -os_pipe2_impl(PyObject *module, int flags) -/*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/ -{ - int fds[2]; - int res; - - res = pipe2(fds, flags); - if (res != 0) - return posix_error(); - return Py_BuildValue("(ii)", fds[0], fds[1]); -} -#endif /* HAVE_PIPE2 */ - - -#ifdef HAVE_WRITEV -/*[clinic input] -os.writev -> Py_ssize_t - fd: int - buffers: object - / - -Iterate over buffers, and write the contents of each to a file descriptor. - -Returns the total number of bytes written. -buffers must be a sequence of bytes-like objects. -[clinic start generated code]*/ - -static Py_ssize_t -os_writev_impl(PyObject *module, int fd, PyObject *buffers) -/*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/ -{ - Py_ssize_t cnt; - Py_ssize_t result; - int async_err = 0; - struct iovec *iov; - Py_buffer *buf; - - if (!PySequence_Check(buffers)) { - PyErr_SetString(PyExc_TypeError, - "writev() arg 2 must be a sequence"); - return -1; - } - cnt = PySequence_Size(buffers); - if (cnt < 0) - return -1; - - if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { - return -1; - } - - do { - Py_BEGIN_ALLOW_THREADS - result = writev(fd, iov, cnt); - Py_END_ALLOW_THREADS - } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - - iov_cleanup(iov, buf, cnt); - if (result < 0 && !async_err) - posix_error(); - - return result; -} -#endif /* HAVE_WRITEV */ - - -#ifdef HAVE_PWRITE -/*[clinic input] -os.pwrite -> Py_ssize_t - - fd: int - buffer: Py_buffer - offset: Py_off_t - / - -Write bytes to a file descriptor starting at a particular offset. - -Write buffer to fd, starting at offset bytes from the beginning of -the file. Returns the number of bytes writte. Does not change the -current file offset. -[clinic start generated code]*/ - -static Py_ssize_t -os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset) -/*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/ -{ - Py_ssize_t size; - int async_err = 0; - - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - - if (size < 0 && !async_err) - posix_error(); - return size; -} -#endif /* HAVE_PWRITE */ - -#if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2) -/*[clinic input] -os.pwritev -> Py_ssize_t - - fd: int - buffers: object - offset: Py_off_t - flags: int = 0 - / - -Writes the contents of bytes-like objects to a file descriptor at a given offset. - -Combines the functionality of writev() and pwrite(). All buffers must be a sequence -of bytes-like objects. Buffers are processed in array order. Entire contents of first -buffer is written before proceeding to second, and so on. The operating system may -set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used. -This function writes the contents of each object to the file descriptor and returns -the total number of bytes written. - -The flags argument contains a bitwise OR of zero or more of the following flags: - -- RWF_DSYNC -- RWF_SYNC -- RWF_APPEND - -Using non-zero flags requires Linux 4.7 or newer. -[clinic start generated code]*/ - -static Py_ssize_t -os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, - int flags) -/*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/ -{ - Py_ssize_t cnt; - Py_ssize_t result; - int async_err = 0; - struct iovec *iov; - Py_buffer *buf; - - if (!PySequence_Check(buffers)) { - PyErr_SetString(PyExc_TypeError, - "pwritev() arg 2 must be a sequence"); - return -1; - } - - cnt = PySequence_Size(buffers); - if (cnt < 0) { - return -1; - } - -#ifndef HAVE_PWRITEV2 - if(flags != 0) { - argument_unavailable_error("pwritev2", "flags"); - return -1; - } -#endif - - if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { - return -1; - } -#ifdef HAVE_PWRITEV2 - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - result = pwritev2(fd, iov, cnt, offset, flags); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); -#else - -#ifdef __APPLE__ -/* This entire function will be removed from the module dict when the API - * is not available. - */ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability" -#pragma clang diagnostic ignored "-Wunguarded-availability-new" -#endif - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - result = pwritev(fd, iov, cnt, offset); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - -#ifdef __APPLE__ -#pragma clang diagnostic pop -#endif - -#endif - - iov_cleanup(iov, buf, cnt); - if (result < 0) { - if (!async_err) { - posix_error(); - } - return -1; - } - - return result; -} -#endif /* HAVE_PWRITEV */ - -#ifdef HAVE_COPY_FILE_RANGE -/*[clinic input] - -os.copy_file_range - src: int - Source file descriptor. - dst: int - Destination file descriptor. - count: Py_ssize_t - Number of bytes to copy. - offset_src: object = None - Starting offset in src. - offset_dst: object = None - Starting offset in dst. - -Copy count bytes from one file descriptor to another. - -If offset_src is None, then src is read from the current position; -respectively for offset_dst. -[clinic start generated code]*/ - -static PyObject * -os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count, - PyObject *offset_src, PyObject *offset_dst) -/*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/ -{ - off_t offset_src_val, offset_dst_val; - off_t *p_offset_src = NULL; - off_t *p_offset_dst = NULL; - Py_ssize_t ret; - int async_err = 0; - /* The flags argument is provided to allow - * for future extensions and currently must be to 0. */ - int flags = 0; - - - if (count < 0) { - PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed"); - return NULL; - } - - if (offset_src != Py_None) { - if (!Py_off_t_converter(offset_src, &offset_src_val)) { - return NULL; - } - p_offset_src = &offset_src_val; - } - - if (offset_dst != Py_None) { - if (!Py_off_t_converter(offset_dst, &offset_dst_val)) { - return NULL; - } - p_offset_dst = &offset_dst_val; - } - - do { - Py_BEGIN_ALLOW_THREADS - ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags); - Py_END_ALLOW_THREADS - } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - - if (ret < 0) { - return (!async_err) ? posix_error() : NULL; - } - - return PyLong_FromSsize_t(ret); -} -#endif /* HAVE_COPY_FILE_RANGE*/ - -#if (defined(HAVE_SPLICE) && !defined(_AIX)) -/*[clinic input] - -os.splice - src: int - Source file descriptor. - dst: int - Destination file descriptor. - count: Py_ssize_t - Number of bytes to copy. - offset_src: object = None - Starting offset in src. - offset_dst: object = None - Starting offset in dst. - flags: unsigned_int = 0 - Flags to modify the semantics of the call. - -Transfer count bytes from one pipe to a descriptor or vice versa. - -If offset_src is None, then src is read from the current position; -respectively for offset_dst. The offset associated to the file -descriptor that refers to a pipe must be None. -[clinic start generated code]*/ - -static PyObject * -os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count, - PyObject *offset_src, PyObject *offset_dst, - unsigned int flags) -/*[clinic end generated code: output=d0386f25a8519dc5 input=047527c66c6d2e0a]*/ -{ - off_t offset_src_val, offset_dst_val; - off_t *p_offset_src = NULL; - off_t *p_offset_dst = NULL; - Py_ssize_t ret; - int async_err = 0; - - if (count < 0) { - PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed"); - return NULL; - } - - if (offset_src != Py_None) { - if (!Py_off_t_converter(offset_src, &offset_src_val)) { - return NULL; - } - p_offset_src = &offset_src_val; - } - - if (offset_dst != Py_None) { - if (!Py_off_t_converter(offset_dst, &offset_dst_val)) { - return NULL; - } - p_offset_dst = &offset_dst_val; - } - - do { - Py_BEGIN_ALLOW_THREADS - ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags); - Py_END_ALLOW_THREADS - } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - - if (ret < 0) { - return (!async_err) ? posix_error() : NULL; - } - - return PyLong_FromSsize_t(ret); -} -#endif /* HAVE_SPLICE*/ - -#ifdef HAVE_MKFIFO -/*[clinic input] -os.mkfifo - - path: path_t - mode: int=0o666 - * - dir_fd: dir_fd(requires='mkfifoat')=None - -Create a "fifo" (a POSIX named pipe). - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -dir_fd may not be implemented on your platform. - If it is unavailable, using it will raise a NotImplementedError. -[clinic start generated code]*/ - -static PyObject * -os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd) -/*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/ -{ - int result; - int async_err = 0; -#ifdef HAVE_MKFIFOAT - int mkfifoat_unavailable = 0; -#endif - - do { - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_MKFIFOAT - if (dir_fd != DEFAULT_DIR_FD) { - if (HAVE_MKFIFOAT_RUNTIME) { - result = mkfifoat(dir_fd, path->narrow, mode); - - } else { - mkfifoat_unavailable = 1; - result = 0; - } - } else -#endif - result = mkfifo(path->narrow, mode); - Py_END_ALLOW_THREADS - } while (result != 0 && errno == EINTR && - !(async_err = PyErr_CheckSignals())); - -#ifdef HAVE_MKFIFOAT - if (mkfifoat_unavailable) { - argument_unavailable_error(NULL, "dir_fd"); - return NULL; - } -#endif - - if (result != 0) - return (!async_err) ? posix_error() : NULL; - - Py_RETURN_NONE; -} -#endif /* HAVE_MKFIFO */ - - -#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) -/*[clinic input] -os.mknod - - path: path_t - mode: int=0o600 - device: dev_t=0 - * - dir_fd: dir_fd(requires='mknodat')=None - -Create a node in the file system. - -Create a node in the file system (file, device special file or named pipe) -at path. mode specifies both the permissions to use and the -type of node to be created, being combined (bitwise OR) with one of -S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode, -device defines the newly created device special file (probably using -os.makedev()). Otherwise device is ignored. - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -dir_fd may not be implemented on your platform. - If it is unavailable, using it will raise a NotImplementedError. -[clinic start generated code]*/ - -static PyObject * -os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device, - int dir_fd) -/*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/ -{ - int result; - int async_err = 0; -#ifdef HAVE_MKNODAT - int mknodat_unavailable = 0; -#endif - - do { - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_MKNODAT - if (dir_fd != DEFAULT_DIR_FD) { - if (HAVE_MKNODAT_RUNTIME) { - result = mknodat(dir_fd, path->narrow, mode, device); - - } else { - mknodat_unavailable = 1; - result = 0; - } - } else -#endif - result = mknod(path->narrow, mode, device); - Py_END_ALLOW_THREADS - } while (result != 0 && errno == EINTR && - !(async_err = PyErr_CheckSignals())); -#ifdef HAVE_MKNODAT - if (mknodat_unavailable) { - argument_unavailable_error(NULL, "dir_fd"); - return NULL; - } -#endif - if (result != 0) - return (!async_err) ? posix_error() : NULL; - - Py_RETURN_NONE; -} -#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */ - - -#ifdef HAVE_DEVICE_MACROS -/*[clinic input] -os.major -> unsigned_int - - device: dev_t - / - -Extracts a device major number from a raw device number. -[clinic start generated code]*/ - -static unsigned int -os_major_impl(PyObject *module, dev_t device) -/*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/ -{ - return major(device); -} - - -/*[clinic input] -os.minor -> unsigned_int - - device: dev_t - / - -Extracts a device minor number from a raw device number. -[clinic start generated code]*/ - -static unsigned int -os_minor_impl(PyObject *module, dev_t device) -/*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/ -{ - return minor(device); -} - - -/*[clinic input] -os.makedev -> dev_t - - major: int - minor: int - / - -Composes a raw device number from the major and minor device numbers. -[clinic start generated code]*/ - -static dev_t -os_makedev_impl(PyObject *module, int major, int minor) -/*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/ -{ - return makedev(major, minor); -} -#endif /* HAVE_DEVICE_MACROS */ - - -#if defined HAVE_FTRUNCATE || defined MS_WINDOWS -/*[clinic input] -os.ftruncate - - fd: int - length: Py_off_t - / - -Truncate a file, specified by file descriptor, to a specific length. -[clinic start generated code]*/ - -static PyObject * -os_ftruncate_impl(PyObject *module, int fd, Py_off_t length) -/*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/ -{ - int result; - int async_err = 0; - - if (PySys_Audit("os.truncate", "in", fd, length) < 0) { - return NULL; - } - - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH -#ifdef MS_WINDOWS - result = _chsize_s(fd, length); -#else - result = ftruncate(fd, length); -#endif - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (result != 0 && errno == EINTR && - !(async_err = PyErr_CheckSignals())); - if (result != 0) - return (!async_err) ? posix_error() : NULL; - Py_RETURN_NONE; -} -#endif /* HAVE_FTRUNCATE || MS_WINDOWS */ - - -#if defined HAVE_TRUNCATE || defined MS_WINDOWS -/*[clinic input] -os.truncate - path: path_t(allow_fd='PATH_HAVE_FTRUNCATE') - length: Py_off_t - -Truncate a file, specified by path, to a specific length. - -On some platforms, path may also be specified as an open file descriptor. - If this functionality is unavailable, using it raises an exception. -[clinic start generated code]*/ - -static PyObject * -os_truncate_impl(PyObject *module, path_t *path, Py_off_t length) -/*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/ -{ - int result; -#ifdef MS_WINDOWS - int fd; -#endif - - if (path->fd != -1) - return os_ftruncate_impl(module, path->fd, length); - - if (PySys_Audit("os.truncate", "On", path->object, length) < 0) { - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH -#ifdef MS_WINDOWS - fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT); - if (fd < 0) - result = -1; - else { - result = _chsize_s(fd, length); - close(fd); - if (result < 0) - errno = result; - } -#else - result = truncate(path->narrow, length); -#endif - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - if (result < 0) - return posix_path_error(path); - - Py_RETURN_NONE; -} -#endif /* HAVE_TRUNCATE || MS_WINDOWS */ - - -/* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise() - and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is - defined, which is the case in Python on AIX. AIX bug report: - http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */ -#if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__) -# define POSIX_FADVISE_AIX_BUG -#endif - - -#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) -/*[clinic input] -os.posix_fallocate - - fd: int - offset: Py_off_t - length: Py_off_t - / - -Ensure a file has allocated at least a particular number of bytes on disk. - -Ensure that the file specified by fd encompasses a range of bytes -starting at offset bytes from the beginning and continuing for length bytes. -[clinic start generated code]*/ - -static PyObject * -os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset, - Py_off_t length) -/*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/ -{ - int result; - int async_err = 0; - - do { - Py_BEGIN_ALLOW_THREADS - result = posix_fallocate(fd, offset, length); - Py_END_ALLOW_THREADS - } while (result == EINTR && !(async_err = PyErr_CheckSignals())); - - if (result == 0) - Py_RETURN_NONE; - - if (async_err) - return NULL; - - errno = result; - return posix_error(); -} -#endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */ - - -#if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG) -/*[clinic input] -os.posix_fadvise - - fd: int - offset: Py_off_t - length: Py_off_t - advice: int - / - -Announce an intention to access data in a specific pattern. - -Announce an intention to access data in a specific pattern, thus allowing -the kernel to make optimizations. -The advice applies to the region of the file specified by fd starting at -offset and continuing for length bytes. -advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL, -POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or -POSIX_FADV_DONTNEED. -[clinic start generated code]*/ - -static PyObject * -os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset, - Py_off_t length, int advice) -/*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/ -{ - int result; - int async_err = 0; - - do { - Py_BEGIN_ALLOW_THREADS - result = posix_fadvise(fd, offset, length, advice); - Py_END_ALLOW_THREADS - } while (result == EINTR && !(async_err = PyErr_CheckSignals())); - - if (result == 0) - Py_RETURN_NONE; - - if (async_err) - return NULL; - - errno = result; - return posix_error(); -} -#endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */ - - -#ifdef MS_WINDOWS -static PyObject* -win32_putenv(PyObject *name, PyObject *value) -{ - /* Search from index 1 because on Windows starting '=' is allowed for - defining hidden environment variables. */ - if (PyUnicode_GET_LENGTH(name) == 0 || - PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1) - { - PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); - return NULL; - } - PyObject *unicode; - if (value != NULL) { - unicode = PyUnicode_FromFormat("%U=%U", name, value); - } - else { - unicode = PyUnicode_FromFormat("%U=", name); - } - if (unicode == NULL) { - return NULL; - } - - Py_ssize_t size; - /* PyUnicode_AsWideCharString() rejects embedded null characters */ - wchar_t *env = PyUnicode_AsWideCharString(unicode, &size); - Py_DECREF(unicode); - - if (env == NULL) { - return NULL; - } - if (size > _MAX_ENV) { - PyErr_Format(PyExc_ValueError, - "the environment variable is longer than %u characters", - _MAX_ENV); - PyMem_Free(env); - return NULL; - } - - /* _wputenv() and SetEnvironmentVariableW() update the environment in the - Process Environment Block (PEB). _wputenv() also updates CRT 'environ' - and '_wenviron' variables, whereas SetEnvironmentVariableW() does not. - - Prefer _wputenv() to be compatible with C libraries using CRT - variables and CRT functions using these variables (ex: getenv()). */ - int err = _wputenv(env); - PyMem_Free(env); - - if (err) { - posix_error(); - return NULL; - } - - Py_RETURN_NONE; -} -#endif - - -#ifdef MS_WINDOWS -/*[clinic input] -os.putenv - - name: unicode - value: unicode - / - -Change or add an environment variable. -[clinic start generated code]*/ - -static PyObject * -os_putenv_impl(PyObject *module, PyObject *name, PyObject *value) -/*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/ -{ - if (PySys_Audit("os.putenv", "OO", name, value) < 0) { - return NULL; - } - return win32_putenv(name, value); -} -#else -/*[clinic input] -os.putenv - - name: FSConverter - value: FSConverter - / - -Change or add an environment variable. -[clinic start generated code]*/ - -static PyObject * -os_putenv_impl(PyObject *module, PyObject *name, PyObject *value) -/*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/ -{ - const char *name_string = PyBytes_AS_STRING(name); - const char *value_string = PyBytes_AS_STRING(value); - - if (strchr(name_string, '=') != NULL) { - PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); - return NULL; - } - - if (PySys_Audit("os.putenv", "OO", name, value) < 0) { - return NULL; - } - - if (setenv(name_string, value_string, 1)) { - return posix_error(); - } - Py_RETURN_NONE; -} -#endif /* !defined(MS_WINDOWS) */ - - -#ifdef MS_WINDOWS -/*[clinic input] -os.unsetenv - name: unicode - / - -Delete an environment variable. -[clinic start generated code]*/ - -static PyObject * -os_unsetenv_impl(PyObject *module, PyObject *name) -/*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/ -{ - if (PySys_Audit("os.unsetenv", "(O)", name) < 0) { - return NULL; - } - return win32_putenv(name, NULL); -} -#else -/*[clinic input] -os.unsetenv - name: FSConverter - / - -Delete an environment variable. -[clinic start generated code]*/ - -static PyObject * -os_unsetenv_impl(PyObject *module, PyObject *name) -/*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/ -{ - if (PySys_Audit("os.unsetenv", "(O)", name) < 0) { - return NULL; - } -#ifdef HAVE_BROKEN_UNSETENV - unsetenv(PyBytes_AS_STRING(name)); -#else - int err = unsetenv(PyBytes_AS_STRING(name)); - if (err) { - return posix_error(); - } -#endif - - Py_RETURN_NONE; -} -#endif /* !MS_WINDOWS */ - - -/*[clinic input] -os.strerror - - code: int - / - -Translate an error code to a message string. -[clinic start generated code]*/ - -static PyObject * -os_strerror_impl(PyObject *module, int code) -/*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/ -{ - char *message = strerror(code); - if (message == NULL) { - PyErr_SetString(PyExc_ValueError, - "strerror() argument out of range"); - return NULL; - } - return PyUnicode_DecodeLocale(message, "surrogateescape"); -} - - -#ifdef HAVE_SYS_WAIT_H -#ifdef WCOREDUMP -/*[clinic input] -os.WCOREDUMP -> bool - - status: int - / - -Return True if the process returning status was dumped to a core file. -[clinic start generated code]*/ - -static int -os_WCOREDUMP_impl(PyObject *module, int status) -/*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/ -{ - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - return WCOREDUMP(wait_status); -} -#endif /* WCOREDUMP */ - - -#ifdef WIFCONTINUED -/*[clinic input] -os.WIFCONTINUED -> bool - - status: int - -Return True if a particular process was continued from a job control stop. - -Return True if the process returning status was continued from a -job control stop. -[clinic start generated code]*/ - -static int -os_WIFCONTINUED_impl(PyObject *module, int status) -/*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/ -{ - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - return WIFCONTINUED(wait_status); -} -#endif /* WIFCONTINUED */ - - -#ifdef WIFSTOPPED -/*[clinic input] -os.WIFSTOPPED -> bool - - status: int - -Return True if the process returning status was stopped. -[clinic start generated code]*/ - -static int -os_WIFSTOPPED_impl(PyObject *module, int status) -/*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/ -{ - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - return WIFSTOPPED(wait_status); -} -#endif /* WIFSTOPPED */ - - -#ifdef WIFSIGNALED -/*[clinic input] -os.WIFSIGNALED -> bool - - status: int - -Return True if the process returning status was terminated by a signal. -[clinic start generated code]*/ - -static int -os_WIFSIGNALED_impl(PyObject *module, int status) -/*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/ -{ - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - return WIFSIGNALED(wait_status); -} -#endif /* WIFSIGNALED */ - - -#ifdef WIFEXITED -/*[clinic input] -os.WIFEXITED -> bool - - status: int - -Return True if the process returning status exited via the exit() system call. -[clinic start generated code]*/ - -static int -os_WIFEXITED_impl(PyObject *module, int status) -/*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/ -{ - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - return WIFEXITED(wait_status); -} -#endif /* WIFEXITED */ - - -#ifdef WEXITSTATUS -/*[clinic input] -os.WEXITSTATUS -> int - - status: int - -Return the process return code from status. -[clinic start generated code]*/ - -static int -os_WEXITSTATUS_impl(PyObject *module, int status) -/*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/ -{ - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - return WEXITSTATUS(wait_status); -} -#endif /* WEXITSTATUS */ - - -#ifdef WTERMSIG -/*[clinic input] -os.WTERMSIG -> int - - status: int - -Return the signal that terminated the process that provided the status value. -[clinic start generated code]*/ - -static int -os_WTERMSIG_impl(PyObject *module, int status) -/*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/ -{ - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - return WTERMSIG(wait_status); -} -#endif /* WTERMSIG */ - - -#ifdef WSTOPSIG -/*[clinic input] -os.WSTOPSIG -> int - - status: int - -Return the signal that stopped the process that provided the status value. -[clinic start generated code]*/ - -static int -os_WSTOPSIG_impl(PyObject *module, int status) -/*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/ -{ - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - return WSTOPSIG(wait_status); -} -#endif /* WSTOPSIG */ -#endif /* HAVE_SYS_WAIT_H */ - - -#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) -#ifdef _SCO_DS -/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the - needed definitions in sys/statvfs.h */ -#define _SVID3 -#endif -#include - -static PyObject* -_pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) { - PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType; - PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType); - if (v == NULL) - return NULL; - -#if !defined(HAVE_LARGEFILE_SUPPORT) - PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize)); - PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize)); - PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks)); - PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree)); - PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail)); - PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files)); - PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree)); - PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail)); - PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag)); - PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax)); -#else - PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize)); - PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize)); - PyStructSequence_SET_ITEM(v, 2, - PyLong_FromLongLong((long long) st.f_blocks)); - PyStructSequence_SET_ITEM(v, 3, - PyLong_FromLongLong((long long) st.f_bfree)); - PyStructSequence_SET_ITEM(v, 4, - PyLong_FromLongLong((long long) st.f_bavail)); - PyStructSequence_SET_ITEM(v, 5, - PyLong_FromLongLong((long long) st.f_files)); - PyStructSequence_SET_ITEM(v, 6, - PyLong_FromLongLong((long long) st.f_ffree)); - PyStructSequence_SET_ITEM(v, 7, - PyLong_FromLongLong((long long) st.f_favail)); - PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag)); - PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax)); -#endif -/* The _ALL_SOURCE feature test macro defines f_fsid as a structure - * (issue #32390). */ -#if defined(_AIX) && defined(_ALL_SOURCE) - PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0])); -#else - PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid)); -#endif - if (PyErr_Occurred()) { - Py_DECREF(v); - return NULL; - } - - return v; -} - - -/*[clinic input] -os.fstatvfs - fd: int - / - -Perform an fstatvfs system call on the given fd. - -Equivalent to statvfs(fd). -[clinic start generated code]*/ - -static PyObject * -os_fstatvfs_impl(PyObject *module, int fd) -/*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/ -{ - int result; - int async_err = 0; - struct statvfs st; - - do { - Py_BEGIN_ALLOW_THREADS - result = fstatvfs(fd, &st); - Py_END_ALLOW_THREADS - } while (result != 0 && errno == EINTR && - !(async_err = PyErr_CheckSignals())); - if (result != 0) - return (!async_err) ? posix_error() : NULL; - - return _pystatvfs_fromstructstatvfs(module, st); -} -#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */ - - -#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) -#include -/*[clinic input] -os.statvfs - - path: path_t(allow_fd='PATH_HAVE_FSTATVFS') - -Perform a statvfs system call on the given path. - -path may always be specified as a string. -On some platforms, path may also be specified as an open file descriptor. - If this functionality is unavailable, using it raises an exception. -[clinic start generated code]*/ - -static PyObject * -os_statvfs_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/ -{ - int result; - struct statvfs st; - - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_FSTATVFS - if (path->fd != -1) { - result = fstatvfs(path->fd, &st); - } - else -#endif - result = statvfs(path->narrow, &st); - Py_END_ALLOW_THREADS - - if (result) { - return path_error(path); - } - - return _pystatvfs_fromstructstatvfs(module, st); -} -#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */ - - -#ifdef MS_WINDOWS -/*[clinic input] -os._getdiskusage - - path: path_t - -Return disk usage statistics about the given path as a (total, free) tuple. -[clinic start generated code]*/ - -static PyObject * -os__getdiskusage_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/ -{ - BOOL retval; - ULARGE_INTEGER _, total, free; - DWORD err = 0; - - Py_BEGIN_ALLOW_THREADS - retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free); - Py_END_ALLOW_THREADS - if (retval == 0) { - if (GetLastError() == ERROR_DIRECTORY) { - wchar_t *dir_path = NULL; - - dir_path = PyMem_New(wchar_t, path->length + 1); - if (dir_path == NULL) { - return PyErr_NoMemory(); - } - - wcscpy_s(dir_path, path->length + 1, path->wide); - - if (_dirnameW(dir_path) != -1) { - Py_BEGIN_ALLOW_THREADS - retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free); - Py_END_ALLOW_THREADS - } - /* Record the last error in case it's modified by PyMem_Free. */ - err = GetLastError(); - PyMem_Free(dir_path); - if (retval) { - goto success; - } - } - return PyErr_SetFromWindowsErr(err); - } - -success: - return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart); -} -#endif /* MS_WINDOWS */ - - -/* This is used for fpathconf(), pathconf(), confstr() and sysconf(). - * It maps strings representing configuration variable names to - * integer values, allowing those functions to be called with the - * magic names instead of polluting the module's namespace with tons of - * rarely-used constants. There are three separate tables that use - * these definitions. - * - * This code is always included, even if none of the interfaces that - * need it are included. The #if hackery needed to avoid it would be - * sufficiently pervasive that it's not worth the loss of readability. - */ -struct constdef { - const char *name; - int value; -}; - -static int -conv_confname(PyObject *arg, int *valuep, struct constdef *table, - size_t tablesize) -{ - if (PyLong_Check(arg)) { - int value = _PyLong_AsInt(arg); - if (value == -1 && PyErr_Occurred()) - return 0; - *valuep = value; - return 1; - } - else { - /* look up the value in the table using a binary search */ - size_t lo = 0; - size_t mid; - size_t hi = tablesize; - int cmp; - const char *confname; - if (!PyUnicode_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "configuration names must be strings or integers"); - return 0; - } - confname = PyUnicode_AsUTF8(arg); - if (confname == NULL) - return 0; - while (lo < hi) { - mid = (lo + hi) / 2; - cmp = strcmp(confname, table[mid].name); - if (cmp < 0) - hi = mid; - else if (cmp > 0) - lo = mid + 1; - else { - *valuep = table[mid].value; - return 1; - } - } - PyErr_SetString(PyExc_ValueError, "unrecognized configuration name"); - return 0; - } -} - - -#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF) -static struct constdef posix_constants_pathconf[] = { -#ifdef _PC_ABI_AIO_XFER_MAX - {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX}, -#endif -#ifdef _PC_ABI_ASYNC_IO - {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO}, -#endif -#ifdef _PC_ASYNC_IO - {"PC_ASYNC_IO", _PC_ASYNC_IO}, -#endif -#ifdef _PC_CHOWN_RESTRICTED - {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED}, -#endif -#ifdef _PC_FILESIZEBITS - {"PC_FILESIZEBITS", _PC_FILESIZEBITS}, -#endif -#ifdef _PC_LAST - {"PC_LAST", _PC_LAST}, -#endif -#ifdef _PC_LINK_MAX - {"PC_LINK_MAX", _PC_LINK_MAX}, -#endif -#ifdef _PC_MAX_CANON - {"PC_MAX_CANON", _PC_MAX_CANON}, -#endif -#ifdef _PC_MAX_INPUT - {"PC_MAX_INPUT", _PC_MAX_INPUT}, -#endif -#ifdef _PC_NAME_MAX - {"PC_NAME_MAX", _PC_NAME_MAX}, -#endif -#ifdef _PC_NO_TRUNC - {"PC_NO_TRUNC", _PC_NO_TRUNC}, -#endif -#ifdef _PC_PATH_MAX - {"PC_PATH_MAX", _PC_PATH_MAX}, -#endif -#ifdef _PC_PIPE_BUF - {"PC_PIPE_BUF", _PC_PIPE_BUF}, -#endif -#ifdef _PC_PRIO_IO - {"PC_PRIO_IO", _PC_PRIO_IO}, -#endif -#ifdef _PC_SOCK_MAXBUF - {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF}, -#endif -#ifdef _PC_SYNC_IO - {"PC_SYNC_IO", _PC_SYNC_IO}, -#endif -#ifdef _PC_VDISABLE - {"PC_VDISABLE", _PC_VDISABLE}, -#endif -#ifdef _PC_ACL_ENABLED - {"PC_ACL_ENABLED", _PC_ACL_ENABLED}, -#endif -#ifdef _PC_MIN_HOLE_SIZE - {"PC_MIN_HOLE_SIZE", _PC_MIN_HOLE_SIZE}, -#endif -#ifdef _PC_ALLOC_SIZE_MIN - {"PC_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN}, -#endif -#ifdef _PC_REC_INCR_XFER_SIZE - {"PC_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE}, -#endif -#ifdef _PC_REC_MAX_XFER_SIZE - {"PC_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE}, -#endif -#ifdef _PC_REC_MIN_XFER_SIZE - {"PC_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE}, -#endif -#ifdef _PC_REC_XFER_ALIGN - {"PC_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN}, -#endif -#ifdef _PC_SYMLINK_MAX - {"PC_SYMLINK_MAX", _PC_SYMLINK_MAX}, -#endif -#ifdef _PC_XATTR_ENABLED - {"PC_XATTR_ENABLED", _PC_XATTR_ENABLED}, -#endif -#ifdef _PC_XATTR_EXISTS - {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS}, -#endif -#ifdef _PC_TIMESTAMP_RESOLUTION - {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION}, -#endif -}; - -static int -conv_path_confname(PyObject *arg, int *valuep) -{ - return conv_confname(arg, valuep, posix_constants_pathconf, - sizeof(posix_constants_pathconf) - / sizeof(struct constdef)); -} -#endif - - -#ifdef HAVE_FPATHCONF -/*[clinic input] -os.fpathconf -> long - - fd: fildes - name: path_confname - / - -Return the configuration limit name for the file descriptor fd. - -If there is no limit, return -1. -[clinic start generated code]*/ - -static long -os_fpathconf_impl(PyObject *module, int fd, int name) -/*[clinic end generated code: output=d5b7042425fc3e21 input=5b8d2471cfaae186]*/ -{ - long limit; - - errno = 0; - limit = fpathconf(fd, name); - if (limit == -1 && errno != 0) - posix_error(); - - return limit; -} -#endif /* HAVE_FPATHCONF */ - - -#ifdef HAVE_PATHCONF -/*[clinic input] -os.pathconf -> long - path: path_t(allow_fd='PATH_HAVE_FPATHCONF') - name: path_confname - -Return the configuration limit name for the file or directory path. - -If there is no limit, return -1. -On some platforms, path may also be specified as an open file descriptor. - If this functionality is unavailable, using it raises an exception. -[clinic start generated code]*/ - -static long -os_pathconf_impl(PyObject *module, path_t *path, int name) -/*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/ -{ - long limit; - - errno = 0; -#ifdef HAVE_FPATHCONF - if (path->fd != -1) - limit = fpathconf(path->fd, name); - else -#endif - limit = pathconf(path->narrow, name); - if (limit == -1 && errno != 0) { - if (errno == EINVAL) - /* could be a path or name problem */ - posix_error(); - else - path_error(path); - } - - return limit; -} -#endif /* HAVE_PATHCONF */ - -#ifdef HAVE_CONFSTR -static struct constdef posix_constants_confstr[] = { -#ifdef _CS_ARCHITECTURE - {"CS_ARCHITECTURE", _CS_ARCHITECTURE}, -#endif -#ifdef _CS_GNU_LIBC_VERSION - {"CS_GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION}, -#endif -#ifdef _CS_GNU_LIBPTHREAD_VERSION - {"CS_GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION}, -#endif -#ifdef _CS_HOSTNAME - {"CS_HOSTNAME", _CS_HOSTNAME}, -#endif -#ifdef _CS_HW_PROVIDER - {"CS_HW_PROVIDER", _CS_HW_PROVIDER}, -#endif -#ifdef _CS_HW_SERIAL - {"CS_HW_SERIAL", _CS_HW_SERIAL}, -#endif -#ifdef _CS_INITTAB_NAME - {"CS_INITTAB_NAME", _CS_INITTAB_NAME}, -#endif -#ifdef _CS_LFS64_CFLAGS - {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS}, -#endif -#ifdef _CS_LFS64_LDFLAGS - {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS}, -#endif -#ifdef _CS_LFS64_LIBS - {"CS_LFS64_LIBS", _CS_LFS64_LIBS}, -#endif -#ifdef _CS_LFS64_LINTFLAGS - {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS}, -#endif -#ifdef _CS_LFS_CFLAGS - {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS}, -#endif -#ifdef _CS_LFS_LDFLAGS - {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS}, -#endif -#ifdef _CS_LFS_LIBS - {"CS_LFS_LIBS", _CS_LFS_LIBS}, -#endif -#ifdef _CS_LFS_LINTFLAGS - {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS}, -#endif -#ifdef _CS_MACHINE - {"CS_MACHINE", _CS_MACHINE}, -#endif -#ifdef _CS_PATH - {"CS_PATH", _CS_PATH}, -#endif -#ifdef _CS_RELEASE - {"CS_RELEASE", _CS_RELEASE}, -#endif -#ifdef _CS_SRPC_DOMAIN - {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN}, -#endif -#ifdef _CS_SYSNAME - {"CS_SYSNAME", _CS_SYSNAME}, -#endif -#ifdef _CS_VERSION - {"CS_VERSION", _CS_VERSION}, -#endif -#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS - {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS}, -#endif -#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS - {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS}, -#endif -#ifdef _CS_XBS5_ILP32_OFF32_LIBS - {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS}, -#endif -#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS - {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS}, -#endif -#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS - {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS}, -#endif -#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS - {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS}, -#endif -#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS - {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS}, -#endif -#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS - {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS}, -#endif -#ifdef _CS_XBS5_LP64_OFF64_CFLAGS - {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS}, -#endif -#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS - {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS}, -#endif -#ifdef _CS_XBS5_LP64_OFF64_LIBS - {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS}, -#endif -#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS - {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS}, -#endif -#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS - {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS}, -#endif -#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS - {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS}, -#endif -#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS - {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS}, -#endif -#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS - {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS}, -#endif -#ifdef _MIPS_CS_AVAIL_PROCESSORS - {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS}, -#endif -#ifdef _MIPS_CS_BASE - {"MIPS_CS_BASE", _MIPS_CS_BASE}, -#endif -#ifdef _MIPS_CS_HOSTID - {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID}, -#endif -#ifdef _MIPS_CS_HW_NAME - {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME}, -#endif -#ifdef _MIPS_CS_NUM_PROCESSORS - {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS}, -#endif -#ifdef _MIPS_CS_OSREL_MAJ - {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ}, -#endif -#ifdef _MIPS_CS_OSREL_MIN - {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN}, -#endif -#ifdef _MIPS_CS_OSREL_PATCH - {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH}, -#endif -#ifdef _MIPS_CS_OS_NAME - {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME}, -#endif -#ifdef _MIPS_CS_OS_PROVIDER - {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER}, -#endif -#ifdef _MIPS_CS_PROCESSORS - {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS}, -#endif -#ifdef _MIPS_CS_SERIAL - {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL}, -#endif -#ifdef _MIPS_CS_VENDOR - {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR}, -#endif -}; - -static int -conv_confstr_confname(PyObject *arg, int *valuep) -{ - return conv_confname(arg, valuep, posix_constants_confstr, - sizeof(posix_constants_confstr) - / sizeof(struct constdef)); -} - - -/*[clinic input] -os.confstr - - name: confstr_confname - / - -Return a string-valued system configuration variable. -[clinic start generated code]*/ - -static PyObject * -os_confstr_impl(PyObject *module, int name) -/*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/ -{ - PyObject *result = NULL; - char buffer[255]; - size_t len; - - errno = 0; - len = confstr(name, buffer, sizeof(buffer)); - if (len == 0) { - if (errno) { - posix_error(); - return NULL; - } - else { - Py_RETURN_NONE; - } - } - - if (len >= sizeof(buffer)) { - size_t len2; - char *buf = PyMem_Malloc(len); - if (buf == NULL) - return PyErr_NoMemory(); - len2 = confstr(name, buf, len); - assert(len == len2); - result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1); - PyMem_Free(buf); - } - else - result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1); - return result; -} -#endif /* HAVE_CONFSTR */ - - -#ifdef HAVE_SYSCONF -static struct constdef posix_constants_sysconf[] = { -#ifdef _SC_2_CHAR_TERM - {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM}, -#endif -#ifdef _SC_2_C_BIND - {"SC_2_C_BIND", _SC_2_C_BIND}, -#endif -#ifdef _SC_2_C_DEV - {"SC_2_C_DEV", _SC_2_C_DEV}, -#endif -#ifdef _SC_2_C_VERSION - {"SC_2_C_VERSION", _SC_2_C_VERSION}, -#endif -#ifdef _SC_2_FORT_DEV - {"SC_2_FORT_DEV", _SC_2_FORT_DEV}, -#endif -#ifdef _SC_2_FORT_RUN - {"SC_2_FORT_RUN", _SC_2_FORT_RUN}, -#endif -#ifdef _SC_2_LOCALEDEF - {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF}, -#endif -#ifdef _SC_2_SW_DEV - {"SC_2_SW_DEV", _SC_2_SW_DEV}, -#endif -#ifdef _SC_2_UPE - {"SC_2_UPE", _SC_2_UPE}, -#endif -#ifdef _SC_2_VERSION - {"SC_2_VERSION", _SC_2_VERSION}, -#endif -#ifdef _SC_ABI_ASYNCHRONOUS_IO - {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO}, -#endif -#ifdef _SC_ACL - {"SC_ACL", _SC_ACL}, -#endif -#ifdef _SC_AIO_LISTIO_MAX - {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX}, -#endif -#ifdef _SC_AIO_MAX - {"SC_AIO_MAX", _SC_AIO_MAX}, -#endif -#ifdef _SC_AIO_PRIO_DELTA_MAX - {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX}, -#endif -#ifdef _SC_ARG_MAX - {"SC_ARG_MAX", _SC_ARG_MAX}, -#endif -#ifdef _SC_ASYNCHRONOUS_IO - {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO}, -#endif -#ifdef _SC_ATEXIT_MAX - {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX}, -#endif -#ifdef _SC_AUDIT - {"SC_AUDIT", _SC_AUDIT}, -#endif -#ifdef _SC_AVPHYS_PAGES - {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES}, -#endif -#ifdef _SC_BC_BASE_MAX - {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX}, -#endif -#ifdef _SC_BC_DIM_MAX - {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX}, -#endif -#ifdef _SC_BC_SCALE_MAX - {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX}, -#endif -#ifdef _SC_BC_STRING_MAX - {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX}, -#endif -#ifdef _SC_CAP - {"SC_CAP", _SC_CAP}, -#endif -#ifdef _SC_CHARCLASS_NAME_MAX - {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX}, -#endif -#ifdef _SC_CHAR_BIT - {"SC_CHAR_BIT", _SC_CHAR_BIT}, -#endif -#ifdef _SC_CHAR_MAX - {"SC_CHAR_MAX", _SC_CHAR_MAX}, -#endif -#ifdef _SC_CHAR_MIN - {"SC_CHAR_MIN", _SC_CHAR_MIN}, -#endif -#ifdef _SC_CHILD_MAX - {"SC_CHILD_MAX", _SC_CHILD_MAX}, -#endif -#ifdef _SC_CLK_TCK - {"SC_CLK_TCK", _SC_CLK_TCK}, -#endif -#ifdef _SC_COHER_BLKSZ - {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ}, -#endif -#ifdef _SC_COLL_WEIGHTS_MAX - {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX}, -#endif -#ifdef _SC_DCACHE_ASSOC - {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC}, -#endif -#ifdef _SC_DCACHE_BLKSZ - {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ}, -#endif -#ifdef _SC_DCACHE_LINESZ - {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ}, -#endif -#ifdef _SC_DCACHE_SZ - {"SC_DCACHE_SZ", _SC_DCACHE_SZ}, -#endif -#ifdef _SC_DCACHE_TBLKSZ - {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ}, -#endif -#ifdef _SC_DELAYTIMER_MAX - {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX}, -#endif -#ifdef _SC_EQUIV_CLASS_MAX - {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX}, -#endif -#ifdef _SC_EXPR_NEST_MAX - {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX}, -#endif -#ifdef _SC_FSYNC - {"SC_FSYNC", _SC_FSYNC}, -#endif -#ifdef _SC_GETGR_R_SIZE_MAX - {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX}, -#endif -#ifdef _SC_GETPW_R_SIZE_MAX - {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX}, -#endif -#ifdef _SC_ICACHE_ASSOC - {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC}, -#endif -#ifdef _SC_ICACHE_BLKSZ - {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ}, -#endif -#ifdef _SC_ICACHE_LINESZ - {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ}, -#endif -#ifdef _SC_ICACHE_SZ - {"SC_ICACHE_SZ", _SC_ICACHE_SZ}, -#endif -#ifdef _SC_INF - {"SC_INF", _SC_INF}, -#endif -#ifdef _SC_INT_MAX - {"SC_INT_MAX", _SC_INT_MAX}, -#endif -#ifdef _SC_INT_MIN - {"SC_INT_MIN", _SC_INT_MIN}, -#endif -#ifdef _SC_IOV_MAX - {"SC_IOV_MAX", _SC_IOV_MAX}, -#endif -#ifdef _SC_IP_SECOPTS - {"SC_IP_SECOPTS", _SC_IP_SECOPTS}, -#endif -#ifdef _SC_JOB_CONTROL - {"SC_JOB_CONTROL", _SC_JOB_CONTROL}, -#endif -#ifdef _SC_KERN_POINTERS - {"SC_KERN_POINTERS", _SC_KERN_POINTERS}, -#endif -#ifdef _SC_KERN_SIM - {"SC_KERN_SIM", _SC_KERN_SIM}, -#endif -#ifdef _SC_LINE_MAX - {"SC_LINE_MAX", _SC_LINE_MAX}, -#endif -#ifdef _SC_LOGIN_NAME_MAX - {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX}, -#endif -#ifdef _SC_LOGNAME_MAX - {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX}, -#endif -#ifdef _SC_LONG_BIT - {"SC_LONG_BIT", _SC_LONG_BIT}, -#endif -#ifdef _SC_MAC - {"SC_MAC", _SC_MAC}, -#endif -#ifdef _SC_MAPPED_FILES - {"SC_MAPPED_FILES", _SC_MAPPED_FILES}, -#endif -#ifdef _SC_MAXPID - {"SC_MAXPID", _SC_MAXPID}, -#endif -#ifdef _SC_MB_LEN_MAX - {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX}, -#endif -#ifdef _SC_MEMLOCK - {"SC_MEMLOCK", _SC_MEMLOCK}, -#endif -#ifdef _SC_MEMLOCK_RANGE - {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE}, -#endif -#ifdef _SC_MEMORY_PROTECTION - {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION}, -#endif -#ifdef _SC_MESSAGE_PASSING - {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING}, -#endif -#ifdef _SC_MMAP_FIXED_ALIGNMENT - {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT}, -#endif -#ifdef _SC_MQ_OPEN_MAX - {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX}, -#endif -#ifdef _SC_MQ_PRIO_MAX - {"SC_MQ_PRIO_MAX", _SC_MQ_PRIO_MAX}, -#endif -#ifdef _SC_NACLS_MAX - {"SC_NACLS_MAX", _SC_NACLS_MAX}, -#endif -#ifdef _SC_NGROUPS_MAX - {"SC_NGROUPS_MAX", _SC_NGROUPS_MAX}, -#endif -#ifdef _SC_NL_ARGMAX - {"SC_NL_ARGMAX", _SC_NL_ARGMAX}, -#endif -#ifdef _SC_NL_LANGMAX - {"SC_NL_LANGMAX", _SC_NL_LANGMAX}, -#endif -#ifdef _SC_NL_MSGMAX - {"SC_NL_MSGMAX", _SC_NL_MSGMAX}, -#endif -#ifdef _SC_NL_NMAX - {"SC_NL_NMAX", _SC_NL_NMAX}, -#endif -#ifdef _SC_NL_SETMAX - {"SC_NL_SETMAX", _SC_NL_SETMAX}, -#endif -#ifdef _SC_NL_TEXTMAX - {"SC_NL_TEXTMAX", _SC_NL_TEXTMAX}, -#endif -#ifdef _SC_NPROCESSORS_CONF - {"SC_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF}, -#endif -#ifdef _SC_NPROCESSORS_ONLN - {"SC_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN}, -#endif -#ifdef _SC_NPROC_CONF - {"SC_NPROC_CONF", _SC_NPROC_CONF}, -#endif -#ifdef _SC_NPROC_ONLN - {"SC_NPROC_ONLN", _SC_NPROC_ONLN}, -#endif -#ifdef _SC_NZERO - {"SC_NZERO", _SC_NZERO}, -#endif -#ifdef _SC_OPEN_MAX - {"SC_OPEN_MAX", _SC_OPEN_MAX}, -#endif -#ifdef _SC_PAGESIZE - {"SC_PAGESIZE", _SC_PAGESIZE}, -#endif -#ifdef _SC_PAGE_SIZE - {"SC_PAGE_SIZE", _SC_PAGE_SIZE}, -#endif -#ifdef _SC_AIX_REALMEM - {"SC_AIX_REALMEM", _SC_AIX_REALMEM}, -#endif -#ifdef _SC_PASS_MAX - {"SC_PASS_MAX", _SC_PASS_MAX}, -#endif -#ifdef _SC_PHYS_PAGES - {"SC_PHYS_PAGES", _SC_PHYS_PAGES}, -#endif -#ifdef _SC_PII - {"SC_PII", _SC_PII}, -#endif -#ifdef _SC_PII_INTERNET - {"SC_PII_INTERNET", _SC_PII_INTERNET}, -#endif -#ifdef _SC_PII_INTERNET_DGRAM - {"SC_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM}, -#endif -#ifdef _SC_PII_INTERNET_STREAM - {"SC_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM}, -#endif -#ifdef _SC_PII_OSI - {"SC_PII_OSI", _SC_PII_OSI}, -#endif -#ifdef _SC_PII_OSI_CLTS - {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS}, -#endif -#ifdef _SC_PII_OSI_COTS - {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS}, -#endif -#ifdef _SC_PII_OSI_M - {"SC_PII_OSI_M", _SC_PII_OSI_M}, -#endif -#ifdef _SC_PII_SOCKET - {"SC_PII_SOCKET", _SC_PII_SOCKET}, -#endif -#ifdef _SC_PII_XTI - {"SC_PII_XTI", _SC_PII_XTI}, -#endif -#ifdef _SC_POLL - {"SC_POLL", _SC_POLL}, -#endif -#ifdef _SC_PRIORITIZED_IO - {"SC_PRIORITIZED_IO", _SC_PRIORITIZED_IO}, -#endif -#ifdef _SC_PRIORITY_SCHEDULING - {"SC_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING}, -#endif -#ifdef _SC_REALTIME_SIGNALS - {"SC_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS}, -#endif -#ifdef _SC_RE_DUP_MAX - {"SC_RE_DUP_MAX", _SC_RE_DUP_MAX}, -#endif -#ifdef _SC_RTSIG_MAX - {"SC_RTSIG_MAX", _SC_RTSIG_MAX}, -#endif -#ifdef _SC_SAVED_IDS - {"SC_SAVED_IDS", _SC_SAVED_IDS}, -#endif -#ifdef _SC_SCHAR_MAX - {"SC_SCHAR_MAX", _SC_SCHAR_MAX}, -#endif -#ifdef _SC_SCHAR_MIN - {"SC_SCHAR_MIN", _SC_SCHAR_MIN}, -#endif -#ifdef _SC_SELECT - {"SC_SELECT", _SC_SELECT}, -#endif -#ifdef _SC_SEMAPHORES - {"SC_SEMAPHORES", _SC_SEMAPHORES}, -#endif -#ifdef _SC_SEM_NSEMS_MAX - {"SC_SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX}, -#endif -#ifdef _SC_SEM_VALUE_MAX - {"SC_SEM_VALUE_MAX", _SC_SEM_VALUE_MAX}, -#endif -#ifdef _SC_SHARED_MEMORY_OBJECTS - {"SC_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS}, -#endif -#ifdef _SC_SHRT_MAX - {"SC_SHRT_MAX", _SC_SHRT_MAX}, -#endif -#ifdef _SC_SHRT_MIN - {"SC_SHRT_MIN", _SC_SHRT_MIN}, -#endif -#ifdef _SC_SIGQUEUE_MAX - {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX}, -#endif -#ifdef _SC_SIGRT_MAX - {"SC_SIGRT_MAX", _SC_SIGRT_MAX}, -#endif -#ifdef _SC_SIGRT_MIN - {"SC_SIGRT_MIN", _SC_SIGRT_MIN}, -#endif -#ifdef _SC_SOFTPOWER - {"SC_SOFTPOWER", _SC_SOFTPOWER}, -#endif -#ifdef _SC_SPLIT_CACHE - {"SC_SPLIT_CACHE", _SC_SPLIT_CACHE}, -#endif -#ifdef _SC_SSIZE_MAX - {"SC_SSIZE_MAX", _SC_SSIZE_MAX}, -#endif -#ifdef _SC_STACK_PROT - {"SC_STACK_PROT", _SC_STACK_PROT}, -#endif -#ifdef _SC_STREAM_MAX - {"SC_STREAM_MAX", _SC_STREAM_MAX}, -#endif -#ifdef _SC_SYNCHRONIZED_IO - {"SC_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO}, -#endif -#ifdef _SC_THREADS - {"SC_THREADS", _SC_THREADS}, -#endif -#ifdef _SC_THREAD_ATTR_STACKADDR - {"SC_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR}, -#endif -#ifdef _SC_THREAD_ATTR_STACKSIZE - {"SC_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE}, -#endif -#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS - {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS}, -#endif -#ifdef _SC_THREAD_KEYS_MAX - {"SC_THREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX}, -#endif -#ifdef _SC_THREAD_PRIORITY_SCHEDULING - {"SC_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING}, -#endif -#ifdef _SC_THREAD_PRIO_INHERIT - {"SC_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT}, -#endif -#ifdef _SC_THREAD_PRIO_PROTECT - {"SC_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT}, -#endif -#ifdef _SC_THREAD_PROCESS_SHARED - {"SC_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED}, -#endif -#ifdef _SC_THREAD_SAFE_FUNCTIONS - {"SC_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS}, -#endif -#ifdef _SC_THREAD_STACK_MIN - {"SC_THREAD_STACK_MIN", _SC_THREAD_STACK_MIN}, -#endif -#ifdef _SC_THREAD_THREADS_MAX - {"SC_THREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX}, -#endif -#ifdef _SC_TIMERS - {"SC_TIMERS", _SC_TIMERS}, -#endif -#ifdef _SC_TIMER_MAX - {"SC_TIMER_MAX", _SC_TIMER_MAX}, -#endif -#ifdef _SC_TTY_NAME_MAX - {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX}, -#endif -#ifdef _SC_TZNAME_MAX - {"SC_TZNAME_MAX", _SC_TZNAME_MAX}, -#endif -#ifdef _SC_T_IOV_MAX - {"SC_T_IOV_MAX", _SC_T_IOV_MAX}, -#endif -#ifdef _SC_UCHAR_MAX - {"SC_UCHAR_MAX", _SC_UCHAR_MAX}, -#endif -#ifdef _SC_UINT_MAX - {"SC_UINT_MAX", _SC_UINT_MAX}, -#endif -#ifdef _SC_UIO_MAXIOV - {"SC_UIO_MAXIOV", _SC_UIO_MAXIOV}, -#endif -#ifdef _SC_ULONG_MAX - {"SC_ULONG_MAX", _SC_ULONG_MAX}, -#endif -#ifdef _SC_USHRT_MAX - {"SC_USHRT_MAX", _SC_USHRT_MAX}, -#endif -#ifdef _SC_VERSION - {"SC_VERSION", _SC_VERSION}, -#endif -#ifdef _SC_WORD_BIT - {"SC_WORD_BIT", _SC_WORD_BIT}, -#endif -#ifdef _SC_XBS5_ILP32_OFF32 - {"SC_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32}, -#endif -#ifdef _SC_XBS5_ILP32_OFFBIG - {"SC_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG}, -#endif -#ifdef _SC_XBS5_LP64_OFF64 - {"SC_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64}, -#endif -#ifdef _SC_XBS5_LPBIG_OFFBIG - {"SC_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG}, -#endif -#ifdef _SC_XOPEN_CRYPT - {"SC_XOPEN_CRYPT", _SC_XOPEN_CRYPT}, -#endif -#ifdef _SC_XOPEN_ENH_I18N - {"SC_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N}, -#endif -#ifdef _SC_XOPEN_LEGACY - {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY}, -#endif -#ifdef _SC_XOPEN_REALTIME - {"SC_XOPEN_REALTIME", _SC_XOPEN_REALTIME}, -#endif -#ifdef _SC_XOPEN_REALTIME_THREADS - {"SC_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS}, -#endif -#ifdef _SC_XOPEN_SHM - {"SC_XOPEN_SHM", _SC_XOPEN_SHM}, -#endif -#ifdef _SC_XOPEN_UNIX - {"SC_XOPEN_UNIX", _SC_XOPEN_UNIX}, -#endif -#ifdef _SC_XOPEN_VERSION - {"SC_XOPEN_VERSION", _SC_XOPEN_VERSION}, -#endif -#ifdef _SC_XOPEN_XCU_VERSION - {"SC_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION}, -#endif -#ifdef _SC_XOPEN_XPG2 - {"SC_XOPEN_XPG2", _SC_XOPEN_XPG2}, -#endif -#ifdef _SC_XOPEN_XPG3 - {"SC_XOPEN_XPG3", _SC_XOPEN_XPG3}, -#endif -#ifdef _SC_XOPEN_XPG4 - {"SC_XOPEN_XPG4", _SC_XOPEN_XPG4}, -#endif -#ifdef _SC_MINSIGSTKSZ - {"SC_MINSIGSTKSZ", _SC_MINSIGSTKSZ}, -#endif -}; - -static int -conv_sysconf_confname(PyObject *arg, int *valuep) -{ - return conv_confname(arg, valuep, posix_constants_sysconf, - sizeof(posix_constants_sysconf) - / sizeof(struct constdef)); -} - - -/*[clinic input] -os.sysconf -> long - name: sysconf_confname - / - -Return an integer-valued system configuration variable. -[clinic start generated code]*/ - -static long -os_sysconf_impl(PyObject *module, int name) -/*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/ -{ - long value; - - errno = 0; - value = sysconf(name); - if (value == -1 && errno != 0) - posix_error(); - return value; -} -#endif /* HAVE_SYSCONF */ - - -/* This code is used to ensure that the tables of configuration value names - * are in sorted order as required by conv_confname(), and also to build - * the exported dictionaries that are used to publish information about the - * names available on the host platform. - * - * Sorting the table at runtime ensures that the table is properly ordered - * when used, even for platforms we're not able to test on. It also makes - * it easier to add additional entries to the tables. - */ - -static int -cmp_constdefs(const void *v1, const void *v2) -{ - const struct constdef *c1 = - (const struct constdef *) v1; - const struct constdef *c2 = - (const struct constdef *) v2; - - return strcmp(c1->name, c2->name); -} - -static int -setup_confname_table(struct constdef *table, size_t tablesize, - const char *tablename, PyObject *module) -{ - PyObject *d = NULL; - size_t i; - - qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs); - d = PyDict_New(); - if (d == NULL) - return -1; - - for (i=0; i < tablesize; ++i) { - PyObject *o = PyLong_FromLong(table[i].value); - if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) { - Py_XDECREF(o); - Py_DECREF(d); - return -1; - } - Py_DECREF(o); - } - return PyModule_AddObject(module, tablename, d); -} - -/* Return -1 on failure, 0 on success. */ -static int -setup_confname_tables(PyObject *module) -{ -#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF) - if (setup_confname_table(posix_constants_pathconf, - sizeof(posix_constants_pathconf) - / sizeof(struct constdef), - "pathconf_names", module)) - return -1; -#endif -#ifdef HAVE_CONFSTR - if (setup_confname_table(posix_constants_confstr, - sizeof(posix_constants_confstr) - / sizeof(struct constdef), - "confstr_names", module)) - return -1; -#endif -#ifdef HAVE_SYSCONF - if (setup_confname_table(posix_constants_sysconf, - sizeof(posix_constants_sysconf) - / sizeof(struct constdef), - "sysconf_names", module)) - return -1; -#endif - return 0; -} - - -/*[clinic input] -os.abort - -Abort the interpreter immediately. - -This function 'dumps core' or otherwise fails in the hardest way possible -on the hosting operating system. This function never returns. -[clinic start generated code]*/ - -static PyObject * -os_abort_impl(PyObject *module) -/*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/ -{ - abort(); - /*NOTREACHED*/ -#ifndef __clang__ - /* Issue #28152: abort() is declared with __attribute__((__noreturn__)). - GCC emits a warning without "return NULL;" (compiler bug?), but Clang - is smarter and emits a warning on the return. */ - Py_FatalError("abort() called from Python code didn't abort!"); - return NULL; -#endif -} - -#ifdef MS_WINDOWS -/* Grab ShellExecute dynamically from shell32 */ -static int has_ShellExecute = -1; -static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR, - LPCWSTR, INT); -static int -check_ShellExecute() -{ - HINSTANCE hShell32; - - /* only recheck */ - if (-1 == has_ShellExecute) { - Py_BEGIN_ALLOW_THREADS - /* Security note: this call is not vulnerable to "DLL hijacking". - SHELL32 is part of "KnownDLLs" and so Windows always load - the system SHELL32.DLL, even if there is another SHELL32.DLL - in the DLL search path. */ - hShell32 = LoadLibraryW(L"SHELL32"); - if (hShell32) { - *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32, - "ShellExecuteW"); - has_ShellExecute = Py_ShellExecuteW != NULL; - } else { - has_ShellExecute = 0; - } - Py_END_ALLOW_THREADS - } - return has_ShellExecute; -} - - -/*[clinic input] -os.startfile - filepath: path_t - operation: Py_UNICODE = NULL - arguments: Py_UNICODE = NULL - cwd: path_t(nullable=True) = None - show_cmd: int = 1 - -Start a file with its associated application. - -When "operation" is not specified or "open", this acts like -double-clicking the file in Explorer, or giving the file name as an -argument to the DOS "start" command: the file is opened with whatever -application (if any) its extension is associated. -When another "operation" is given, it specifies what should be done with -the file. A typical operation is "print". - -"arguments" is passed to the application, but should be omitted if the -file is a document. - -"cwd" is the working directory for the operation. If "filepath" is -relative, it will be resolved against this directory. This argument -should usually be an absolute path. - -"show_cmd" can be used to override the recommended visibility option. -See the Windows ShellExecute documentation for values. - -startfile returns as soon as the associated application is launched. -There is no option to wait for the application to close, and no way -to retrieve the application's exit status. - -The filepath is relative to the current directory. If you want to use -an absolute path, make sure the first character is not a slash ("/"); -the underlying Win32 ShellExecute function doesn't work if it is. -[clinic start generated code]*/ - -static PyObject * -os_startfile_impl(PyObject *module, path_t *filepath, - const Py_UNICODE *operation, const Py_UNICODE *arguments, - path_t *cwd, int show_cmd) -/*[clinic end generated code: output=3baa4f9795841880 input=8248997b80669622]*/ -{ - HINSTANCE rc; - - if(!check_ShellExecute()) { - /* If the OS doesn't have ShellExecute, return a - NotImplementedError. */ - return PyErr_Format(PyExc_NotImplementedError, - "startfile not available on this platform"); - } - - if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) { - return NULL; - } - if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation, - arguments, cwd->object ? cwd->object : Py_None, - show_cmd) < 0) { - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide, - arguments, cwd->wide, show_cmd); - Py_END_ALLOW_THREADS - - if (rc <= (HINSTANCE)32) { - win32_error_object("startfile", filepath->object); - return NULL; - } - Py_RETURN_NONE; -} -#endif /* MS_WINDOWS */ - - -#ifdef HAVE_GETLOADAVG -/*[clinic input] -os.getloadavg - -Return average recent system load information. - -Return the number of processes in the system run queue averaged over -the last 1, 5, and 15 minutes as a tuple of three floats. -Raises OSError if the load average was unobtainable. -[clinic start generated code]*/ - -static PyObject * -os_getloadavg_impl(PyObject *module) -/*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/ -{ - double loadavg[3]; - if (getloadavg(loadavg, 3)!=3) { - PyErr_SetString(PyExc_OSError, "Load averages are unobtainable"); - return NULL; - } else - return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]); -} -#endif /* HAVE_GETLOADAVG */ - - -/*[clinic input] -os.device_encoding - fd: int - -Return a string describing the encoding of a terminal's file descriptor. - -The file descriptor must be attached to a terminal. -If the device is not a terminal, return None. -[clinic start generated code]*/ - -static PyObject * -os_device_encoding_impl(PyObject *module, int fd) -/*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/ -{ - return _Py_device_encoding(fd); -} - - -#ifdef HAVE_SETRESUID -/*[clinic input] -os.setresuid - - ruid: uid_t - euid: uid_t - suid: uid_t - / - -Set the current process's real, effective, and saved user ids. -[clinic start generated code]*/ - -static PyObject * -os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid) -/*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/ -{ - if (setresuid(ruid, euid, suid) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETRESUID */ - - -#ifdef HAVE_SETRESGID -/*[clinic input] -os.setresgid - - rgid: gid_t - egid: gid_t - sgid: gid_t - / - -Set the current process's real, effective, and saved group ids. -[clinic start generated code]*/ - -static PyObject * -os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid) -/*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/ -{ - if (setresgid(rgid, egid, sgid) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETRESGID */ - - -#ifdef HAVE_GETRESUID -/*[clinic input] -os.getresuid - -Return a tuple of the current process's real, effective, and saved user ids. -[clinic start generated code]*/ - -static PyObject * -os_getresuid_impl(PyObject *module) -/*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/ -{ - uid_t ruid, euid, suid; - if (getresuid(&ruid, &euid, &suid) < 0) - return posix_error(); - return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid), - _PyLong_FromUid(euid), - _PyLong_FromUid(suid)); -} -#endif /* HAVE_GETRESUID */ - - -#ifdef HAVE_GETRESGID -/*[clinic input] -os.getresgid - -Return a tuple of the current process's real, effective, and saved group ids. -[clinic start generated code]*/ - -static PyObject * -os_getresgid_impl(PyObject *module) -/*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/ -{ - gid_t rgid, egid, sgid; - if (getresgid(&rgid, &egid, &sgid) < 0) - return posix_error(); - return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid), - _PyLong_FromGid(egid), - _PyLong_FromGid(sgid)); -} -#endif /* HAVE_GETRESGID */ - - -#ifdef USE_XATTRS -/*[clinic input] -os.getxattr - - path: path_t(allow_fd=True) - attribute: path_t - * - follow_symlinks: bool = True - -Return the value of extended attribute attribute on path. - -path may be either a string, a path-like object, or an open file descriptor. -If follow_symlinks is False, and the last element of the path is a symbolic - link, getxattr will examine the symbolic link itself instead of the file - the link points to. - -[clinic start generated code]*/ - -static PyObject * -os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute, - int follow_symlinks) -/*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/ -{ - Py_ssize_t i; - PyObject *buffer = NULL; - - if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks)) - return NULL; - - if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) { - return NULL; - } - - for (i = 0; ; i++) { - void *ptr; - ssize_t result; - static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0}; - Py_ssize_t buffer_size = buffer_sizes[i]; - if (!buffer_size) { - path_error(path); - return NULL; - } - buffer = PyBytes_FromStringAndSize(NULL, buffer_size); - if (!buffer) - return NULL; - ptr = PyBytes_AS_STRING(buffer); - - Py_BEGIN_ALLOW_THREADS; - if (path->fd >= 0) - result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size); - else if (follow_symlinks) - result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size); - else - result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size); - Py_END_ALLOW_THREADS; - - if (result < 0) { - Py_DECREF(buffer); - if (errno == ERANGE) - continue; - path_error(path); - return NULL; - } - - if (result != buffer_size) { - /* Can only shrink. */ - _PyBytes_Resize(&buffer, result); - } - break; - } - - return buffer; -} - - -/*[clinic input] -os.setxattr - - path: path_t(allow_fd=True) - attribute: path_t - value: Py_buffer - flags: int = 0 - * - follow_symlinks: bool = True - -Set extended attribute attribute on path to value. - -path may be either a string, a path-like object, or an open file descriptor. -If follow_symlinks is False, and the last element of the path is a symbolic - link, setxattr will modify the symbolic link itself instead of the file - the link points to. - -[clinic start generated code]*/ - -static PyObject * -os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute, - Py_buffer *value, int flags, int follow_symlinks) -/*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/ -{ - ssize_t result; - - if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks)) - return NULL; - - if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object, - value->buf, value->len, flags) < 0) { - return NULL; - } - - Py_BEGIN_ALLOW_THREADS; - if (path->fd > -1) - result = fsetxattr(path->fd, attribute->narrow, - value->buf, value->len, flags); - else if (follow_symlinks) - result = setxattr(path->narrow, attribute->narrow, - value->buf, value->len, flags); - else - result = lsetxattr(path->narrow, attribute->narrow, - value->buf, value->len, flags); - Py_END_ALLOW_THREADS; - - if (result) { - path_error(path); - return NULL; - } - - Py_RETURN_NONE; -} - - -/*[clinic input] -os.removexattr - - path: path_t(allow_fd=True) - attribute: path_t - * - follow_symlinks: bool = True - -Remove extended attribute attribute on path. - -path may be either a string, a path-like object, or an open file descriptor. -If follow_symlinks is False, and the last element of the path is a symbolic - link, removexattr will modify the symbolic link itself instead of the file - the link points to. - -[clinic start generated code]*/ - -static PyObject * -os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute, - int follow_symlinks) -/*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/ -{ - ssize_t result; - - if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks)) - return NULL; - - if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) { - return NULL; - } - - Py_BEGIN_ALLOW_THREADS; - if (path->fd > -1) - result = fremovexattr(path->fd, attribute->narrow); - else if (follow_symlinks) - result = removexattr(path->narrow, attribute->narrow); - else - result = lremovexattr(path->narrow, attribute->narrow); - Py_END_ALLOW_THREADS; - - if (result) { - return path_error(path); - } - - Py_RETURN_NONE; -} - - -/*[clinic input] -os.listxattr - - path: path_t(allow_fd=True, nullable=True) = None - * - follow_symlinks: bool = True - -Return a list of extended attributes on path. - -path may be either None, a string, a path-like object, or an open file descriptor. -if path is None, listxattr will examine the current directory. -If follow_symlinks is False, and the last element of the path is a symbolic - link, listxattr will examine the symbolic link itself instead of the file - the link points to. -[clinic start generated code]*/ - -static PyObject * -os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks) -/*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/ -{ - Py_ssize_t i; - PyObject *result = NULL; - const char *name; - char *buffer = NULL; - - if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks)) - goto exit; - - if (PySys_Audit("os.listxattr", "(O)", - path->object ? path->object : Py_None) < 0) { - return NULL; - } - - name = path->narrow ? path->narrow : "."; - - for (i = 0; ; i++) { - const char *start, *trace, *end; - ssize_t length; - static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 }; - Py_ssize_t buffer_size = buffer_sizes[i]; - if (!buffer_size) { - /* ERANGE */ - path_error(path); - break; - } - buffer = PyMem_Malloc(buffer_size); - if (!buffer) { - PyErr_NoMemory(); - break; - } - - Py_BEGIN_ALLOW_THREADS; - if (path->fd > -1) - length = flistxattr(path->fd, buffer, buffer_size); - else if (follow_symlinks) - length = listxattr(name, buffer, buffer_size); - else - length = llistxattr(name, buffer, buffer_size); - Py_END_ALLOW_THREADS; - - if (length < 0) { - if (errno == ERANGE) { - PyMem_Free(buffer); - buffer = NULL; - continue; - } - path_error(path); - break; - } - - result = PyList_New(0); - if (!result) { - goto exit; - } - - end = buffer + length; - for (trace = start = buffer; trace != end; trace++) { - if (!*trace) { - int error; - PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start, - trace - start); - if (!attribute) { - Py_DECREF(result); - result = NULL; - goto exit; - } - error = PyList_Append(result, attribute); - Py_DECREF(attribute); - if (error) { - Py_DECREF(result); - result = NULL; - goto exit; - } - start = trace + 1; - } - } - break; - } -exit: - if (buffer) - PyMem_Free(buffer); - return result; -} -#endif /* USE_XATTRS */ - - -/*[clinic input] -os.urandom - - size: Py_ssize_t - / - -Return a bytes object containing random bytes suitable for cryptographic use. -[clinic start generated code]*/ - -static PyObject * -os_urandom_impl(PyObject *module, Py_ssize_t size) -/*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/ -{ - PyObject *bytes; - int result; - - if (size < 0) - return PyErr_Format(PyExc_ValueError, - "negative argument not allowed"); - bytes = PyBytes_FromStringAndSize(NULL, size); - if (bytes == NULL) - return NULL; - - result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes)); - if (result == -1) { - Py_DECREF(bytes); - return NULL; - } - return bytes; -} - -#ifdef HAVE_MEMFD_CREATE -/*[clinic input] -os.memfd_create - - name: FSConverter - flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC - -[clinic start generated code]*/ - -static PyObject * -os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags) -/*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/ -{ - int fd; - const char *bytes = PyBytes_AS_STRING(name); - Py_BEGIN_ALLOW_THREADS - fd = memfd_create(bytes, flags); - Py_END_ALLOW_THREADS - if (fd == -1) { - return PyErr_SetFromErrno(PyExc_OSError); - } - return PyLong_FromLong(fd); -} -#endif - -#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC) -/*[clinic input] -os.eventfd - - initval: unsigned_int - flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC - -Creates and returns an event notification file descriptor. -[clinic start generated code]*/ - -static PyObject * -os_eventfd_impl(PyObject *module, unsigned int initval, int flags) -/*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/ - -{ - /* initval is limited to uint32_t, internal counter is uint64_t */ - int fd; - Py_BEGIN_ALLOW_THREADS - fd = eventfd(initval, flags); - Py_END_ALLOW_THREADS - if (fd == -1) { - return PyErr_SetFromErrno(PyExc_OSError); - } - return PyLong_FromLong(fd); -} - -/*[clinic input] -os.eventfd_read - - fd: fildes - -Read eventfd value -[clinic start generated code]*/ - -static PyObject * -os_eventfd_read_impl(PyObject *module, int fd) -/*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/ -{ - eventfd_t value; - int result; - Py_BEGIN_ALLOW_THREADS - result = eventfd_read(fd, &value); - Py_END_ALLOW_THREADS - if (result == -1) { - return PyErr_SetFromErrno(PyExc_OSError); - } - return PyLong_FromUnsignedLongLong(value); -} - -/*[clinic input] -os.eventfd_write - - fd: fildes - value: unsigned_long_long - -Write eventfd value. -[clinic start generated code]*/ - -static PyObject * -os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value) -/*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/ -{ - int result; - Py_BEGIN_ALLOW_THREADS - result = eventfd_write(fd, value); - Py_END_ALLOW_THREADS - if (result == -1) { - return PyErr_SetFromErrno(PyExc_OSError); - } - Py_RETURN_NONE; -} -#endif /* HAVE_EVENTFD && EFD_CLOEXEC */ - -/* Terminal size querying */ - -PyDoc_STRVAR(TerminalSize_docstring, - "A tuple of (columns, lines) for holding terminal window size"); - -static PyStructSequence_Field TerminalSize_fields[] = { - {"columns", "width of the terminal window in characters"}, - {"lines", "height of the terminal window in characters"}, - {NULL, NULL} -}; - -static PyStructSequence_Desc TerminalSize_desc = { - "os.terminal_size", - TerminalSize_docstring, - TerminalSize_fields, - 2, -}; - -#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) -/*[clinic input] -os.get_terminal_size - - fd: int(c_default="fileno(stdout)", py_default="") = -1 - / - -Return the size of the terminal window as (columns, lines). - -The optional argument fd (default standard output) specifies -which file descriptor should be queried. - -If the file descriptor is not connected to a terminal, an OSError -is thrown. - -This function will only be defined if an implementation is -available for this system. - -shutil.get_terminal_size is the high-level function which should -normally be used, os.get_terminal_size is the low-level implementation. -[clinic start generated code]*/ - -static PyObject * -os_get_terminal_size_impl(PyObject *module, int fd) -/*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/ -{ - int columns, lines; - PyObject *termsize; - - /* Under some conditions stdout may not be connected and - * fileno(stdout) may point to an invalid file descriptor. For example - * GUI apps don't have valid standard streams by default. - * - * If this happens, and the optional fd argument is not present, - * the ioctl below will fail returning EBADF. This is what we want. - */ - -#ifdef TERMSIZE_USE_IOCTL - { - struct winsize w; - if (ioctl(fd, TIOCGWINSZ, &w)) - return PyErr_SetFromErrno(PyExc_OSError); - columns = w.ws_col; - lines = w.ws_row; - } -#endif /* TERMSIZE_USE_IOCTL */ - -#ifdef TERMSIZE_USE_CONIO - { - HANDLE handle; - CONSOLE_SCREEN_BUFFER_INFO csbi; - handle = _Py_get_osfhandle(fd); - if (handle == INVALID_HANDLE_VALUE) - return NULL; - - if (!GetConsoleScreenBufferInfo(handle, &csbi)) - return PyErr_SetFromWindowsErr(0); - - columns = csbi.srWindow.Right - csbi.srWindow.Left + 1; - lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; - } -#endif /* TERMSIZE_USE_CONIO */ - - PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType; - termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType); - if (termsize == NULL) - return NULL; - PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns)); - PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines)); - if (PyErr_Occurred()) { - Py_DECREF(termsize); - return NULL; - } - return termsize; -} -#endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */ - - -/*[clinic input] -os.cpu_count - -Return the number of CPUs in the system; return None if indeterminable. - -This number is not equivalent to the number of CPUs the current process can -use. The number of usable CPUs can be obtained with -``len(os.sched_getaffinity(0))`` -[clinic start generated code]*/ - -static PyObject * -os_cpu_count_impl(PyObject *module) -/*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/ -{ - int ncpu = 0; -#ifdef MS_WINDOWS - ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS); -#elif defined(__hpux) - ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL); -#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) - ncpu = sysconf(_SC_NPROCESSORS_ONLN); -#elif defined(__VXWORKS__) - ncpu = _Py_popcount32(vxCpuEnabledGet()); -#elif defined(__DragonFly__) || \ - defined(__OpenBSD__) || \ - defined(__FreeBSD__) || \ - defined(__NetBSD__) || \ - defined(__APPLE__) - int mib[2]; - size_t len = sizeof(ncpu); - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) - ncpu = 0; -#endif - if (ncpu >= 1) - return PyLong_FromLong(ncpu); - else - Py_RETURN_NONE; -} - - -/*[clinic input] -os.get_inheritable -> bool - - fd: int - / - -Get the close-on-exe flag of the specified file descriptor. -[clinic start generated code]*/ - -static int -os_get_inheritable_impl(PyObject *module, int fd) -/*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/ -{ - int return_value; - _Py_BEGIN_SUPPRESS_IPH - return_value = _Py_get_inheritable(fd); - _Py_END_SUPPRESS_IPH - return return_value; -} - - -/*[clinic input] -os.set_inheritable - fd: int - inheritable: int - / - -Set the inheritable flag of the specified file descriptor. -[clinic start generated code]*/ - -static PyObject * -os_set_inheritable_impl(PyObject *module, int fd, int inheritable) -/*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/ -{ - int result; - - _Py_BEGIN_SUPPRESS_IPH - result = _Py_set_inheritable(fd, inheritable, NULL); - _Py_END_SUPPRESS_IPH - if (result < 0) - return NULL; - Py_RETURN_NONE; -} - - -#ifdef MS_WINDOWS -/*[clinic input] -os.get_handle_inheritable -> bool - handle: intptr_t - / - -Get the close-on-exe flag of the specified file descriptor. -[clinic start generated code]*/ - -static int -os_get_handle_inheritable_impl(PyObject *module, intptr_t handle) -/*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/ -{ - DWORD flags; - - if (!GetHandleInformation((HANDLE)handle, &flags)) { - PyErr_SetFromWindowsErr(0); - return -1; - } - - return flags & HANDLE_FLAG_INHERIT; -} - - -/*[clinic input] -os.set_handle_inheritable - handle: intptr_t - inheritable: bool - / - -Set the inheritable flag of the specified handle. -[clinic start generated code]*/ - -static PyObject * -os_set_handle_inheritable_impl(PyObject *module, intptr_t handle, - int inheritable) -/*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/ -{ - DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0; - if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) { - PyErr_SetFromWindowsErr(0); - return NULL; - } - Py_RETURN_NONE; -} -#endif /* MS_WINDOWS */ - -#ifndef MS_WINDOWS -/*[clinic input] -os.get_blocking -> bool - fd: int - / - -Get the blocking mode of the file descriptor. - -Return False if the O_NONBLOCK flag is set, True if the flag is cleared. -[clinic start generated code]*/ - -static int -os_get_blocking_impl(PyObject *module, int fd) -/*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/ -{ - int blocking; - - _Py_BEGIN_SUPPRESS_IPH - blocking = _Py_get_blocking(fd); - _Py_END_SUPPRESS_IPH - return blocking; -} - -/*[clinic input] -os.set_blocking - fd: int - blocking: bool(accept={int}) - / - -Set the blocking mode of the specified file descriptor. - -Set the O_NONBLOCK flag if blocking is False, -clear the O_NONBLOCK flag otherwise. -[clinic start generated code]*/ - -static PyObject * -os_set_blocking_impl(PyObject *module, int fd, int blocking) -/*[clinic end generated code: output=384eb43aa0762a9d input=bf5c8efdc5860ff3]*/ -{ - int result; - - _Py_BEGIN_SUPPRESS_IPH - result = _Py_set_blocking(fd, blocking); - _Py_END_SUPPRESS_IPH - if (result < 0) - return NULL; - Py_RETURN_NONE; -} -#endif /* !MS_WINDOWS */ - - -/*[clinic input] -class os.DirEntry "DirEntry *" "DirEntryType" -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/ - -typedef struct { - PyObject_HEAD - PyObject *name; - PyObject *path; - PyObject *stat; - PyObject *lstat; -#ifdef MS_WINDOWS - struct _Py_stat_struct win32_lstat; - uint64_t win32_file_index; - int got_file_index; -#else /* POSIX */ -#ifdef HAVE_DIRENT_D_TYPE - unsigned char d_type; -#endif - ino_t d_ino; - int dir_fd; -#endif -} DirEntry; - -static void -DirEntry_dealloc(DirEntry *entry) -{ - PyTypeObject *tp = Py_TYPE(entry); - Py_XDECREF(entry->name); - Py_XDECREF(entry->path); - Py_XDECREF(entry->stat); - Py_XDECREF(entry->lstat); - freefunc free_func = PyType_GetSlot(tp, Py_tp_free); - free_func(entry); - Py_DECREF(tp); -} - -/* Forward reference */ -static int -DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self, - int follow_symlinks, unsigned short mode_bits); - -/*[clinic input] -os.DirEntry.is_symlink -> bool - defining_class: defining_class - / - -Return True if the entry is a symbolic link; cached per entry. -[clinic start generated code]*/ - -static int -os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class) -/*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/ -{ -#ifdef MS_WINDOWS - return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK; -#elif defined(HAVE_DIRENT_D_TYPE) - /* POSIX */ - if (self->d_type != DT_UNKNOWN) - return self->d_type == DT_LNK; - else - return DirEntry_test_mode(defining_class, self, 0, S_IFLNK); -#else - /* POSIX without d_type */ - return DirEntry_test_mode(defining_class, self, 0, S_IFLNK); -#endif -} - -/*[clinic input] -os.DirEntry.is_junction -> bool - defining_class: defining_class - / - -Return True if the entry is a junction; cached per entry. -[clinic start generated code]*/ - -static int -os_DirEntry_is_junction_impl(DirEntry *self, PyTypeObject *defining_class) -/*[clinic end generated code: output=7061a07b0ef2cd1f input=475cd36fb7d4723f]*/ -{ -#ifdef MS_WINDOWS - return self->win32_lstat.st_reparse_tag == IO_REPARSE_TAG_MOUNT_POINT; -#else - return 0; -#endif -} - -static PyObject * -DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks) -{ - int result; - STRUCT_STAT st; - PyObject *ub; - -#ifdef MS_WINDOWS - if (!PyUnicode_FSDecoder(self->path, &ub)) - return NULL; - wchar_t *path = PyUnicode_AsWideCharString(ub, NULL); - Py_DECREF(ub); -#else /* POSIX */ - if (!PyUnicode_FSConverter(self->path, &ub)) - return NULL; - const char *path = PyBytes_AS_STRING(ub); - if (self->dir_fd != DEFAULT_DIR_FD) { -#ifdef HAVE_FSTATAT - if (HAVE_FSTATAT_RUNTIME) { - Py_BEGIN_ALLOW_THREADS - result = fstatat(self->dir_fd, path, &st, - follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); - Py_END_ALLOW_THREADS - } else - -#endif /* HAVE_FSTATAT */ - { - Py_DECREF(ub); - PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat"); - return NULL; - } - } - else -#endif - { - Py_BEGIN_ALLOW_THREADS - if (follow_symlinks) { - result = STAT(path, &st); - } - else { - result = LSTAT(path, &st); - } - Py_END_ALLOW_THREADS - } -#if defined(MS_WINDOWS) - PyMem_Free(path); -#else - Py_DECREF(ub); -#endif - - if (result != 0) - return path_object_error(self->path); - - return _pystat_fromstructstat(module, &st); -} - -static PyObject * -DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self) -{ - if (!self->lstat) { - PyObject *module = PyType_GetModule(defining_class); -#ifdef MS_WINDOWS - self->lstat = _pystat_fromstructstat(module, &self->win32_lstat); -#else /* POSIX */ - self->lstat = DirEntry_fetch_stat(module, self, 0); -#endif - } - return Py_XNewRef(self->lstat); -} - -/*[clinic input] -os.DirEntry.stat - defining_class: defining_class - / - * - follow_symlinks: bool = True - -Return stat_result object for the entry; cached per entry. -[clinic start generated code]*/ - -static PyObject * -os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class, - int follow_symlinks) -/*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/ -{ - if (!follow_symlinks) { - return DirEntry_get_lstat(defining_class, self); - } - - if (!self->stat) { - int result = os_DirEntry_is_symlink_impl(self, defining_class); - if (result == -1) { - return NULL; - } - if (result) { - PyObject *module = PyType_GetModule(defining_class); - self->stat = DirEntry_fetch_stat(module, self, 1); - } - else { - self->stat = DirEntry_get_lstat(defining_class, self); - } - } - - return Py_XNewRef(self->stat); -} - -/* Set exception and return -1 on error, 0 for False, 1 for True */ -static int -DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self, - int follow_symlinks, unsigned short mode_bits) -{ - PyObject *stat = NULL; - PyObject *st_mode = NULL; - long mode; - int result; -#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE) - int is_symlink; - int need_stat; -#endif -#ifdef MS_WINDOWS - unsigned long dir_bits; -#endif - -#ifdef MS_WINDOWS - is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK; - need_stat = follow_symlinks && is_symlink; -#elif defined(HAVE_DIRENT_D_TYPE) - is_symlink = self->d_type == DT_LNK; - need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink); -#endif - -#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE) - if (need_stat) { -#endif - stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks); - if (!stat) { - if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) { - /* If file doesn't exist (anymore), then return False - (i.e., say it's not a file/directory) */ - PyErr_Clear(); - return 0; - } - goto error; - } - _posixstate* state = get_posix_state(PyType_GetModule(defining_class)); - st_mode = PyObject_GetAttr(stat, state->st_mode); - if (!st_mode) - goto error; - - mode = PyLong_AsLong(st_mode); - if (mode == -1 && PyErr_Occurred()) - goto error; - Py_CLEAR(st_mode); - Py_CLEAR(stat); - result = (mode & S_IFMT) == mode_bits; -#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE) - } - else if (is_symlink) { - assert(mode_bits != S_IFLNK); - result = 0; - } - else { - assert(mode_bits == S_IFDIR || mode_bits == S_IFREG); -#ifdef MS_WINDOWS - dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY; - if (mode_bits == S_IFDIR) - result = dir_bits != 0; - else - result = dir_bits == 0; -#else /* POSIX */ - if (mode_bits == S_IFDIR) - result = self->d_type == DT_DIR; - else - result = self->d_type == DT_REG; -#endif - } -#endif - - return result; - -error: - Py_XDECREF(st_mode); - Py_XDECREF(stat); - return -1; -} - -/*[clinic input] -os.DirEntry.is_dir -> bool - defining_class: defining_class - / - * - follow_symlinks: bool = True - -Return True if the entry is a directory; cached per entry. -[clinic start generated code]*/ - -static int -os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class, - int follow_symlinks) -/*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/ -{ - return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR); -} - -/*[clinic input] -os.DirEntry.is_file -> bool - defining_class: defining_class - / - * - follow_symlinks: bool = True - -Return True if the entry is a file; cached per entry. -[clinic start generated code]*/ - -static int -os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class, - int follow_symlinks) -/*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/ -{ - return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG); -} - -/*[clinic input] -os.DirEntry.inode - -Return inode of the entry; cached per entry. -[clinic start generated code]*/ - -static PyObject * -os_DirEntry_inode_impl(DirEntry *self) -/*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/ -{ -#ifdef MS_WINDOWS - if (!self->got_file_index) { - PyObject *unicode; - STRUCT_STAT stat; - int result; - - if (!PyUnicode_FSDecoder(self->path, &unicode)) - return NULL; - wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL); - Py_DECREF(unicode); - result = LSTAT(path, &stat); - PyMem_Free(path); - - if (result != 0) - return path_object_error(self->path); - - self->win32_file_index = stat.st_ino; - self->got_file_index = 1; - } - static_assert(sizeof(unsigned long long) >= sizeof(self->win32_file_index), - "DirEntry.win32_file_index is larger than unsigned long long"); - return PyLong_FromUnsignedLongLong(self->win32_file_index); -#else /* POSIX */ - static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino), - "DirEntry.d_ino is larger than unsigned long long"); - return PyLong_FromUnsignedLongLong(self->d_ino); -#endif -} - -static PyObject * -DirEntry_repr(DirEntry *self) -{ - return PyUnicode_FromFormat("", self->name); -} - -/*[clinic input] -os.DirEntry.__fspath__ - -Returns the path for the entry. -[clinic start generated code]*/ - -static PyObject * -os_DirEntry___fspath___impl(DirEntry *self) -/*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/ -{ - return Py_NewRef(self->path); -} - -static PyMemberDef DirEntry_members[] = { - {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY, - "the entry's base filename, relative to scandir() \"path\" argument"}, - {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY, - "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"}, - {NULL} -}; - -#include "clinic/posixmodule.c.h" - -static PyMethodDef DirEntry_methods[] = { - OS_DIRENTRY_IS_DIR_METHODDEF - OS_DIRENTRY_IS_FILE_METHODDEF - OS_DIRENTRY_IS_SYMLINK_METHODDEF - OS_DIRENTRY_IS_JUNCTION_METHODDEF - OS_DIRENTRY_STAT_METHODDEF - OS_DIRENTRY_INODE_METHODDEF - OS_DIRENTRY___FSPATH___METHODDEF - {"__class_getitem__", Py_GenericAlias, - METH_O|METH_CLASS, PyDoc_STR("See PEP 585")}, - {NULL} -}; - -static PyType_Slot DirEntryType_slots[] = { - {Py_tp_dealloc, DirEntry_dealloc}, - {Py_tp_repr, DirEntry_repr}, - {Py_tp_methods, DirEntry_methods}, - {Py_tp_members, DirEntry_members}, - {0, 0}, -}; - -static PyType_Spec DirEntryType_spec = { - MODNAME ".DirEntry", - sizeof(DirEntry), - 0, - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, - DirEntryType_slots -}; - - -#ifdef MS_WINDOWS - -static wchar_t * -join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename) -{ - Py_ssize_t path_len; - Py_ssize_t size; - wchar_t *result; - wchar_t ch; - - if (!path_wide) { /* Default arg: "." */ - path_wide = L"."; - path_len = 1; - } - else { - path_len = wcslen(path_wide); - } - - /* The +1's are for the path separator and the NUL */ - size = path_len + 1 + wcslen(filename) + 1; - result = PyMem_New(wchar_t, size); - if (!result) { - PyErr_NoMemory(); - return NULL; - } - wcscpy(result, path_wide); - if (path_len > 0) { - ch = result[path_len - 1]; - if (ch != SEP && ch != ALTSEP && ch != L':') - result[path_len++] = SEP; - wcscpy(result + path_len, filename); - } - return result; -} - -static PyObject * -DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW) -{ - DirEntry *entry; - BY_HANDLE_FILE_INFORMATION file_info; - ULONG reparse_tag; - wchar_t *joined_path; - - PyObject *DirEntryType = get_posix_state(module)->DirEntryType; - entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType); - if (!entry) - return NULL; - entry->name = NULL; - entry->path = NULL; - entry->stat = NULL; - entry->lstat = NULL; - entry->got_file_index = 0; - - entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1); - if (!entry->name) - goto error; - if (path->narrow) { - Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name)); - if (!entry->name) - goto error; - } - - joined_path = join_path_filenameW(path->wide, dataW->cFileName); - if (!joined_path) - goto error; - - entry->path = PyUnicode_FromWideChar(joined_path, -1); - PyMem_Free(joined_path); - if (!entry->path) - goto error; - if (path->narrow) { - Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path)); - if (!entry->path) - goto error; - } - - find_data_to_file_info(dataW, &file_info, &reparse_tag); - _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat); - - return (PyObject *)entry; - -error: - Py_DECREF(entry); - return NULL; -} - -#else /* POSIX */ - -static char * -join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len) -{ - Py_ssize_t path_len; - Py_ssize_t size; - char *result; - - if (!path_narrow) { /* Default arg: "." */ - path_narrow = "."; - path_len = 1; - } - else { - path_len = strlen(path_narrow); - } - - if (filename_len == -1) - filename_len = strlen(filename); - - /* The +1's are for the path separator and the NUL */ - size = path_len + 1 + filename_len + 1; - result = PyMem_New(char, size); - if (!result) { - PyErr_NoMemory(); - return NULL; - } - strcpy(result, path_narrow); - if (path_len > 0 && result[path_len - 1] != '/') - result[path_len++] = '/'; - strcpy(result + path_len, filename); - return result; -} - -static PyObject * -DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name, - Py_ssize_t name_len, ino_t d_ino -#ifdef HAVE_DIRENT_D_TYPE - , unsigned char d_type -#endif - ) -{ - DirEntry *entry; - char *joined_path; - - PyObject *DirEntryType = get_posix_state(module)->DirEntryType; - entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType); - if (!entry) - return NULL; - entry->name = NULL; - entry->path = NULL; - entry->stat = NULL; - entry->lstat = NULL; - - if (path->fd != -1) { - entry->dir_fd = path->fd; - joined_path = NULL; - } - else { - entry->dir_fd = DEFAULT_DIR_FD; - joined_path = join_path_filename(path->narrow, name, name_len); - if (!joined_path) - goto error; - } - - if (!path->narrow || !PyBytes_Check(path->object)) { - entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len); - if (joined_path) - entry->path = PyUnicode_DecodeFSDefault(joined_path); - } - else { - entry->name = PyBytes_FromStringAndSize(name, name_len); - if (joined_path) - entry->path = PyBytes_FromString(joined_path); - } - PyMem_Free(joined_path); - if (!entry->name) - goto error; - - if (path->fd != -1) { - entry->path = Py_NewRef(entry->name); - } - else if (!entry->path) - goto error; - -#ifdef HAVE_DIRENT_D_TYPE - entry->d_type = d_type; -#endif - entry->d_ino = d_ino; - - return (PyObject *)entry; - -error: - Py_XDECREF(entry); - return NULL; -} - -#endif - - -typedef struct { - PyObject_HEAD - path_t path; -#ifdef MS_WINDOWS - HANDLE handle; - WIN32_FIND_DATAW file_data; - int first_time; -#else /* POSIX */ - DIR *dirp; -#endif -#ifdef HAVE_FDOPENDIR - int fd; -#endif -} ScandirIterator; - -#ifdef MS_WINDOWS - -static int -ScandirIterator_is_closed(ScandirIterator *iterator) -{ - return iterator->handle == INVALID_HANDLE_VALUE; -} - -static void -ScandirIterator_closedir(ScandirIterator *iterator) -{ - HANDLE handle = iterator->handle; - - if (handle == INVALID_HANDLE_VALUE) - return; - - iterator->handle = INVALID_HANDLE_VALUE; - Py_BEGIN_ALLOW_THREADS - FindClose(handle); - Py_END_ALLOW_THREADS -} - -static PyObject * -ScandirIterator_iternext(ScandirIterator *iterator) -{ - WIN32_FIND_DATAW *file_data = &iterator->file_data; - BOOL success; - PyObject *entry; - - /* Happens if the iterator is iterated twice, or closed explicitly */ - if (iterator->handle == INVALID_HANDLE_VALUE) - return NULL; - - while (1) { - if (!iterator->first_time) { - Py_BEGIN_ALLOW_THREADS - success = FindNextFileW(iterator->handle, file_data); - Py_END_ALLOW_THREADS - if (!success) { - /* Error or no more files */ - if (GetLastError() != ERROR_NO_MORE_FILES) - path_error(&iterator->path); - break; - } - } - iterator->first_time = 0; - - /* Skip over . and .. */ - if (wcscmp(file_data->cFileName, L".") != 0 && - wcscmp(file_data->cFileName, L"..") != 0) - { - PyObject *module = PyType_GetModule(Py_TYPE(iterator)); - entry = DirEntry_from_find_data(module, &iterator->path, file_data); - if (!entry) - break; - return entry; - } - - /* Loop till we get a non-dot directory or finish iterating */ - } - - /* Error or no more files */ - ScandirIterator_closedir(iterator); - return NULL; -} - -#else /* POSIX */ - -static int -ScandirIterator_is_closed(ScandirIterator *iterator) -{ - return !iterator->dirp; -} - -static void -ScandirIterator_closedir(ScandirIterator *iterator) -{ - DIR *dirp = iterator->dirp; - - if (!dirp) - return; - - iterator->dirp = NULL; - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_FDOPENDIR - if (iterator->path.fd != -1) - rewinddir(dirp); -#endif - closedir(dirp); - Py_END_ALLOW_THREADS - return; -} - -static PyObject * -ScandirIterator_iternext(ScandirIterator *iterator) -{ - struct dirent *direntp; - Py_ssize_t name_len; - int is_dot; - PyObject *entry; - - /* Happens if the iterator is iterated twice, or closed explicitly */ - if (!iterator->dirp) - return NULL; - - while (1) { - errno = 0; - Py_BEGIN_ALLOW_THREADS - direntp = readdir(iterator->dirp); - Py_END_ALLOW_THREADS - - if (!direntp) { - /* Error or no more files */ - if (errno != 0) - path_error(&iterator->path); - break; - } - - /* Skip over . and .. */ - name_len = NAMLEN(direntp); - is_dot = direntp->d_name[0] == '.' && - (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2)); - if (!is_dot) { - PyObject *module = PyType_GetModule(Py_TYPE(iterator)); - entry = DirEntry_from_posix_info(module, - &iterator->path, direntp->d_name, - name_len, direntp->d_ino -#ifdef HAVE_DIRENT_D_TYPE - , direntp->d_type -#endif - ); - if (!entry) - break; - return entry; - } - - /* Loop till we get a non-dot directory or finish iterating */ - } - - /* Error or no more files */ - ScandirIterator_closedir(iterator); - return NULL; -} - -#endif - -static PyObject * -ScandirIterator_close(ScandirIterator *self, PyObject *args) -{ - ScandirIterator_closedir(self); - Py_RETURN_NONE; -} - -static PyObject * -ScandirIterator_enter(PyObject *self, PyObject *args) -{ - return Py_NewRef(self); -} - -static PyObject * -ScandirIterator_exit(ScandirIterator *self, PyObject *args) -{ - ScandirIterator_closedir(self); - Py_RETURN_NONE; -} - -static void -ScandirIterator_finalize(ScandirIterator *iterator) -{ - PyObject *error_type, *error_value, *error_traceback; - - /* Save the current exception, if any. */ - PyErr_Fetch(&error_type, &error_value, &error_traceback); - - if (!ScandirIterator_is_closed(iterator)) { - ScandirIterator_closedir(iterator); - - if (PyErr_ResourceWarning((PyObject *)iterator, 1, - "unclosed scandir iterator %R", iterator)) { - /* Spurious errors can appear at shutdown */ - if (PyErr_ExceptionMatches(PyExc_Warning)) { - PyErr_WriteUnraisable((PyObject *) iterator); - } - } - } - - path_cleanup(&iterator->path); - - /* Restore the saved exception. */ - PyErr_Restore(error_type, error_value, error_traceback); -} - -static void -ScandirIterator_dealloc(ScandirIterator *iterator) -{ - PyTypeObject *tp = Py_TYPE(iterator); - if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0) - return; - - freefunc free_func = PyType_GetSlot(tp, Py_tp_free); - free_func(iterator); - Py_DECREF(tp); -} - -static PyMethodDef ScandirIterator_methods[] = { - {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS}, - {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS}, - {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS}, - {NULL} -}; - -static PyType_Slot ScandirIteratorType_slots[] = { - {Py_tp_dealloc, ScandirIterator_dealloc}, - {Py_tp_finalize, ScandirIterator_finalize}, - {Py_tp_iter, PyObject_SelfIter}, - {Py_tp_iternext, ScandirIterator_iternext}, - {Py_tp_methods, ScandirIterator_methods}, - {0, 0}, -}; - -static PyType_Spec ScandirIteratorType_spec = { - MODNAME ".ScandirIterator", - sizeof(ScandirIterator), - 0, - // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since - // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance. - (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE - | Py_TPFLAGS_DISALLOW_INSTANTIATION), - ScandirIteratorType_slots -}; - -/*[clinic input] -os.scandir - - path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None - -Return an iterator of DirEntry objects for given path. - -path can be specified as either str, bytes, or a path-like object. If path -is bytes, the names of yielded DirEntry objects will also be bytes; in -all other circumstances they will be str. - -If path is None, uses the path='.'. -[clinic start generated code]*/ - -static PyObject * -os_scandir_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/ -{ - ScandirIterator *iterator; -#ifdef MS_WINDOWS - wchar_t *path_strW; -#else - const char *path_str; -#ifdef HAVE_FDOPENDIR - int fd = -1; -#endif -#endif - - if (PySys_Audit("os.scandir", "O", - path->object ? path->object : Py_None) < 0) { - return NULL; - } - - PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType; - iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType); - if (!iterator) - return NULL; - -#ifdef MS_WINDOWS - iterator->handle = INVALID_HANDLE_VALUE; -#else - iterator->dirp = NULL; -#endif - - /* Move the ownership to iterator->path */ - memcpy(&iterator->path, path, sizeof(path_t)); - memset(path, 0, sizeof(path_t)); - -#ifdef MS_WINDOWS - iterator->first_time = 1; - - path_strW = join_path_filenameW(iterator->path.wide, L"*.*"); - if (!path_strW) - goto error; - - Py_BEGIN_ALLOW_THREADS - iterator->handle = FindFirstFileW(path_strW, &iterator->file_data); - Py_END_ALLOW_THREADS - - PyMem_Free(path_strW); - - if (iterator->handle == INVALID_HANDLE_VALUE) { - path_error(&iterator->path); - goto error; - } -#else /* POSIX */ - errno = 0; -#ifdef HAVE_FDOPENDIR - if (iterator->path.fd != -1) { - if (HAVE_FDOPENDIR_RUNTIME) { - /* closedir() closes the FD, so we duplicate it */ - fd = _Py_dup(iterator->path.fd); - if (fd == -1) - goto error; - - Py_BEGIN_ALLOW_THREADS - iterator->dirp = fdopendir(fd); - Py_END_ALLOW_THREADS - } else { - PyErr_SetString(PyExc_TypeError, - "scandir: path should be string, bytes, os.PathLike or None, not int"); - return NULL; - } - } - else -#endif - { - if (iterator->path.narrow) - path_str = iterator->path.narrow; - else - path_str = "."; - - Py_BEGIN_ALLOW_THREADS - iterator->dirp = opendir(path_str); - Py_END_ALLOW_THREADS - } - - if (!iterator->dirp) { - path_error(&iterator->path); -#ifdef HAVE_FDOPENDIR - if (fd != -1) { - Py_BEGIN_ALLOW_THREADS - close(fd); - Py_END_ALLOW_THREADS - } -#endif - goto error; - } -#endif - - return (PyObject *)iterator; - -error: - Py_DECREF(iterator); - return NULL; -} - -/* - Return the file system path representation of the object. - - If the object is str or bytes, then allow it to pass through with - an incremented refcount. If the object defines __fspath__(), then - return the result of that method. All other types raise a TypeError. -*/ -PyObject * -PyOS_FSPath(PyObject *path) -{ - /* For error message reasons, this function is manually inlined in - path_converter(). */ - PyObject *func = NULL; - PyObject *path_repr = NULL; - - if (PyUnicode_Check(path) || PyBytes_Check(path)) { - return Py_NewRef(path); - } - - func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__)); - if (NULL == func) { - return PyErr_Format(PyExc_TypeError, - "expected str, bytes or os.PathLike object, " - "not %.200s", - _PyType_Name(Py_TYPE(path))); - } - - path_repr = _PyObject_CallNoArgs(func); - Py_DECREF(func); - if (NULL == path_repr) { - return NULL; - } - - if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) { - PyErr_Format(PyExc_TypeError, - "expected %.200s.__fspath__() to return str or bytes, " - "not %.200s", _PyType_Name(Py_TYPE(path)), - _PyType_Name(Py_TYPE(path_repr))); - Py_DECREF(path_repr); - return NULL; - } - - return path_repr; -} - -/*[clinic input] -os.fspath - - path: object - -Return the file system path representation of the object. - -If the object is str or bytes, then allow it to pass through as-is. If the -object defines __fspath__(), then return the result of that method. All other -types raise a TypeError. -[clinic start generated code]*/ - -static PyObject * -os_fspath_impl(PyObject *module, PyObject *path) -/*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/ -{ - return PyOS_FSPath(path); -} - -#ifdef HAVE_GETRANDOM_SYSCALL -/*[clinic input] -os.getrandom - - size: Py_ssize_t - flags: int=0 - -Obtain a series of random bytes. -[clinic start generated code]*/ - -static PyObject * -os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags) -/*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/ -{ - PyObject *bytes; - Py_ssize_t n; - - if (size < 0) { - errno = EINVAL; - return posix_error(); - } - - bytes = PyBytes_FromStringAndSize(NULL, size); - if (bytes == NULL) { - PyErr_NoMemory(); - return NULL; - } - - while (1) { - n = syscall(SYS_getrandom, - PyBytes_AS_STRING(bytes), - PyBytes_GET_SIZE(bytes), - flags); - if (n < 0 && errno == EINTR) { - if (PyErr_CheckSignals() < 0) { - goto error; - } - - /* getrandom() was interrupted by a signal: retry */ - continue; - } - break; - } - - if (n < 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - if (n != size) { - _PyBytes_Resize(&bytes, n); - } - - return bytes; - -error: - Py_DECREF(bytes); - return NULL; -} -#endif /* HAVE_GETRANDOM_SYSCALL */ - -#ifdef MS_WINDOWS -/* bpo-36085: Helper functions for managing DLL search directories - * on win32 - */ - -typedef DLL_DIRECTORY_COOKIE (WINAPI *PAddDllDirectory)(PCWSTR newDirectory); -typedef BOOL (WINAPI *PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie); - -/*[clinic input] -os._add_dll_directory - - path: path_t - -Add a path to the DLL search path. - -This search path is used when resolving dependencies for imported -extension modules (the module itself is resolved through sys.path), -and also by ctypes. - -Returns an opaque value that may be passed to os.remove_dll_directory -to remove this directory from the search path. -[clinic start generated code]*/ - -static PyObject * -os__add_dll_directory_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/ -{ - HMODULE hKernel32; - PAddDllDirectory AddDllDirectory; - DLL_DIRECTORY_COOKIE cookie = 0; - DWORD err = 0; - - if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) { - return NULL; - } - - /* For Windows 7, we have to load this. As this will be a fairly - infrequent operation, just do it each time. Kernel32 is always - loaded. */ - Py_BEGIN_ALLOW_THREADS - if (!(hKernel32 = GetModuleHandleW(L"kernel32")) || - !(AddDllDirectory = (PAddDllDirectory)GetProcAddress( - hKernel32, "AddDllDirectory")) || - !(cookie = (*AddDllDirectory)(path->wide))) { - err = GetLastError(); - } - Py_END_ALLOW_THREADS - - if (err) { - return win32_error_object_err("add_dll_directory", - path->object, err); - } - - return PyCapsule_New(cookie, "DLL directory cookie", NULL); -} - -/*[clinic input] -os._remove_dll_directory - - cookie: object - -Removes a path from the DLL search path. - -The parameter is an opaque value that was returned from -os.add_dll_directory. You can only remove directories that you added -yourself. -[clinic start generated code]*/ - -static PyObject * -os__remove_dll_directory_impl(PyObject *module, PyObject *cookie) -/*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/ -{ - HMODULE hKernel32; - PRemoveDllDirectory RemoveDllDirectory; - DLL_DIRECTORY_COOKIE cookieValue; - DWORD err = 0; - - if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) { - PyErr_SetString(PyExc_TypeError, - "Provided cookie was not returned from os.add_dll_directory"); - return NULL; - } - - cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer( - cookie, "DLL directory cookie"); - - /* For Windows 7, we have to load this. As this will be a fairly - infrequent operation, just do it each time. Kernel32 is always - loaded. */ - Py_BEGIN_ALLOW_THREADS - if (!(hKernel32 = GetModuleHandleW(L"kernel32")) || - !(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress( - hKernel32, "RemoveDllDirectory")) || - !(*RemoveDllDirectory)(cookieValue)) { - err = GetLastError(); - } - Py_END_ALLOW_THREADS - - if (err) { - return win32_error_object_err("remove_dll_directory", - NULL, err); - } - - if (PyCapsule_SetName(cookie, NULL)) { - return NULL; - } - - Py_RETURN_NONE; -} - -#endif - - -/* Only check if WIFEXITED is available: expect that it comes - with WEXITSTATUS, WIFSIGNALED, etc. - - os.waitstatus_to_exitcode() is implemented in C and not in Python, so - subprocess can safely call it during late Python finalization without - risking that used os attributes were set to None by finalize_modules(). */ -#if defined(WIFEXITED) || defined(MS_WINDOWS) -/*[clinic input] -os.waitstatus_to_exitcode - - status as status_obj: object - -Convert a wait status to an exit code. - -On Unix: - -* If WIFEXITED(status) is true, return WEXITSTATUS(status). -* If WIFSIGNALED(status) is true, return -WTERMSIG(status). -* Otherwise, raise a ValueError. - -On Windows, return status shifted right by 8 bits. - -On Unix, if the process is being traced or if waitpid() was called with -WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true. -This function must not be called if WIFSTOPPED(status) is true. -[clinic start generated code]*/ - -static PyObject * -os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj) -/*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/ -{ -#ifndef MS_WINDOWS - int status = _PyLong_AsInt(status_obj); - if (status == -1 && PyErr_Occurred()) { - return NULL; - } - - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - int exitcode; - if (WIFEXITED(wait_status)) { - exitcode = WEXITSTATUS(wait_status); - /* Sanity check to provide warranty on the function behavior. - It should not occur in practice */ - if (exitcode < 0) { - PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode); - return NULL; - } - } - else if (WIFSIGNALED(wait_status)) { - int signum = WTERMSIG(wait_status); - /* Sanity check to provide warranty on the function behavior. - It should not occurs in practice */ - if (signum <= 0) { - PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum); - return NULL; - } - exitcode = -signum; - } else if (WIFSTOPPED(wait_status)) { - /* Status only received if the process is being traced - or if waitpid() was called with WUNTRACED option. */ - int signum = WSTOPSIG(wait_status); - PyErr_Format(PyExc_ValueError, - "process stopped by delivery of signal %i", - signum); - return NULL; - } - else { - PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status); - return NULL; - } - return PyLong_FromLong(exitcode); -#else - /* Windows implementation: see os.waitpid() implementation - which uses _cwait(). */ - unsigned long long status = PyLong_AsUnsignedLongLong(status_obj); - if (status == (unsigned long long)-1 && PyErr_Occurred()) { - return NULL; - } - - unsigned long long exitcode = (status >> 8); - /* ExitProcess() accepts an UINT type: - reject exit code which doesn't fit in an UINT */ - if (exitcode > UINT_MAX) { - PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode); - return NULL; - } - return PyLong_FromUnsignedLong((unsigned long)exitcode); -#endif -} -#endif - - -static PyMethodDef posix_methods[] = { - - OS_STAT_METHODDEF - OS_ACCESS_METHODDEF - OS_TTYNAME_METHODDEF - OS_CHDIR_METHODDEF - OS_CHFLAGS_METHODDEF - OS_CHMOD_METHODDEF - OS_FCHMOD_METHODDEF - OS_LCHMOD_METHODDEF - OS_CHOWN_METHODDEF - OS_FCHOWN_METHODDEF - OS_LCHOWN_METHODDEF - OS_LCHFLAGS_METHODDEF - OS_CHROOT_METHODDEF - OS_CTERMID_METHODDEF - OS_GETCWD_METHODDEF - OS_GETCWDB_METHODDEF - OS_LINK_METHODDEF - OS_LISTDIR_METHODDEF - OS_LSTAT_METHODDEF - OS_MKDIR_METHODDEF - OS_NICE_METHODDEF - OS_GETPRIORITY_METHODDEF - OS_SETPRIORITY_METHODDEF - OS_POSIX_SPAWN_METHODDEF - OS_POSIX_SPAWNP_METHODDEF - OS_READLINK_METHODDEF - OS_COPY_FILE_RANGE_METHODDEF - OS_SPLICE_METHODDEF - OS_RENAME_METHODDEF - OS_REPLACE_METHODDEF - OS_RMDIR_METHODDEF - OS_SYMLINK_METHODDEF - OS_SYSTEM_METHODDEF - OS_UMASK_METHODDEF - OS_UNAME_METHODDEF - OS_UNLINK_METHODDEF - OS_REMOVE_METHODDEF - OS_UTIME_METHODDEF - OS_TIMES_METHODDEF - OS__EXIT_METHODDEF - OS__FCOPYFILE_METHODDEF - OS_EXECV_METHODDEF - OS_EXECVE_METHODDEF - OS_SPAWNV_METHODDEF - OS_SPAWNVE_METHODDEF - OS_FORK1_METHODDEF - OS_FORK_METHODDEF - OS_REGISTER_AT_FORK_METHODDEF - OS_SCHED_GET_PRIORITY_MAX_METHODDEF - OS_SCHED_GET_PRIORITY_MIN_METHODDEF - OS_SCHED_GETPARAM_METHODDEF - OS_SCHED_GETSCHEDULER_METHODDEF - OS_SCHED_RR_GET_INTERVAL_METHODDEF - OS_SCHED_SETPARAM_METHODDEF - OS_SCHED_SETSCHEDULER_METHODDEF - OS_SCHED_YIELD_METHODDEF - OS_SCHED_SETAFFINITY_METHODDEF - OS_SCHED_GETAFFINITY_METHODDEF - OS_OPENPTY_METHODDEF - OS_LOGIN_TTY_METHODDEF - OS_FORKPTY_METHODDEF - OS_GETEGID_METHODDEF - OS_GETEUID_METHODDEF - OS_GETGID_METHODDEF - OS_GETGROUPLIST_METHODDEF - OS_GETGROUPS_METHODDEF - OS_GETPID_METHODDEF - OS_GETPGRP_METHODDEF - OS_GETPPID_METHODDEF - OS_GETUID_METHODDEF - OS_GETLOGIN_METHODDEF - OS_KILL_METHODDEF - OS_KILLPG_METHODDEF - OS_PLOCK_METHODDEF - OS_STARTFILE_METHODDEF - OS_SETUID_METHODDEF - OS_SETEUID_METHODDEF - OS_SETREUID_METHODDEF - OS_SETGID_METHODDEF - OS_SETEGID_METHODDEF - OS_SETREGID_METHODDEF - OS_SETGROUPS_METHODDEF - OS_INITGROUPS_METHODDEF - OS_GETPGID_METHODDEF - OS_SETPGRP_METHODDEF - OS_WAIT_METHODDEF - OS_WAIT3_METHODDEF - OS_WAIT4_METHODDEF - OS_WAITID_METHODDEF - OS_WAITPID_METHODDEF - OS_PIDFD_OPEN_METHODDEF - OS_GETSID_METHODDEF - OS_SETSID_METHODDEF - OS_SETPGID_METHODDEF - OS_TCGETPGRP_METHODDEF - OS_TCSETPGRP_METHODDEF - OS_OPEN_METHODDEF - OS_CLOSE_METHODDEF - OS_CLOSERANGE_METHODDEF - OS_DEVICE_ENCODING_METHODDEF - OS_DUP_METHODDEF - OS_DUP2_METHODDEF - OS_LOCKF_METHODDEF - OS_LSEEK_METHODDEF - OS_READ_METHODDEF - OS_READV_METHODDEF - OS_PREAD_METHODDEF - OS_PREADV_METHODDEF - OS_WRITE_METHODDEF - OS_WRITEV_METHODDEF - OS_PWRITE_METHODDEF - OS_PWRITEV_METHODDEF - OS_SENDFILE_METHODDEF - OS_FSTAT_METHODDEF - OS_ISATTY_METHODDEF - OS_PIPE_METHODDEF - OS_PIPE2_METHODDEF - OS_MKFIFO_METHODDEF - OS_MKNOD_METHODDEF - OS_MAJOR_METHODDEF - OS_MINOR_METHODDEF - OS_MAKEDEV_METHODDEF - OS_FTRUNCATE_METHODDEF - OS_TRUNCATE_METHODDEF - OS_POSIX_FALLOCATE_METHODDEF - OS_POSIX_FADVISE_METHODDEF - OS_PUTENV_METHODDEF - OS_UNSETENV_METHODDEF - OS_STRERROR_METHODDEF - OS_FCHDIR_METHODDEF - OS_FSYNC_METHODDEF - OS_SYNC_METHODDEF - OS_FDATASYNC_METHODDEF - OS_WCOREDUMP_METHODDEF - OS_WIFCONTINUED_METHODDEF - OS_WIFSTOPPED_METHODDEF - OS_WIFSIGNALED_METHODDEF - OS_WIFEXITED_METHODDEF - OS_WEXITSTATUS_METHODDEF - OS_WTERMSIG_METHODDEF - OS_WSTOPSIG_METHODDEF - OS_FSTATVFS_METHODDEF - OS_STATVFS_METHODDEF - OS_CONFSTR_METHODDEF - OS_SYSCONF_METHODDEF - OS_FPATHCONF_METHODDEF - OS_PATHCONF_METHODDEF - OS_ABORT_METHODDEF - OS__GETFULLPATHNAME_METHODDEF - OS__GETDISKUSAGE_METHODDEF - OS__GETFINALPATHNAME_METHODDEF - OS__GETVOLUMEPATHNAME_METHODDEF - OS__PATH_SPLITROOT_METHODDEF - OS__PATH_NORMPATH_METHODDEF - OS_GETLOADAVG_METHODDEF - OS_URANDOM_METHODDEF - OS_SETRESUID_METHODDEF - OS_SETRESGID_METHODDEF - OS_GETRESUID_METHODDEF - OS_GETRESGID_METHODDEF - - OS_GETXATTR_METHODDEF - OS_SETXATTR_METHODDEF - OS_REMOVEXATTR_METHODDEF - OS_LISTXATTR_METHODDEF - - OS_GET_TERMINAL_SIZE_METHODDEF - OS_CPU_COUNT_METHODDEF - OS_GET_INHERITABLE_METHODDEF - OS_SET_INHERITABLE_METHODDEF - OS_GET_HANDLE_INHERITABLE_METHODDEF - OS_SET_HANDLE_INHERITABLE_METHODDEF - OS_GET_BLOCKING_METHODDEF - OS_SET_BLOCKING_METHODDEF - OS_SCANDIR_METHODDEF - OS_FSPATH_METHODDEF - OS_GETRANDOM_METHODDEF - OS_MEMFD_CREATE_METHODDEF - OS_EVENTFD_METHODDEF - OS_EVENTFD_READ_METHODDEF - OS_EVENTFD_WRITE_METHODDEF - OS__ADD_DLL_DIRECTORY_METHODDEF - OS__REMOVE_DLL_DIRECTORY_METHODDEF - OS_WAITSTATUS_TO_EXITCODE_METHODDEF - OS_SETNS_METHODDEF - OS_UNSHARE_METHODDEF - {NULL, NULL} /* Sentinel */ -}; - -static int -all_ins(PyObject *m) -{ -#ifdef F_OK - if (PyModule_AddIntMacro(m, F_OK)) return -1; -#endif -#ifdef R_OK - if (PyModule_AddIntMacro(m, R_OK)) return -1; -#endif -#ifdef W_OK - if (PyModule_AddIntMacro(m, W_OK)) return -1; -#endif -#ifdef X_OK - if (PyModule_AddIntMacro(m, X_OK)) return -1; -#endif -#ifdef NGROUPS_MAX - if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1; -#endif -#ifdef TMP_MAX - if (PyModule_AddIntMacro(m, TMP_MAX)) return -1; -#endif -#ifdef WCONTINUED - if (PyModule_AddIntMacro(m, WCONTINUED)) return -1; -#endif -#ifdef WNOHANG - if (PyModule_AddIntMacro(m, WNOHANG)) return -1; -#endif -#ifdef WUNTRACED - if (PyModule_AddIntMacro(m, WUNTRACED)) return -1; -#endif -#ifdef O_RDONLY - if (PyModule_AddIntMacro(m, O_RDONLY)) return -1; -#endif -#ifdef O_WRONLY - if (PyModule_AddIntMacro(m, O_WRONLY)) return -1; -#endif -#ifdef O_RDWR - if (PyModule_AddIntMacro(m, O_RDWR)) return -1; -#endif -#ifdef O_NDELAY - if (PyModule_AddIntMacro(m, O_NDELAY)) return -1; -#endif -#ifdef O_NONBLOCK - if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1; -#endif -#ifdef O_APPEND - if (PyModule_AddIntMacro(m, O_APPEND)) return -1; -#endif -#ifdef O_DSYNC - if (PyModule_AddIntMacro(m, O_DSYNC)) return -1; -#endif -#ifdef O_RSYNC - if (PyModule_AddIntMacro(m, O_RSYNC)) return -1; -#endif -#ifdef O_SYNC - if (PyModule_AddIntMacro(m, O_SYNC)) return -1; -#endif -#ifdef O_NOCTTY - if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1; -#endif -#ifdef O_CREAT - if (PyModule_AddIntMacro(m, O_CREAT)) return -1; -#endif -#ifdef O_EXCL - if (PyModule_AddIntMacro(m, O_EXCL)) return -1; -#endif -#ifdef O_TRUNC - if (PyModule_AddIntMacro(m, O_TRUNC)) return -1; -#endif -#ifdef O_BINARY - if (PyModule_AddIntMacro(m, O_BINARY)) return -1; -#endif -#ifdef O_TEXT - if (PyModule_AddIntMacro(m, O_TEXT)) return -1; -#endif -#ifdef O_XATTR - if (PyModule_AddIntMacro(m, O_XATTR)) return -1; -#endif -#ifdef O_LARGEFILE - if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1; -#endif -#ifndef __GNU__ -#ifdef O_SHLOCK - if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1; -#endif -#ifdef O_EXLOCK - if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1; -#endif -#endif -#ifdef O_EXEC - if (PyModule_AddIntMacro(m, O_EXEC)) return -1; -#endif -#ifdef O_SEARCH - if (PyModule_AddIntMacro(m, O_SEARCH)) return -1; -#endif -#ifdef O_PATH - if (PyModule_AddIntMacro(m, O_PATH)) return -1; -#endif -#ifdef O_TTY_INIT - if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1; -#endif -#ifdef O_TMPFILE - if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1; -#endif -#ifdef PRIO_PROCESS - if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1; -#endif -#ifdef PRIO_PGRP - if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1; -#endif -#ifdef PRIO_USER - if (PyModule_AddIntMacro(m, PRIO_USER)) return -1; -#endif -#ifdef O_CLOEXEC - if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1; -#endif -#ifdef O_ACCMODE - if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1; -#endif -#ifdef O_EVTONLY - if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1; -#endif -#ifdef O_FSYNC - if (PyModule_AddIntMacro(m, O_FSYNC)) return -1; -#endif -#ifdef O_SYMLINK - if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1; -#endif - -#ifdef SEEK_HOLE - if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1; -#endif -#ifdef SEEK_DATA - if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1; -#endif - -/* MS Windows */ -#ifdef O_NOINHERIT - /* Don't inherit in child processes. */ - if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1; -#endif -#ifdef _O_SHORT_LIVED - /* Optimize for short life (keep in memory). */ - /* MS forgot to define this one with a non-underscore form too. */ - if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1; -#endif -#ifdef O_TEMPORARY - /* Automatically delete when last handle is closed. */ - if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1; -#endif -#ifdef O_RANDOM - /* Optimize for random access. */ - if (PyModule_AddIntMacro(m, O_RANDOM)) return -1; -#endif -#ifdef O_SEQUENTIAL - /* Optimize for sequential access. */ - if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1; -#endif - -/* GNU extensions. */ -#ifdef O_ASYNC - /* Send a SIGIO signal whenever input or output - becomes available on file descriptor */ - if (PyModule_AddIntMacro(m, O_ASYNC)) return -1; -#endif -#ifdef O_DIRECT - /* Direct disk access. */ - if (PyModule_AddIntMacro(m, O_DIRECT)) return -1; -#endif -#ifdef O_DIRECTORY - /* Must be a directory. */ - if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1; -#endif -#ifdef O_NOFOLLOW - /* Do not follow links. */ - if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1; -#endif -#ifdef O_NOFOLLOW_ANY - if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1; -#endif -#ifdef O_NOLINKS - /* Fails if link count of the named file is greater than 1 */ - if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1; -#endif -#ifdef O_NOATIME - /* Do not update the access time. */ - if (PyModule_AddIntMacro(m, O_NOATIME)) return -1; -#endif - - /* These come from sysexits.h */ -#ifdef EX_OK - if (PyModule_AddIntMacro(m, EX_OK)) return -1; -#endif /* EX_OK */ -#ifdef EX_USAGE - if (PyModule_AddIntMacro(m, EX_USAGE)) return -1; -#endif /* EX_USAGE */ -#ifdef EX_DATAERR - if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1; -#endif /* EX_DATAERR */ -#ifdef EX_NOINPUT - if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1; -#endif /* EX_NOINPUT */ -#ifdef EX_NOUSER - if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1; -#endif /* EX_NOUSER */ -#ifdef EX_NOHOST - if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1; -#endif /* EX_NOHOST */ -#ifdef EX_UNAVAILABLE - if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1; -#endif /* EX_UNAVAILABLE */ -#ifdef EX_SOFTWARE - if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1; -#endif /* EX_SOFTWARE */ -#ifdef EX_OSERR - if (PyModule_AddIntMacro(m, EX_OSERR)) return -1; -#endif /* EX_OSERR */ -#ifdef EX_OSFILE - if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1; -#endif /* EX_OSFILE */ -#ifdef EX_CANTCREAT - if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1; -#endif /* EX_CANTCREAT */ -#ifdef EX_IOERR - if (PyModule_AddIntMacro(m, EX_IOERR)) return -1; -#endif /* EX_IOERR */ -#ifdef EX_TEMPFAIL - if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1; -#endif /* EX_TEMPFAIL */ -#ifdef EX_PROTOCOL - if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1; -#endif /* EX_PROTOCOL */ -#ifdef EX_NOPERM - if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1; -#endif /* EX_NOPERM */ -#ifdef EX_CONFIG - if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1; -#endif /* EX_CONFIG */ -#ifdef EX_NOTFOUND - if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1; -#endif /* EX_NOTFOUND */ - - /* statvfs */ -#ifdef ST_RDONLY - if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1; -#endif /* ST_RDONLY */ -#ifdef ST_NOSUID - if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1; -#endif /* ST_NOSUID */ - - /* GNU extensions */ -#ifdef ST_NODEV - if (PyModule_AddIntMacro(m, ST_NODEV)) return -1; -#endif /* ST_NODEV */ -#ifdef ST_NOEXEC - if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1; -#endif /* ST_NOEXEC */ -#ifdef ST_SYNCHRONOUS - if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1; -#endif /* ST_SYNCHRONOUS */ -#ifdef ST_MANDLOCK - if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1; -#endif /* ST_MANDLOCK */ -#ifdef ST_WRITE - if (PyModule_AddIntMacro(m, ST_WRITE)) return -1; -#endif /* ST_WRITE */ -#ifdef ST_APPEND - if (PyModule_AddIntMacro(m, ST_APPEND)) return -1; -#endif /* ST_APPEND */ -#ifdef ST_NOATIME - if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1; -#endif /* ST_NOATIME */ -#ifdef ST_NODIRATIME - if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1; -#endif /* ST_NODIRATIME */ -#ifdef ST_RELATIME - if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1; -#endif /* ST_RELATIME */ - - /* FreeBSD sendfile() constants */ -#ifdef SF_NODISKIO - if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1; -#endif - /* is obsolete since the 11.x release */ -#ifdef SF_MNOWAIT - if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1; -#endif -#ifdef SF_SYNC - if (PyModule_AddIntMacro(m, SF_SYNC)) return -1; -#endif -#ifdef SF_NOCACHE - if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1; -#endif - - /* constants for posix_fadvise */ -#ifdef POSIX_FADV_NORMAL - if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1; -#endif -#ifdef POSIX_FADV_SEQUENTIAL - if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1; -#endif -#ifdef POSIX_FADV_RANDOM - if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1; -#endif -#ifdef POSIX_FADV_NOREUSE - if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1; -#endif -#ifdef POSIX_FADV_WILLNEED - if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1; -#endif -#ifdef POSIX_FADV_DONTNEED - if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1; -#endif - - /* constants for waitid */ -#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID) - if (PyModule_AddIntMacro(m, P_PID)) return -1; - if (PyModule_AddIntMacro(m, P_PGID)) return -1; - if (PyModule_AddIntMacro(m, P_ALL)) return -1; -#ifdef P_PIDFD - if (PyModule_AddIntMacro(m, P_PIDFD)) return -1; -#endif -#ifdef PIDFD_NONBLOCK - if (PyModule_AddIntMacro(m, PIDFD_NONBLOCK)) return -1; -#endif -#endif -#ifdef WEXITED - if (PyModule_AddIntMacro(m, WEXITED)) return -1; -#endif -#ifdef WNOWAIT - if (PyModule_AddIntMacro(m, WNOWAIT)) return -1; -#endif -#ifdef WSTOPPED - if (PyModule_AddIntMacro(m, WSTOPPED)) return -1; -#endif -#ifdef CLD_EXITED - if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1; -#endif -#ifdef CLD_KILLED - if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1; -#endif -#ifdef CLD_DUMPED - if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1; -#endif -#ifdef CLD_TRAPPED - if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1; -#endif -#ifdef CLD_STOPPED - if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1; -#endif -#ifdef CLD_CONTINUED - if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1; -#endif - - /* constants for lockf */ -#ifdef F_LOCK - if (PyModule_AddIntMacro(m, F_LOCK)) return -1; -#endif -#ifdef F_TLOCK - if (PyModule_AddIntMacro(m, F_TLOCK)) return -1; -#endif -#ifdef F_ULOCK - if (PyModule_AddIntMacro(m, F_ULOCK)) return -1; -#endif -#ifdef F_TEST - if (PyModule_AddIntMacro(m, F_TEST)) return -1; -#endif - -#ifdef RWF_DSYNC - if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1; -#endif -#ifdef RWF_HIPRI - if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1; -#endif -#ifdef RWF_SYNC - if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1; -#endif -#ifdef RWF_NOWAIT - if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1; -#endif -#ifdef RWF_APPEND - if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1; -#endif - -/* constants for splice */ -#if defined(HAVE_SPLICE) && defined(__linux__) - if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1; - if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1; - if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1; -#endif - -/* constants for posix_spawn */ -#ifdef HAVE_POSIX_SPAWN - if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1; - if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1; - if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1; -#endif - -#if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN) - if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1; - if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1; - if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1; -#endif -#ifdef HAVE_SPAWNV - if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1; - if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1; -#endif - -#ifdef HAVE_SCHED_H -#ifdef SCHED_OTHER - if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1; -#endif -#ifdef SCHED_FIFO - if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1; -#endif -#ifdef SCHED_RR - if (PyModule_AddIntMacro(m, SCHED_RR)) return -1; -#endif -#ifdef SCHED_SPORADIC - if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1; -#endif -#ifdef SCHED_BATCH - if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1; -#endif -#ifdef SCHED_IDLE - if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1; -#endif -#ifdef SCHED_RESET_ON_FORK - if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1; -#endif -#ifdef SCHED_SYS - if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1; -#endif -#ifdef SCHED_IA - if (PyModule_AddIntMacro(m, SCHED_IA)) return -1; -#endif -#ifdef SCHED_FSS - if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1; -#endif -#ifdef SCHED_FX - if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1; -#endif - -/* constants for namespaces */ -#if defined(HAVE_SETNS) || defined(HAVE_UNSHARE) -#ifdef CLONE_FS - if (PyModule_AddIntMacro(m, CLONE_FS)) return -1; -#endif -#ifdef CLONE_FILES - if (PyModule_AddIntMacro(m, CLONE_FILES)) return -1; -#endif -#ifdef CLONE_NEWNS - if (PyModule_AddIntMacro(m, CLONE_NEWNS)) return -1; -#endif -#ifdef CLONE_NEWCGROUP - if (PyModule_AddIntMacro(m, CLONE_NEWCGROUP)) return -1; -#endif -#ifdef CLONE_NEWUTS - if (PyModule_AddIntMacro(m, CLONE_NEWUTS)) return -1; -#endif -#ifdef CLONE_NEWIPC - if (PyModule_AddIntMacro(m, CLONE_NEWIPC)) return -1; -#endif -#ifdef CLONE_NEWUSER - if (PyModule_AddIntMacro(m, CLONE_NEWUSER)) return -1; -#endif -#ifdef CLONE_NEWPID - if (PyModule_AddIntMacro(m, CLONE_NEWPID)) return -1; -#endif -#ifdef CLONE_NEWNET - if (PyModule_AddIntMacro(m, CLONE_NEWNET)) return -1; -#endif -#ifdef CLONE_NEWTIME - if (PyModule_AddIntMacro(m, CLONE_NEWTIME)) return -1; -#endif -#ifdef CLONE_SYSVSEM - if (PyModule_AddIntMacro(m, CLONE_SYSVSEM)) return -1; -#endif -#ifdef CLONE_THREAD - if (PyModule_AddIntMacro(m, CLONE_THREAD)) return -1; -#endif -#ifdef CLONE_SIGHAND - if (PyModule_AddIntMacro(m, CLONE_SIGHAND)) return -1; -#endif -#ifdef CLONE_VM - if (PyModule_AddIntMacro(m, CLONE_VM)) return -1; -#endif -#endif - -#endif - -#ifdef USE_XATTRS - if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1; - if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1; - if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1; -#endif - -#if HAVE_DECL_RTLD_LAZY - if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1; -#endif -#if HAVE_DECL_RTLD_NOW - if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1; -#endif -#if HAVE_DECL_RTLD_GLOBAL - if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1; -#endif -#if HAVE_DECL_RTLD_LOCAL - if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1; -#endif -#if HAVE_DECL_RTLD_NODELETE - if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1; -#endif -#if HAVE_DECL_RTLD_NOLOAD - if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1; -#endif -#if HAVE_DECL_RTLD_DEEPBIND - if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1; -#endif -#if HAVE_DECL_RTLD_MEMBER - if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1; -#endif - -#ifdef HAVE_GETRANDOM_SYSCALL - if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1; - if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1; -#endif -#ifdef HAVE_MEMFD_CREATE - if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1; - if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1; -#ifdef MFD_HUGETLB - if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1; -#endif -#ifdef MFD_HUGE_SHIFT - if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1; -#endif -#ifdef MFD_HUGE_MASK - if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1; -#endif -#ifdef MFD_HUGE_64KB - if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1; -#endif -#ifdef MFD_HUGE_512KB - if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1; -#endif -#ifdef MFD_HUGE_1MB - if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1; -#endif -#ifdef MFD_HUGE_2MB - if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1; -#endif -#ifdef MFD_HUGE_8MB - if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1; -#endif -#ifdef MFD_HUGE_16MB - if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1; -#endif -#ifdef MFD_HUGE_32MB - if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1; -#endif -#ifdef MFD_HUGE_256MB - if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1; -#endif -#ifdef MFD_HUGE_512MB - if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1; -#endif -#ifdef MFD_HUGE_1GB - if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1; -#endif -#ifdef MFD_HUGE_2GB - if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1; -#endif -#ifdef MFD_HUGE_16GB - if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1; -#endif -#endif /* HAVE_MEMFD_CREATE */ - -#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC) - if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1; -#ifdef EFD_NONBLOCK - if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1; -#endif -#ifdef EFD_SEMAPHORE - if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1; -#endif -#endif /* HAVE_EVENTFD && EFD_CLOEXEC */ - -#if defined(__APPLE__) - if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1; - if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1; - if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1; - if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1; -#endif - -#ifdef MS_WINDOWS - if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1; - if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1; - if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1; - if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1; - if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1; -#endif - - return 0; -} - - - -#define PROBE(name, test) \ - static int name(void) \ - { \ - if (test) { \ - return 1; \ - } else { \ - return 0; \ - } \ - } - -#ifdef HAVE_FSTATAT -PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME) -#endif - -#ifdef HAVE_FACCESSAT -PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME) -#endif - -#ifdef HAVE_FCHMODAT -PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME) -#endif - -#ifdef HAVE_FCHOWNAT -PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME) -#endif - -#ifdef HAVE_LINKAT -PROBE(probe_linkat, HAVE_LINKAT_RUNTIME) -#endif - -#ifdef HAVE_FDOPENDIR -PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME) -#endif - -#ifdef HAVE_MKDIRAT -PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME) -#endif - -#ifdef HAVE_MKFIFOAT -PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME) -#endif - -#ifdef HAVE_MKNODAT -PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME) -#endif - -#ifdef HAVE_RENAMEAT -PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME) -#endif - -#ifdef HAVE_UNLINKAT -PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME) -#endif - -#ifdef HAVE_OPENAT -PROBE(probe_openat, HAVE_OPENAT_RUNTIME) -#endif - -#ifdef HAVE_READLINKAT -PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME) -#endif - -#ifdef HAVE_SYMLINKAT -PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME) -#endif - -#ifdef HAVE_FUTIMENS -PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME) -#endif - -#ifdef HAVE_UTIMENSAT -PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME) -#endif - - - - -static const struct have_function { - const char * const label; - int (*probe)(void); -} have_functions[] = { - -#ifdef HAVE_EVENTFD - {"HAVE_EVENTFD", NULL}, -#endif - -#ifdef HAVE_FACCESSAT - { "HAVE_FACCESSAT", probe_faccessat }, -#endif - -#ifdef HAVE_FCHDIR - { "HAVE_FCHDIR", NULL }, -#endif - -#ifdef HAVE_FCHMOD - { "HAVE_FCHMOD", NULL }, -#endif - -#ifdef HAVE_FCHMODAT - { "HAVE_FCHMODAT", probe_fchmodat }, -#endif - -#ifdef HAVE_FCHOWN - { "HAVE_FCHOWN", NULL }, -#endif - -#ifdef HAVE_FCHOWNAT - { "HAVE_FCHOWNAT", probe_fchownat }, -#endif - -#ifdef HAVE_FEXECVE - { "HAVE_FEXECVE", NULL }, -#endif - -#ifdef HAVE_FDOPENDIR - { "HAVE_FDOPENDIR", probe_fdopendir }, -#endif - -#ifdef HAVE_FPATHCONF - { "HAVE_FPATHCONF", NULL }, -#endif - -#ifdef HAVE_FSTATAT - { "HAVE_FSTATAT", probe_fstatat }, -#endif - -#ifdef HAVE_FSTATVFS - { "HAVE_FSTATVFS", NULL }, -#endif - -#if defined HAVE_FTRUNCATE || defined MS_WINDOWS - { "HAVE_FTRUNCATE", NULL }, -#endif - -#ifdef HAVE_FUTIMENS - { "HAVE_FUTIMENS", probe_futimens }, -#endif - -#ifdef HAVE_FUTIMES - { "HAVE_FUTIMES", NULL }, -#endif - -#ifdef HAVE_FUTIMESAT - { "HAVE_FUTIMESAT", NULL }, -#endif - -#ifdef HAVE_LINKAT - { "HAVE_LINKAT", probe_linkat }, -#endif - -#ifdef HAVE_LCHFLAGS - { "HAVE_LCHFLAGS", NULL }, -#endif - -#ifdef HAVE_LCHMOD - { "HAVE_LCHMOD", NULL }, -#endif - -#ifdef HAVE_LCHOWN - { "HAVE_LCHOWN", NULL }, -#endif - -#ifdef HAVE_LSTAT - { "HAVE_LSTAT", NULL }, -#endif - -#ifdef HAVE_LUTIMES - { "HAVE_LUTIMES", NULL }, -#endif - -#ifdef HAVE_MEMFD_CREATE - { "HAVE_MEMFD_CREATE", NULL }, -#endif - -#ifdef HAVE_MKDIRAT - { "HAVE_MKDIRAT", probe_mkdirat }, -#endif - -#ifdef HAVE_MKFIFOAT - { "HAVE_MKFIFOAT", probe_mkfifoat }, -#endif - -#ifdef HAVE_MKNODAT - { "HAVE_MKNODAT", probe_mknodat }, -#endif - -#ifdef HAVE_OPENAT - { "HAVE_OPENAT", probe_openat }, -#endif - -#ifdef HAVE_READLINKAT - { "HAVE_READLINKAT", probe_readlinkat }, -#endif - -#ifdef HAVE_RENAMEAT - { "HAVE_RENAMEAT", probe_renameat }, -#endif - -#ifdef HAVE_SYMLINKAT - { "HAVE_SYMLINKAT", probe_symlinkat }, -#endif - -#ifdef HAVE_UNLINKAT - { "HAVE_UNLINKAT", probe_unlinkat }, -#endif - -#ifdef HAVE_UTIMENSAT - { "HAVE_UTIMENSAT", probe_utimensat }, -#endif - -#ifdef MS_WINDOWS - { "MS_WINDOWS", NULL }, -#endif - - { NULL, NULL } -}; - - -static int -posixmodule_exec(PyObject *m) -{ - _posixstate *state = get_posix_state(m); - -#if defined(HAVE_PWRITEV) - if (HAVE_PWRITEV_RUNTIME) {} else { - PyObject* dct = PyModule_GetDict(m); - - if (dct == NULL) { - return -1; - } - - if (PyDict_DelItemString(dct, "pwritev") == -1) { - PyErr_Clear(); - } - if (PyDict_DelItemString(dct, "preadv") == -1) { - PyErr_Clear(); - } - } -#endif - - /* Initialize environ dictionary */ - PyObject *v = convertenviron(); - Py_XINCREF(v); - if (v == NULL || PyModule_AddObject(m, "environ", v) != 0) - return -1; - Py_DECREF(v); - - if (all_ins(m)) - return -1; - - if (setup_confname_tables(m)) - return -1; - - PyModule_AddObject(m, "error", Py_NewRef(PyExc_OSError)); - -#if defined(HAVE_WAITID) && !defined(__APPLE__) - waitid_result_desc.name = MODNAME ".waitid_result"; - PyObject *WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc); - if (WaitidResultType == NULL) { - return -1; - } - PyModule_AddObject(m, "waitid_result", Py_NewRef(WaitidResultType)); - state->WaitidResultType = WaitidResultType; -#endif - - stat_result_desc.name = "os.stat_result"; /* see issue #19209 */ - stat_result_desc.fields[7].name = PyStructSequence_UnnamedField; - stat_result_desc.fields[8].name = PyStructSequence_UnnamedField; - stat_result_desc.fields[9].name = PyStructSequence_UnnamedField; - PyObject *StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc); - if (StatResultType == NULL) { - return -1; - } - PyModule_AddObject(m, "stat_result", Py_NewRef(StatResultType)); - state->StatResultType = StatResultType; - structseq_new = ((PyTypeObject *)StatResultType)->tp_new; - ((PyTypeObject *)StatResultType)->tp_new = statresult_new; - - statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */ - PyObject *StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc); - if (StatVFSResultType == NULL) { - return -1; - } - PyModule_AddObject(m, "statvfs_result", Py_NewRef(StatVFSResultType)); - state->StatVFSResultType = StatVFSResultType; -#ifdef NEED_TICKS_PER_SECOND -# if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK) - ticks_per_second = sysconf(_SC_CLK_TCK); -# elif defined(HZ) - ticks_per_second = HZ; -# else - ticks_per_second = 60; /* magic fallback value; may be bogus */ -# endif -#endif - -#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) - sched_param_desc.name = MODNAME ".sched_param"; - PyObject *SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc); - if (SchedParamType == NULL) { - return -1; - } - PyModule_AddObject(m, "sched_param", Py_NewRef(SchedParamType)); - state->SchedParamType = SchedParamType; - ((PyTypeObject *)SchedParamType)->tp_new = os_sched_param; -#endif - - /* initialize TerminalSize_info */ - PyObject *TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc); - if (TerminalSizeType == NULL) { - return -1; - } - PyModule_AddObject(m, "terminal_size", Py_NewRef(TerminalSizeType)); - state->TerminalSizeType = TerminalSizeType; - - /* initialize scandir types */ - PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL); - if (ScandirIteratorType == NULL) { - return -1; - } - state->ScandirIteratorType = ScandirIteratorType; - - PyObject *DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL); - if (DirEntryType == NULL) { - return -1; - } - PyModule_AddObject(m, "DirEntry", Py_NewRef(DirEntryType)); - state->DirEntryType = DirEntryType; - - times_result_desc.name = MODNAME ".times_result"; - PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(×_result_desc); - if (TimesResultType == NULL) { - return -1; - } - PyModule_AddObject(m, "times_result", Py_NewRef(TimesResultType)); - state->TimesResultType = TimesResultType; - - PyTypeObject *UnameResultType = PyStructSequence_NewType(&uname_result_desc); - if (UnameResultType == NULL) { - return -1; - } - ; - PyModule_AddObject(m, "uname_result", Py_NewRef(UnameResultType)); - state->UnameResultType = (PyObject *)UnameResultType; - - if ((state->billion = PyLong_FromLong(1000000000)) == NULL) - return -1; -#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) - state->struct_rusage = PyUnicode_InternFromString("struct_rusage"); - if (state->struct_rusage == NULL) - return -1; -#endif - state->st_mode = PyUnicode_InternFromString("st_mode"); - if (state->st_mode == NULL) - return -1; - - /* suppress "function not used" warnings */ - { - int ignored; - fd_specified("", -1); - follow_symlinks_specified("", 1); - dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1); - dir_fd_converter(Py_None, &ignored); - dir_fd_unavailable(Py_None, &ignored); - } - - /* - * provide list of locally available functions - * so os.py can populate support_* lists - */ - PyObject *list = PyList_New(0); - if (!list) { - return -1; - } - for (const struct have_function *trace = have_functions; trace->label; trace++) { - PyObject *unicode; - if (trace->probe && !trace->probe()) continue; - unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL); - if (!unicode) - return -1; - if (PyList_Append(list, unicode)) - return -1; - Py_DECREF(unicode); - } - - PyModule_AddObject(m, "_have_functions", list); - - return 0; -} - - -static PyModuleDef_Slot posixmodile_slots[] = { - {Py_mod_exec, posixmodule_exec}, - {0, NULL} -}; - -static struct PyModuleDef posixmodule = { - PyModuleDef_HEAD_INIT, - .m_name = MODNAME, - .m_doc = posix__doc__, - .m_size = sizeof(_posixstate), - .m_methods = posix_methods, - .m_slots = posixmodile_slots, - .m_traverse = _posix_traverse, - .m_clear = _posix_clear, - .m_free = _posix_free, -}; - -PyMODINIT_FUNC -INITFUNC(void) -{ - return PyModuleDef_Init(&posixmodule); -} - -#ifdef __cplusplus -} -#endif +/* POSIX module implementation */ + +/* This file is also used for Windows NT/MS-Win. In that case the + module actually calls itself 'nt', not 'posix', and a few + functions are either unimplemented or implemented differently. The source + assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent + of the compiler used. Different compilers define their own feature + test macro, e.g. '_MSC_VER'. */ + +#define PY_SSIZE_T_CLEAN + +#include "Python.h" +// Include before pycore internal headers. FSCTL_GET_REPARSE_POINT +// is not exported by if the WIN32_LEAN_AND_MEAN macro is defined, +// whereas pycore_condvar.h defines the WIN32_LEAN_AND_MEAN macro. +#ifdef MS_WINDOWS +# include +# include +#endif + +#ifdef __VXWORKS__ +# include "pycore_bitutils.h" // _Py_popcount32() +#endif +#include "pycore_call.h" // _PyObject_CallNoArgs() +#include "pycore_ceval.h" // _PyEval_ReInitThreads() +#include "pycore_fileutils.h" // _Py_closerange() +#include "pycore_import.h" // _PyImport_ReInitLock() +#include "pycore_initconfig.h" // _PyStatus_EXCEPTION() +#include "pycore_moduleobject.h" // _PyModule_GetState() +#include "pycore_object.h" // _PyObject_LookupSpecial() +#include "pycore_pystate.h" // _PyInterpreterState_GET() +#include "pycore_signal.h" // Py_NSIG + +#include "structmember.h" // PyMemberDef +#ifndef MS_WINDOWS +# include "posixmodule.h" +#else +# include "winreparse.h" +#endif + +#if !defined(EX_OK) && defined(EXIT_SUCCESS) +# define EX_OK EXIT_SUCCESS +#endif + +/* On android API level 21, 'AT_EACCESS' is not declared although + * HAVE_FACCESSAT is defined. */ +#ifdef __ANDROID__ +# undef HAVE_FACCESSAT +#endif + +#include // ctermid() +#include // system() + +/* + * A number of APIs are available on macOS from a certain macOS version. + * To support building with a new SDK while deploying to older versions + * the availability test is split into two: + * - HAVE_: The configure check for compile time availability + * - HAVE__RUNTIME: Runtime check for availability + * + * The latter is always true when not on macOS, or when using a compiler + * that does not support __has_builtin (older versions of Xcode). + * + * Due to compiler restrictions there is one valid use of HAVE__RUNTIME: + * if (HAVE__RUNTIME) { ... } + * + * In mixing the test with other tests or using negations will result in compile + * errors. + */ +#if defined(__APPLE__) + +#if defined(__has_builtin) +#if __has_builtin(__builtin_available) +#define HAVE_BUILTIN_AVAILABLE 1 +#endif +#endif + +#ifdef HAVE_BUILTIN_AVAILABLE +# define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) +# define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) +# define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) +# define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) +# define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) +# define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) +# define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) +# define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) +# define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) +# define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) +# define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) +# define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) +# define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *) +# define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *) +# define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *) +# define HAVE_MKFIFOAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *) +# define HAVE_MKNODAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *) + +# define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *) + +#else /* Xcode 8 or earlier */ + + /* __builtin_available is not present in these compilers, but + * some of the symbols might be weak linked (10.10 SDK or later + * deploying on 10.9. + * + * Fall back to the older style of availability checking for + * symbols introduced in macOS 10.10. + */ + +# ifdef HAVE_FSTATAT +# define HAVE_FSTATAT_RUNTIME (fstatat != NULL) +# endif + +# ifdef HAVE_FACCESSAT +# define HAVE_FACCESSAT_RUNTIME (faccessat != NULL) +# endif + +# ifdef HAVE_FCHMODAT +# define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL) +# endif + +# ifdef HAVE_FCHOWNAT +# define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL) +# endif + +# ifdef HAVE_LINKAT +# define HAVE_LINKAT_RUNTIME (linkat != NULL) +# endif + +# ifdef HAVE_FDOPENDIR +# define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL) +# endif + +# ifdef HAVE_MKDIRAT +# define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL) +# endif + +# ifdef HAVE_RENAMEAT +# define HAVE_RENAMEAT_RUNTIME (renameat != NULL) +# endif + +# ifdef HAVE_UNLINKAT +# define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL) +# endif + +# ifdef HAVE_OPENAT +# define HAVE_OPENAT_RUNTIME (openat != NULL) +# endif + +# ifdef HAVE_READLINKAT +# define HAVE_READLINKAT_RUNTIME (readlinkat != NULL) +# endif + +# ifdef HAVE_SYMLINKAT +# define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL) +# endif + +#endif + +#ifdef HAVE_FUTIMESAT +/* Some of the logic for weak linking depends on this assertion */ +# error "HAVE_FUTIMESAT unexpectedly defined" +#endif + +#else +# define HAVE_FSTATAT_RUNTIME 1 +# define HAVE_FACCESSAT_RUNTIME 1 +# define HAVE_FCHMODAT_RUNTIME 1 +# define HAVE_FCHOWNAT_RUNTIME 1 +# define HAVE_LINKAT_RUNTIME 1 +# define HAVE_FDOPENDIR_RUNTIME 1 +# define HAVE_MKDIRAT_RUNTIME 1 +# define HAVE_RENAMEAT_RUNTIME 1 +# define HAVE_UNLINKAT_RUNTIME 1 +# define HAVE_OPENAT_RUNTIME 1 +# define HAVE_READLINKAT_RUNTIME 1 +# define HAVE_SYMLINKAT_RUNTIME 1 +# define HAVE_FUTIMENS_RUNTIME 1 +# define HAVE_UTIMENSAT_RUNTIME 1 +# define HAVE_PWRITEV_RUNTIME 1 +# define HAVE_MKFIFOAT_RUNTIME 1 +# define HAVE_MKNODAT_RUNTIME 1 +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +PyDoc_STRVAR(posix__doc__, +"This module provides access to operating system functionality that is\n\ +standardized by the C Standard and the POSIX standard (a thinly\n\ +disguised Unix interface). Refer to the library manual and\n\ +corresponding Unix manual entries for more information on calls."); + + +#ifdef HAVE_SYS_UIO_H +# include +#endif + +#ifdef HAVE_SYS_SYSMACROS_H +/* GNU C Library: major(), minor(), makedev() */ +# include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif /* HAVE_SYS_TYPES_H */ + +#ifdef HAVE_SYS_STAT_H +# include +#endif /* HAVE_SYS_STAT_H */ + +#ifdef HAVE_SYS_WAIT_H +# include // WNOHANG +#endif +#ifdef HAVE_LINUX_WAIT_H +# include // P_PIDFD +#endif + +#ifdef HAVE_SIGNAL_H +# include +#endif + +#ifdef HAVE_FCNTL_H +# include +#endif + +#ifdef HAVE_GRP_H +# include +#endif + +#ifdef HAVE_SYSEXITS_H +# include +#endif + +#ifdef HAVE_SYS_LOADAVG_H +# include +#endif + +#ifdef HAVE_SYS_SENDFILE_H +# include +#endif + +#if defined(__APPLE__) +# include +#endif + +#ifdef HAVE_SCHED_H +# include +#endif + +#ifdef HAVE_COPY_FILE_RANGE +# include +#endif + +#if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY) +# undef HAVE_SCHED_SETAFFINITY +#endif + +#if defined(HAVE_SYS_XATTR_H) && defined(__GLIBC__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__) +# define USE_XATTRS +#endif + +#ifdef USE_XATTRS +# include +#endif + +#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) +# ifdef HAVE_SYS_SOCKET_H +# include +# endif +#endif + +#ifdef HAVE_DLFCN_H +# include +#endif + +#ifdef __hpux +# include +#endif + +#if defined(__DragonFly__) || \ + defined(__OpenBSD__) || \ + defined(__FreeBSD__) || \ + defined(__NetBSD__) || \ + defined(__APPLE__) +# include +#endif + +#ifdef HAVE_LINUX_RANDOM_H +# include +#endif +#ifdef HAVE_GETRANDOM_SYSCALL +# include +#endif + +#if defined(MS_WINDOWS) +# define TERMSIZE_USE_CONIO +#elif defined(HAVE_SYS_IOCTL_H) +# include +# if defined(HAVE_TERMIOS_H) +# include +# endif +# if defined(TIOCGWINSZ) +# define TERMSIZE_USE_IOCTL +# endif +#endif /* MS_WINDOWS */ + +/* Various compilers have only certain posix functions */ +/* XXX Gosh I wish these were all moved into pyconfig.h */ +#if defined(__WATCOMC__) && !defined(__QNX__) /* Watcom compiler */ +# define HAVE_OPENDIR 1 +# define HAVE_SYSTEM 1 +# include +#else +# ifdef _MSC_VER + /* Microsoft compiler */ +# define HAVE_GETPPID 1 +# define HAVE_GETLOGIN 1 +# define HAVE_SPAWNV 1 +# define HAVE_EXECV 1 +# define HAVE_WSPAWNV 1 +# define HAVE_WEXECV 1 +# define HAVE_PIPE 1 +# define HAVE_SYSTEM 1 +# define HAVE_CWAIT 1 +# define HAVE_FSYNC 1 +# define fsync _commit +# endif /* _MSC_VER */ +#endif /* ! __WATCOMC__ || __QNX__ */ + +/*[clinic input] +# one of the few times we lie about this name! +module os +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/ + +#ifndef _MSC_VER + +#if defined(__sgi)&&_COMPILER_VERSION>=700 +/* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode + (default) */ +extern char *ctermid_r(char *); +#endif + +#endif /* !_MSC_VER */ + +#if defined(__VXWORKS__) +# include +# include +# include +# include +# ifndef _P_WAIT +# define _P_WAIT 0 +# define _P_NOWAIT 1 +# define _P_NOWAITO 1 +# endif +#endif /* __VXWORKS__ */ + +#ifdef HAVE_POSIX_SPAWN +# include +#endif + +#ifdef HAVE_UTIME_H +# include +#endif /* HAVE_UTIME_H */ + +#ifdef HAVE_SYS_UTIME_H +# include +# define HAVE_UTIME_H /* pretend we do for the rest of this file */ +#endif /* HAVE_SYS_UTIME_H */ + +#ifdef HAVE_SYS_TIMES_H +# include +#endif /* HAVE_SYS_TIMES_H */ + +#ifdef HAVE_SYS_PARAM_H +# include +#endif /* HAVE_SYS_PARAM_H */ + +#ifdef HAVE_SYS_UTSNAME_H +# include +#endif /* HAVE_SYS_UTSNAME_H */ + +#ifdef HAVE_DIRENT_H +# include +# define NAMLEN(dirent) strlen((dirent)->d_name) +#else +# if defined(__WATCOMC__) && !defined(__QNX__) +# include +# define NAMLEN(dirent) strlen((dirent)->d_name) +# else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# endif +# ifdef HAVE_SYS_NDIR_H +# include +# endif +# ifdef HAVE_SYS_DIR_H +# include +# endif +# ifdef HAVE_NDIR_H +# include +# endif +#endif + +#ifdef _MSC_VER +# ifdef HAVE_DIRECT_H +# include +# endif +# ifdef HAVE_IO_H +# include +# endif +# ifdef HAVE_PROCESS_H +# include +# endif +# ifndef IO_REPARSE_TAG_SYMLINK +# define IO_REPARSE_TAG_SYMLINK (0xA000000CL) +# endif +# ifndef IO_REPARSE_TAG_MOUNT_POINT +# define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) +# endif +# include "osdefs.h" // SEP +# include +# include +# include // ShellExecute() +# include // UNLEN +# define HAVE_SYMLINK +#endif /* _MSC_VER */ + +#ifndef MAXPATHLEN +# if defined(PATH_MAX) && PATH_MAX > 1024 +# define MAXPATHLEN PATH_MAX +# else +# define MAXPATHLEN 1024 +# endif +#endif /* MAXPATHLEN */ + +#ifdef UNION_WAIT + /* Emulate some macros on systems that have a union instead of macros */ +# ifndef WIFEXITED +# define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump) +# endif +# ifndef WEXITSTATUS +# define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1) +# endif +# ifndef WTERMSIG +# define WTERMSIG(u_wait) ((u_wait).w_termsig) +# endif +# define WAIT_TYPE union wait +# define WAIT_STATUS_INT(s) (s.w_status) +#else + /* !UNION_WAIT */ +# define WAIT_TYPE int +# define WAIT_STATUS_INT(s) (s) +#endif /* UNION_WAIT */ + +/* Don't use the "_r" form if we don't need it (also, won't have a + prototype for it, at least on Solaris -- maybe others as well?). */ +#if defined(HAVE_CTERMID_R) +# define USE_CTERMID_R +#endif + +/* choose the appropriate stat and fstat functions and return structs */ +#undef STAT +#undef FSTAT +#undef STRUCT_STAT +#ifdef MS_WINDOWS +# define STAT win32_stat +# define LSTAT win32_lstat +# define FSTAT _Py_fstat_noraise +# define STRUCT_STAT struct _Py_stat_struct +#else +# define STAT stat +# define LSTAT lstat +# define FSTAT fstat +# define STRUCT_STAT struct stat +#endif + +#if defined(MAJOR_IN_MKDEV) +# include +#else +# if defined(MAJOR_IN_SYSMACROS) +# include +# endif +# if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H) +# include +# endif +#endif + +#ifdef MS_WINDOWS +# define INITFUNC PyInit_nt +# define MODNAME "nt" +#else +# define INITFUNC PyInit_posix +# define MODNAME "posix" +#endif + +#if defined(__sun) +/* Something to implement in autoconf, not present in autoconf 2.69 */ +# define HAVE_STRUCT_STAT_ST_FSTYPE 1 +#endif + +/* memfd_create is either defined in sys/mman.h or sys/memfd.h + * linux/memfd.h defines additional flags + */ +#ifdef HAVE_SYS_MMAN_H +# include +#endif +#ifdef HAVE_SYS_MEMFD_H +# include +#endif +#ifdef HAVE_LINUX_MEMFD_H +# include +#endif + +/* eventfd() */ +#ifdef HAVE_SYS_EVENTFD_H +# include +#endif + +#ifdef _Py_MEMORY_SANITIZER +# include +#endif + +#ifdef HAVE_FORK +static void +run_at_forkers(PyObject *lst, int reverse) +{ + Py_ssize_t i; + PyObject *cpy; + + if (lst != NULL) { + assert(PyList_CheckExact(lst)); + + /* Use a list copy in case register_at_fork() is called from + * one of the callbacks. + */ + cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst)); + if (cpy == NULL) + PyErr_WriteUnraisable(lst); + else { + if (reverse) + PyList_Reverse(cpy); + for (i = 0; i < PyList_GET_SIZE(cpy); i++) { + PyObject *func, *res; + func = PyList_GET_ITEM(cpy, i); + res = _PyObject_CallNoArgs(func); + if (res == NULL) + PyErr_WriteUnraisable(func); + else + Py_DECREF(res); + } + Py_DECREF(cpy); + } + } +} + +void +PyOS_BeforeFork(void) +{ + run_at_forkers(_PyInterpreterState_GET()->before_forkers, 1); + + _PyImport_AcquireLock(); +} + +void +PyOS_AfterFork_Parent(void) +{ + if (_PyImport_ReleaseLock() <= 0) + Py_FatalError("failed releasing import lock after fork"); + + run_at_forkers(_PyInterpreterState_GET()->after_forkers_parent, 0); +} + +void +PyOS_AfterFork_Child(void) +{ + PyStatus status; + _PyRuntimeState *runtime = &_PyRuntime; + + status = _PyGILState_Reinit(runtime); + if (_PyStatus_EXCEPTION(status)) { + goto fatal_error; + } + + PyThreadState *tstate = _PyThreadState_GET(); + _Py_EnsureTstateNotNULL(tstate); + + status = _PyEval_ReInitThreads(tstate); + if (_PyStatus_EXCEPTION(status)) { + goto fatal_error; + } + + status = _PyImport_ReInitLock(); + if (_PyStatus_EXCEPTION(status)) { + goto fatal_error; + } + + _PySignal_AfterFork(); + + status = _PyRuntimeState_ReInitThreads(runtime); + if (_PyStatus_EXCEPTION(status)) { + goto fatal_error; + } + + status = _PyInterpreterState_DeleteExceptMain(runtime); + if (_PyStatus_EXCEPTION(status)) { + goto fatal_error; + } + assert(_PyThreadState_GET() == tstate); + + status = _PyPerfTrampoline_AfterFork_Child(); + if (_PyStatus_EXCEPTION(status)) { + goto fatal_error; + } + + run_at_forkers(tstate->interp->after_forkers_child, 0); + return; + +fatal_error: + Py_ExitStatusException(status); +} + +static int +register_at_forker(PyObject **lst, PyObject *func) +{ + if (func == NULL) /* nothing to register? do nothing. */ + return 0; + if (*lst == NULL) { + *lst = PyList_New(0); + if (*lst == NULL) + return -1; + } + return PyList_Append(*lst, func); +} +#endif /* HAVE_FORK */ + + +/* Legacy wrapper */ +void +PyOS_AfterFork(void) +{ +#ifdef HAVE_FORK + PyOS_AfterFork_Child(); +#endif +} + + +#ifdef MS_WINDOWS +/* defined in fileutils.c */ +void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *); +void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *, + ULONG, struct _Py_stat_struct *); +#endif + + +#ifndef MS_WINDOWS +PyObject * +_PyLong_FromUid(uid_t uid) +{ + if (uid == (uid_t)-1) + return PyLong_FromLong(-1); + return PyLong_FromUnsignedLong(uid); +} + +PyObject * +_PyLong_FromGid(gid_t gid) +{ + if (gid == (gid_t)-1) + return PyLong_FromLong(-1); + return PyLong_FromUnsignedLong(gid); +} + +int +_Py_Uid_Converter(PyObject *obj, uid_t *p) +{ + uid_t uid; + PyObject *index; + int overflow; + long result; + unsigned long uresult; + + index = _PyNumber_Index(obj); + if (index == NULL) { + PyErr_Format(PyExc_TypeError, + "uid should be integer, not %.200s", + _PyType_Name(Py_TYPE(obj))); + return 0; + } + + /* + * Handling uid_t is complicated for two reasons: + * * Although uid_t is (always?) unsigned, it still + * accepts -1. + * * We don't know its size in advance--it may be + * bigger than an int, or it may be smaller than + * a long. + * + * So a bit of defensive programming is in order. + * Start with interpreting the value passed + * in as a signed long and see if it works. + */ + + result = PyLong_AsLongAndOverflow(index, &overflow); + + if (!overflow) { + uid = (uid_t)result; + + if (result == -1) { + if (PyErr_Occurred()) + goto fail; + /* It's a legitimate -1, we're done. */ + goto success; + } + + /* Any other negative number is disallowed. */ + if (result < 0) + goto underflow; + + /* Ensure the value wasn't truncated. */ + if (sizeof(uid_t) < sizeof(long) && + (long)uid != result) + goto underflow; + goto success; + } + + if (overflow < 0) + goto underflow; + + /* + * Okay, the value overflowed a signed long. If it + * fits in an *unsigned* long, it may still be okay, + * as uid_t may be unsigned long on this platform. + */ + uresult = PyLong_AsUnsignedLong(index); + if (PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_OverflowError)) + goto overflow; + goto fail; + } + + uid = (uid_t)uresult; + + /* + * If uid == (uid_t)-1, the user actually passed in ULONG_MAX, + * but this value would get interpreted as (uid_t)-1 by chown + * and its siblings. That's not what the user meant! So we + * throw an overflow exception instead. (We already + * handled a real -1 with PyLong_AsLongAndOverflow() above.) + */ + if (uid == (uid_t)-1) + goto overflow; + + /* Ensure the value wasn't truncated. */ + if (sizeof(uid_t) < sizeof(long) && + (unsigned long)uid != uresult) + goto overflow; + /* fallthrough */ + +success: + Py_DECREF(index); + *p = uid; + return 1; + +underflow: + PyErr_SetString(PyExc_OverflowError, + "uid is less than minimum"); + goto fail; + +overflow: + PyErr_SetString(PyExc_OverflowError, + "uid is greater than maximum"); + /* fallthrough */ + +fail: + Py_DECREF(index); + return 0; +} + +int +_Py_Gid_Converter(PyObject *obj, gid_t *p) +{ + gid_t gid; + PyObject *index; + int overflow; + long result; + unsigned long uresult; + + index = _PyNumber_Index(obj); + if (index == NULL) { + PyErr_Format(PyExc_TypeError, + "gid should be integer, not %.200s", + _PyType_Name(Py_TYPE(obj))); + return 0; + } + + /* + * Handling gid_t is complicated for two reasons: + * * Although gid_t is (always?) unsigned, it still + * accepts -1. + * * We don't know its size in advance--it may be + * bigger than an int, or it may be smaller than + * a long. + * + * So a bit of defensive programming is in order. + * Start with interpreting the value passed + * in as a signed long and see if it works. + */ + + result = PyLong_AsLongAndOverflow(index, &overflow); + + if (!overflow) { + gid = (gid_t)result; + + if (result == -1) { + if (PyErr_Occurred()) + goto fail; + /* It's a legitimate -1, we're done. */ + goto success; + } + + /* Any other negative number is disallowed. */ + if (result < 0) { + goto underflow; + } + + /* Ensure the value wasn't truncated. */ + if (sizeof(gid_t) < sizeof(long) && + (long)gid != result) + goto underflow; + goto success; + } + + if (overflow < 0) + goto underflow; + + /* + * Okay, the value overflowed a signed long. If it + * fits in an *unsigned* long, it may still be okay, + * as gid_t may be unsigned long on this platform. + */ + uresult = PyLong_AsUnsignedLong(index); + if (PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_OverflowError)) + goto overflow; + goto fail; + } + + gid = (gid_t)uresult; + + /* + * If gid == (gid_t)-1, the user actually passed in ULONG_MAX, + * but this value would get interpreted as (gid_t)-1 by chown + * and its siblings. That's not what the user meant! So we + * throw an overflow exception instead. (We already + * handled a real -1 with PyLong_AsLongAndOverflow() above.) + */ + if (gid == (gid_t)-1) + goto overflow; + + /* Ensure the value wasn't truncated. */ + if (sizeof(gid_t) < sizeof(long) && + (unsigned long)gid != uresult) + goto overflow; + /* fallthrough */ + +success: + Py_DECREF(index); + *p = gid; + return 1; + +underflow: + PyErr_SetString(PyExc_OverflowError, + "gid is less than minimum"); + goto fail; + +overflow: + PyErr_SetString(PyExc_OverflowError, + "gid is greater than maximum"); + /* fallthrough */ + +fail: + Py_DECREF(index); + return 0; +} +#endif /* MS_WINDOWS */ + + +#define _PyLong_FromDev PyLong_FromLongLong + + +#if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) || defined(HAVE_DEVICE_MACROS) +static int +_Py_Dev_Converter(PyObject *obj, void *p) +{ + *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj); + if (PyErr_Occurred()) + return 0; + return 1; +} +#endif /* (HAVE_MKNOD && HAVE_MAKEDEV) || HAVE_DEVICE_MACROS */ + + +#ifdef AT_FDCWD +/* + * Why the (int) cast? Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965); + * without the int cast, the value gets interpreted as uint (4291925331), + * which doesn't play nicely with all the initializer lines in this file that + * look like this: + * int dir_fd = DEFAULT_DIR_FD; + */ +#define DEFAULT_DIR_FD (int)AT_FDCWD +#else +#define DEFAULT_DIR_FD (-100) +#endif + +static int +_fd_converter(PyObject *o, int *p) +{ + int overflow; + long long_value; + + PyObject *index = _PyNumber_Index(o); + if (index == NULL) { + return 0; + } + + assert(PyLong_Check(index)); + long_value = PyLong_AsLongAndOverflow(index, &overflow); + Py_DECREF(index); + assert(!PyErr_Occurred()); + if (overflow > 0 || long_value > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "fd is greater than maximum"); + return 0; + } + if (overflow < 0 || long_value < INT_MIN) { + PyErr_SetString(PyExc_OverflowError, + "fd is less than minimum"); + return 0; + } + + *p = (int)long_value; + return 1; +} + +static int +dir_fd_converter(PyObject *o, void *p) +{ + if (o == Py_None) { + *(int *)p = DEFAULT_DIR_FD; + return 1; + } + else if (PyIndex_Check(o)) { + return _fd_converter(o, (int *)p); + } + else { + PyErr_Format(PyExc_TypeError, + "argument should be integer or None, not %.200s", + _PyType_Name(Py_TYPE(o))); + return 0; + } +} + +typedef struct { + PyObject *billion; + PyObject *DirEntryType; + PyObject *ScandirIteratorType; +#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) + PyObject *SchedParamType; +#endif + PyObject *StatResultType; + PyObject *StatVFSResultType; + PyObject *TerminalSizeType; + PyObject *TimesResultType; + PyObject *UnameResultType; +#if defined(HAVE_WAITID) && !defined(__APPLE__) + PyObject *WaitidResultType; +#endif +#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) + PyObject *struct_rusage; +#endif + PyObject *st_mode; +} _posixstate; + + +static inline _posixstate* +get_posix_state(PyObject *module) +{ + void *state = _PyModule_GetState(module); + assert(state != NULL); + return (_posixstate *)state; +} + +/* + * A PyArg_ParseTuple "converter" function + * that handles filesystem paths in the manner + * preferred by the os module. + * + * path_converter accepts (Unicode) strings and their + * subclasses, and bytes and their subclasses. What + * it does with the argument depends on the platform: + * + * * On Windows, if we get a (Unicode) string we + * extract the wchar_t * and return it; if we get + * bytes we decode to wchar_t * and return that. + * + * * On all other platforms, strings are encoded + * to bytes using PyUnicode_FSConverter, then we + * extract the char * from the bytes object and + * return that. + * + * path_converter also optionally accepts signed + * integers (representing open file descriptors) instead + * of path strings. + * + * Input fields: + * path.nullable + * If nonzero, the path is permitted to be None. + * path.allow_fd + * If nonzero, the path is permitted to be a file handle + * (a signed int) instead of a string. + * path.function_name + * If non-NULL, path_converter will use that as the name + * of the function in error messages. + * (If path.function_name is NULL it omits the function name.) + * path.argument_name + * If non-NULL, path_converter will use that as the name + * of the parameter in error messages. + * (If path.argument_name is NULL it uses "path".) + * + * Output fields: + * path.wide + * Points to the path if it was expressed as Unicode + * and was not encoded. (Only used on Windows.) + * path.narrow + * Points to the path if it was expressed as bytes, + * or it was Unicode and was encoded to bytes. (On Windows, + * is a non-zero integer if the path was expressed as bytes. + * The type is deliberately incompatible to prevent misuse.) + * path.fd + * Contains a file descriptor if path.accept_fd was true + * and the caller provided a signed integer instead of any + * sort of string. + * + * WARNING: if your "path" parameter is optional, and is + * unspecified, path_converter will never get called. + * So if you set allow_fd, you *MUST* initialize path.fd = -1 + * yourself! + * path.length + * The length of the path in characters, if specified as + * a string. + * path.object + * The original object passed in (if get a PathLike object, + * the result of PyOS_FSPath() is treated as the original object). + * Own a reference to the object. + * path.cleanup + * For internal use only. May point to a temporary object. + * (Pay no attention to the man behind the curtain.) + * + * At most one of path.wide or path.narrow will be non-NULL. + * If path was None and path.nullable was set, + * or if path was an integer and path.allow_fd was set, + * both path.wide and path.narrow will be NULL + * and path.length will be 0. + * + * path_converter takes care to not write to the path_t + * unless it's successful. However it must reset the + * "cleanup" field each time it's called. + * + * Use as follows: + * path_t path; + * memset(&path, 0, sizeof(path)); + * PyArg_ParseTuple(args, "O&", path_converter, &path); + * // ... use values from path ... + * path_cleanup(&path); + * + * (Note that if PyArg_Parse fails you don't need to call + * path_cleanup(). However it is safe to do so.) + */ +typedef struct { + const char *function_name; + const char *argument_name; + int nullable; + int allow_fd; + const wchar_t *wide; +#ifdef MS_WINDOWS + BOOL narrow; +#else + const char *narrow; +#endif + int fd; + Py_ssize_t length; + PyObject *object; + PyObject *cleanup; +} path_t; + +#ifdef MS_WINDOWS +#define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \ + {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL} +#else +#define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \ + {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL} +#endif + +static void +path_cleanup(path_t *path) +{ + wchar_t *wide = (wchar_t *)path->wide; + path->wide = NULL; + PyMem_Free(wide); + Py_CLEAR(path->object); + Py_CLEAR(path->cleanup); +} + +static int +path_converter(PyObject *o, void *p) +{ + path_t *path = (path_t *)p; + PyObject *bytes = NULL; + Py_ssize_t length = 0; + int is_index, is_bytes, is_unicode; + const char *narrow; +#ifdef MS_WINDOWS + PyObject *wo = NULL; + wchar_t *wide = NULL; +#endif + +#define FORMAT_EXCEPTION(exc, fmt) \ + PyErr_Format(exc, "%s%s" fmt, \ + path->function_name ? path->function_name : "", \ + path->function_name ? ": " : "", \ + path->argument_name ? path->argument_name : "path") + + /* Py_CLEANUP_SUPPORTED support */ + if (o == NULL) { + path_cleanup(path); + return 1; + } + + /* Ensure it's always safe to call path_cleanup(). */ + path->object = path->cleanup = NULL; + /* path->object owns a reference to the original object */ + Py_INCREF(o); + + if ((o == Py_None) && path->nullable) { + path->wide = NULL; +#ifdef MS_WINDOWS + path->narrow = FALSE; +#else + path->narrow = NULL; +#endif + path->fd = -1; + goto success_exit; + } + + /* Only call this here so that we don't treat the return value of + os.fspath() as an fd or buffer. */ + is_index = path->allow_fd && PyIndex_Check(o); + is_bytes = PyBytes_Check(o); + is_unicode = PyUnicode_Check(o); + + if (!is_index && !is_unicode && !is_bytes) { + /* Inline PyOS_FSPath() for better error messages. */ + PyObject *func, *res; + + func = _PyObject_LookupSpecial(o, &_Py_ID(__fspath__)); + if (NULL == func) { + goto error_format; + } + res = _PyObject_CallNoArgs(func); + Py_DECREF(func); + if (NULL == res) { + goto error_exit; + } + else if (PyUnicode_Check(res)) { + is_unicode = 1; + } + else if (PyBytes_Check(res)) { + is_bytes = 1; + } + else { + PyErr_Format(PyExc_TypeError, + "expected %.200s.__fspath__() to return str or bytes, " + "not %.200s", _PyType_Name(Py_TYPE(o)), + _PyType_Name(Py_TYPE(res))); + Py_DECREF(res); + goto error_exit; + } + + /* still owns a reference to the original object */ + Py_DECREF(o); + o = res; + } + + if (is_unicode) { +#ifdef MS_WINDOWS + wide = PyUnicode_AsWideCharString(o, &length); + if (!wide) { + goto error_exit; + } + if (length > 32767) { + FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); + goto error_exit; + } + if (wcslen(wide) != length) { + FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); + goto error_exit; + } + + path->wide = wide; + path->narrow = FALSE; + path->fd = -1; + wide = NULL; + goto success_exit; +#else + if (!PyUnicode_FSConverter(o, &bytes)) { + goto error_exit; + } +#endif + } + else if (is_bytes) { + bytes = Py_NewRef(o); + } + else if (is_index) { + if (!_fd_converter(o, &path->fd)) { + goto error_exit; + } + path->wide = NULL; +#ifdef MS_WINDOWS + path->narrow = FALSE; +#else + path->narrow = NULL; +#endif + goto success_exit; + } + else { + error_format: + PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s", + path->function_name ? path->function_name : "", + path->function_name ? ": " : "", + path->argument_name ? path->argument_name : "path", + path->allow_fd && path->nullable ? "string, bytes, os.PathLike, " + "integer or None" : + path->allow_fd ? "string, bytes, os.PathLike or integer" : + path->nullable ? "string, bytes, os.PathLike or None" : + "string, bytes or os.PathLike", + _PyType_Name(Py_TYPE(o))); + goto error_exit; + } + + length = PyBytes_GET_SIZE(bytes); + narrow = PyBytes_AS_STRING(bytes); + if ((size_t)length != strlen(narrow)) { + FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); + goto error_exit; + } + +#ifdef MS_WINDOWS + wo = PyUnicode_DecodeFSDefaultAndSize( + narrow, + length + ); + if (!wo) { + goto error_exit; + } + + wide = PyUnicode_AsWideCharString(wo, &length); + Py_DECREF(wo); + if (!wide) { + goto error_exit; + } + if (length > 32767) { + FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); + goto error_exit; + } + if (wcslen(wide) != length) { + FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); + goto error_exit; + } + path->wide = wide; + path->narrow = TRUE; + Py_DECREF(bytes); + wide = NULL; +#else + path->wide = NULL; + path->narrow = narrow; + if (bytes == o) { + /* Still a reference owned by path->object, don't have to + worry about path->narrow is used after free. */ + Py_DECREF(bytes); + } + else { + path->cleanup = bytes; + } +#endif + path->fd = -1; + + success_exit: + path->length = length; + path->object = o; + return Py_CLEANUP_SUPPORTED; + + error_exit: + Py_XDECREF(o); + Py_XDECREF(bytes); +#ifdef MS_WINDOWS + PyMem_Free(wide); +#endif + return 0; +} + +static void +argument_unavailable_error(const char *function_name, const char *argument_name) +{ + PyErr_Format(PyExc_NotImplementedError, + "%s%s%s unavailable on this platform", + (function_name != NULL) ? function_name : "", + (function_name != NULL) ? ": ": "", + argument_name); +} + +static int +dir_fd_unavailable(PyObject *o, void *p) +{ + int dir_fd; + if (!dir_fd_converter(o, &dir_fd)) + return 0; + if (dir_fd != DEFAULT_DIR_FD) { + argument_unavailable_error(NULL, "dir_fd"); + return 0; + } + *(int *)p = dir_fd; + return 1; +} + +static int +fd_specified(const char *function_name, int fd) +{ + if (fd == -1) + return 0; + + argument_unavailable_error(function_name, "fd"); + return 1; +} + +static int +follow_symlinks_specified(const char *function_name, int follow_symlinks) +{ + if (follow_symlinks) + return 0; + + argument_unavailable_error(function_name, "follow_symlinks"); + return 1; +} + +static int +path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd) +{ + if (!path->wide && (dir_fd != DEFAULT_DIR_FD) +#ifndef MS_WINDOWS + && !path->narrow +#endif + ) { + PyErr_Format(PyExc_ValueError, + "%s: can't specify dir_fd without matching path", + function_name); + return 1; + } + return 0; +} + +static int +dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd) +{ + if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) { + PyErr_Format(PyExc_ValueError, + "%s: can't specify both dir_fd and fd", + function_name); + return 1; + } + return 0; +} + +static int +fd_and_follow_symlinks_invalid(const char *function_name, int fd, + int follow_symlinks) +{ + if ((fd > 0) && (!follow_symlinks)) { + PyErr_Format(PyExc_ValueError, + "%s: cannot use fd and follow_symlinks together", + function_name); + return 1; + } + return 0; +} + +static int +dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd, + int follow_symlinks) +{ + if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) { + PyErr_Format(PyExc_ValueError, + "%s: cannot use dir_fd and follow_symlinks together", + function_name); + return 1; + } + return 0; +} + +#ifdef MS_WINDOWS + typedef long long Py_off_t; +#else + typedef off_t Py_off_t; +#endif + +static int +Py_off_t_converter(PyObject *arg, void *addr) +{ +#ifdef HAVE_LARGEFILE_SUPPORT + *((Py_off_t *)addr) = PyLong_AsLongLong(arg); +#else + *((Py_off_t *)addr) = PyLong_AsLong(arg); +#endif + if (PyErr_Occurred()) + return 0; + return 1; +} + +static PyObject * +PyLong_FromPy_off_t(Py_off_t offset) +{ +#ifdef HAVE_LARGEFILE_SUPPORT + return PyLong_FromLongLong(offset); +#else + return PyLong_FromLong(offset); +#endif +} + +#ifdef HAVE_SIGSET_T +/* Convert an iterable of integers to a sigset. + Return 1 on success, return 0 and raise an exception on error. */ +int +_Py_Sigset_Converter(PyObject *obj, void *addr) +{ + sigset_t *mask = (sigset_t *)addr; + PyObject *iterator, *item; + long signum; + int overflow; + + // The extra parens suppress the unreachable-code warning with clang on MacOS + if (sigemptyset(mask) < (0)) { + /* Probably only if mask == NULL. */ + PyErr_SetFromErrno(PyExc_OSError); + return 0; + } + + iterator = PyObject_GetIter(obj); + if (iterator == NULL) { + return 0; + } + + while ((item = PyIter_Next(iterator)) != NULL) { + signum = PyLong_AsLongAndOverflow(item, &overflow); + Py_DECREF(item); + if (signum <= 0 || signum >= Py_NSIG) { + if (overflow || signum != -1 || !PyErr_Occurred()) { + PyErr_Format(PyExc_ValueError, + "signal number %ld out of range [1; %i]", + signum, Py_NSIG - 1); + } + goto error; + } + if (sigaddset(mask, (int)signum)) { + if (errno != EINVAL) { + /* Probably impossible */ + PyErr_SetFromErrno(PyExc_OSError); + goto error; + } + /* For backwards compatibility, allow idioms such as + * `range(1, NSIG)` but warn about invalid signal numbers + */ + const char msg[] = + "invalid signal number %ld, please use valid_signals()"; + if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) { + goto error; + } + } + } + if (!PyErr_Occurred()) { + Py_DECREF(iterator); + return 1; + } + +error: + Py_DECREF(iterator); + return 0; +} +#endif /* HAVE_SIGSET_T */ + +#ifdef MS_WINDOWS + +static int +win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag) +{ + char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer; + DWORD n_bytes_returned; + + if (0 == DeviceIoControl( + reparse_point_handle, + FSCTL_GET_REPARSE_POINT, + NULL, 0, /* in buffer */ + target_buffer, sizeof(target_buffer), + &n_bytes_returned, + NULL)) /* we're not using OVERLAPPED_IO */ + return FALSE; + + if (reparse_tag) + *reparse_tag = rdb->ReparseTag; + + return TRUE; +} + +#endif /* MS_WINDOWS */ + +/* Return a dictionary corresponding to the POSIX environment table */ +#if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED)) +/* On Darwin/MacOSX a shared library or framework has no access to +** environ directly, we must obtain it with _NSGetEnviron(). See also +** man environ(7). +*/ +#include +#elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__)) +extern char **environ; +#endif /* !_MSC_VER */ + +static PyObject * +convertenviron(void) +{ + PyObject *d; +#ifdef MS_WINDOWS + wchar_t **e; +#else + char **e; +#endif + + d = PyDict_New(); + if (d == NULL) + return NULL; +#ifdef MS_WINDOWS + /* _wenviron must be initialized in this way if the program is started + through main() instead of wmain(). */ + _wgetenv(L""); + e = _wenviron; +#elif defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED)) + /* environ is not accessible as an extern in a shared object on OSX; use + _NSGetEnviron to resolve it. The value changes if you add environment + variables between calls to Py_Initialize, so don't cache the value. */ + e = *_NSGetEnviron(); +#else + e = environ; +#endif + if (e == NULL) + return d; + for (; *e != NULL; e++) { + PyObject *k; + PyObject *v; +#ifdef MS_WINDOWS + const wchar_t *p = wcschr(*e, L'='); +#else + const char *p = strchr(*e, '='); +#endif + if (p == NULL) + continue; +#ifdef MS_WINDOWS + k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e)); +#else + k = PyBytes_FromStringAndSize(*e, (int)(p-*e)); +#endif + if (k == NULL) { + Py_DECREF(d); + return NULL; + } +#ifdef MS_WINDOWS + v = PyUnicode_FromWideChar(p+1, wcslen(p+1)); +#else + v = PyBytes_FromStringAndSize(p+1, strlen(p+1)); +#endif + if (v == NULL) { + Py_DECREF(k); + Py_DECREF(d); + return NULL; + } + if (PyDict_SetDefault(d, k, v) == NULL) { + Py_DECREF(v); + Py_DECREF(k); + Py_DECREF(d); + return NULL; + } + Py_DECREF(k); + Py_DECREF(v); + } + return d; +} + +/* Set a POSIX-specific error from errno, and return NULL */ + +static PyObject * +posix_error(void) +{ + return PyErr_SetFromErrno(PyExc_OSError); +} + +#ifdef MS_WINDOWS +static PyObject * +win32_error(const char* function, const char* filename) +{ + /* XXX We should pass the function name along in the future. + (winreg.c also wants to pass the function name.) + This would however require an additional param to the + Windows error object, which is non-trivial. + */ + errno = GetLastError(); + if (filename) + return PyErr_SetFromWindowsErrWithFilename(errno, filename); + else + return PyErr_SetFromWindowsErr(errno); +} + +static PyObject * +win32_error_object_err(const char* function, PyObject* filename, DWORD err) +{ + /* XXX - see win32_error for comments on 'function' */ + if (filename) + return PyErr_SetExcFromWindowsErrWithFilenameObject( + PyExc_OSError, + err, + filename); + else + return PyErr_SetFromWindowsErr(err); +} + +static PyObject * +win32_error_object(const char* function, PyObject* filename) +{ + errno = GetLastError(); + return win32_error_object_err(function, filename, errno); +} + +#endif /* MS_WINDOWS */ + +static PyObject * +posix_path_object_error(PyObject *path) +{ + return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path); +} + +static PyObject * +path_object_error(PyObject *path) +{ +#ifdef MS_WINDOWS + return PyErr_SetExcFromWindowsErrWithFilenameObject( + PyExc_OSError, 0, path); +#else + return posix_path_object_error(path); +#endif +} + +static PyObject * +path_object_error2(PyObject *path, PyObject *path2) +{ +#ifdef MS_WINDOWS + return PyErr_SetExcFromWindowsErrWithFilenameObjects( + PyExc_OSError, 0, path, path2); +#else + return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2); +#endif +} + +static PyObject * +path_error(path_t *path) +{ + return path_object_error(path->object); +} + +static PyObject * +posix_path_error(path_t *path) +{ + return posix_path_object_error(path->object); +} + +static PyObject * +path_error2(path_t *path, path_t *path2) +{ + return path_object_error2(path->object, path2->object); +} + + +/* POSIX generic methods */ + +static PyObject * +posix_fildes_fd(int fd, int (*func)(int)) +{ + int res; + int async_err = 0; + + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + res = (*func)(fd); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (res != 0) + return (!async_err) ? posix_error() : NULL; + Py_RETURN_NONE; +} + + +#ifdef MS_WINDOWS +/* This is a reimplementation of the C library's chdir function, + but one that produces Win32 errors instead of DOS error codes. + chdir is essentially a wrapper around SetCurrentDirectory; however, + it also needs to set "magic" environment variables indicating + the per-drive current directory, which are of the form =: */ +static BOOL __stdcall +win32_wchdir(LPCWSTR path) +{ + wchar_t path_buf[MAX_PATH], *new_path = path_buf; + int result; + wchar_t env[4] = L"=x:"; + + if(!SetCurrentDirectoryW(path)) + return FALSE; + result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path); + if (!result) + return FALSE; + if (result > Py_ARRAY_LENGTH(path_buf)) { + new_path = PyMem_RawMalloc(result * sizeof(wchar_t)); + if (!new_path) { + SetLastError(ERROR_OUTOFMEMORY); + return FALSE; + } + result = GetCurrentDirectoryW(result, new_path); + if (!result) { + PyMem_RawFree(new_path); + return FALSE; + } + } + int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 || + wcsncmp(new_path, L"//", 2) == 0); + if (!is_unc_like_path) { + env[1] = new_path[0]; + result = SetEnvironmentVariableW(env, new_path); + } + if (new_path != path_buf) + PyMem_RawFree(new_path); + return result ? TRUE : FALSE; +} +#endif + +#ifdef MS_WINDOWS +/* The CRT of Windows has a number of flaws wrt. its stat() implementation: + - time stamps are restricted to second resolution + - file modification times suffer from forth-and-back conversions between + UTC and local time + Therefore, we implement our own stat, based on the Win32 API directly. +*/ +#define HAVE_STAT_NSEC 1 +#define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1 +#define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1 + +static void +find_data_to_file_info(WIN32_FIND_DATAW *pFileData, + BY_HANDLE_FILE_INFORMATION *info, + ULONG *reparse_tag) +{ + memset(info, 0, sizeof(*info)); + info->dwFileAttributes = pFileData->dwFileAttributes; + info->ftCreationTime = pFileData->ftCreationTime; + info->ftLastAccessTime = pFileData->ftLastAccessTime; + info->ftLastWriteTime = pFileData->ftLastWriteTime; + info->nFileSizeHigh = pFileData->nFileSizeHigh; + info->nFileSizeLow = pFileData->nFileSizeLow; +/* info->nNumberOfLinks = 1; */ + if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) + *reparse_tag = pFileData->dwReserved0; + else + *reparse_tag = 0; +} + +static BOOL +attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag) +{ + HANDLE hFindFile; + WIN32_FIND_DATAW FileData; + LPCWSTR filename = pszFile; + size_t n = wcslen(pszFile); + if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) { + // cannot use PyMem_Malloc here because we do not hold the GIL + filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0])); + wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n); + while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) { + ((LPWSTR)filename)[n] = L'\0'; + } + if (!n || (n == 1 && filename[1] == L':')) { + // Nothing left to query + free((void *)filename); + return FALSE; + } + } + hFindFile = FindFirstFileW(filename, &FileData); + if (pszFile != filename) { + free((void *)filename); + } + if (hFindFile == INVALID_HANDLE_VALUE) { + return FALSE; + } + FindClose(hFindFile); + find_data_to_file_info(&FileData, info, reparse_tag); + return TRUE; +} + +static int +win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result, + BOOL traverse) +{ + HANDLE hFile; + BY_HANDLE_FILE_INFORMATION fileInfo; + FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 }; + DWORD fileType, error; + BOOL isUnhandledTag = FALSE; + int retval = 0; + + DWORD access = FILE_READ_ATTRIBUTES; + DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */ + if (!traverse) { + flags |= FILE_FLAG_OPEN_REPARSE_POINT; + } + + hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + /* Either the path doesn't exist, or the caller lacks access. */ + error = GetLastError(); + switch (error) { + case ERROR_ACCESS_DENIED: /* Cannot sync or read attributes. */ + case ERROR_SHARING_VIOLATION: /* It's a paging file. */ + /* Try reading the parent directory. */ + if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) { + /* Cannot read the parent directory. */ + switch (GetLastError()) { + case ERROR_FILE_NOT_FOUND: /* File cannot be found */ + case ERROR_PATH_NOT_FOUND: /* File parent directory cannot be found */ + case ERROR_NOT_READY: /* Drive exists but unavailable */ + case ERROR_BAD_NET_NAME: /* Remote drive unavailable */ + break; + /* Restore the error from CreateFileW(). */ + default: + SetLastError(error); + } + + return -1; + } + if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { + if (traverse || + !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) { + /* The stat call has to traverse but cannot, so fail. */ + SetLastError(error); + return -1; + } + } + break; + + case ERROR_INVALID_PARAMETER: + /* \\.\con requires read or write access. */ + hFile = CreateFileW(path, access | GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, flags, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + SetLastError(error); + return -1; + } + break; + + case ERROR_CANT_ACCESS_FILE: + /* bpo37834: open unhandled reparse points if traverse fails. */ + if (traverse) { + traverse = FALSE; + isUnhandledTag = TRUE; + hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, + flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL); + } + if (hFile == INVALID_HANDLE_VALUE) { + SetLastError(error); + return -1; + } + break; + + default: + return -1; + } + } + + if (hFile != INVALID_HANDLE_VALUE) { + /* Handle types other than files on disk. */ + fileType = GetFileType(hFile); + if (fileType != FILE_TYPE_DISK) { + if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) { + retval = -1; + goto cleanup; + } + DWORD fileAttributes = GetFileAttributesW(path); + memset(result, 0, sizeof(*result)); + if (fileAttributes != INVALID_FILE_ATTRIBUTES && + fileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + /* \\.\pipe\ or \\.\mailslot\ */ + result->st_mode = _S_IFDIR; + } else if (fileType == FILE_TYPE_CHAR) { + /* \\.\nul */ + result->st_mode = _S_IFCHR; + } else if (fileType == FILE_TYPE_PIPE) { + /* \\.\pipe\spam */ + result->st_mode = _S_IFIFO; + } + /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */ + goto cleanup; + } + + /* Query the reparse tag, and traverse a non-link. */ + if (!traverse) { + if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo, + &tagInfo, sizeof(tagInfo))) { + /* Allow devices that do not support FileAttributeTagInfo. */ + switch (GetLastError()) { + case ERROR_INVALID_PARAMETER: + case ERROR_INVALID_FUNCTION: + case ERROR_NOT_SUPPORTED: + tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL; + tagInfo.ReparseTag = 0; + break; + default: + retval = -1; + goto cleanup; + } + } else if (tagInfo.FileAttributes & + FILE_ATTRIBUTE_REPARSE_POINT) { + if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) { + if (isUnhandledTag) { + /* Traversing previously failed for either this link + or its target. */ + SetLastError(ERROR_CANT_ACCESS_FILE); + retval = -1; + goto cleanup; + } + /* Traverse a non-link, but not if traversing already failed + for an unhandled tag. */ + } else if (!isUnhandledTag) { + CloseHandle(hFile); + return win32_xstat_impl(path, result, TRUE); + } + } + } + + if (!GetFileInformationByHandle(hFile, &fileInfo)) { + switch (GetLastError()) { + case ERROR_INVALID_PARAMETER: + case ERROR_INVALID_FUNCTION: + case ERROR_NOT_SUPPORTED: + /* Volumes and physical disks are block devices, e.g. + \\.\C: and \\.\PhysicalDrive0. */ + memset(result, 0, sizeof(*result)); + result->st_mode = 0x6000; /* S_IFBLK */ + goto cleanup; + } + retval = -1; + goto cleanup; + } + } + + _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, result); + + if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + /* Fix the file execute permissions. This hack sets S_IEXEC if + the filename has an extension that is commonly used by files + that CreateProcessW can execute. A real implementation calls + GetSecurityInfo, OpenThreadToken/OpenProcessToken, and + AccessCheck to check for generic read, write, and execute + access. */ + const wchar_t *fileExtension = wcsrchr(path, '.'); + if (fileExtension) { + if (_wcsicmp(fileExtension, L".exe") == 0 || + _wcsicmp(fileExtension, L".bat") == 0 || + _wcsicmp(fileExtension, L".cmd") == 0 || + _wcsicmp(fileExtension, L".com") == 0) { + result->st_mode |= 0111; + } + } + } + +cleanup: + if (hFile != INVALID_HANDLE_VALUE) { + /* Preserve last error if we are failing */ + error = retval ? GetLastError() : 0; + if (!CloseHandle(hFile)) { + retval = -1; + } else if (retval) { + /* Restore last error */ + SetLastError(error); + } + } + + return retval; +} + +static int +win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse) +{ + /* Protocol violation: we explicitly clear errno, instead of + setting it to a POSIX error. Callers should use GetLastError. */ + int code = win32_xstat_impl(path, result, traverse); + errno = 0; + return code; +} +/* About the following functions: win32_lstat_w, win32_stat, win32_stat_w + + In Posix, stat automatically traverses symlinks and returns the stat + structure for the target. In Windows, the equivalent GetFileAttributes by + default does not traverse symlinks and instead returns attributes for + the symlink. + + Instead, we will open the file (which *does* traverse symlinks by default) + and GetFileInformationByHandle(). */ + +static int +win32_lstat(const wchar_t* path, struct _Py_stat_struct *result) +{ + return win32_xstat(path, result, FALSE); +} + +static int +win32_stat(const wchar_t* path, struct _Py_stat_struct *result) +{ + return win32_xstat(path, result, TRUE); +} + +#endif /* MS_WINDOWS */ + +PyDoc_STRVAR(stat_result__doc__, +"stat_result: Result from stat, fstat, or lstat.\n\n\ +This object may be accessed either as a tuple of\n\ + (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\ +or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\ +\n\ +Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\ +or st_flags, they are available as attributes only.\n\ +\n\ +See os.stat for more information."); + +static PyStructSequence_Field stat_result_fields[] = { + {"st_mode", "protection bits"}, + {"st_ino", "inode"}, + {"st_dev", "device"}, + {"st_nlink", "number of hard links"}, + {"st_uid", "user ID of owner"}, + {"st_gid", "group ID of owner"}, + {"st_size", "total size, in bytes"}, + /* The NULL is replaced with PyStructSequence_UnnamedField later. */ + {NULL, "integer time of last access"}, + {NULL, "integer time of last modification"}, + {NULL, "integer time of last change"}, + {"st_atime", "time of last access"}, + {"st_mtime", "time of last modification"}, + {"st_ctime", "time of last change"}, + {"st_atime_ns", "time of last access in nanoseconds"}, + {"st_mtime_ns", "time of last modification in nanoseconds"}, + {"st_ctime_ns", "time of last change in nanoseconds"}, +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + {"st_blksize", "blocksize for filesystem I/O"}, +#endif +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS + {"st_blocks", "number of blocks allocated"}, +#endif +#ifdef HAVE_STRUCT_STAT_ST_RDEV + {"st_rdev", "device type (if inode device)"}, +#endif +#ifdef HAVE_STRUCT_STAT_ST_FLAGS + {"st_flags", "user defined flags for file"}, +#endif +#ifdef HAVE_STRUCT_STAT_ST_GEN + {"st_gen", "generation number"}, +#endif +#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME + {"st_birthtime", "time of creation"}, +#endif +#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES + {"st_file_attributes", "Windows file attribute bits"}, +#endif +#ifdef HAVE_STRUCT_STAT_ST_FSTYPE + {"st_fstype", "Type of filesystem"}, +#endif +#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG + {"st_reparse_tag", "Windows reparse tag"}, +#endif + {0} +}; + +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE +#define ST_BLKSIZE_IDX 16 +#else +#define ST_BLKSIZE_IDX 15 +#endif + +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS +#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1) +#else +#define ST_BLOCKS_IDX ST_BLKSIZE_IDX +#endif + +#ifdef HAVE_STRUCT_STAT_ST_RDEV +#define ST_RDEV_IDX (ST_BLOCKS_IDX+1) +#else +#define ST_RDEV_IDX ST_BLOCKS_IDX +#endif + +#ifdef HAVE_STRUCT_STAT_ST_FLAGS +#define ST_FLAGS_IDX (ST_RDEV_IDX+1) +#else +#define ST_FLAGS_IDX ST_RDEV_IDX +#endif + +#ifdef HAVE_STRUCT_STAT_ST_GEN +#define ST_GEN_IDX (ST_FLAGS_IDX+1) +#else +#define ST_GEN_IDX ST_FLAGS_IDX +#endif + +#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME +#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1) +#else +#define ST_BIRTHTIME_IDX ST_GEN_IDX +#endif + +#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES +#define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1) +#else +#define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX +#endif + +#ifdef HAVE_STRUCT_STAT_ST_FSTYPE +#define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1) +#else +#define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX +#endif + +#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG +#define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1) +#else +#define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX +#endif + +static PyStructSequence_Desc stat_result_desc = { + "stat_result", /* name */ + stat_result__doc__, /* doc */ + stat_result_fields, + 10 +}; + +PyDoc_STRVAR(statvfs_result__doc__, +"statvfs_result: Result from statvfs or fstatvfs.\n\n\ +This object may be accessed either as a tuple of\n\ + (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\ +or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\ +\n\ +See os.statvfs for more information."); + +static PyStructSequence_Field statvfs_result_fields[] = { + {"f_bsize", }, + {"f_frsize", }, + {"f_blocks", }, + {"f_bfree", }, + {"f_bavail", }, + {"f_files", }, + {"f_ffree", }, + {"f_favail", }, + {"f_flag", }, + {"f_namemax",}, + {"f_fsid", }, + {0} +}; + +static PyStructSequence_Desc statvfs_result_desc = { + "statvfs_result", /* name */ + statvfs_result__doc__, /* doc */ + statvfs_result_fields, + 10 +}; + +#if defined(HAVE_WAITID) && !defined(__APPLE__) +PyDoc_STRVAR(waitid_result__doc__, +"waitid_result: Result from waitid.\n\n\ +This object may be accessed either as a tuple of\n\ + (si_pid, si_uid, si_signo, si_status, si_code),\n\ +or via the attributes si_pid, si_uid, and so on.\n\ +\n\ +See os.waitid for more information."); + +static PyStructSequence_Field waitid_result_fields[] = { + {"si_pid", }, + {"si_uid", }, + {"si_signo", }, + {"si_status", }, + {"si_code", }, + {0} +}; + +static PyStructSequence_Desc waitid_result_desc = { + "waitid_result", /* name */ + waitid_result__doc__, /* doc */ + waitid_result_fields, + 5 +}; +#endif +static newfunc structseq_new; + +static PyObject * +statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyStructSequence *result; + int i; + + result = (PyStructSequence*)structseq_new(type, args, kwds); + if (!result) + return NULL; + /* If we have been initialized from a tuple, + st_?time might be set to None. Initialize it + from the int slots. */ + for (i = 7; i <= 9; i++) { + if (result->ob_item[i+3] == Py_None) { + Py_DECREF(Py_None); + result->ob_item[i+3] = Py_NewRef(result->ob_item[i]); + } + } + return (PyObject*)result; +} + +static int +_posix_clear(PyObject *module) +{ + _posixstate *state = get_posix_state(module); + Py_CLEAR(state->billion); + Py_CLEAR(state->DirEntryType); + Py_CLEAR(state->ScandirIteratorType); +#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) + Py_CLEAR(state->SchedParamType); +#endif + Py_CLEAR(state->StatResultType); + Py_CLEAR(state->StatVFSResultType); + Py_CLEAR(state->TerminalSizeType); + Py_CLEAR(state->TimesResultType); + Py_CLEAR(state->UnameResultType); +#if defined(HAVE_WAITID) && !defined(__APPLE__) + Py_CLEAR(state->WaitidResultType); +#endif +#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) + Py_CLEAR(state->struct_rusage); +#endif + Py_CLEAR(state->st_mode); + return 0; +} + +static int +_posix_traverse(PyObject *module, visitproc visit, void *arg) +{ + _posixstate *state = get_posix_state(module); + Py_VISIT(state->billion); + Py_VISIT(state->DirEntryType); + Py_VISIT(state->ScandirIteratorType); +#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) + Py_VISIT(state->SchedParamType); +#endif + Py_VISIT(state->StatResultType); + Py_VISIT(state->StatVFSResultType); + Py_VISIT(state->TerminalSizeType); + Py_VISIT(state->TimesResultType); + Py_VISIT(state->UnameResultType); +#if defined(HAVE_WAITID) && !defined(__APPLE__) + Py_VISIT(state->WaitidResultType); +#endif +#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) + Py_VISIT(state->struct_rusage); +#endif + Py_VISIT(state->st_mode); + return 0; +} + +static void +_posix_free(void *module) +{ + _posix_clear((PyObject *)module); +} + +static void +fill_time(PyObject *module, PyObject *v, int index, time_t sec, unsigned long nsec) +{ + PyObject *s = _PyLong_FromTime_t(sec); + PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec); + PyObject *s_in_ns = NULL; + PyObject *ns_total = NULL; + PyObject *float_s = NULL; + + if (!(s && ns_fractional)) + goto exit; + + s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion); + if (!s_in_ns) + goto exit; + + ns_total = PyNumber_Add(s_in_ns, ns_fractional); + if (!ns_total) + goto exit; + + float_s = PyFloat_FromDouble(sec + 1e-9*nsec); + if (!float_s) { + goto exit; + } + + PyStructSequence_SET_ITEM(v, index, s); + PyStructSequence_SET_ITEM(v, index+3, float_s); + PyStructSequence_SET_ITEM(v, index+6, ns_total); + s = NULL; + float_s = NULL; + ns_total = NULL; +exit: + Py_XDECREF(s); + Py_XDECREF(ns_fractional); + Py_XDECREF(s_in_ns); + Py_XDECREF(ns_total); + Py_XDECREF(float_s); +} + +/* pack a system stat C structure into the Python stat tuple + (used by posix_stat() and posix_fstat()) */ +static PyObject* +_pystat_fromstructstat(PyObject *module, STRUCT_STAT *st) +{ + unsigned long ansec, mnsec, cnsec; + PyObject *StatResultType = get_posix_state(module)->StatResultType; + PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType); + if (v == NULL) + return NULL; + + PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode)); + static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino), + "stat.st_ino is larger than unsigned long long"); + PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLongLong(st->st_ino)); +#ifdef MS_WINDOWS + PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev)); +#else + PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev)); +#endif + PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink)); +#if defined(MS_WINDOWS) + PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0)); + PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0)); +#else + PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid)); + PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid)); +#endif + static_assert(sizeof(long long) >= sizeof(st->st_size), + "stat.st_size is larger than long long"); + PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size)); + +#if defined(HAVE_STAT_TV_NSEC) + ansec = st->st_atim.tv_nsec; + mnsec = st->st_mtim.tv_nsec; + cnsec = st->st_ctim.tv_nsec; +#elif defined(HAVE_STAT_TV_NSEC2) + ansec = st->st_atimespec.tv_nsec; + mnsec = st->st_mtimespec.tv_nsec; + cnsec = st->st_ctimespec.tv_nsec; +#elif defined(HAVE_STAT_NSEC) + ansec = st->st_atime_nsec; + mnsec = st->st_mtime_nsec; + cnsec = st->st_ctime_nsec; +#else + ansec = mnsec = cnsec = 0; +#endif + fill_time(module, v, 7, st->st_atime, ansec); + fill_time(module, v, 8, st->st_mtime, mnsec); + fill_time(module, v, 9, st->st_ctime, cnsec); + +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX, + PyLong_FromLong((long)st->st_blksize)); +#endif +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS + PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX, + PyLong_FromLong((long)st->st_blocks)); +#endif +#ifdef HAVE_STRUCT_STAT_ST_RDEV + PyStructSequence_SET_ITEM(v, ST_RDEV_IDX, + PyLong_FromLong((long)st->st_rdev)); +#endif +#ifdef HAVE_STRUCT_STAT_ST_GEN + PyStructSequence_SET_ITEM(v, ST_GEN_IDX, + PyLong_FromLong((long)st->st_gen)); +#endif +#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME + { + PyObject *val; + unsigned long bsec,bnsec; + bsec = (long)st->st_birthtime; +#ifdef HAVE_STAT_TV_NSEC2 + bnsec = st->st_birthtimespec.tv_nsec; +#else + bnsec = 0; +#endif + val = PyFloat_FromDouble(bsec + 1e-9*bnsec); + PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX, + val); + } +#endif +#ifdef HAVE_STRUCT_STAT_ST_FLAGS + PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX, + PyLong_FromLong((long)st->st_flags)); +#endif +#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES + PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX, + PyLong_FromUnsignedLong(st->st_file_attributes)); +#endif +#ifdef HAVE_STRUCT_STAT_ST_FSTYPE + PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX, + PyUnicode_FromString(st->st_fstype)); +#endif +#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG + PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX, + PyLong_FromUnsignedLong(st->st_reparse_tag)); +#endif + + if (PyErr_Occurred()) { + Py_DECREF(v); + return NULL; + } + + return v; +} + +/* POSIX methods */ + + +static PyObject * +posix_do_stat(PyObject *module, const char *function_name, path_t *path, + int dir_fd, int follow_symlinks) +{ + STRUCT_STAT st; + int result; + +#ifdef HAVE_FSTATAT + int fstatat_unavailable = 0; +#endif + +#if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT) + if (follow_symlinks_specified(function_name, follow_symlinks)) + return NULL; +#endif + + if (path_and_dir_fd_invalid("stat", path, dir_fd) || + dir_fd_and_fd_invalid("stat", dir_fd, path->fd) || + fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + if (path->fd != -1) + result = FSTAT(path->fd, &st); +#ifdef MS_WINDOWS + else if (follow_symlinks) + result = win32_stat(path->wide, &st); + else + result = win32_lstat(path->wide, &st); +#else + else +#if defined(HAVE_LSTAT) + if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) + result = LSTAT(path->narrow, &st); + else +#endif /* HAVE_LSTAT */ +#ifdef HAVE_FSTATAT + if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) { + if (HAVE_FSTATAT_RUNTIME) { + result = fstatat(dir_fd, path->narrow, &st, + follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); + + } else { + fstatat_unavailable = 1; + } + } else +#endif /* HAVE_FSTATAT */ + result = STAT(path->narrow, &st); +#endif /* MS_WINDOWS */ + Py_END_ALLOW_THREADS + +#ifdef HAVE_FSTATAT + if (fstatat_unavailable) { + argument_unavailable_error("stat", "dir_fd"); + return NULL; + } +#endif + + if (result != 0) { + return path_error(path); + } + + return _pystat_fromstructstat(module, &st); +} + +/*[python input] + +for s in """ + +FACCESSAT +FCHMODAT +FCHOWNAT +FSTATAT +LINKAT +MKDIRAT +MKFIFOAT +MKNODAT +OPENAT +READLINKAT +SYMLINKAT +UNLINKAT + +""".strip().split(): + s = s.strip() + print(""" +#ifdef HAVE_{s} + #define {s}_DIR_FD_CONVERTER dir_fd_converter +#else + #define {s}_DIR_FD_CONVERTER dir_fd_unavailable +#endif +""".rstrip().format(s=s)) + +for s in """ + +FCHDIR +FCHMOD +FCHOWN +FDOPENDIR +FEXECVE +FPATHCONF +FSTATVFS +FTRUNCATE + +""".strip().split(): + s = s.strip() + print(""" +#ifdef HAVE_{s} + #define PATH_HAVE_{s} 1 +#else + #define PATH_HAVE_{s} 0 +#endif + +""".rstrip().format(s=s)) +[python start generated code]*/ + +#ifdef HAVE_FACCESSAT + #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#ifdef HAVE_FCHMODAT + #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#ifdef HAVE_FCHOWNAT + #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#ifdef HAVE_FSTATAT + #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#ifdef HAVE_LINKAT + #define LINKAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#ifdef HAVE_MKDIRAT + #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#ifdef HAVE_MKFIFOAT + #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#ifdef HAVE_MKNODAT + #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#ifdef HAVE_OPENAT + #define OPENAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#ifdef HAVE_READLINKAT + #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#ifdef HAVE_SYMLINKAT + #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#ifdef HAVE_UNLINKAT + #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#ifdef HAVE_FCHDIR + #define PATH_HAVE_FCHDIR 1 +#else + #define PATH_HAVE_FCHDIR 0 +#endif + +#ifdef HAVE_FCHMOD + #define PATH_HAVE_FCHMOD 1 +#else + #define PATH_HAVE_FCHMOD 0 +#endif + +#ifdef HAVE_FCHOWN + #define PATH_HAVE_FCHOWN 1 +#else + #define PATH_HAVE_FCHOWN 0 +#endif + +#ifdef HAVE_FDOPENDIR + #define PATH_HAVE_FDOPENDIR 1 +#else + #define PATH_HAVE_FDOPENDIR 0 +#endif + +#ifdef HAVE_FEXECVE + #define PATH_HAVE_FEXECVE 1 +#else + #define PATH_HAVE_FEXECVE 0 +#endif + +#ifdef HAVE_FPATHCONF + #define PATH_HAVE_FPATHCONF 1 +#else + #define PATH_HAVE_FPATHCONF 0 +#endif + +#ifdef HAVE_FSTATVFS + #define PATH_HAVE_FSTATVFS 1 +#else + #define PATH_HAVE_FSTATVFS 0 +#endif + +#ifdef HAVE_FTRUNCATE + #define PATH_HAVE_FTRUNCATE 1 +#else + #define PATH_HAVE_FTRUNCATE 0 +#endif +/*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/ + +#ifdef MS_WINDOWS + #undef PATH_HAVE_FTRUNCATE + #define PATH_HAVE_FTRUNCATE 1 +#endif + +/*[python input] + +class path_t_converter(CConverter): + + type = "path_t" + impl_by_reference = True + parse_by_reference = True + + converter = 'path_converter' + + def converter_init(self, *, allow_fd=False, nullable=False): + # right now path_t doesn't support default values. + # to support a default value, you'll need to override initialize(). + if self.default not in (unspecified, None): + fail("Can't specify a default to the path_t converter!") + + if self.c_default not in (None, 'Py_None'): + raise RuntimeError("Can't specify a c_default to the path_t converter!") + + self.nullable = nullable + self.allow_fd = allow_fd + + def pre_render(self): + def strify(value): + if isinstance(value, str): + return value + return str(int(bool(value))) + + # add self.py_name here when merging with posixmodule conversion + self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format( + self.function.name, + self.name, + strify(self.nullable), + strify(self.allow_fd), + ) + + def cleanup(self): + return "path_cleanup(&" + self.name + ");\n" + + +class dir_fd_converter(CConverter): + type = 'int' + + def converter_init(self, requires=None): + if self.default in (unspecified, None): + self.c_default = 'DEFAULT_DIR_FD' + if isinstance(requires, str): + self.converter = requires.upper() + '_DIR_FD_CONVERTER' + else: + self.converter = 'dir_fd_converter' + +class uid_t_converter(CConverter): + type = "uid_t" + converter = '_Py_Uid_Converter' + +class gid_t_converter(CConverter): + type = "gid_t" + converter = '_Py_Gid_Converter' + +class dev_t_converter(CConverter): + type = 'dev_t' + converter = '_Py_Dev_Converter' + +class dev_t_return_converter(unsigned_long_return_converter): + type = 'dev_t' + conversion_fn = '_PyLong_FromDev' + unsigned_cast = '(dev_t)' + +class FSConverter_converter(CConverter): + type = 'PyObject *' + converter = 'PyUnicode_FSConverter' + def converter_init(self): + if self.default is not unspecified: + fail("FSConverter_converter does not support default values") + self.c_default = 'NULL' + + def cleanup(self): + return "Py_XDECREF(" + self.name + ");\n" + +class pid_t_converter(CConverter): + type = 'pid_t' + format_unit = '" _Py_PARSE_PID "' + +class idtype_t_converter(int_converter): + type = 'idtype_t' + +class id_t_converter(CConverter): + type = 'id_t' + format_unit = '" _Py_PARSE_PID "' + +class intptr_t_converter(CConverter): + type = 'intptr_t' + format_unit = '" _Py_PARSE_INTPTR "' + +class Py_off_t_converter(CConverter): + type = 'Py_off_t' + converter = 'Py_off_t_converter' + +class Py_off_t_return_converter(long_return_converter): + type = 'Py_off_t' + conversion_fn = 'PyLong_FromPy_off_t' + +class path_confname_converter(CConverter): + type="int" + converter="conv_path_confname" + +class confstr_confname_converter(path_confname_converter): + converter='conv_confstr_confname' + +class sysconf_confname_converter(path_confname_converter): + converter="conv_sysconf_confname" + +[python start generated code]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=3338733161aa7879]*/ + +/*[clinic input] + +os.stat + + path : path_t(allow_fd=True) + Path to be examined; can be string, bytes, a path-like object or + open-file-descriptor int. + + * + + dir_fd : dir_fd(requires='fstatat') = None + If not None, it should be a file descriptor open to a directory, + and path should be a relative string; path will then be relative to + that directory. + + follow_symlinks: bool = True + If False, and the last element of the path is a symbolic link, + stat will examine the symbolic link itself instead of the file + the link points to. + +Perform a stat system call on the given path. + +dir_fd and follow_symlinks may not be implemented + on your platform. If they are unavailable, using them will raise a + NotImplementedError. + +It's an error to use dir_fd or follow_symlinks when specifying path as + an open file descriptor. + +[clinic start generated code]*/ + +static PyObject * +os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks) +/*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/ +{ + return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks); +} + + +/*[clinic input] +os.lstat + + path : path_t + + * + + dir_fd : dir_fd(requires='fstatat') = None + +Perform a stat system call on the given path, without following symbolic links. + +Like stat(), but do not follow symbolic links. +Equivalent to stat(path, follow_symlinks=False). +[clinic start generated code]*/ + +static PyObject * +os_lstat_impl(PyObject *module, path_t *path, int dir_fd) +/*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/ +{ + int follow_symlinks = 0; + return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks); +} + + +/*[clinic input] +os.access -> bool + + path: path_t + Path to be tested; can be string, bytes, or a path-like object. + + mode: int + Operating-system mode bitfield. Can be F_OK to test existence, + or the inclusive-OR of R_OK, W_OK, and X_OK. + + * + + dir_fd : dir_fd(requires='faccessat') = None + If not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that + directory. + + effective_ids: bool = False + If True, access will use the effective uid/gid instead of + the real uid/gid. + + follow_symlinks: bool = True + If False, and the last element of the path is a symbolic link, + access will examine the symbolic link itself instead of the file + the link points to. + +Use the real uid/gid to test for access to a path. + +{parameters} +dir_fd, effective_ids, and follow_symlinks may not be implemented + on your platform. If they are unavailable, using them will raise a + NotImplementedError. + +Note that most operations will use the effective uid/gid, therefore this + routine can be used in a suid/sgid environment to test if the invoking user + has the specified access to the path. + +[clinic start generated code]*/ + +static int +os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd, + int effective_ids, int follow_symlinks) +/*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/ +{ + int return_value; + +#ifdef MS_WINDOWS + DWORD attr; +#else + int result; +#endif + +#ifdef HAVE_FACCESSAT + int faccessat_unavailable = 0; +#endif + +#ifndef HAVE_FACCESSAT + if (follow_symlinks_specified("access", follow_symlinks)) + return -1; + + if (effective_ids) { + argument_unavailable_error("access", "effective_ids"); + return -1; + } +#endif + +#ifdef MS_WINDOWS + Py_BEGIN_ALLOW_THREADS + attr = GetFileAttributesW(path->wide); + Py_END_ALLOW_THREADS + + /* + * Access is possible if + * * we didn't get a -1, and + * * write access wasn't requested, + * * or the file isn't read-only, + * * or it's a directory. + * (Directories cannot be read-only on Windows.) + */ + return_value = (attr != INVALID_FILE_ATTRIBUTES) && + (!(mode & 2) || + !(attr & FILE_ATTRIBUTE_READONLY) || + (attr & FILE_ATTRIBUTE_DIRECTORY)); +#else + + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_FACCESSAT + if ((dir_fd != DEFAULT_DIR_FD) || + effective_ids || + !follow_symlinks) { + + if (HAVE_FACCESSAT_RUNTIME) { + int flags = 0; + if (!follow_symlinks) + flags |= AT_SYMLINK_NOFOLLOW; + if (effective_ids) + flags |= AT_EACCESS; + result = faccessat(dir_fd, path->narrow, mode, flags); + } else { + faccessat_unavailable = 1; + } + } + else +#endif + result = access(path->narrow, mode); + Py_END_ALLOW_THREADS + +#ifdef HAVE_FACCESSAT + if (faccessat_unavailable) { + if (dir_fd != DEFAULT_DIR_FD) { + argument_unavailable_error("access", "dir_fd"); + return -1; + } + if (follow_symlinks_specified("access", follow_symlinks)) + return -1; + + if (effective_ids) { + argument_unavailable_error("access", "effective_ids"); + return -1; + } + /* should be unreachable */ + return -1; + } +#endif + return_value = !result; +#endif + + return return_value; +} + +#ifndef F_OK +#define F_OK 0 +#endif +#ifndef R_OK +#define R_OK 4 +#endif +#ifndef W_OK +#define W_OK 2 +#endif +#ifndef X_OK +#define X_OK 1 +#endif + + +#ifdef HAVE_TTYNAME +/*[clinic input] +os.ttyname + + fd: int + Integer file descriptor handle. + + / + +Return the name of the terminal device connected to 'fd'. +[clinic start generated code]*/ + +static PyObject * +os_ttyname_impl(PyObject *module, int fd) +/*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/ +{ + + long size = sysconf(_SC_TTY_NAME_MAX); + if (size == -1) { + return posix_error(); + } + char *buffer = (char *)PyMem_RawMalloc(size); + if (buffer == NULL) { + return PyErr_NoMemory(); + } + int ret = ttyname_r(fd, buffer, size); + if (ret != 0) { + PyMem_RawFree(buffer); + errno = ret; + return posix_error(); + } + PyObject *res = PyUnicode_DecodeFSDefault(buffer); + PyMem_RawFree(buffer); + return res; +} +#endif + +#ifdef HAVE_CTERMID +/*[clinic input] +os.ctermid + +Return the name of the controlling terminal for this process. +[clinic start generated code]*/ + +static PyObject * +os_ctermid_impl(PyObject *module) +/*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/ +{ + char *ret; + char buffer[L_ctermid]; + +#ifdef USE_CTERMID_R + ret = ctermid_r(buffer); +#else + ret = ctermid(buffer); +#endif + if (ret == NULL) + return posix_error(); + return PyUnicode_DecodeFSDefault(buffer); +} +#endif /* HAVE_CTERMID */ + + +/*[clinic input] +os.chdir + + path: path_t(allow_fd='PATH_HAVE_FCHDIR') + +Change the current working directory to the specified path. + +path may always be specified as a string. +On some platforms, path may also be specified as an open file descriptor. + If this functionality is unavailable, using it raises an exception. +[clinic start generated code]*/ + +static PyObject * +os_chdir_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/ +{ + int result; + + if (PySys_Audit("os.chdir", "(O)", path->object) < 0) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS +#ifdef MS_WINDOWS + /* on unix, success = 0, on windows, success = !0 */ + result = !win32_wchdir(path->wide); +#else +#ifdef HAVE_FCHDIR + if (path->fd != -1) + result = fchdir(path->fd); + else +#endif + result = chdir(path->narrow); +#endif + Py_END_ALLOW_THREADS + + if (result) { + return path_error(path); + } + + Py_RETURN_NONE; +} + + +#ifdef HAVE_FCHDIR +/*[clinic input] +os.fchdir + + fd: fildes + +Change to the directory of the given file descriptor. + +fd must be opened on a directory, not a file. +Equivalent to os.chdir(fd). + +[clinic start generated code]*/ + +static PyObject * +os_fchdir_impl(PyObject *module, int fd) +/*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/ +{ + if (PySys_Audit("os.chdir", "(i)", fd) < 0) { + return NULL; + } + return posix_fildes_fd(fd, fchdir); +} +#endif /* HAVE_FCHDIR */ + + +/*[clinic input] +os.chmod + + path: path_t(allow_fd='PATH_HAVE_FCHMOD') + Path to be modified. May always be specified as a str, bytes, or a path-like object. + On some platforms, path may also be specified as an open file descriptor. + If this functionality is unavailable, using it raises an exception. + + mode: int + Operating-system mode bitfield. + + * + + dir_fd : dir_fd(requires='fchmodat') = None + If not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that + directory. + + follow_symlinks: bool = True + If False, and the last element of the path is a symbolic link, + chmod will modify the symbolic link itself instead of the file + the link points to. + +Change the access permissions of a file. + +It is an error to use dir_fd or follow_symlinks when specifying path as + an open file descriptor. +dir_fd and follow_symlinks may not be implemented on your platform. + If they are unavailable, using them will raise a NotImplementedError. + +[clinic start generated code]*/ + +static PyObject * +os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, + int follow_symlinks) +/*[clinic end generated code: output=5cf6a94915cc7bff input=989081551c00293b]*/ +{ + int result; + +#ifdef MS_WINDOWS + DWORD attr; +#endif + +#ifdef HAVE_FCHMODAT + int fchmodat_nofollow_unsupported = 0; + int fchmodat_unsupported = 0; +#endif + +#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD)) + if (follow_symlinks_specified("chmod", follow_symlinks)) + return NULL; +#endif + + if (PySys_Audit("os.chmod", "Oii", path->object, mode, + dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { + return NULL; + } + +#ifdef MS_WINDOWS + Py_BEGIN_ALLOW_THREADS + attr = GetFileAttributesW(path->wide); + if (attr == INVALID_FILE_ATTRIBUTES) + result = 0; + else { + if (mode & _S_IWRITE) + attr &= ~FILE_ATTRIBUTE_READONLY; + else + attr |= FILE_ATTRIBUTE_READONLY; + result = SetFileAttributesW(path->wide, attr); + } + Py_END_ALLOW_THREADS + + if (!result) { + return path_error(path); + } +#else /* MS_WINDOWS */ + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_FCHMOD + if (path->fd != -1) + result = fchmod(path->fd, mode); + else +#endif /* HAVE_CHMOD */ +#ifdef HAVE_LCHMOD + if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) + result = lchmod(path->narrow, mode); + else +#endif /* HAVE_LCHMOD */ +#ifdef HAVE_FCHMODAT + if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) { + if (HAVE_FCHMODAT_RUNTIME) { + /* + * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW! + * The documentation specifically shows how to use it, + * and then says it isn't implemented yet. + * (true on linux with glibc 2.15, and openindiana 3.x) + * + * Once it is supported, os.chmod will automatically + * support dir_fd and follow_symlinks=False. (Hopefully.) + * Until then, we need to be careful what exception we raise. + */ + result = fchmodat(dir_fd, path->narrow, mode, + follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); + /* + * But wait! We can't throw the exception without allowing threads, + * and we can't do that in this nested scope. (Macro trickery, sigh.) + */ + fchmodat_nofollow_unsupported = + result && + ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) && + !follow_symlinks; + } else { + fchmodat_unsupported = 1; + fchmodat_nofollow_unsupported = 1; + + result = -1; + } + } + else +#endif /* HAVE_FHCMODAT */ + { +#ifdef HAVE_CHMOD + result = chmod(path->narrow, mode); +#elif defined(__wasi__) + // WASI SDK 15.0 does not support chmod. + // Ignore missing syscall for now. + result = 0; +#else + result = -1; + errno = ENOSYS; +#endif + } + Py_END_ALLOW_THREADS + + if (result) { +#ifdef HAVE_FCHMODAT + if (fchmodat_unsupported) { + if (dir_fd != DEFAULT_DIR_FD) { + argument_unavailable_error("chmod", "dir_fd"); + return NULL; + } + } + + if (fchmodat_nofollow_unsupported) { + if (dir_fd != DEFAULT_DIR_FD) + dir_fd_and_follow_symlinks_invalid("chmod", + dir_fd, follow_symlinks); + else + follow_symlinks_specified("chmod", follow_symlinks); + return NULL; + } + else +#endif /* HAVE_FCHMODAT */ + return path_error(path); + } +#endif /* MS_WINDOWS */ + + Py_RETURN_NONE; +} + + +#ifdef HAVE_FCHMOD +/*[clinic input] +os.fchmod + + fd: int + mode: int + +Change the access permissions of the file given by file descriptor fd. + +Equivalent to os.chmod(fd, mode). +[clinic start generated code]*/ + +static PyObject * +os_fchmod_impl(PyObject *module, int fd, int mode) +/*[clinic end generated code: output=afd9bc05b4e426b3 input=8ab11975ca01ee5b]*/ +{ + int res; + int async_err = 0; + + if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) { + return NULL; + } + + do { + Py_BEGIN_ALLOW_THREADS + res = fchmod(fd, mode); + Py_END_ALLOW_THREADS + } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (res != 0) + return (!async_err) ? posix_error() : NULL; + + Py_RETURN_NONE; +} +#endif /* HAVE_FCHMOD */ + + +#ifdef HAVE_LCHMOD +/*[clinic input] +os.lchmod + + path: path_t + mode: int + +Change the access permissions of a file, without following symbolic links. + +If path is a symlink, this affects the link itself rather than the target. +Equivalent to chmod(path, mode, follow_symlinks=False)." +[clinic start generated code]*/ + +static PyObject * +os_lchmod_impl(PyObject *module, path_t *path, int mode) +/*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/ +{ + int res; + if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) { + return NULL; + } + Py_BEGIN_ALLOW_THREADS + res = lchmod(path->narrow, mode); + Py_END_ALLOW_THREADS + if (res < 0) { + path_error(path); + return NULL; + } + Py_RETURN_NONE; +} +#endif /* HAVE_LCHMOD */ + + +#ifdef HAVE_CHFLAGS +/*[clinic input] +os.chflags + + path: path_t + flags: unsigned_long(bitwise=True) + follow_symlinks: bool=True + +Set file flags. + +If follow_symlinks is False, and the last element of the path is a symbolic + link, chflags will change flags on the symbolic link itself instead of the + file the link points to. +follow_symlinks may not be implemented on your platform. If it is +unavailable, using it will raise a NotImplementedError. + +[clinic start generated code]*/ + +static PyObject * +os_chflags_impl(PyObject *module, path_t *path, unsigned long flags, + int follow_symlinks) +/*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/ +{ + int result; + +#ifndef HAVE_LCHFLAGS + if (follow_symlinks_specified("chflags", follow_symlinks)) + return NULL; +#endif + + if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_LCHFLAGS + if (!follow_symlinks) + result = lchflags(path->narrow, flags); + else +#endif + result = chflags(path->narrow, flags); + Py_END_ALLOW_THREADS + + if (result) + return path_error(path); + + Py_RETURN_NONE; +} +#endif /* HAVE_CHFLAGS */ + + +#ifdef HAVE_LCHFLAGS +/*[clinic input] +os.lchflags + + path: path_t + flags: unsigned_long(bitwise=True) + +Set file flags. + +This function will not follow symbolic links. +Equivalent to chflags(path, flags, follow_symlinks=False). +[clinic start generated code]*/ + +static PyObject * +os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags) +/*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/ +{ + int res; + if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) { + return NULL; + } + Py_BEGIN_ALLOW_THREADS + res = lchflags(path->narrow, flags); + Py_END_ALLOW_THREADS + if (res < 0) { + return path_error(path); + } + Py_RETURN_NONE; +} +#endif /* HAVE_LCHFLAGS */ + + +#ifdef HAVE_CHROOT +/*[clinic input] +os.chroot + path: path_t + +Change root directory to path. + +[clinic start generated code]*/ + +static PyObject * +os_chroot_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/ +{ + int res; + Py_BEGIN_ALLOW_THREADS + res = chroot(path->narrow); + Py_END_ALLOW_THREADS + if (res < 0) + return path_error(path); + Py_RETURN_NONE; +} +#endif /* HAVE_CHROOT */ + + +#ifdef HAVE_FSYNC +/*[clinic input] +os.fsync + + fd: fildes + +Force write of fd to disk. +[clinic start generated code]*/ + +static PyObject * +os_fsync_impl(PyObject *module, int fd) +/*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/ +{ + return posix_fildes_fd(fd, fsync); +} +#endif /* HAVE_FSYNC */ + + +#ifdef HAVE_SYNC +/*[clinic input] +os.sync + +Force write of everything to disk. +[clinic start generated code]*/ + +static PyObject * +os_sync_impl(PyObject *module) +/*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/ +{ + Py_BEGIN_ALLOW_THREADS + sync(); + Py_END_ALLOW_THREADS + Py_RETURN_NONE; +} +#endif /* HAVE_SYNC */ + + +#ifdef HAVE_FDATASYNC +#ifdef __hpux +extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */ +#endif + +/*[clinic input] +os.fdatasync + + fd: fildes + +Force write of fd to disk without forcing update of metadata. +[clinic start generated code]*/ + +static PyObject * +os_fdatasync_impl(PyObject *module, int fd) +/*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/ +{ + return posix_fildes_fd(fd, fdatasync); +} +#endif /* HAVE_FDATASYNC */ + + +#ifdef HAVE_CHOWN +/*[clinic input] +os.chown + + path : path_t(allow_fd='PATH_HAVE_FCHOWN') + Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int. + + uid: uid_t + + gid: gid_t + + * + + dir_fd : dir_fd(requires='fchownat') = None + If not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that + directory. + + follow_symlinks: bool = True + If False, and the last element of the path is a symbolic link, + stat will examine the symbolic link itself instead of the file + the link points to. + +Change the owner and group id of path to the numeric uid and gid.\ + +path may always be specified as a string. +On some platforms, path may also be specified as an open file descriptor. + If this functionality is unavailable, using it raises an exception. +If dir_fd is not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that directory. +If follow_symlinks is False, and the last element of the path is a symbolic + link, chown will modify the symbolic link itself instead of the file the + link points to. +It is an error to use dir_fd or follow_symlinks when specifying path as + an open file descriptor. +dir_fd and follow_symlinks may not be implemented on your platform. + If they are unavailable, using them will raise a NotImplementedError. + +[clinic start generated code]*/ + +static PyObject * +os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid, + int dir_fd, int follow_symlinks) +/*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/ +{ + int result; + +#if defined(HAVE_FCHOWNAT) + int fchownat_unsupported = 0; +#endif + +#if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT)) + if (follow_symlinks_specified("chown", follow_symlinks)) + return NULL; +#endif + if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) || + fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks)) + return NULL; + + if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, + dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_FCHOWN + if (path->fd != -1) + result = fchown(path->fd, uid, gid); + else +#endif +#ifdef HAVE_LCHOWN + if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) + result = lchown(path->narrow, uid, gid); + else +#endif +#ifdef HAVE_FCHOWNAT + if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) { + if (HAVE_FCHOWNAT_RUNTIME) { + result = fchownat(dir_fd, path->narrow, uid, gid, + follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); + } else { + fchownat_unsupported = 1; + } + } else +#endif + result = chown(path->narrow, uid, gid); + Py_END_ALLOW_THREADS + +#ifdef HAVE_FCHOWNAT + if (fchownat_unsupported) { + /* This would be incorrect if the current platform + * doesn't support lchown. + */ + argument_unavailable_error(NULL, "dir_fd"); + return NULL; + } +#endif + + if (result) + return path_error(path); + + Py_RETURN_NONE; +} +#endif /* HAVE_CHOWN */ + + +#ifdef HAVE_FCHOWN +/*[clinic input] +os.fchown + + fd: int + uid: uid_t + gid: gid_t + +Change the owner and group id of the file specified by file descriptor. + +Equivalent to os.chown(fd, uid, gid). + +[clinic start generated code]*/ + +static PyObject * +os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid) +/*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/ +{ + int res; + int async_err = 0; + + if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) { + return NULL; + } + + do { + Py_BEGIN_ALLOW_THREADS + res = fchown(fd, uid, gid); + Py_END_ALLOW_THREADS + } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (res != 0) + return (!async_err) ? posix_error() : NULL; + + Py_RETURN_NONE; +} +#endif /* HAVE_FCHOWN */ + + +#ifdef HAVE_LCHOWN +/*[clinic input] +os.lchown + + path : path_t + uid: uid_t + gid: gid_t + +Change the owner and group id of path to the numeric uid and gid. + +This function will not follow symbolic links. +Equivalent to os.chown(path, uid, gid, follow_symlinks=False). +[clinic start generated code]*/ + +static PyObject * +os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid) +/*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/ +{ + int res; + if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) { + return NULL; + } + Py_BEGIN_ALLOW_THREADS + res = lchown(path->narrow, uid, gid); + Py_END_ALLOW_THREADS + if (res < 0) { + return path_error(path); + } + Py_RETURN_NONE; +} +#endif /* HAVE_LCHOWN */ + + +static PyObject * +posix_getcwd(int use_bytes) +{ +#ifdef MS_WINDOWS + wchar_t wbuf[MAXPATHLEN]; + wchar_t *wbuf2 = wbuf; + DWORD len; + + Py_BEGIN_ALLOW_THREADS + len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf); + /* If the buffer is large enough, len does not include the + terminating \0. If the buffer is too small, len includes + the space needed for the terminator. */ + if (len >= Py_ARRAY_LENGTH(wbuf)) { + if (len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) { + wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t)); + } + else { + wbuf2 = NULL; + } + if (wbuf2) { + len = GetCurrentDirectoryW(len, wbuf2); + } + } + Py_END_ALLOW_THREADS + + if (!wbuf2) { + PyErr_NoMemory(); + return NULL; + } + if (!len) { + if (wbuf2 != wbuf) + PyMem_RawFree(wbuf2); + return PyErr_SetFromWindowsErr(0); + } + + PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len); + if (wbuf2 != wbuf) { + PyMem_RawFree(wbuf2); + } + + if (use_bytes) { + if (resobj == NULL) { + return NULL; + } + Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj)); + } + + return resobj; +#else + const size_t chunk = 1024; + + char *buf = NULL; + char *cwd = NULL; + size_t buflen = 0; + + Py_BEGIN_ALLOW_THREADS + do { + char *newbuf; + if (buflen <= PY_SSIZE_T_MAX - chunk) { + buflen += chunk; + newbuf = PyMem_RawRealloc(buf, buflen); + } + else { + newbuf = NULL; + } + if (newbuf == NULL) { + PyMem_RawFree(buf); + buf = NULL; + break; + } + buf = newbuf; + + cwd = getcwd(buf, buflen); + } while (cwd == NULL && errno == ERANGE); + Py_END_ALLOW_THREADS + + if (buf == NULL) { + return PyErr_NoMemory(); + } + if (cwd == NULL) { + PyMem_RawFree(buf); + return posix_error(); + } + + PyObject *obj; + if (use_bytes) { + obj = PyBytes_FromStringAndSize(buf, strlen(buf)); + } + else { + obj = PyUnicode_DecodeFSDefault(buf); + } + PyMem_RawFree(buf); + + return obj; +#endif /* !MS_WINDOWS */ +} + + +/*[clinic input] +os.getcwd + +Return a unicode string representing the current working directory. +[clinic start generated code]*/ + +static PyObject * +os_getcwd_impl(PyObject *module) +/*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/ +{ + return posix_getcwd(0); +} + + +/*[clinic input] +os.getcwdb + +Return a bytes string representing the current working directory. +[clinic start generated code]*/ + +static PyObject * +os_getcwdb_impl(PyObject *module) +/*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/ +{ + return posix_getcwd(1); +} + + +#if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS)) +#define HAVE_LINK 1 +#endif + +#ifdef HAVE_LINK +/*[clinic input] + +os.link + + src : path_t + dst : path_t + * + src_dir_fd : dir_fd = None + dst_dir_fd : dir_fd = None + follow_symlinks: bool = True + +Create a hard link to a file. + +If either src_dir_fd or dst_dir_fd is not None, it should be a file + descriptor open to a directory, and the respective path string (src or dst) + should be relative; the path will then be relative to that directory. +If follow_symlinks is False, and the last element of src is a symbolic + link, link will create a link to the symbolic link itself instead of the + file the link points to. +src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your + platform. If they are unavailable, using them will raise a + NotImplementedError. +[clinic start generated code]*/ + +static PyObject * +os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, + int dst_dir_fd, int follow_symlinks) +/*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/ +{ +#ifdef MS_WINDOWS + BOOL result = FALSE; +#else + int result; +#endif +#if defined(HAVE_LINKAT) + int linkat_unavailable = 0; +#endif + +#ifndef HAVE_LINKAT + if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) { + argument_unavailable_error("link", "src_dir_fd and dst_dir_fd"); + return NULL; + } +#endif + +#ifndef MS_WINDOWS + if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { + PyErr_SetString(PyExc_NotImplementedError, + "link: src and dst must be the same type"); + return NULL; + } +#endif + + if (PySys_Audit("os.link", "OOii", src->object, dst->object, + src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd, + dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) { + return NULL; + } + +#ifdef MS_WINDOWS + Py_BEGIN_ALLOW_THREADS + result = CreateHardLinkW(dst->wide, src->wide, NULL); + Py_END_ALLOW_THREADS + + if (!result) + return path_error2(src, dst); +#else + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_LINKAT + if ((src_dir_fd != DEFAULT_DIR_FD) || + (dst_dir_fd != DEFAULT_DIR_FD) || + (!follow_symlinks)) { + + if (HAVE_LINKAT_RUNTIME) { + + result = linkat(src_dir_fd, src->narrow, + dst_dir_fd, dst->narrow, + follow_symlinks ? AT_SYMLINK_FOLLOW : 0); + + } +#ifdef __APPLE__ + else { + if (src_dir_fd == DEFAULT_DIR_FD && dst_dir_fd == DEFAULT_DIR_FD) { + /* See issue 41355: This matches the behaviour of !HAVE_LINKAT */ + result = link(src->narrow, dst->narrow); + } else { + linkat_unavailable = 1; + } + } +#endif + } + else +#endif /* HAVE_LINKAT */ + result = link(src->narrow, dst->narrow); + Py_END_ALLOW_THREADS + +#ifdef HAVE_LINKAT + if (linkat_unavailable) { + /* Either or both dir_fd arguments were specified */ + if (src_dir_fd != DEFAULT_DIR_FD) { + argument_unavailable_error("link", "src_dir_fd"); + } else { + argument_unavailable_error("link", "dst_dir_fd"); + } + return NULL; + } +#endif + + if (result) + return path_error2(src, dst); +#endif /* MS_WINDOWS */ + + Py_RETURN_NONE; +} +#endif + + +#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR) +static PyObject * +_listdir_windows_no_opendir(path_t *path, PyObject *list) +{ + PyObject *v; + HANDLE hFindFile = INVALID_HANDLE_VALUE; + BOOL result; + wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */ + /* only claim to have space for MAX_PATH */ + Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4; + wchar_t *wnamebuf = NULL; + + WIN32_FIND_DATAW wFileData; + const wchar_t *po_wchars; + + if (!path->wide) { /* Default arg: "." */ + po_wchars = L"."; + len = 1; + } else { + po_wchars = path->wide; + len = wcslen(path->wide); + } + /* The +5 is so we can append "\\*.*\0" */ + wnamebuf = PyMem_New(wchar_t, len + 5); + if (!wnamebuf) { + PyErr_NoMemory(); + goto exit; + } + wcscpy(wnamebuf, po_wchars); + if (len > 0) { + wchar_t wch = wnamebuf[len-1]; + if (wch != SEP && wch != ALTSEP && wch != L':') + wnamebuf[len++] = SEP; + wcscpy(wnamebuf + len, L"*.*"); + } + if ((list = PyList_New(0)) == NULL) { + goto exit; + } + Py_BEGIN_ALLOW_THREADS + hFindFile = FindFirstFileW(wnamebuf, &wFileData); + Py_END_ALLOW_THREADS + if (hFindFile == INVALID_HANDLE_VALUE) { + int error = GetLastError(); + if (error == ERROR_FILE_NOT_FOUND) + goto exit; + Py_DECREF(list); + list = path_error(path); + goto exit; + } + do { + /* Skip over . and .. */ + if (wcscmp(wFileData.cFileName, L".") != 0 && + wcscmp(wFileData.cFileName, L"..") != 0) { + v = PyUnicode_FromWideChar(wFileData.cFileName, + wcslen(wFileData.cFileName)); + if (path->narrow && v) { + Py_SETREF(v, PyUnicode_EncodeFSDefault(v)); + } + if (v == NULL) { + Py_DECREF(list); + list = NULL; + break; + } + if (PyList_Append(list, v) != 0) { + Py_DECREF(v); + Py_DECREF(list); + list = NULL; + break; + } + Py_DECREF(v); + } + Py_BEGIN_ALLOW_THREADS + result = FindNextFileW(hFindFile, &wFileData); + Py_END_ALLOW_THREADS + /* FindNextFile sets error to ERROR_NO_MORE_FILES if + it got to the end of the directory. */ + if (!result && GetLastError() != ERROR_NO_MORE_FILES) { + Py_DECREF(list); + list = path_error(path); + goto exit; + } + } while (result == TRUE); + +exit: + if (hFindFile != INVALID_HANDLE_VALUE) { + if (FindClose(hFindFile) == FALSE) { + if (list != NULL) { + Py_DECREF(list); + list = path_error(path); + } + } + } + PyMem_Free(wnamebuf); + + return list; +} /* end of _listdir_windows_no_opendir */ + +#else /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */ + +static PyObject * +_posix_listdir(path_t *path, PyObject *list) +{ + PyObject *v; + DIR *dirp = NULL; + struct dirent *ep; + int return_str; /* if false, return bytes */ +#ifdef HAVE_FDOPENDIR + int fd = -1; +#endif + + errno = 0; +#ifdef HAVE_FDOPENDIR + if (path->fd != -1) { + if (HAVE_FDOPENDIR_RUNTIME) { + /* closedir() closes the FD, so we duplicate it */ + fd = _Py_dup(path->fd); + if (fd == -1) + return NULL; + + return_str = 1; + + Py_BEGIN_ALLOW_THREADS + dirp = fdopendir(fd); + Py_END_ALLOW_THREADS + } else { + PyErr_SetString(PyExc_TypeError, + "listdir: path should be string, bytes, os.PathLike or None, not int"); + return NULL; + } + } + else +#endif + { + const char *name; + if (path->narrow) { + name = path->narrow; + /* only return bytes if they specified a bytes object */ + return_str = !PyBytes_Check(path->object); + } + else { + name = "."; + return_str = 1; + } + + Py_BEGIN_ALLOW_THREADS + dirp = opendir(name); + Py_END_ALLOW_THREADS + } + + if (dirp == NULL) { + list = path_error(path); +#ifdef HAVE_FDOPENDIR + if (fd != -1) { + Py_BEGIN_ALLOW_THREADS + close(fd); + Py_END_ALLOW_THREADS + } +#endif + goto exit; + } + if ((list = PyList_New(0)) == NULL) { + goto exit; + } + for (;;) { + errno = 0; + Py_BEGIN_ALLOW_THREADS + ep = readdir(dirp); + Py_END_ALLOW_THREADS + if (ep == NULL) { + if (errno == 0) { + break; + } else { + Py_DECREF(list); + list = path_error(path); + goto exit; + } + } + if (ep->d_name[0] == '.' && + (NAMLEN(ep) == 1 || + (ep->d_name[1] == '.' && NAMLEN(ep) == 2))) + continue; + if (return_str) + v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep)); + else + v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep)); + if (v == NULL) { + Py_CLEAR(list); + break; + } + if (PyList_Append(list, v) != 0) { + Py_DECREF(v); + Py_CLEAR(list); + break; + } + Py_DECREF(v); + } + +exit: + if (dirp != NULL) { + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_FDOPENDIR + if (fd > -1) + rewinddir(dirp); +#endif + closedir(dirp); + Py_END_ALLOW_THREADS + } + + return list; +} /* end of _posix_listdir */ +#endif /* which OS */ + + +/*[clinic input] +os.listdir + + path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None + +Return a list containing the names of the files in the directory. + +path can be specified as either str, bytes, or a path-like object. If path is bytes, + the filenames returned will also be bytes; in all other circumstances + the filenames returned will be str. +If path is None, uses the path='.'. +On some platforms, path may also be specified as an open file descriptor;\ + the file descriptor must refer to a directory. + If this functionality is unavailable, using it raises NotImplementedError. + +The list is in arbitrary order. It does not include the special +entries '.' and '..' even if they are present in the directory. + + +[clinic start generated code]*/ + +static PyObject * +os_listdir_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/ +{ + if (PySys_Audit("os.listdir", "O", + path->object ? path->object : Py_None) < 0) { + return NULL; + } +#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR) + return _listdir_windows_no_opendir(path, NULL); +#else + return _posix_listdir(path, NULL); +#endif +} + +#ifdef MS_WINDOWS +int +_PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p) +{ + wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf; + DWORD result; + + result = GetFullPathNameW(path, + Py_ARRAY_LENGTH(woutbuf), woutbuf, + NULL); + if (!result) { + return -1; + } + + if (result >= Py_ARRAY_LENGTH(woutbuf)) { + if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) { + woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t)); + } + else { + woutbufp = NULL; + } + if (!woutbufp) { + *abspath_p = NULL; + return 0; + } + + result = GetFullPathNameW(path, result, woutbufp, NULL); + if (!result) { + PyMem_RawFree(woutbufp); + return -1; + } + } + + if (woutbufp != woutbuf) { + *abspath_p = woutbufp; + return 0; + } + + *abspath_p = _PyMem_RawWcsdup(woutbufp); + return 0; +} + + +/* A helper function for abspath on win32 */ +/*[clinic input] +os._getfullpathname + + path: path_t + / + +[clinic start generated code]*/ + +static PyObject * +os__getfullpathname_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/ +{ + wchar_t *abspath; + + if (_PyOS_getfullpathname(path->wide, &abspath) < 0) { + return win32_error_object("GetFullPathNameW", path->object); + } + if (abspath == NULL) { + return PyErr_NoMemory(); + } + + PyObject *str = PyUnicode_FromWideChar(abspath, wcslen(abspath)); + PyMem_RawFree(abspath); + if (str == NULL) { + return NULL; + } + if (path->narrow) { + Py_SETREF(str, PyUnicode_EncodeFSDefault(str)); + } + return str; +} + + +/*[clinic input] +os._getfinalpathname + + path: path_t + / + +A helper function for samepath on windows. +[clinic start generated code]*/ + +static PyObject * +os__getfinalpathname_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/ +{ + HANDLE hFile; + wchar_t buf[MAXPATHLEN], *target_path = buf; + int buf_size = Py_ARRAY_LENGTH(buf); + int result_length; + PyObject *result; + + Py_BEGIN_ALLOW_THREADS + hFile = CreateFileW( + path->wide, + 0, /* desired access */ + 0, /* share mode */ + NULL, /* security attributes */ + OPEN_EXISTING, + /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ + FILE_FLAG_BACKUP_SEMANTICS, + NULL); + Py_END_ALLOW_THREADS + + if (hFile == INVALID_HANDLE_VALUE) { + return win32_error_object("CreateFileW", path->object); + } + + /* We have a good handle to the target, use it to determine the + target path name. */ + while (1) { + Py_BEGIN_ALLOW_THREADS + result_length = GetFinalPathNameByHandleW(hFile, target_path, + buf_size, VOLUME_NAME_DOS); + Py_END_ALLOW_THREADS + + if (!result_length) { + result = win32_error_object("GetFinalPathNameByHandleW", + path->object); + goto cleanup; + } + + if (result_length < buf_size) { + break; + } + + wchar_t *tmp; + tmp = PyMem_Realloc(target_path != buf ? target_path : NULL, + result_length * sizeof(*tmp)); + if (!tmp) { + result = PyErr_NoMemory(); + goto cleanup; + } + + buf_size = result_length; + target_path = tmp; + } + + result = PyUnicode_FromWideChar(target_path, result_length); + if (result && path->narrow) { + Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); + } + +cleanup: + if (target_path != buf) { + PyMem_Free(target_path); + } + CloseHandle(hFile); + return result; +} + + +/*[clinic input] +os._getvolumepathname + + path: path_t + +A helper function for ismount on Win32. +[clinic start generated code]*/ + +static PyObject * +os__getvolumepathname_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/ +{ + PyObject *result; + wchar_t *mountpath=NULL; + size_t buflen; + BOOL ret; + + /* Volume path should be shorter than entire path */ + buflen = Py_MAX(path->length, MAX_PATH); + + if (buflen > PY_DWORD_MAX) { + PyErr_SetString(PyExc_OverflowError, "path too long"); + return NULL; + } + + mountpath = PyMem_New(wchar_t, buflen); + if (mountpath == NULL) + return PyErr_NoMemory(); + + Py_BEGIN_ALLOW_THREADS + ret = GetVolumePathNameW(path->wide, mountpath, + Py_SAFE_DOWNCAST(buflen, size_t, DWORD)); + Py_END_ALLOW_THREADS + + if (!ret) { + result = win32_error_object("_getvolumepathname", path->object); + goto exit; + } + result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath)); + if (path->narrow) + Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); + +exit: + PyMem_Free(mountpath); + return result; +} + + +/*[clinic input] +os._path_splitroot + + path: path_t + +Removes everything after the root on Win32. +[clinic start generated code]*/ + +static PyObject * +os__path_splitroot_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=ab7f1a88b654581c input=dc93b1d3984cffb6]*/ +{ + wchar_t *buffer; + wchar_t *end; + PyObject *result = NULL; + HRESULT ret; + + buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1)); + if (!buffer) { + return NULL; + } + wcscpy(buffer, path->wide); + for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) { + *p = L'\\'; + } + + Py_BEGIN_ALLOW_THREADS + ret = PathCchSkipRoot(buffer, &end); + Py_END_ALLOW_THREADS + if (FAILED(ret)) { + result = Py_BuildValue("sO", "", path->object); + } else if (end != buffer) { + size_t rootLen = (size_t)(end - buffer); + result = Py_BuildValue("NN", + PyUnicode_FromWideChar(path->wide, rootLen), + PyUnicode_FromWideChar(path->wide + rootLen, -1) + ); + } else { + result = Py_BuildValue("Os", path->object, ""); + } + PyMem_Free(buffer); + + return result; +} + + +#endif /* MS_WINDOWS */ + + +/*[clinic input] +os._path_normpath + + path: object + +Basic path normalization. +[clinic start generated code]*/ + +static PyObject * +os__path_normpath_impl(PyObject *module, PyObject *path) +/*[clinic end generated code: output=b94d696d828019da input=5e90c39e12549dc0]*/ +{ + if (!PyUnicode_Check(path)) { + PyErr_Format(PyExc_TypeError, "expected 'str', not '%.200s'", + Py_TYPE(path)->tp_name); + return NULL; + } + Py_ssize_t len; + wchar_t *buffer = PyUnicode_AsWideCharString(path, &len); + if (!buffer) { + return NULL; + } + PyObject *result = PyUnicode_FromWideChar(_Py_normpath(buffer, len), -1); + PyMem_Free(buffer); + return result; +} + +/*[clinic input] +os.mkdir + + path : path_t + + mode: int = 0o777 + + * + + dir_fd : dir_fd(requires='mkdirat') = None + +# "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\ + +Create a directory. + +If dir_fd is not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that directory. +dir_fd may not be implemented on your platform. + If it is unavailable, using it will raise a NotImplementedError. + +The mode argument is ignored on Windows. Where it is used, the current umask +value is first masked out. +[clinic start generated code]*/ + +static PyObject * +os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd) +/*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/ +{ + int result; +#ifdef HAVE_MKDIRAT + int mkdirat_unavailable = 0; +#endif + + if (PySys_Audit("os.mkdir", "Oii", path->object, mode, + dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { + return NULL; + } + +#ifdef MS_WINDOWS + Py_BEGIN_ALLOW_THREADS + result = CreateDirectoryW(path->wide, NULL); + Py_END_ALLOW_THREADS + + if (!result) + return path_error(path); +#else + Py_BEGIN_ALLOW_THREADS +#if HAVE_MKDIRAT + if (dir_fd != DEFAULT_DIR_FD) { + if (HAVE_MKDIRAT_RUNTIME) { + result = mkdirat(dir_fd, path->narrow, mode); + + } else { + mkdirat_unavailable = 1; + } + } else +#endif +#if defined(__WATCOMC__) && !defined(__QNX__) + result = mkdir(path->narrow); +#else + result = mkdir(path->narrow, mode); +#endif + Py_END_ALLOW_THREADS + +#if HAVE_MKDIRAT + if (mkdirat_unavailable) { + argument_unavailable_error(NULL, "dir_fd"); + return NULL; + } +#endif + + if (result < 0) + return path_error(path); +#endif /* MS_WINDOWS */ + Py_RETURN_NONE; +} + + +/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */ +#if defined(HAVE_SYS_RESOURCE_H) +#include +#endif + + +#ifdef HAVE_NICE +/*[clinic input] +os.nice + + increment: int + / + +Add increment to the priority of process and return the new priority. +[clinic start generated code]*/ + +static PyObject * +os_nice_impl(PyObject *module, int increment) +/*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/ +{ + int value; + + /* There are two flavours of 'nice': one that returns the new + priority (as required by almost all standards out there) and the + Linux/FreeBSD one, which returns '0' on success and advices + the use of getpriority() to get the new priority. + + If we are of the nice family that returns the new priority, we + need to clear errno before the call, and check if errno is filled + before calling posix_error() on a returnvalue of -1, because the + -1 may be the actual new priority! */ + + errno = 0; + value = nice(increment); +#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY) + if (value == 0) + value = getpriority(PRIO_PROCESS, 0); +#endif + if (value == -1 && errno != 0) + /* either nice() or getpriority() returned an error */ + return posix_error(); + return PyLong_FromLong((long) value); +} +#endif /* HAVE_NICE */ + + +#ifdef HAVE_GETPRIORITY +/*[clinic input] +os.getpriority + + which: int + who: int + +Return program scheduling priority. +[clinic start generated code]*/ + +static PyObject * +os_getpriority_impl(PyObject *module, int which, int who) +/*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/ +{ + int retval; + + errno = 0; + retval = getpriority(which, who); + if (errno != 0) + return posix_error(); + return PyLong_FromLong((long)retval); +} +#endif /* HAVE_GETPRIORITY */ + + +#ifdef HAVE_SETPRIORITY +/*[clinic input] +os.setpriority + + which: int + who: int + priority: int + +Set program scheduling priority. +[clinic start generated code]*/ + +static PyObject * +os_setpriority_impl(PyObject *module, int which, int who, int priority) +/*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/ +{ + int retval; + + retval = setpriority(which, who, priority); + if (retval == -1) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETPRIORITY */ + + +static PyObject * +internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace) +{ + const char *function_name = is_replace ? "replace" : "rename"; + int dir_fd_specified; + +#ifdef HAVE_RENAMEAT + int renameat_unavailable = 0; +#endif + +#ifdef MS_WINDOWS + BOOL result; + int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0; +#else + int result; +#endif + + dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) || + (dst_dir_fd != DEFAULT_DIR_FD); +#ifndef HAVE_RENAMEAT + if (dir_fd_specified) { + argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd"); + return NULL; + } +#endif + + if (PySys_Audit("os.rename", "OOii", src->object, dst->object, + src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd, + dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) { + return NULL; + } + +#ifdef MS_WINDOWS + Py_BEGIN_ALLOW_THREADS + result = MoveFileExW(src->wide, dst->wide, flags); + Py_END_ALLOW_THREADS + + if (!result) + return path_error2(src, dst); + +#else + if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { + PyErr_Format(PyExc_ValueError, + "%s: src and dst must be the same type", function_name); + return NULL; + } + + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_RENAMEAT + if (dir_fd_specified) { + if (HAVE_RENAMEAT_RUNTIME) { + result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow); + } else { + renameat_unavailable = 1; + } + } else +#endif + result = rename(src->narrow, dst->narrow); + Py_END_ALLOW_THREADS + + +#ifdef HAVE_RENAMEAT + if (renameat_unavailable) { + argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd"); + return NULL; + } +#endif + + if (result) + return path_error2(src, dst); +#endif + Py_RETURN_NONE; +} + + +/*[clinic input] +os.rename + + src : path_t + dst : path_t + * + src_dir_fd : dir_fd = None + dst_dir_fd : dir_fd = None + +Rename a file or directory. + +If either src_dir_fd or dst_dir_fd is not None, it should be a file + descriptor open to a directory, and the respective path string (src or dst) + should be relative; the path will then be relative to that directory. +src_dir_fd and dst_dir_fd, may not be implemented on your platform. + If they are unavailable, using them will raise a NotImplementedError. +[clinic start generated code]*/ + +static PyObject * +os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, + int dst_dir_fd) +/*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/ +{ + return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0); +} + + +/*[clinic input] +os.replace = os.rename + +Rename a file or directory, overwriting the destination. + +If either src_dir_fd or dst_dir_fd is not None, it should be a file + descriptor open to a directory, and the respective path string (src or dst) + should be relative; the path will then be relative to that directory. +src_dir_fd and dst_dir_fd, may not be implemented on your platform. + If they are unavailable, using them will raise a NotImplementedError. +[clinic start generated code]*/ + +static PyObject * +os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, + int dst_dir_fd) +/*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/ +{ + return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1); +} + + +/*[clinic input] +os.rmdir + + path: path_t + * + dir_fd: dir_fd(requires='unlinkat') = None + +Remove a directory. + +If dir_fd is not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that directory. +dir_fd may not be implemented on your platform. + If it is unavailable, using it will raise a NotImplementedError. +[clinic start generated code]*/ + +static PyObject * +os_rmdir_impl(PyObject *module, path_t *path, int dir_fd) +/*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/ +{ + int result; +#ifdef HAVE_UNLINKAT + int unlinkat_unavailable = 0; +#endif + + if (PySys_Audit("os.rmdir", "Oi", path->object, + dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS +#ifdef MS_WINDOWS + /* Windows, success=1, UNIX, success=0 */ + result = !RemoveDirectoryW(path->wide); +#else +#ifdef HAVE_UNLINKAT + if (dir_fd != DEFAULT_DIR_FD) { + if (HAVE_UNLINKAT_RUNTIME) { + result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR); + } else { + unlinkat_unavailable = 1; + result = -1; + } + } else +#endif + result = rmdir(path->narrow); +#endif + Py_END_ALLOW_THREADS + +#ifdef HAVE_UNLINKAT + if (unlinkat_unavailable) { + argument_unavailable_error("rmdir", "dir_fd"); + return NULL; + } +#endif + + if (result) + return path_error(path); + + Py_RETURN_NONE; +} + + +#ifdef HAVE_SYSTEM +#ifdef MS_WINDOWS +/*[clinic input] +os.system -> long + + command: Py_UNICODE + +Execute the command in a subshell. +[clinic start generated code]*/ + +static long +os_system_impl(PyObject *module, const Py_UNICODE *command) +/*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/ +{ + long result; + + if (PySys_Audit("os.system", "(u)", command) < 0) { + return -1; + } + + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + result = _wsystem(command); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + return result; +} +#else /* MS_WINDOWS */ +/*[clinic input] +os.system -> long + + command: FSConverter + +Execute the command in a subshell. +[clinic start generated code]*/ + +static long +os_system_impl(PyObject *module, PyObject *command) +/*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/ +{ + long result; + const char *bytes = PyBytes_AsString(command); + + if (PySys_Audit("os.system", "(O)", command) < 0) { + return -1; + } + + Py_BEGIN_ALLOW_THREADS + result = system(bytes); + Py_END_ALLOW_THREADS + return result; +} +#endif +#endif /* HAVE_SYSTEM */ + + +#ifdef HAVE_UMASK +/*[clinic input] +os.umask + + mask: int + / + +Set the current numeric umask and return the previous umask. +[clinic start generated code]*/ + +static PyObject * +os_umask_impl(PyObject *module, int mask) +/*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/ +{ + int i = (int)umask(mask); + if (i < 0) + return posix_error(); + return PyLong_FromLong((long)i); +} +#endif + +#ifdef MS_WINDOWS + +/* override the default DeleteFileW behavior so that directory +symlinks can be removed with this function, the same as with +Unix symlinks */ +BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName) +{ + WIN32_FILE_ATTRIBUTE_DATA info; + WIN32_FIND_DATAW find_data; + HANDLE find_data_handle; + int is_directory = 0; + int is_link = 0; + + if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) { + is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; + + /* Get WIN32_FIND_DATA structure for the path to determine if + it is a symlink */ + if(is_directory && + info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { + find_data_handle = FindFirstFileW(lpFileName, &find_data); + + if(find_data_handle != INVALID_HANDLE_VALUE) { + /* IO_REPARSE_TAG_SYMLINK if it is a symlink and + IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */ + is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK || + find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT; + FindClose(find_data_handle); + } + } + } + + if (is_directory && is_link) + return RemoveDirectoryW(lpFileName); + + return DeleteFileW(lpFileName); +} +#endif /* MS_WINDOWS */ + + +/*[clinic input] +os.unlink + + path: path_t + * + dir_fd: dir_fd(requires='unlinkat')=None + +Remove a file (same as remove()). + +If dir_fd is not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that directory. +dir_fd may not be implemented on your platform. + If it is unavailable, using it will raise a NotImplementedError. + +[clinic start generated code]*/ + +static PyObject * +os_unlink_impl(PyObject *module, path_t *path, int dir_fd) +/*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/ +{ + int result; +#ifdef HAVE_UNLINKAT + int unlinkat_unavailable = 0; +#endif + + if (PySys_Audit("os.remove", "Oi", path->object, + dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH +#ifdef MS_WINDOWS + /* Windows, success=1, UNIX, success=0 */ + result = !Py_DeleteFileW(path->wide); +#else +#ifdef HAVE_UNLINKAT + if (dir_fd != DEFAULT_DIR_FD) { + if (HAVE_UNLINKAT_RUNTIME) { + + result = unlinkat(dir_fd, path->narrow, 0); + } else { + unlinkat_unavailable = 1; + } + } else +#endif /* HAVE_UNLINKAT */ + result = unlink(path->narrow); +#endif + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + +#ifdef HAVE_UNLINKAT + if (unlinkat_unavailable) { + argument_unavailable_error(NULL, "dir_fd"); + return NULL; + } +#endif + + if (result) + return path_error(path); + + Py_RETURN_NONE; +} + + +/*[clinic input] +os.remove = os.unlink + +Remove a file (same as unlink()). + +If dir_fd is not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that directory. +dir_fd may not be implemented on your platform. + If it is unavailable, using it will raise a NotImplementedError. +[clinic start generated code]*/ + +static PyObject * +os_remove_impl(PyObject *module, path_t *path, int dir_fd) +/*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/ +{ + return os_unlink_impl(module, path, dir_fd); +} + + +static PyStructSequence_Field uname_result_fields[] = { + {"sysname", "operating system name"}, + {"nodename", "name of machine on network (implementation-defined)"}, + {"release", "operating system release"}, + {"version", "operating system version"}, + {"machine", "hardware identifier"}, + {NULL} +}; + +PyDoc_STRVAR(uname_result__doc__, +"uname_result: Result from os.uname().\n\n\ +This object may be accessed either as a tuple of\n\ + (sysname, nodename, release, version, machine),\n\ +or via the attributes sysname, nodename, release, version, and machine.\n\ +\n\ +See os.uname for more information."); + +static PyStructSequence_Desc uname_result_desc = { + MODNAME ".uname_result", /* name */ + uname_result__doc__, /* doc */ + uname_result_fields, + 5 +}; + +#ifdef HAVE_UNAME +/*[clinic input] +os.uname + +Return an object identifying the current operating system. + +The object behaves like a named tuple with the following fields: + (sysname, nodename, release, version, machine) + +[clinic start generated code]*/ + +static PyObject * +os_uname_impl(PyObject *module) +/*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/ +{ + struct utsname u; + int res; + PyObject *value; + + Py_BEGIN_ALLOW_THREADS + res = uname(&u); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error(); + + PyObject *UnameResultType = get_posix_state(module)->UnameResultType; + value = PyStructSequence_New((PyTypeObject *)UnameResultType); + if (value == NULL) + return NULL; + +#define SET(i, field) \ + { \ + PyObject *o = PyUnicode_DecodeFSDefault(field); \ + if (!o) { \ + Py_DECREF(value); \ + return NULL; \ + } \ + PyStructSequence_SET_ITEM(value, i, o); \ + } \ + + SET(0, u.sysname); + SET(1, u.nodename); + SET(2, u.release); + SET(3, u.version); + SET(4, u.machine); + +#undef SET + + return value; +} +#endif /* HAVE_UNAME */ + + + +typedef struct { + int now; + time_t atime_s; + long atime_ns; + time_t mtime_s; + long mtime_ns; +} utime_t; + +/* + * these macros assume that "ut" is a pointer to a utime_t + * they also intentionally leak the declaration of a pointer named "time" + */ +#define UTIME_TO_TIMESPEC \ + struct timespec ts[2]; \ + struct timespec *time; \ + if (ut->now) \ + time = NULL; \ + else { \ + ts[0].tv_sec = ut->atime_s; \ + ts[0].tv_nsec = ut->atime_ns; \ + ts[1].tv_sec = ut->mtime_s; \ + ts[1].tv_nsec = ut->mtime_ns; \ + time = ts; \ + } \ + +#define UTIME_TO_TIMEVAL \ + struct timeval tv[2]; \ + struct timeval *time; \ + if (ut->now) \ + time = NULL; \ + else { \ + tv[0].tv_sec = ut->atime_s; \ + tv[0].tv_usec = ut->atime_ns / 1000; \ + tv[1].tv_sec = ut->mtime_s; \ + tv[1].tv_usec = ut->mtime_ns / 1000; \ + time = tv; \ + } \ + +#define UTIME_TO_UTIMBUF \ + struct utimbuf u; \ + struct utimbuf *time; \ + if (ut->now) \ + time = NULL; \ + else { \ + u.actime = ut->atime_s; \ + u.modtime = ut->mtime_s; \ + time = &u; \ + } + +#define UTIME_TO_TIME_T \ + time_t timet[2]; \ + time_t *time; \ + if (ut->now) \ + time = NULL; \ + else { \ + timet[0] = ut->atime_s; \ + timet[1] = ut->mtime_s; \ + time = timet; \ + } \ + + +#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT) + +static int +utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks) +{ +#if defined(__APPLE__) && defined(HAVE_UTIMENSAT) + if (HAVE_UTIMENSAT_RUNTIME) { + int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW; + UTIME_TO_TIMESPEC; + return utimensat(dir_fd, path, time, flags); + } else { + errno = ENOSYS; + return -1; + } +#elif defined(HAVE_UTIMENSAT) + int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW; + UTIME_TO_TIMESPEC; + return utimensat(dir_fd, path, time, flags); +#elif defined(HAVE_FUTIMESAT) + UTIME_TO_TIMEVAL; + /* + * follow_symlinks will never be false here; + * we only allow !follow_symlinks and dir_fd together + * if we have utimensat() + */ + assert(follow_symlinks); + return futimesat(dir_fd, path, time); +#endif +} + + #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + +#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS) + +static int +utime_fd(utime_t *ut, int fd) +{ +#ifdef HAVE_FUTIMENS + + if (HAVE_FUTIMENS_RUNTIME) { + + UTIME_TO_TIMESPEC; + return futimens(fd, time); + + } else +#ifndef HAVE_FUTIMES + { + /* Not sure if this can happen */ + PyErr_SetString( + PyExc_RuntimeError, + "neither futimens nor futimes are supported" + " on this system"); + return -1; + } +#endif + +#endif +#ifdef HAVE_FUTIMES + { + UTIME_TO_TIMEVAL; + return futimes(fd, time); + } +#endif +} + + #define PATH_UTIME_HAVE_FD 1 +#else + #define PATH_UTIME_HAVE_FD 0 +#endif + +#if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES) +# define UTIME_HAVE_NOFOLLOW_SYMLINKS +#endif + +#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS + +static int +utime_nofollow_symlinks(utime_t *ut, const char *path) +{ +#ifdef HAVE_UTIMENSAT + if (HAVE_UTIMENSAT_RUNTIME) { + UTIME_TO_TIMESPEC; + return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW); + } else +#ifndef HAVE_LUTIMES + { + /* Not sure if this can happen */ + PyErr_SetString( + PyExc_RuntimeError, + "neither utimensat nor lutimes are supported" + " on this system"); + return -1; + } +#endif +#endif + +#ifdef HAVE_LUTIMES + { + UTIME_TO_TIMEVAL; + return lutimes(path, time); + } +#endif +} + +#endif + +#ifndef MS_WINDOWS + +static int +utime_default(utime_t *ut, const char *path) +{ +#if defined(__APPLE__) && defined(HAVE_UTIMENSAT) + if (HAVE_UTIMENSAT_RUNTIME) { + UTIME_TO_TIMESPEC; + return utimensat(DEFAULT_DIR_FD, path, time, 0); + } else { + UTIME_TO_TIMEVAL; + return utimes(path, time); + } +#elif defined(HAVE_UTIMENSAT) + UTIME_TO_TIMESPEC; + return utimensat(DEFAULT_DIR_FD, path, time, 0); +#elif defined(HAVE_UTIMES) + UTIME_TO_TIMEVAL; + return utimes(path, time); +#elif defined(HAVE_UTIME_H) + UTIME_TO_UTIMBUF; + return utime(path, time); +#else + UTIME_TO_TIME_T; + return utime(path, time); +#endif +} + +#endif + +static int +split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns) +{ + int result = 0; + PyObject *divmod; + divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion); + if (!divmod) + goto exit; + if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) { + PyErr_Format(PyExc_TypeError, + "%.200s.__divmod__() must return a 2-tuple, not %.200s", + _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod))); + goto exit; + } + *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0)); + if ((*s == -1) && PyErr_Occurred()) + goto exit; + *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1)); + if ((*ns == -1) && PyErr_Occurred()) + goto exit; + + result = 1; +exit: + Py_XDECREF(divmod); + return result; +} + + +/*[clinic input] +os.utime + + path: path_t(allow_fd='PATH_UTIME_HAVE_FD') + times: object = None + * + ns: object = NULL + dir_fd: dir_fd(requires='futimensat') = None + follow_symlinks: bool=True + +# "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\ + +Set the access and modified time of path. + +path may always be specified as a string. +On some platforms, path may also be specified as an open file descriptor. + If this functionality is unavailable, using it raises an exception. + +If times is not None, it must be a tuple (atime, mtime); + atime and mtime should be expressed as float seconds since the epoch. +If ns is specified, it must be a tuple (atime_ns, mtime_ns); + atime_ns and mtime_ns should be expressed as integer nanoseconds + since the epoch. +If times is None and ns is unspecified, utime uses the current time. +Specifying tuples for both times and ns is an error. + +If dir_fd is not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that directory. +If follow_symlinks is False, and the last element of the path is a symbolic + link, utime will modify the symbolic link itself instead of the file the + link points to. +It is an error to use dir_fd or follow_symlinks when specifying path + as an open file descriptor. +dir_fd and follow_symlinks may not be available on your platform. + If they are unavailable, using them will raise a NotImplementedError. + +[clinic start generated code]*/ + +static PyObject * +os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, + int dir_fd, int follow_symlinks) +/*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/ +{ +#ifdef MS_WINDOWS + HANDLE hFile; + FILETIME atime, mtime; +#else + int result; +#endif + + utime_t utime; + + memset(&utime, 0, sizeof(utime_t)); + + if (times != Py_None && ns) { + PyErr_SetString(PyExc_ValueError, + "utime: you may specify either 'times'" + " or 'ns' but not both"); + return NULL; + } + + if (times != Py_None) { + time_t a_sec, m_sec; + long a_nsec, m_nsec; + if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) { + PyErr_SetString(PyExc_TypeError, + "utime: 'times' must be either" + " a tuple of two ints or None"); + return NULL; + } + utime.now = 0; + if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0), + &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 || + _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1), + &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) { + return NULL; + } + utime.atime_s = a_sec; + utime.atime_ns = a_nsec; + utime.mtime_s = m_sec; + utime.mtime_ns = m_nsec; + } + else if (ns) { + if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) { + PyErr_SetString(PyExc_TypeError, + "utime: 'ns' must be a tuple of two ints"); + return NULL; + } + utime.now = 0; + if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0), + &utime.atime_s, &utime.atime_ns) || + !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1), + &utime.mtime_s, &utime.mtime_ns)) { + return NULL; + } + } + else { + /* times and ns are both None/unspecified. use "now". */ + utime.now = 1; + } + +#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS) + if (follow_symlinks_specified("utime", follow_symlinks)) + return NULL; +#endif + + if (path_and_dir_fd_invalid("utime", path, dir_fd) || + dir_fd_and_fd_invalid("utime", dir_fd, path->fd) || + fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks)) + return NULL; + +#if !defined(HAVE_UTIMENSAT) + if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) { + PyErr_SetString(PyExc_ValueError, + "utime: cannot use dir_fd and follow_symlinks " + "together on this platform"); + return NULL; + } +#endif + + if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None, + dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { + return NULL; + } + +#ifdef MS_WINDOWS + Py_BEGIN_ALLOW_THREADS + hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0, + NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, NULL); + Py_END_ALLOW_THREADS + if (hFile == INVALID_HANDLE_VALUE) { + path_error(path); + return NULL; + } + + if (utime.now) { + GetSystemTimeAsFileTime(&mtime); + atime = mtime; + } + else { + _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime); + _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime); + } + if (!SetFileTime(hFile, NULL, &atime, &mtime)) { + /* Avoid putting the file name into the error here, + as that may confuse the user into believing that + something is wrong with the file, when it also + could be the time stamp that gives a problem. */ + PyErr_SetFromWindowsErr(0); + CloseHandle(hFile); + return NULL; + } + CloseHandle(hFile); +#else /* MS_WINDOWS */ + Py_BEGIN_ALLOW_THREADS + +#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS + if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) + result = utime_nofollow_symlinks(&utime, path->narrow); + else +#endif + +#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT) + if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) { + result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks); + + } else +#endif + +#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS) + if (path->fd != -1) + result = utime_fd(&utime, path->fd); + else +#endif + + result = utime_default(&utime, path->narrow); + + Py_END_ALLOW_THREADS + +#if defined(__APPLE__) && defined(HAVE_UTIMENSAT) + /* See utime_dir_fd implementation */ + if (result == -1 && errno == ENOSYS) { + argument_unavailable_error(NULL, "dir_fd"); + return NULL; + } +#endif + + if (result < 0) { + /* see previous comment about not putting filename in error here */ + posix_error(); + return NULL; + } + +#endif /* MS_WINDOWS */ + + Py_RETURN_NONE; +} + +/* Process operations */ + + +/*[clinic input] +os._exit + + status: int + +Exit to the system with specified status, without normal exit processing. +[clinic start generated code]*/ + +static PyObject * +os__exit_impl(PyObject *module, int status) +/*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/ +{ + _exit(status); + return NULL; /* Make gcc -Wall happy */ +} + +#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV) +#define EXECV_CHAR wchar_t +#else +#define EXECV_CHAR char +#endif + +#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN) +static void +free_string_array(EXECV_CHAR **array, Py_ssize_t count) +{ + Py_ssize_t i; + for (i = 0; i < count; i++) + PyMem_Free(array[i]); + PyMem_Free(array); +} + +static int +fsconvert_strdup(PyObject *o, EXECV_CHAR **out) +{ + Py_ssize_t size; + PyObject *ub; + int result = 0; +#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV) + if (!PyUnicode_FSDecoder(o, &ub)) + return 0; + *out = PyUnicode_AsWideCharString(ub, &size); + if (*out) + result = 1; +#else + if (!PyUnicode_FSConverter(o, &ub)) + return 0; + size = PyBytes_GET_SIZE(ub); + *out = PyMem_Malloc(size + 1); + if (*out) { + memcpy(*out, PyBytes_AS_STRING(ub), size + 1); + result = 1; + } else + PyErr_NoMemory(); +#endif + Py_DECREF(ub); + return result; +} +#endif + +#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN) +static EXECV_CHAR** +parse_envlist(PyObject* env, Py_ssize_t *envc_ptr) +{ + Py_ssize_t i, pos, envc; + PyObject *keys=NULL, *vals=NULL; + PyObject *key, *val, *key2, *val2, *keyval; + EXECV_CHAR **envlist; + + i = PyMapping_Size(env); + if (i < 0) + return NULL; + envlist = PyMem_NEW(EXECV_CHAR *, i + 1); + if (envlist == NULL) { + PyErr_NoMemory(); + return NULL; + } + envc = 0; + keys = PyMapping_Keys(env); + if (!keys) + goto error; + vals = PyMapping_Values(env); + if (!vals) + goto error; + if (!PyList_Check(keys) || !PyList_Check(vals)) { + PyErr_Format(PyExc_TypeError, + "env.keys() or env.values() is not a list"); + goto error; + } + + for (pos = 0; pos < i; pos++) { + key = PyList_GetItem(keys, pos); + val = PyList_GetItem(vals, pos); + if (!key || !val) + goto error; + +#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV) + if (!PyUnicode_FSDecoder(key, &key2)) + goto error; + if (!PyUnicode_FSDecoder(val, &val2)) { + Py_DECREF(key2); + goto error; + } + /* Search from index 1 because on Windows starting '=' is allowed for + defining hidden environment variables. */ + if (PyUnicode_GET_LENGTH(key2) == 0 || + PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1) + { + PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); + Py_DECREF(key2); + Py_DECREF(val2); + goto error; + } + keyval = PyUnicode_FromFormat("%U=%U", key2, val2); +#else + if (!PyUnicode_FSConverter(key, &key2)) + goto error; + if (!PyUnicode_FSConverter(val, &val2)) { + Py_DECREF(key2); + goto error; + } + if (PyBytes_GET_SIZE(key2) == 0 || + strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL) + { + PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); + Py_DECREF(key2); + Py_DECREF(val2); + goto error; + } + keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2), + PyBytes_AS_STRING(val2)); +#endif + Py_DECREF(key2); + Py_DECREF(val2); + if (!keyval) + goto error; + + if (!fsconvert_strdup(keyval, &envlist[envc++])) { + Py_DECREF(keyval); + goto error; + } + + Py_DECREF(keyval); + } + Py_DECREF(vals); + Py_DECREF(keys); + + envlist[envc] = 0; + *envc_ptr = envc; + return envlist; + +error: + Py_XDECREF(keys); + Py_XDECREF(vals); + free_string_array(envlist, envc); + return NULL; +} + +static EXECV_CHAR** +parse_arglist(PyObject* argv, Py_ssize_t *argc) +{ + int i; + EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1); + if (argvlist == NULL) { + PyErr_NoMemory(); + return NULL; + } + for (i = 0; i < *argc; i++) { + PyObject* item = PySequence_ITEM(argv, i); + if (item == NULL) + goto fail; + if (!fsconvert_strdup(item, &argvlist[i])) { + Py_DECREF(item); + goto fail; + } + Py_DECREF(item); + } + argvlist[*argc] = NULL; + return argvlist; +fail: + *argc = i; + free_string_array(argvlist, *argc); + return NULL; +} + +#endif + + +#ifdef HAVE_EXECV +/*[clinic input] +os.execv + + path: path_t + Path of executable file. + argv: object + Tuple or list of strings. + / + +Execute an executable path with arguments, replacing current process. +[clinic start generated code]*/ + +static PyObject * +os_execv_impl(PyObject *module, path_t *path, PyObject *argv) +/*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/ +{ + EXECV_CHAR **argvlist; + Py_ssize_t argc; + + PyInterpreterState *interp = _PyInterpreterState_GET(); + if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) { + PyErr_SetString(PyExc_RuntimeError, + "exec not supported for isolated subinterpreters"); + return NULL; + } + + /* execv has two arguments: (path, argv), where + argv is a list or tuple of strings. */ + + if (!PyList_Check(argv) && !PyTuple_Check(argv)) { + PyErr_SetString(PyExc_TypeError, + "execv() arg 2 must be a tuple or list"); + return NULL; + } + argc = PySequence_Size(argv); + if (argc < 1) { + PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty"); + return NULL; + } + + argvlist = parse_arglist(argv, &argc); + if (argvlist == NULL) { + return NULL; + } + if (!argvlist[0][0]) { + PyErr_SetString(PyExc_ValueError, + "execv() arg 2 first element cannot be empty"); + free_string_array(argvlist, argc); + return NULL; + } + + if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) { + free_string_array(argvlist, argc); + return NULL; + } + + _Py_BEGIN_SUPPRESS_IPH +#ifdef HAVE_WEXECV + _wexecv(path->wide, argvlist); +#else + execv(path->narrow, argvlist); +#endif + _Py_END_SUPPRESS_IPH + + /* If we get here it's definitely an error */ + + free_string_array(argvlist, argc); + return posix_error(); +} + + +/*[clinic input] +os.execve + + path: path_t(allow_fd='PATH_HAVE_FEXECVE') + Path of executable file. + argv: object + Tuple or list of strings. + env: object + Dictionary of strings mapping to strings. + +Execute an executable path with arguments, replacing current process. +[clinic start generated code]*/ + +static PyObject * +os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env) +/*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/ +{ + EXECV_CHAR **argvlist = NULL; + EXECV_CHAR **envlist; + Py_ssize_t argc, envc; + + PyInterpreterState *interp = _PyInterpreterState_GET(); + if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) { + PyErr_SetString(PyExc_RuntimeError, + "exec not supported for isolated subinterpreters"); + return NULL; + } + + /* execve has three arguments: (path, argv, env), where + argv is a list or tuple of strings and env is a dictionary + like posix.environ. */ + + if (!PyList_Check(argv) && !PyTuple_Check(argv)) { + PyErr_SetString(PyExc_TypeError, + "execve: argv must be a tuple or list"); + goto fail_0; + } + argc = PySequence_Size(argv); + if (argc < 1) { + PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty"); + return NULL; + } + + if (!PyMapping_Check(env)) { + PyErr_SetString(PyExc_TypeError, + "execve: environment must be a mapping object"); + goto fail_0; + } + + argvlist = parse_arglist(argv, &argc); + if (argvlist == NULL) { + goto fail_0; + } + if (!argvlist[0][0]) { + PyErr_SetString(PyExc_ValueError, + "execve: argv first element cannot be empty"); + goto fail_0; + } + + envlist = parse_envlist(env, &envc); + if (envlist == NULL) + goto fail_0; + + if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) { + goto fail_1; + } + + _Py_BEGIN_SUPPRESS_IPH +#ifdef HAVE_FEXECVE + if (path->fd > -1) + fexecve(path->fd, argvlist, envlist); + else +#endif +#ifdef HAVE_WEXECV + _wexecve(path->wide, argvlist, envlist); +#else + execve(path->narrow, argvlist, envlist); +#endif + _Py_END_SUPPRESS_IPH + + /* If we get here it's definitely an error */ + + posix_path_error(path); + fail_1: + free_string_array(envlist, envc); + fail_0: + if (argvlist) + free_string_array(argvlist, argc); + return NULL; +} + +#endif /* HAVE_EXECV */ + +#ifdef HAVE_POSIX_SPAWN + +enum posix_spawn_file_actions_identifier { + POSIX_SPAWN_OPEN, + POSIX_SPAWN_CLOSE, + POSIX_SPAWN_DUP2 +}; + +#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) +static int +convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res); +#endif + +static int +parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup, + int resetids, int setsid, PyObject *setsigmask, + PyObject *setsigdef, PyObject *scheduler, + posix_spawnattr_t *attrp) +{ + long all_flags = 0; + + errno = posix_spawnattr_init(attrp); + if (errno) { + posix_error(); + return -1; + } + + if (setpgroup) { + pid_t pgid = PyLong_AsPid(setpgroup); + if (pgid == (pid_t)-1 && PyErr_Occurred()) { + goto fail; + } + errno = posix_spawnattr_setpgroup(attrp, pgid); + if (errno) { + posix_error(); + goto fail; + } + all_flags |= POSIX_SPAWN_SETPGROUP; + } + + if (resetids) { + all_flags |= POSIX_SPAWN_RESETIDS; + } + + if (setsid) { +#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME + if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) { +#endif +#ifdef POSIX_SPAWN_SETSID + all_flags |= POSIX_SPAWN_SETSID; +#elif defined(POSIX_SPAWN_SETSID_NP) + all_flags |= POSIX_SPAWN_SETSID_NP; +#else + argument_unavailable_error(func_name, "setsid"); + return -1; +#endif + +#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME + } else { + argument_unavailable_error(func_name, "setsid"); + return -1; + } +#endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */ + + } + +#ifdef HAVE_SIGSET_T + if (setsigmask) { + sigset_t set; + if (!_Py_Sigset_Converter(setsigmask, &set)) { + goto fail; + } + errno = posix_spawnattr_setsigmask(attrp, &set); + if (errno) { + posix_error(); + goto fail; + } + all_flags |= POSIX_SPAWN_SETSIGMASK; + } + + if (setsigdef) { + sigset_t set; + if (!_Py_Sigset_Converter(setsigdef, &set)) { + goto fail; + } + errno = posix_spawnattr_setsigdefault(attrp, &set); + if (errno) { + posix_error(); + goto fail; + } + all_flags |= POSIX_SPAWN_SETSIGDEF; + } +#else + if (setsigmask || setsigdef) { + PyErr_SetString(PyExc_NotImplementedError, + "sigset is not supported on this platform"); + goto fail; + } +#endif + + if (scheduler) { +#ifdef POSIX_SPAWN_SETSCHEDULER + PyObject *py_schedpolicy; + PyObject *schedparam_obj; + struct sched_param schedparam; + + if (!PyArg_ParseTuple(scheduler, "OO" + ";A scheduler tuple must have two elements", + &py_schedpolicy, &schedparam_obj)) { + goto fail; + } + if (!convert_sched_param(module, schedparam_obj, &schedparam)) { + goto fail; + } + if (py_schedpolicy != Py_None) { + int schedpolicy = _PyLong_AsInt(py_schedpolicy); + + if (schedpolicy == -1 && PyErr_Occurred()) { + goto fail; + } + errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy); + if (errno) { + posix_error(); + goto fail; + } + all_flags |= POSIX_SPAWN_SETSCHEDULER; + } + errno = posix_spawnattr_setschedparam(attrp, &schedparam); + if (errno) { + posix_error(); + goto fail; + } + all_flags |= POSIX_SPAWN_SETSCHEDPARAM; +#else + PyErr_SetString(PyExc_NotImplementedError, + "The scheduler option is not supported in this system."); + goto fail; +#endif + } + + errno = posix_spawnattr_setflags(attrp, all_flags); + if (errno) { + posix_error(); + goto fail; + } + + return 0; + +fail: + (void)posix_spawnattr_destroy(attrp); + return -1; +} + +static int +parse_file_actions(PyObject *file_actions, + posix_spawn_file_actions_t *file_actionsp, + PyObject *temp_buffer) +{ + PyObject *seq; + PyObject *file_action = NULL; + PyObject *tag_obj; + + seq = PySequence_Fast(file_actions, + "file_actions must be a sequence or None"); + if (seq == NULL) { + return -1; + } + + errno = posix_spawn_file_actions_init(file_actionsp); + if (errno) { + posix_error(); + Py_DECREF(seq); + return -1; + } + + for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) { + file_action = PySequence_Fast_GET_ITEM(seq, i); + Py_INCREF(file_action); + if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) { + PyErr_SetString(PyExc_TypeError, + "Each file_actions element must be a non-empty tuple"); + goto fail; + } + long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0)); + if (tag == -1 && PyErr_Occurred()) { + goto fail; + } + + /* Populate the file_actions object */ + switch (tag) { + case POSIX_SPAWN_OPEN: { + int fd, oflag; + PyObject *path; + unsigned long mode; + if (!PyArg_ParseTuple(file_action, "OiO&ik" + ";A open file_action tuple must have 5 elements", + &tag_obj, &fd, PyUnicode_FSConverter, &path, + &oflag, &mode)) + { + goto fail; + } + if (PyList_Append(temp_buffer, path)) { + Py_DECREF(path); + goto fail; + } + errno = posix_spawn_file_actions_addopen(file_actionsp, + fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode); + Py_DECREF(path); + if (errno) { + posix_error(); + goto fail; + } + break; + } + case POSIX_SPAWN_CLOSE: { + int fd; + if (!PyArg_ParseTuple(file_action, "Oi" + ";A close file_action tuple must have 2 elements", + &tag_obj, &fd)) + { + goto fail; + } + errno = posix_spawn_file_actions_addclose(file_actionsp, fd); + if (errno) { + posix_error(); + goto fail; + } + break; + } + case POSIX_SPAWN_DUP2: { + int fd1, fd2; + if (!PyArg_ParseTuple(file_action, "Oii" + ";A dup2 file_action tuple must have 3 elements", + &tag_obj, &fd1, &fd2)) + { + goto fail; + } + errno = posix_spawn_file_actions_adddup2(file_actionsp, + fd1, fd2); + if (errno) { + posix_error(); + goto fail; + } + break; + } + default: { + PyErr_SetString(PyExc_TypeError, + "Unknown file_actions identifier"); + goto fail; + } + } + Py_DECREF(file_action); + } + + Py_DECREF(seq); + return 0; + +fail: + Py_DECREF(seq); + Py_DECREF(file_action); + (void)posix_spawn_file_actions_destroy(file_actionsp); + return -1; +} + + +static PyObject * +py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv, + PyObject *env, PyObject *file_actions, + PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask, + PyObject *setsigdef, PyObject *scheduler) +{ + const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn"; + EXECV_CHAR **argvlist = NULL; + EXECV_CHAR **envlist = NULL; + posix_spawn_file_actions_t file_actions_buf; + posix_spawn_file_actions_t *file_actionsp = NULL; + posix_spawnattr_t attr; + posix_spawnattr_t *attrp = NULL; + Py_ssize_t argc, envc; + PyObject *result = NULL; + PyObject *temp_buffer = NULL; + pid_t pid; + int err_code; + + /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where + argv is a list or tuple of strings and env is a dictionary + like posix.environ. */ + + if (!PyList_Check(argv) && !PyTuple_Check(argv)) { + PyErr_Format(PyExc_TypeError, + "%s: argv must be a tuple or list", func_name); + goto exit; + } + argc = PySequence_Size(argv); + if (argc < 1) { + PyErr_Format(PyExc_ValueError, + "%s: argv must not be empty", func_name); + return NULL; + } + + if (!PyMapping_Check(env)) { + PyErr_Format(PyExc_TypeError, + "%s: environment must be a mapping object", func_name); + goto exit; + } + + argvlist = parse_arglist(argv, &argc); + if (argvlist == NULL) { + goto exit; + } + if (!argvlist[0][0]) { + PyErr_Format(PyExc_ValueError, + "%s: argv first element cannot be empty", func_name); + goto exit; + } + + envlist = parse_envlist(env, &envc); + if (envlist == NULL) { + goto exit; + } + + if (file_actions != NULL && file_actions != Py_None) { + /* There is a bug in old versions of glibc that makes some of the + * helper functions for manipulating file actions not copy the provided + * buffers. The problem is that posix_spawn_file_actions_addopen does not + * copy the value of path for some old versions of glibc (<2.20). + * The use of temp_buffer here is a workaround that keeps the + * python objects that own the buffers alive until posix_spawn gets called. + * Check https://bugs.python.org/issue33630 and + * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/ + temp_buffer = PyList_New(0); + if (!temp_buffer) { + goto exit; + } + if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) { + goto exit; + } + file_actionsp = &file_actions_buf; + } + + if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid, + setsigmask, setsigdef, scheduler, &attr)) { + goto exit; + } + attrp = &attr; + + if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) { + goto exit; + } + + _Py_BEGIN_SUPPRESS_IPH +#ifdef HAVE_POSIX_SPAWNP + if (use_posix_spawnp) { + err_code = posix_spawnp(&pid, path->narrow, + file_actionsp, attrp, argvlist, envlist); + } + else +#endif /* HAVE_POSIX_SPAWNP */ + { + err_code = posix_spawn(&pid, path->narrow, + file_actionsp, attrp, argvlist, envlist); + } + _Py_END_SUPPRESS_IPH + + if (err_code) { + errno = err_code; + PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object); + goto exit; + } +#ifdef _Py_MEMORY_SANITIZER + __msan_unpoison(&pid, sizeof(pid)); +#endif + result = PyLong_FromPid(pid); + +exit: + if (file_actionsp) { + (void)posix_spawn_file_actions_destroy(file_actionsp); + } + if (attrp) { + (void)posix_spawnattr_destroy(attrp); + } + if (envlist) { + free_string_array(envlist, envc); + } + if (argvlist) { + free_string_array(argvlist, argc); + } + Py_XDECREF(temp_buffer); + return result; +} + + +/*[clinic input] + +os.posix_spawn + path: path_t + Path of executable file. + argv: object + Tuple or list of strings. + env: object + Dictionary of strings mapping to strings. + / + * + file_actions: object(c_default='NULL') = () + A sequence of file action tuples. + setpgroup: object = NULL + The pgroup to use with the POSIX_SPAWN_SETPGROUP flag. + resetids: bool(accept={int}) = False + If the value is `true` the POSIX_SPAWN_RESETIDS will be activated. + setsid: bool(accept={int}) = False + If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated. + setsigmask: object(c_default='NULL') = () + The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag. + setsigdef: object(c_default='NULL') = () + The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag. + scheduler: object = NULL + A tuple with the scheduler policy (optional) and parameters. + +Execute the program specified by path in a new process. +[clinic start generated code]*/ + +static PyObject * +os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, + PyObject *env, PyObject *file_actions, + PyObject *setpgroup, int resetids, int setsid, + PyObject *setsigmask, PyObject *setsigdef, + PyObject *scheduler) +/*[clinic end generated code: output=14a1098c566bc675 input=8c6305619a00ad04]*/ +{ + return py_posix_spawn(0, module, path, argv, env, file_actions, + setpgroup, resetids, setsid, setsigmask, setsigdef, + scheduler); +} + #endif /* HAVE_POSIX_SPAWN */ + + + +#ifdef HAVE_POSIX_SPAWNP +/*[clinic input] + +os.posix_spawnp + path: path_t + Path of executable file. + argv: object + Tuple or list of strings. + env: object + Dictionary of strings mapping to strings. + / + * + file_actions: object(c_default='NULL') = () + A sequence of file action tuples. + setpgroup: object = NULL + The pgroup to use with the POSIX_SPAWN_SETPGROUP flag. + resetids: bool(accept={int}) = False + If the value is `True` the POSIX_SPAWN_RESETIDS will be activated. + setsid: bool(accept={int}) = False + If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated. + setsigmask: object(c_default='NULL') = () + The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag. + setsigdef: object(c_default='NULL') = () + The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag. + scheduler: object = NULL + A tuple with the scheduler policy (optional) and parameters. + +Execute the program specified by path in a new process. +[clinic start generated code]*/ + +static PyObject * +os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv, + PyObject *env, PyObject *file_actions, + PyObject *setpgroup, int resetids, int setsid, + PyObject *setsigmask, PyObject *setsigdef, + PyObject *scheduler) +/*[clinic end generated code: output=7b9aaefe3031238d input=c1911043a22028da]*/ +{ + return py_posix_spawn(1, module, path, argv, env, file_actions, + setpgroup, resetids, setsid, setsigmask, setsigdef, + scheduler); +} +#endif /* HAVE_POSIX_SPAWNP */ + +#ifdef HAVE_RTPSPAWN +static intptr_t +_rtp_spawn(int mode, const char *rtpFileName, const char *argv[], + const char *envp[]) +{ + RTP_ID rtpid; + int status; + pid_t res; + int async_err = 0; + + /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes. + uStackSize=0 cannot be used, the default stack size is too small for + Python. */ + if (envp) { + rtpid = rtpSpawn(rtpFileName, argv, envp, + 100, 0x1000000, 0, VX_FP_TASK); + } + else { + rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ, + 100, 0x1000000, 0, VX_FP_TASK); + } + if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) { + do { + res = waitpid((pid_t)rtpid, &status, 0); + } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + + if (res < 0) + return RTP_ID_ERROR; + return ((intptr_t)status); + } + return ((intptr_t)rtpid); +} +#endif + +#if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN) +/*[clinic input] +os.spawnv + + mode: int + Mode of process creation. + path: path_t + Path of executable file. + argv: object + Tuple or list of strings. + / + +Execute the program specified by path in a new process. +[clinic start generated code]*/ + +static PyObject * +os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv) +/*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/ +{ + EXECV_CHAR **argvlist; + int i; + Py_ssize_t argc; + intptr_t spawnval; + PyObject *(*getitem)(PyObject *, Py_ssize_t); + + /* spawnv has three arguments: (mode, path, argv), where + argv is a list or tuple of strings. */ + + if (PyList_Check(argv)) { + argc = PyList_Size(argv); + getitem = PyList_GetItem; + } + else if (PyTuple_Check(argv)) { + argc = PyTuple_Size(argv); + getitem = PyTuple_GetItem; + } + else { + PyErr_SetString(PyExc_TypeError, + "spawnv() arg 2 must be a tuple or list"); + return NULL; + } + if (argc == 0) { + PyErr_SetString(PyExc_ValueError, + "spawnv() arg 2 cannot be empty"); + return NULL; + } + + argvlist = PyMem_NEW(EXECV_CHAR *, argc+1); + if (argvlist == NULL) { + return PyErr_NoMemory(); + } + for (i = 0; i < argc; i++) { + if (!fsconvert_strdup((*getitem)(argv, i), + &argvlist[i])) { + free_string_array(argvlist, i); + PyErr_SetString( + PyExc_TypeError, + "spawnv() arg 2 must contain only strings"); + return NULL; + } + if (i == 0 && !argvlist[0][0]) { + free_string_array(argvlist, i + 1); + PyErr_SetString( + PyExc_ValueError, + "spawnv() arg 2 first element cannot be empty"); + return NULL; + } + } + argvlist[argc] = NULL; + +#if !defined(HAVE_RTPSPAWN) + if (mode == _OLD_P_OVERLAY) + mode = _P_OVERLAY; +#endif + + if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, + Py_None) < 0) { + free_string_array(argvlist, argc); + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH +#ifdef HAVE_WSPAWNV + spawnval = _wspawnv(mode, path->wide, argvlist); +#elif defined(HAVE_RTPSPAWN) + spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL); +#else + spawnval = _spawnv(mode, path->narrow, argvlist); +#endif + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + + free_string_array(argvlist, argc); + + if (spawnval == -1) + return posix_error(); + else + return Py_BuildValue(_Py_PARSE_INTPTR, spawnval); +} + +/*[clinic input] +os.spawnve + + mode: int + Mode of process creation. + path: path_t + Path of executable file. + argv: object + Tuple or list of strings. + env: object + Dictionary of strings mapping to strings. + / + +Execute the program specified by path in a new process. +[clinic start generated code]*/ + +static PyObject * +os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv, + PyObject *env) +/*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/ +{ + EXECV_CHAR **argvlist; + EXECV_CHAR **envlist; + PyObject *res = NULL; + Py_ssize_t argc, i, envc; + intptr_t spawnval; + PyObject *(*getitem)(PyObject *, Py_ssize_t); + Py_ssize_t lastarg = 0; + + /* spawnve has four arguments: (mode, path, argv, env), where + argv is a list or tuple of strings and env is a dictionary + like posix.environ. */ + + if (PyList_Check(argv)) { + argc = PyList_Size(argv); + getitem = PyList_GetItem; + } + else if (PyTuple_Check(argv)) { + argc = PyTuple_Size(argv); + getitem = PyTuple_GetItem; + } + else { + PyErr_SetString(PyExc_TypeError, + "spawnve() arg 2 must be a tuple or list"); + goto fail_0; + } + if (argc == 0) { + PyErr_SetString(PyExc_ValueError, + "spawnve() arg 2 cannot be empty"); + goto fail_0; + } + if (!PyMapping_Check(env)) { + PyErr_SetString(PyExc_TypeError, + "spawnve() arg 3 must be a mapping object"); + goto fail_0; + } + + argvlist = PyMem_NEW(EXECV_CHAR *, argc+1); + if (argvlist == NULL) { + PyErr_NoMemory(); + goto fail_0; + } + for (i = 0; i < argc; i++) { + if (!fsconvert_strdup((*getitem)(argv, i), + &argvlist[i])) + { + lastarg = i; + goto fail_1; + } + if (i == 0 && !argvlist[0][0]) { + lastarg = i + 1; + PyErr_SetString( + PyExc_ValueError, + "spawnv() arg 2 first element cannot be empty"); + goto fail_1; + } + } + lastarg = argc; + argvlist[argc] = NULL; + + envlist = parse_envlist(env, &envc); + if (envlist == NULL) + goto fail_1; + +#if !defined(HAVE_RTPSPAWN) + if (mode == _OLD_P_OVERLAY) + mode = _P_OVERLAY; +#endif + + if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) { + goto fail_2; + } + + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH +#ifdef HAVE_WSPAWNV + spawnval = _wspawnve(mode, path->wide, argvlist, envlist); +#elif defined(HAVE_RTPSPAWN) + spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, + (const char **)envlist); +#else + spawnval = _spawnve(mode, path->narrow, argvlist, envlist); +#endif + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + + if (spawnval == -1) + (void) posix_error(); + else + res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval); + + fail_2: + while (--envc >= 0) { + PyMem_Free(envlist[envc]); + } + PyMem_Free(envlist); + fail_1: + free_string_array(argvlist, lastarg); + fail_0: + return res; +} + +#endif /* HAVE_SPAWNV */ + +#ifdef HAVE_FORK + +/* Helper function to validate arguments. + Returns 0 on success. non-zero on failure with a TypeError raised. + If obj is non-NULL it must be callable. */ +static int +check_null_or_callable(PyObject *obj, const char* obj_name) +{ + if (obj && !PyCallable_Check(obj)) { + PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s", + obj_name, _PyType_Name(Py_TYPE(obj))); + return -1; + } + return 0; +} + +/*[clinic input] +os.register_at_fork + + * + before: object=NULL + A callable to be called in the parent before the fork() syscall. + after_in_child: object=NULL + A callable to be called in the child after fork(). + after_in_parent: object=NULL + A callable to be called in the parent after fork(). + +Register callables to be called when forking a new process. + +'before' callbacks are called in reverse order. +'after_in_child' and 'after_in_parent' callbacks are called in order. + +[clinic start generated code]*/ + +static PyObject * +os_register_at_fork_impl(PyObject *module, PyObject *before, + PyObject *after_in_child, PyObject *after_in_parent) +/*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/ +{ + PyInterpreterState *interp; + + if (!before && !after_in_child && !after_in_parent) { + PyErr_SetString(PyExc_TypeError, "At least one argument is required."); + return NULL; + } + if (check_null_or_callable(before, "before") || + check_null_or_callable(after_in_child, "after_in_child") || + check_null_or_callable(after_in_parent, "after_in_parent")) { + return NULL; + } + interp = _PyInterpreterState_GET(); + + if (register_at_forker(&interp->before_forkers, before)) { + return NULL; + } + if (register_at_forker(&interp->after_forkers_child, after_in_child)) { + return NULL; + } + if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) { + return NULL; + } + Py_RETURN_NONE; +} +#endif /* HAVE_FORK */ + + +#ifdef HAVE_FORK1 +/*[clinic input] +os.fork1 + +Fork a child process with a single multiplexed (i.e., not bound) thread. + +Return 0 to child process and PID of child to parent process. +[clinic start generated code]*/ + +static PyObject * +os_fork1_impl(PyObject *module) +/*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/ +{ + pid_t pid; + + if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) { + PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters"); + return NULL; + } + PyOS_BeforeFork(); + pid = fork1(); + if (pid == 0) { + /* child: this clobbers and resets the import lock. */ + PyOS_AfterFork_Child(); + } else { + /* parent: release the import lock. */ + PyOS_AfterFork_Parent(); + } + if (pid == -1) + return posix_error(); + return PyLong_FromPid(pid); +} +#endif /* HAVE_FORK1 */ + + +#ifdef HAVE_FORK +/*[clinic input] +os.fork + +Fork a child process. + +Return 0 to child process and PID of child to parent process. +[clinic start generated code]*/ + +static PyObject * +os_fork_impl(PyObject *module) +/*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/ +{ + pid_t pid; + PyInterpreterState *interp = _PyInterpreterState_GET(); + if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_FORK)) { + PyErr_SetString(PyExc_RuntimeError, + "fork not supported for isolated subinterpreters"); + return NULL; + } + if (PySys_Audit("os.fork", NULL) < 0) { + return NULL; + } + PyOS_BeforeFork(); + pid = fork(); + if (pid == 0) { + /* child: this clobbers and resets the import lock. */ + PyOS_AfterFork_Child(); + } else { + /* parent: release the import lock. */ + PyOS_AfterFork_Parent(); + } + if (pid == -1) + return posix_error(); + return PyLong_FromPid(pid); +} +#endif /* HAVE_FORK */ + + +#ifdef HAVE_SCHED_H +#ifdef HAVE_SCHED_GET_PRIORITY_MAX +/*[clinic input] +os.sched_get_priority_max + + policy: int + +Get the maximum scheduling priority for policy. +[clinic start generated code]*/ + +static PyObject * +os_sched_get_priority_max_impl(PyObject *module, int policy) +/*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/ +{ + int max; + + max = sched_get_priority_max(policy); + if (max < 0) + return posix_error(); + return PyLong_FromLong(max); +} + + +/*[clinic input] +os.sched_get_priority_min + + policy: int + +Get the minimum scheduling priority for policy. +[clinic start generated code]*/ + +static PyObject * +os_sched_get_priority_min_impl(PyObject *module, int policy) +/*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/ +{ + int min = sched_get_priority_min(policy); + if (min < 0) + return posix_error(); + return PyLong_FromLong(min); +} +#endif /* HAVE_SCHED_GET_PRIORITY_MAX */ + + +#ifdef HAVE_SCHED_SETSCHEDULER +/*[clinic input] +os.sched_getscheduler + pid: pid_t + / + +Get the scheduling policy for the process identified by pid. + +Passing 0 for pid returns the scheduling policy for the calling process. +[clinic start generated code]*/ + +static PyObject * +os_sched_getscheduler_impl(PyObject *module, pid_t pid) +/*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/ +{ + int policy; + + policy = sched_getscheduler(pid); + if (policy < 0) + return posix_error(); + return PyLong_FromLong(policy); +} +#endif /* HAVE_SCHED_SETSCHEDULER */ + + +#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) +/*[clinic input] +class os.sched_param "PyObject *" "SchedParamType" + +@classmethod +os.sched_param.__new__ + + sched_priority: object + A scheduling parameter. + +Currently has only one field: sched_priority +[clinic start generated code]*/ + +static PyObject * +os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority) +/*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/ +{ + PyObject *res; + + res = PyStructSequence_New(type); + if (!res) + return NULL; + PyStructSequence_SET_ITEM(res, 0, Py_NewRef(sched_priority)); + return res; +} + +PyDoc_VAR(os_sched_param__doc__); + +static PyStructSequence_Field sched_param_fields[] = { + {"sched_priority", "the scheduling priority"}, + {0} +}; + +static PyStructSequence_Desc sched_param_desc = { + "sched_param", /* name */ + os_sched_param__doc__, /* doc */ + sched_param_fields, + 1 +}; + +static int +convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res) +{ + long priority; + + if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) { + PyErr_SetString(PyExc_TypeError, "must have a sched_param object"); + return 0; + } + priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0)); + if (priority == -1 && PyErr_Occurred()) + return 0; + if (priority > INT_MAX || priority < INT_MIN) { + PyErr_SetString(PyExc_OverflowError, "sched_priority out of range"); + return 0; + } + res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int); + return 1; +} +#endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */ + + +#ifdef HAVE_SCHED_SETSCHEDULER +/*[clinic input] +os.sched_setscheduler + + pid: pid_t + policy: int + param as param_obj: object + / + +Set the scheduling policy for the process identified by pid. + +If pid is 0, the calling process is changed. +param is an instance of sched_param. +[clinic start generated code]*/ + +static PyObject * +os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy, + PyObject *param_obj) +/*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/ +{ + struct sched_param param; + if (!convert_sched_param(module, param_obj, ¶m)) { + return NULL; + } + + /* + ** sched_setscheduler() returns 0 in Linux, but the previous + ** scheduling policy under Solaris/Illumos, and others. + ** On error, -1 is returned in all Operating Systems. + */ + if (sched_setscheduler(pid, policy, ¶m) == -1) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SCHED_SETSCHEDULER*/ + + +#ifdef HAVE_SCHED_SETPARAM +/*[clinic input] +os.sched_getparam + pid: pid_t + / + +Returns scheduling parameters for the process identified by pid. + +If pid is 0, returns parameters for the calling process. +Return value is an instance of sched_param. +[clinic start generated code]*/ + +static PyObject * +os_sched_getparam_impl(PyObject *module, pid_t pid) +/*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/ +{ + struct sched_param param; + PyObject *result; + PyObject *priority; + + if (sched_getparam(pid, ¶m)) + return posix_error(); + PyObject *SchedParamType = get_posix_state(module)->SchedParamType; + result = PyStructSequence_New((PyTypeObject *)SchedParamType); + if (!result) + return NULL; + priority = PyLong_FromLong(param.sched_priority); + if (!priority) { + Py_DECREF(result); + return NULL; + } + PyStructSequence_SET_ITEM(result, 0, priority); + return result; +} + + +/*[clinic input] +os.sched_setparam + pid: pid_t + param as param_obj: object + / + +Set scheduling parameters for the process identified by pid. + +If pid is 0, sets parameters for the calling process. +param should be an instance of sched_param. +[clinic start generated code]*/ + +static PyObject * +os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj) +/*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/ +{ + struct sched_param param; + if (!convert_sched_param(module, param_obj, ¶m)) { + return NULL; + } + + if (sched_setparam(pid, ¶m)) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SCHED_SETPARAM */ + + +#ifdef HAVE_SCHED_RR_GET_INTERVAL +/*[clinic input] +os.sched_rr_get_interval -> double + pid: pid_t + / + +Return the round-robin quantum for the process identified by pid, in seconds. + +Value returned is a float. +[clinic start generated code]*/ + +static double +os_sched_rr_get_interval_impl(PyObject *module, pid_t pid) +/*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/ +{ + struct timespec interval; + if (sched_rr_get_interval(pid, &interval)) { + posix_error(); + return -1.0; + } +#ifdef _Py_MEMORY_SANITIZER + __msan_unpoison(&interval, sizeof(interval)); +#endif + return (double)interval.tv_sec + 1e-9*interval.tv_nsec; +} +#endif /* HAVE_SCHED_RR_GET_INTERVAL */ + + +/*[clinic input] +os.sched_yield + +Voluntarily relinquish the CPU. +[clinic start generated code]*/ + +static PyObject * +os_sched_yield_impl(PyObject *module) +/*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/ +{ + int result; + Py_BEGIN_ALLOW_THREADS + result = sched_yield(); + Py_END_ALLOW_THREADS + if (result < 0) { + return posix_error(); + } + Py_RETURN_NONE; +} + +#ifdef HAVE_SCHED_SETAFFINITY +/* The minimum number of CPUs allocated in a cpu_set_t */ +static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT; + +/*[clinic input] +os.sched_setaffinity + pid: pid_t + mask : object + / + +Set the CPU affinity of the process identified by pid to mask. + +mask should be an iterable of integers identifying CPUs. +[clinic start generated code]*/ + +static PyObject * +os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask) +/*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/ +{ + int ncpus; + size_t setsize; + cpu_set_t *cpu_set = NULL; + PyObject *iterator = NULL, *item; + + iterator = PyObject_GetIter(mask); + if (iterator == NULL) + return NULL; + + ncpus = NCPUS_START; + setsize = CPU_ALLOC_SIZE(ncpus); + cpu_set = CPU_ALLOC(ncpus); + if (cpu_set == NULL) { + PyErr_NoMemory(); + goto error; + } + CPU_ZERO_S(setsize, cpu_set); + + while ((item = PyIter_Next(iterator))) { + long cpu; + if (!PyLong_Check(item)) { + PyErr_Format(PyExc_TypeError, + "expected an iterator of ints, " + "but iterator yielded %R", + Py_TYPE(item)); + Py_DECREF(item); + goto error; + } + cpu = PyLong_AsLong(item); + Py_DECREF(item); + if (cpu < 0) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_ValueError, "negative CPU number"); + goto error; + } + if (cpu > INT_MAX - 1) { + PyErr_SetString(PyExc_OverflowError, "CPU number too large"); + goto error; + } + if (cpu >= ncpus) { + /* Grow CPU mask to fit the CPU number */ + int newncpus = ncpus; + cpu_set_t *newmask; + size_t newsetsize; + while (newncpus <= cpu) { + if (newncpus > INT_MAX / 2) + newncpus = cpu + 1; + else + newncpus = newncpus * 2; + } + newmask = CPU_ALLOC(newncpus); + if (newmask == NULL) { + PyErr_NoMemory(); + goto error; + } + newsetsize = CPU_ALLOC_SIZE(newncpus); + CPU_ZERO_S(newsetsize, newmask); + memcpy(newmask, cpu_set, setsize); + CPU_FREE(cpu_set); + setsize = newsetsize; + cpu_set = newmask; + ncpus = newncpus; + } + CPU_SET_S(cpu, setsize, cpu_set); + } + if (PyErr_Occurred()) { + goto error; + } + Py_CLEAR(iterator); + + if (sched_setaffinity(pid, setsize, cpu_set)) { + posix_error(); + goto error; + } + CPU_FREE(cpu_set); + Py_RETURN_NONE; + +error: + if (cpu_set) + CPU_FREE(cpu_set); + Py_XDECREF(iterator); + return NULL; +} + + +/*[clinic input] +os.sched_getaffinity + pid: pid_t + / + +Return the affinity of the process identified by pid (or the current process if zero). + +The affinity is returned as a set of CPU identifiers. +[clinic start generated code]*/ + +static PyObject * +os_sched_getaffinity_impl(PyObject *module, pid_t pid) +/*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/ +{ + int cpu, ncpus, count; + size_t setsize; + cpu_set_t *mask = NULL; + PyObject *res = NULL; + + ncpus = NCPUS_START; + while (1) { + setsize = CPU_ALLOC_SIZE(ncpus); + mask = CPU_ALLOC(ncpus); + if (mask == NULL) + return PyErr_NoMemory(); + if (sched_getaffinity(pid, setsize, mask) == 0) + break; + CPU_FREE(mask); + if (errno != EINVAL) + return posix_error(); + if (ncpus > INT_MAX / 2) { + PyErr_SetString(PyExc_OverflowError, "could not allocate " + "a large enough CPU set"); + return NULL; + } + ncpus = ncpus * 2; + } + + res = PySet_New(NULL); + if (res == NULL) + goto error; + for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) { + if (CPU_ISSET_S(cpu, setsize, mask)) { + PyObject *cpu_num = PyLong_FromLong(cpu); + --count; + if (cpu_num == NULL) + goto error; + if (PySet_Add(res, cpu_num)) { + Py_DECREF(cpu_num); + goto error; + } + Py_DECREF(cpu_num); + } + } + CPU_FREE(mask); + return res; + +error: + if (mask) + CPU_FREE(mask); + Py_XDECREF(res); + return NULL; +} + +#endif /* HAVE_SCHED_SETAFFINITY */ + +#endif /* HAVE_SCHED_H */ + + +/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */ +#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX) +# define DEV_PTY_FILE "/dev/ptc" +# define HAVE_DEV_PTMX +#else +# define DEV_PTY_FILE "/dev/ptmx" +#endif + +#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) +#ifdef HAVE_PTY_H +#include +#ifdef HAVE_UTMP_H +#include +#endif /* HAVE_UTMP_H */ +#elif defined(HAVE_LIBUTIL_H) +#include +#elif defined(HAVE_UTIL_H) +#include +#endif /* HAVE_PTY_H */ +#ifdef HAVE_STROPTS_H +#include +#endif +#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */ + + +#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) +/*[clinic input] +os.openpty + +Open a pseudo-terminal. + +Return a tuple of (master_fd, slave_fd) containing open file descriptors +for both the master and slave ends. +[clinic start generated code]*/ + +static PyObject * +os_openpty_impl(PyObject *module) +/*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/ +{ + int master_fd = -1, slave_fd = -1; +#ifndef HAVE_OPENPTY + char * slave_name; +#endif +#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY) + PyOS_sighandler_t sig_saved; +#if defined(__sun) && defined(__SVR4) + extern char *ptsname(int fildes); +#endif +#endif + +#ifdef HAVE_OPENPTY + if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0) + goto posix_error; + + if (_Py_set_inheritable(master_fd, 0, NULL) < 0) + goto error; + if (_Py_set_inheritable(slave_fd, 0, NULL) < 0) + goto error; + +#elif defined(HAVE__GETPTY) + slave_name = _getpty(&master_fd, O_RDWR, 0666, 0); + if (slave_name == NULL) + goto posix_error; + if (_Py_set_inheritable(master_fd, 0, NULL) < 0) + goto error; + + slave_fd = _Py_open(slave_name, O_RDWR); + if (slave_fd < 0) + goto error; + +#else + master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */ + if (master_fd < 0) + goto posix_error; + + sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL); + + /* change permission of slave */ + if (grantpt(master_fd) < 0) { + PyOS_setsig(SIGCHLD, sig_saved); + goto posix_error; + } + + /* unlock slave */ + if (unlockpt(master_fd) < 0) { + PyOS_setsig(SIGCHLD, sig_saved); + goto posix_error; + } + + PyOS_setsig(SIGCHLD, sig_saved); + + slave_name = ptsname(master_fd); /* get name of slave */ + if (slave_name == NULL) + goto posix_error; + + slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */ + if (slave_fd == -1) + goto error; + + if (_Py_set_inheritable(master_fd, 0, NULL) < 0) + goto posix_error; + +#if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC) + ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */ + ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */ +#ifndef __hpux + ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */ +#endif /* __hpux */ +#endif /* HAVE_CYGWIN */ +#endif /* HAVE_OPENPTY */ + + return Py_BuildValue("(ii)", master_fd, slave_fd); + +posix_error: + posix_error(); +error: + if (master_fd != -1) + close(master_fd); + if (slave_fd != -1) + close(slave_fd); + return NULL; +} +#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */ + + +#if defined(HAVE_SETSID) && defined(TIOCSCTTY) +#define HAVE_FALLBACK_LOGIN_TTY 1 +#endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */ + +#if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) +/*[clinic input] +os.login_tty + + fd: fildes + / + +Prepare the tty of which fd is a file descriptor for a new login session. + +Make the calling process a session leader; make the tty the +controlling tty, the stdin, the stdout, and the stderr of the +calling process; close fd. +[clinic start generated code]*/ + +static PyObject * +os_login_tty_impl(PyObject *module, int fd) +/*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/ +{ +#ifdef HAVE_LOGIN_TTY + if (login_tty(fd) == -1) { + return posix_error(); + } +#else /* defined(HAVE_FALLBACK_LOGIN_TTY) */ + /* Establish a new session. */ + if (setsid() == -1) { + return posix_error(); + } + + /* The tty becomes the controlling terminal. */ + if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) { + return posix_error(); + } + + /* The tty becomes stdin/stdout/stderr */ + if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) { + return posix_error(); + } + if (fd > 2) { + close(fd); + } +#endif /* HAVE_LOGIN_TTY */ + Py_RETURN_NONE; +} +#endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */ + + +#ifdef HAVE_FORKPTY +/*[clinic input] +os.forkpty + +Fork a new process with a new pseudo-terminal as controlling tty. + +Returns a tuple of (pid, master_fd). +Like fork(), return pid of 0 to the child process, +and pid of child to the parent process. +To both, return fd of newly opened pseudo-terminal. +[clinic start generated code]*/ + +static PyObject * +os_forkpty_impl(PyObject *module) +/*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/ +{ + int master_fd = -1; + pid_t pid; + + if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) { + PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters"); + return NULL; + } + if (PySys_Audit("os.forkpty", NULL) < 0) { + return NULL; + } + PyOS_BeforeFork(); + pid = forkpty(&master_fd, NULL, NULL, NULL); + if (pid == 0) { + /* child: this clobbers and resets the import lock. */ + PyOS_AfterFork_Child(); + } else { + /* parent: release the import lock. */ + PyOS_AfterFork_Parent(); + } + if (pid == -1) { + return posix_error(); + } + return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd); +} +#endif /* HAVE_FORKPTY */ + + +#ifdef HAVE_GETEGID +/*[clinic input] +os.getegid + +Return the current process's effective group id. +[clinic start generated code]*/ + +static PyObject * +os_getegid_impl(PyObject *module) +/*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/ +{ + return _PyLong_FromGid(getegid()); +} +#endif /* HAVE_GETEGID */ + + +#ifdef HAVE_GETEUID +/*[clinic input] +os.geteuid + +Return the current process's effective user id. +[clinic start generated code]*/ + +static PyObject * +os_geteuid_impl(PyObject *module) +/*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/ +{ + return _PyLong_FromUid(geteuid()); +} +#endif /* HAVE_GETEUID */ + + +#ifdef HAVE_GETGID +/*[clinic input] +os.getgid + +Return the current process's group id. +[clinic start generated code]*/ + +static PyObject * +os_getgid_impl(PyObject *module) +/*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/ +{ + return _PyLong_FromGid(getgid()); +} +#endif /* HAVE_GETGID */ + + +#ifdef HAVE_GETPID +/*[clinic input] +os.getpid + +Return the current process id. +[clinic start generated code]*/ + +static PyObject * +os_getpid_impl(PyObject *module) +/*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/ +{ + return PyLong_FromPid(getpid()); +} +#endif /* HAVE_GETPID */ + +#ifdef NGROUPS_MAX +#define MAX_GROUPS NGROUPS_MAX +#else + /* defined to be 16 on Solaris7, so this should be a small number */ +#define MAX_GROUPS 64 +#endif + +#ifdef HAVE_GETGROUPLIST + +#ifdef __APPLE__ +/*[clinic input] +os.getgrouplist + + user: str + username to lookup + group as basegid: int + base group id of the user + / + +Returns a list of groups to which a user belongs. +[clinic start generated code]*/ + +static PyObject * +os_getgrouplist_impl(PyObject *module, const char *user, int basegid) +/*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/ +#else +/*[clinic input] +os.getgrouplist + + user: str + username to lookup + group as basegid: gid_t + base group id of the user + / + +Returns a list of groups to which a user belongs. +[clinic start generated code]*/ + +static PyObject * +os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid) +/*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/ +#endif +{ + int i, ngroups; + PyObject *list; +#ifdef __APPLE__ + int *groups; +#else + gid_t *groups; +#endif + + /* + * NGROUPS_MAX is defined by POSIX.1 as the maximum + * number of supplimental groups a users can belong to. + * We have to increment it by one because + * getgrouplist() returns both the supplemental groups + * and the primary group, i.e. all of the groups the + * user belongs to. + */ + ngroups = 1 + MAX_GROUPS; + + while (1) { +#ifdef __APPLE__ + groups = PyMem_New(int, ngroups); +#else + groups = PyMem_New(gid_t, ngroups); +#endif + if (groups == NULL) { + return PyErr_NoMemory(); + } + + int old_ngroups = ngroups; + if (getgrouplist(user, basegid, groups, &ngroups) != -1) { + /* Success */ + break; + } + + /* getgrouplist() fails if the group list is too small */ + PyMem_Free(groups); + + if (ngroups > old_ngroups) { + /* If the group list is too small, the glibc implementation of + getgrouplist() sets ngroups to the total number of groups and + returns -1. */ + } + else { + /* Double the group list size */ + if (ngroups > INT_MAX / 2) { + return PyErr_NoMemory(); + } + ngroups *= 2; + } + + /* Retry getgrouplist() with a larger group list */ + } + +#ifdef _Py_MEMORY_SANITIZER + /* Clang memory sanitizer libc intercepts don't know getgrouplist. */ + __msan_unpoison(&ngroups, sizeof(ngroups)); + __msan_unpoison(groups, ngroups*sizeof(*groups)); +#endif + + list = PyList_New(ngroups); + if (list == NULL) { + PyMem_Free(groups); + return NULL; + } + + for (i = 0; i < ngroups; i++) { +#ifdef __APPLE__ + PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]); +#else + PyObject *o = _PyLong_FromGid(groups[i]); +#endif + if (o == NULL) { + Py_DECREF(list); + PyMem_Free(groups); + return NULL; + } + PyList_SET_ITEM(list, i, o); + } + + PyMem_Free(groups); + + return list; +} +#endif /* HAVE_GETGROUPLIST */ + + +#ifdef HAVE_GETGROUPS +/*[clinic input] +os.getgroups + +Return list of supplemental group IDs for the process. +[clinic start generated code]*/ + +static PyObject * +os_getgroups_impl(PyObject *module) +/*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/ +{ + // Call getgroups with length 0 to get the actual number of groups + int n = getgroups(0, NULL); + if (n < 0) { + return posix_error(); + } + + if (n == 0) { + return PyList_New(0); + } + + gid_t *grouplist = PyMem_New(gid_t, n); + if (grouplist == NULL) { + return PyErr_NoMemory(); + } + + n = getgroups(n, grouplist); + if (n == -1) { + PyMem_Free(grouplist); + return posix_error(); + } + + PyObject *result = PyList_New(n); + if (result == NULL) { + goto error; + } + + for (int i = 0; i < n; ++i) { + PyObject *group = _PyLong_FromGid(grouplist[i]); + if (group == NULL) { + goto error; + } + PyList_SET_ITEM(result, i, group); + } + PyMem_Free(grouplist); + + return result; + +error: + PyMem_Free(grouplist); + Py_XDECREF(result); + return NULL; +} +#endif /* HAVE_GETGROUPS */ + +#ifdef HAVE_INITGROUPS +#ifdef __APPLE__ +/*[clinic input] +os.initgroups + + username as oname: FSConverter + gid: int + / + +Initialize the group access list. + +Call the system initgroups() to initialize the group access list with all of +the groups of which the specified username is a member, plus the specified +group id. +[clinic start generated code]*/ + +static PyObject * +os_initgroups_impl(PyObject *module, PyObject *oname, int gid) +/*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/ +#else +/*[clinic input] +os.initgroups + + username as oname: FSConverter + gid: gid_t + / + +Initialize the group access list. + +Call the system initgroups() to initialize the group access list with all of +the groups of which the specified username is a member, plus the specified +group id. +[clinic start generated code]*/ + +static PyObject * +os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid) +/*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/ +#endif +{ + const char *username = PyBytes_AS_STRING(oname); + + if (initgroups(username, gid) == -1) + return PyErr_SetFromErrno(PyExc_OSError); + + Py_RETURN_NONE; +} +#endif /* HAVE_INITGROUPS */ + + +#ifdef HAVE_GETPGID +/*[clinic input] +os.getpgid + + pid: pid_t + +Call the system call getpgid(), and return the result. +[clinic start generated code]*/ + +static PyObject * +os_getpgid_impl(PyObject *module, pid_t pid) +/*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/ +{ + pid_t pgid = getpgid(pid); + if (pgid < 0) + return posix_error(); + return PyLong_FromPid(pgid); +} +#endif /* HAVE_GETPGID */ + + +#ifdef HAVE_GETPGRP +/*[clinic input] +os.getpgrp + +Return the current process group id. +[clinic start generated code]*/ + +static PyObject * +os_getpgrp_impl(PyObject *module) +/*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/ +{ +#ifdef GETPGRP_HAVE_ARG + return PyLong_FromPid(getpgrp(0)); +#else /* GETPGRP_HAVE_ARG */ + return PyLong_FromPid(getpgrp()); +#endif /* GETPGRP_HAVE_ARG */ +} +#endif /* HAVE_GETPGRP */ + + +#ifdef HAVE_SETPGRP +/*[clinic input] +os.setpgrp + +Make the current process the leader of its process group. +[clinic start generated code]*/ + +static PyObject * +os_setpgrp_impl(PyObject *module) +/*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/ +{ +#ifdef SETPGRP_HAVE_ARG + if (setpgrp(0, 0) < 0) +#else /* SETPGRP_HAVE_ARG */ + if (setpgrp() < 0) +#endif /* SETPGRP_HAVE_ARG */ + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETPGRP */ + +#ifdef HAVE_GETPPID + +#ifdef MS_WINDOWS +#include + +static PyObject* +win32_getppid() +{ + HANDLE snapshot; + pid_t mypid; + PyObject* result = NULL; + BOOL have_record; + PROCESSENTRY32 pe; + + mypid = getpid(); /* This function never fails */ + + snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (snapshot == INVALID_HANDLE_VALUE) + return PyErr_SetFromWindowsErr(GetLastError()); + + pe.dwSize = sizeof(pe); + have_record = Process32First(snapshot, &pe); + while (have_record) { + if (mypid == (pid_t)pe.th32ProcessID) { + /* We could cache the ulong value in a static variable. */ + result = PyLong_FromPid((pid_t)pe.th32ParentProcessID); + break; + } + + have_record = Process32Next(snapshot, &pe); + } + + /* If our loop exits and our pid was not found (result will be NULL) + * then GetLastError will return ERROR_NO_MORE_FILES. This is an + * error anyway, so let's raise it. */ + if (!result) + result = PyErr_SetFromWindowsErr(GetLastError()); + + CloseHandle(snapshot); + + return result; +} +#endif /*MS_WINDOWS*/ + + +/*[clinic input] +os.getppid + +Return the parent's process id. + +If the parent process has already exited, Windows machines will still +return its id; others systems will return the id of the 'init' process (1). +[clinic start generated code]*/ + +static PyObject * +os_getppid_impl(PyObject *module) +/*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/ +{ +#ifdef MS_WINDOWS + return win32_getppid(); +#else + return PyLong_FromPid(getppid()); +#endif +} +#endif /* HAVE_GETPPID */ + + +#ifdef HAVE_GETLOGIN +/*[clinic input] +os.getlogin + +Return the actual login name. +[clinic start generated code]*/ + +static PyObject * +os_getlogin_impl(PyObject *module) +/*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/ +{ + PyObject *result = NULL; +#ifdef MS_WINDOWS + wchar_t user_name[UNLEN + 1]; + DWORD num_chars = Py_ARRAY_LENGTH(user_name); + + if (GetUserNameW(user_name, &num_chars)) { + /* num_chars is the number of unicode chars plus null terminator */ + result = PyUnicode_FromWideChar(user_name, num_chars - 1); + } + else + result = PyErr_SetFromWindowsErr(GetLastError()); +#else + char *name; + int old_errno = errno; + + errno = 0; + name = getlogin(); + if (name == NULL) { + if (errno) + posix_error(); + else + PyErr_SetString(PyExc_OSError, "unable to determine login name"); + } + else + result = PyUnicode_DecodeFSDefault(name); + errno = old_errno; +#endif + return result; +} +#endif /* HAVE_GETLOGIN */ + + +#ifdef HAVE_GETUID +/*[clinic input] +os.getuid + +Return the current process's user id. +[clinic start generated code]*/ + +static PyObject * +os_getuid_impl(PyObject *module) +/*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/ +{ + return _PyLong_FromUid(getuid()); +} +#endif /* HAVE_GETUID */ + + +#ifdef MS_WINDOWS +#define HAVE_KILL +#endif /* MS_WINDOWS */ + +#ifdef HAVE_KILL +/*[clinic input] +os.kill + + pid: pid_t + signal: Py_ssize_t + / + +Kill a process with a signal. +[clinic start generated code]*/ + +static PyObject * +os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal) +/*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/ +{ + if (PySys_Audit("os.kill", "in", pid, signal) < 0) { + return NULL; + } +#ifndef MS_WINDOWS + if (kill(pid, (int)signal) == -1) { + return posix_error(); + } + + // Check immediately if the signal was sent to the current process. + // Don't micro-optimize pid == getpid(), since PyErr_SetString() check + // is cheap. + if (PyErr_CheckSignals()) { + return NULL; + } + + Py_RETURN_NONE; +#else /* !MS_WINDOWS */ + PyObject *result; + DWORD sig = (DWORD)signal; + DWORD err; + HANDLE handle; + + /* Console processes which share a common console can be sent CTRL+C or + CTRL+BREAK events, provided they handle said events. */ + if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) { + if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) { + err = GetLastError(); + PyErr_SetFromWindowsErr(err); + } + else + Py_RETURN_NONE; + } + + /* If the signal is outside of what GenerateConsoleCtrlEvent can use, + attempt to open and terminate the process. */ + handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid); + if (handle == NULL) { + err = GetLastError(); + return PyErr_SetFromWindowsErr(err); + } + + if (TerminateProcess(handle, sig) == 0) { + err = GetLastError(); + result = PyErr_SetFromWindowsErr(err); + } else { + result = Py_NewRef(Py_None); + } + + CloseHandle(handle); + return result; +#endif /* !MS_WINDOWS */ +} +#endif /* HAVE_KILL */ + + +#ifdef HAVE_KILLPG +/*[clinic input] +os.killpg + + pgid: pid_t + signal: int + / + +Kill a process group with a signal. +[clinic start generated code]*/ + +static PyObject * +os_killpg_impl(PyObject *module, pid_t pgid, int signal) +/*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/ +{ + if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) { + return NULL; + } + /* XXX some man pages make the `pgid` parameter an int, others + a pid_t. Since getpgrp() returns a pid_t, we assume killpg should + take the same type. Moreover, pid_t is always at least as wide as + int (else compilation of this module fails), which is safe. */ + if (killpg(pgid, signal) == -1) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_KILLPG */ + + +#ifdef HAVE_PLOCK +#ifdef HAVE_SYS_LOCK_H +#include +#endif + +/*[clinic input] +os.plock + op: int + / + +Lock program segments into memory."); +[clinic start generated code]*/ + +static PyObject * +os_plock_impl(PyObject *module, int op) +/*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/ +{ + if (plock(op) == -1) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_PLOCK */ + + +#ifdef HAVE_SETUID +/*[clinic input] +os.setuid + + uid: uid_t + / + +Set the current process's user id. +[clinic start generated code]*/ + +static PyObject * +os_setuid_impl(PyObject *module, uid_t uid) +/*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/ +{ + if (setuid(uid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETUID */ + + +#ifdef HAVE_SETEUID +/*[clinic input] +os.seteuid + + euid: uid_t + / + +Set the current process's effective user id. +[clinic start generated code]*/ + +static PyObject * +os_seteuid_impl(PyObject *module, uid_t euid) +/*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/ +{ + if (seteuid(euid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETEUID */ + + +#ifdef HAVE_SETEGID +/*[clinic input] +os.setegid + + egid: gid_t + / + +Set the current process's effective group id. +[clinic start generated code]*/ + +static PyObject * +os_setegid_impl(PyObject *module, gid_t egid) +/*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/ +{ + if (setegid(egid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETEGID */ + + +#ifdef HAVE_SETREUID +/*[clinic input] +os.setreuid + + ruid: uid_t + euid: uid_t + / + +Set the current process's real and effective user ids. +[clinic start generated code]*/ + +static PyObject * +os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid) +/*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/ +{ + if (setreuid(ruid, euid) < 0) { + return posix_error(); + } else { + Py_RETURN_NONE; + } +} +#endif /* HAVE_SETREUID */ + + +#ifdef HAVE_SETREGID +/*[clinic input] +os.setregid + + rgid: gid_t + egid: gid_t + / + +Set the current process's real and effective group ids. +[clinic start generated code]*/ + +static PyObject * +os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid) +/*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/ +{ + if (setregid(rgid, egid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETREGID */ + + +#ifdef HAVE_SETGID +/*[clinic input] +os.setgid + gid: gid_t + / + +Set the current process's group id. +[clinic start generated code]*/ + +static PyObject * +os_setgid_impl(PyObject *module, gid_t gid) +/*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/ +{ + if (setgid(gid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETGID */ + + +#ifdef HAVE_SETGROUPS +/*[clinic input] +os.setgroups + + groups: object + / + +Set the groups of the current process to list. +[clinic start generated code]*/ + +static PyObject * +os_setgroups(PyObject *module, PyObject *groups) +/*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/ +{ + if (!PySequence_Check(groups)) { + PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence"); + return NULL; + } + Py_ssize_t len = PySequence_Size(groups); + if (len < 0) { + return NULL; + } + if (len > MAX_GROUPS) { + PyErr_SetString(PyExc_ValueError, "too many groups"); + return NULL; + } + + gid_t *grouplist = PyMem_New(gid_t, len); + for (Py_ssize_t i = 0; i < len; i++) { + PyObject *elem; + elem = PySequence_GetItem(groups, i); + if (!elem) { + PyMem_Free(grouplist); + return NULL; + } + if (!PyLong_Check(elem)) { + PyErr_SetString(PyExc_TypeError, + "groups must be integers"); + Py_DECREF(elem); + PyMem_Free(grouplist); + return NULL; + } else { + if (!_Py_Gid_Converter(elem, &grouplist[i])) { + Py_DECREF(elem); + PyMem_Free(grouplist); + return NULL; + } + } + Py_DECREF(elem); + } + + if (setgroups(len, grouplist) < 0) { + PyMem_Free(grouplist); + return posix_error(); + } + PyMem_Free(grouplist); + Py_RETURN_NONE; +} +#endif /* HAVE_SETGROUPS */ + +#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) +static PyObject * +wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru) +{ + PyObject *result; + PyObject *struct_rusage; + + if (pid == -1) + return posix_error(); + + // If wait succeeded but no child was ready to report status, ru will not + // have been populated. + if (pid == 0) { + memset(ru, 0, sizeof(*ru)); + } + + struct_rusage = _PyImport_GetModuleAttrString("resource", "struct_rusage"); + if (struct_rusage == NULL) + return NULL; + + /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */ + result = PyStructSequence_New((PyTypeObject*) struct_rusage); + Py_DECREF(struct_rusage); + if (!result) + return NULL; + +#ifndef doubletime +#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001) +#endif + + PyStructSequence_SET_ITEM(result, 0, + PyFloat_FromDouble(doubletime(ru->ru_utime))); + PyStructSequence_SET_ITEM(result, 1, + PyFloat_FromDouble(doubletime(ru->ru_stime))); +#define SET_INT(result, index, value)\ + PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value)) + SET_INT(result, 2, ru->ru_maxrss); + SET_INT(result, 3, ru->ru_ixrss); + SET_INT(result, 4, ru->ru_idrss); + SET_INT(result, 5, ru->ru_isrss); + SET_INT(result, 6, ru->ru_minflt); + SET_INT(result, 7, ru->ru_majflt); + SET_INT(result, 8, ru->ru_nswap); + SET_INT(result, 9, ru->ru_inblock); + SET_INT(result, 10, ru->ru_oublock); + SET_INT(result, 11, ru->ru_msgsnd); + SET_INT(result, 12, ru->ru_msgrcv); + SET_INT(result, 13, ru->ru_nsignals); + SET_INT(result, 14, ru->ru_nvcsw); + SET_INT(result, 15, ru->ru_nivcsw); +#undef SET_INT + + if (PyErr_Occurred()) { + Py_DECREF(result); + return NULL; + } + + return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result); +} +#endif /* HAVE_WAIT3 || HAVE_WAIT4 */ + + +#ifdef HAVE_WAIT3 +/*[clinic input] +os.wait3 + + options: int +Wait for completion of a child process. + +Returns a tuple of information about the child process: + (pid, status, rusage) +[clinic start generated code]*/ + +static PyObject * +os_wait3_impl(PyObject *module, int options) +/*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/ +{ + pid_t pid; + struct rusage ru; + int async_err = 0; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + do { + Py_BEGIN_ALLOW_THREADS + pid = wait3(&status, options, &ru); + Py_END_ALLOW_THREADS + } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (pid < 0) + return (!async_err) ? posix_error() : NULL; + + return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru); +} +#endif /* HAVE_WAIT3 */ + + +#ifdef HAVE_WAIT4 +/*[clinic input] + +os.wait4 + + pid: pid_t + options: int + +Wait for completion of a specific child process. + +Returns a tuple of information about the child process: + (pid, status, rusage) +[clinic start generated code]*/ + +static PyObject * +os_wait4_impl(PyObject *module, pid_t pid, int options) +/*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/ +{ + pid_t res; + struct rusage ru; + int async_err = 0; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + do { + Py_BEGIN_ALLOW_THREADS + res = wait4(pid, &status, options, &ru); + Py_END_ALLOW_THREADS + } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (res < 0) + return (!async_err) ? posix_error() : NULL; + + return wait_helper(module, res, WAIT_STATUS_INT(status), &ru); +} +#endif /* HAVE_WAIT4 */ + + +#if defined(HAVE_WAITID) && !defined(__APPLE__) +/*[clinic input] +os.waitid + + idtype: idtype_t + Must be one of be P_PID, P_PGID or P_ALL. + id: id_t + The id to wait on. + options: int + Constructed from the ORing of one or more of WEXITED, WSTOPPED + or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT. + / + +Returns the result of waiting for a process or processes. + +Returns either waitid_result or None if WNOHANG is specified and there are +no children in a waitable state. +[clinic start generated code]*/ + +static PyObject * +os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options) +/*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/ +{ + PyObject *result; + int res; + int async_err = 0; + siginfo_t si; + si.si_pid = 0; + + do { + Py_BEGIN_ALLOW_THREADS + res = waitid(idtype, id, &si, options); + Py_END_ALLOW_THREADS + } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (res < 0) + return (!async_err) ? posix_error() : NULL; + + if (si.si_pid == 0) + Py_RETURN_NONE; + + PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType; + result = PyStructSequence_New((PyTypeObject *)WaitidResultType); + if (!result) + return NULL; + + PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid)); + PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid)); + PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo))); + PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status))); + PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code))); + if (PyErr_Occurred()) { + Py_DECREF(result); + return NULL; + } + + return result; +} +#endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */ + + +#if defined(HAVE_WAITPID) +/*[clinic input] +os.waitpid + pid: pid_t + options: int + / + +Wait for completion of a given child process. + +Returns a tuple of information regarding the child process: + (pid, status) + +The options argument is ignored on Windows. +[clinic start generated code]*/ + +static PyObject * +os_waitpid_impl(PyObject *module, pid_t pid, int options) +/*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/ +{ + pid_t res; + int async_err = 0; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + do { + Py_BEGIN_ALLOW_THREADS + res = waitpid(pid, &status, options); + Py_END_ALLOW_THREADS + } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (res < 0) + return (!async_err) ? posix_error() : NULL; + + return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status)); +} +#elif defined(HAVE_CWAIT) +/* MS C has a variant of waitpid() that's usable for most purposes. */ +/*[clinic input] +os.waitpid + pid: intptr_t + options: int + / + +Wait for completion of a given process. + +Returns a tuple of information regarding the process: + (pid, status << 8) + +The options argument is ignored on Windows. +[clinic start generated code]*/ + +static PyObject * +os_waitpid_impl(PyObject *module, intptr_t pid, int options) +/*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/ +{ + int status; + intptr_t res; + int async_err = 0; + + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + res = _cwait(&status, pid, options); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (res < 0) + return (!async_err) ? posix_error() : NULL; + + unsigned long long ustatus = (unsigned int)status; + + /* shift the status left a byte so this is more like the POSIX waitpid */ + return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8); +} +#endif + + +#ifdef HAVE_WAIT +/*[clinic input] +os.wait + +Wait for completion of a child process. + +Returns a tuple of information about the child process: + (pid, status) +[clinic start generated code]*/ + +static PyObject * +os_wait_impl(PyObject *module) +/*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/ +{ + pid_t pid; + int async_err = 0; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + do { + Py_BEGIN_ALLOW_THREADS + pid = wait(&status); + Py_END_ALLOW_THREADS + } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (pid < 0) + return (!async_err) ? posix_error() : NULL; + + return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status)); +} +#endif /* HAVE_WAIT */ + +#if defined(__linux__) && defined(__NR_pidfd_open) +/*[clinic input] +os.pidfd_open + pid: pid_t + flags: unsigned_int = 0 + +Return a file descriptor referring to the process *pid*. + +The descriptor can be used to perform process management without races and +signals. +[clinic start generated code]*/ + +static PyObject * +os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags) +/*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/ +{ + int fd = syscall(__NR_pidfd_open, pid, flags); + if (fd < 0) { + return posix_error(); + } + return PyLong_FromLong(fd); +} +#endif + + +#ifdef HAVE_SETNS +/*[clinic input] +os.setns + fd: fildes + A file descriptor to a namespace. + nstype: int = 0 + Type of namespace. + +Move the calling thread into different namespaces. +[clinic start generated code]*/ + +static PyObject * +os_setns_impl(PyObject *module, int fd, int nstype) +/*[clinic end generated code: output=5dbd055bfb66ecd0 input=42787871226bf3ee]*/ +{ + int res; + + Py_BEGIN_ALLOW_THREADS + res = setns(fd, nstype); + Py_END_ALLOW_THREADS + + if (res != 0) { + return posix_error(); + } + + Py_RETURN_NONE; +} +#endif + + +#ifdef HAVE_UNSHARE +/*[clinic input] +os.unshare + flags: int + Namespaces to be unshared. + +Disassociate parts of a process (or thread) execution context. +[clinic start generated code]*/ + +static PyObject * +os_unshare_impl(PyObject *module, int flags) +/*[clinic end generated code: output=1b3177906dd237ee input=9e065db3232b8b1b]*/ +{ + int res; + + Py_BEGIN_ALLOW_THREADS + res = unshare(flags); + Py_END_ALLOW_THREADS + + if (res != 0) { + return posix_error(); + } + + Py_RETURN_NONE; +} +#endif + + +#if defined(HAVE_READLINK) || defined(MS_WINDOWS) +/*[clinic input] +os.readlink + + path: path_t + * + dir_fd: dir_fd(requires='readlinkat') = None + +Return a string representing the path to which the symbolic link points. + +If dir_fd is not None, it should be a file descriptor open to a directory, +and path should be relative; path will then be relative to that directory. + +dir_fd may not be implemented on your platform. If it is unavailable, +using it will raise a NotImplementedError. +[clinic start generated code]*/ + +static PyObject * +os_readlink_impl(PyObject *module, path_t *path, int dir_fd) +/*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/ +{ +#if defined(HAVE_READLINK) + char buffer[MAXPATHLEN+1]; + ssize_t length; +#ifdef HAVE_READLINKAT + int readlinkat_unavailable = 0; +#endif + + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_READLINKAT + if (dir_fd != DEFAULT_DIR_FD) { + if (HAVE_READLINKAT_RUNTIME) { + length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN); + } else { + readlinkat_unavailable = 1; + } + } else +#endif + length = readlink(path->narrow, buffer, MAXPATHLEN); + Py_END_ALLOW_THREADS + +#ifdef HAVE_READLINKAT + if (readlinkat_unavailable) { + argument_unavailable_error(NULL, "dir_fd"); + return NULL; + } +#endif + + if (length < 0) { + return path_error(path); + } + buffer[length] = '\0'; + + if (PyUnicode_Check(path->object)) + return PyUnicode_DecodeFSDefaultAndSize(buffer, length); + else + return PyBytes_FromStringAndSize(buffer, length); +#elif defined(MS_WINDOWS) + DWORD n_bytes_returned; + DWORD io_result = 0; + HANDLE reparse_point_handle; + char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer; + PyObject *result = NULL; + + /* First get a handle to the reparse point */ + Py_BEGIN_ALLOW_THREADS + reparse_point_handle = CreateFileW( + path->wide, + 0, + 0, + 0, + OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, + 0); + if (reparse_point_handle != INVALID_HANDLE_VALUE) { + /* New call DeviceIoControl to read the reparse point */ + io_result = DeviceIoControl( + reparse_point_handle, + FSCTL_GET_REPARSE_POINT, + 0, 0, /* in buffer */ + target_buffer, sizeof(target_buffer), + &n_bytes_returned, + 0 /* we're not using OVERLAPPED_IO */ + ); + CloseHandle(reparse_point_handle); + } + Py_END_ALLOW_THREADS + + if (io_result == 0) { + return path_error(path); + } + + wchar_t *name = NULL; + Py_ssize_t nameLen = 0; + if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK) + { + name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer + + rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset); + nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t); + } + else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) + { + name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer + + rdb->MountPointReparseBuffer.SubstituteNameOffset); + nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t); + } + else + { + PyErr_SetString(PyExc_ValueError, "not a symbolic link"); + } + if (name) { + if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) { + /* Our buffer is mutable, so this is okay */ + name[1] = L'\\'; + } + result = PyUnicode_FromWideChar(name, nameLen); + if (result && path->narrow) { + Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); + } + } + return result; +#endif +} +#endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */ + +#if defined(MS_WINDOWS) + +/* Remove the last portion of the path - return 0 on success */ +static int +_dirnameW(WCHAR *path) +{ + WCHAR *ptr; + size_t length = wcsnlen_s(path, MAX_PATH); + if (length == MAX_PATH) { + return -1; + } + + /* walk the path from the end until a backslash is encountered */ + for(ptr = path + length; ptr != path; ptr--) { + if (*ptr == L'\\' || *ptr == L'/') { + break; + } + } + *ptr = 0; + return 0; +} + +#endif + +#ifdef HAVE_SYMLINK + +#if defined(MS_WINDOWS) + +/* Is this path absolute? */ +static int +_is_absW(const WCHAR *path) +{ + return path[0] == L'\\' || path[0] == L'/' || + (path[0] && path[1] == L':'); +} + +/* join root and rest with a backslash - return 0 on success */ +static int +_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest) +{ + if (_is_absW(rest)) { + return wcscpy_s(dest_path, MAX_PATH, rest); + } + + if (wcscpy_s(dest_path, MAX_PATH, root)) { + return -1; + } + + if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) { + return -1; + } + + return wcscat_s(dest_path, MAX_PATH, rest); +} + +/* Return True if the path at src relative to dest is a directory */ +static int +_check_dirW(LPCWSTR src, LPCWSTR dest) +{ + WIN32_FILE_ATTRIBUTE_DATA src_info; + WCHAR dest_parent[MAX_PATH]; + WCHAR src_resolved[MAX_PATH] = L""; + + /* dest_parent = os.path.dirname(dest) */ + if (wcscpy_s(dest_parent, MAX_PATH, dest) || + _dirnameW(dest_parent)) { + return 0; + } + /* src_resolved = os.path.join(dest_parent, src) */ + if (_joinW(src_resolved, dest_parent, src)) { + return 0; + } + return ( + GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info) + && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY + ); +} +#endif + + +/*[clinic input] +os.symlink + src: path_t + dst: path_t + target_is_directory: bool = False + * + dir_fd: dir_fd(requires='symlinkat')=None + +# "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\ + +Create a symbolic link pointing to src named dst. + +target_is_directory is required on Windows if the target is to be + interpreted as a directory. (On Windows, symlink requires + Windows 6.0 or greater, and raises a NotImplementedError otherwise.) + target_is_directory is ignored on non-Windows platforms. + +If dir_fd is not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that directory. +dir_fd may not be implemented on your platform. + If it is unavailable, using it will raise a NotImplementedError. + +[clinic start generated code]*/ + +static PyObject * +os_symlink_impl(PyObject *module, path_t *src, path_t *dst, + int target_is_directory, int dir_fd) +/*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/ +{ +#ifdef MS_WINDOWS + DWORD result; + DWORD flags = 0; + + /* Assumed true, set to false if detected to not be available. */ + static int windows_has_symlink_unprivileged_flag = TRUE; +#else + int result; +#ifdef HAVE_SYMLINKAT + int symlinkat_unavailable = 0; +#endif +#endif + + if (PySys_Audit("os.symlink", "OOi", src->object, dst->object, + dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { + return NULL; + } + +#ifdef MS_WINDOWS + + if (windows_has_symlink_unprivileged_flag) { + /* Allow non-admin symlinks if system allows it. */ + flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE; + } + + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + /* if src is a directory, ensure flags==1 (target_is_directory bit) */ + if (target_is_directory || _check_dirW(src->wide, dst->wide)) { + flags |= SYMBOLIC_LINK_FLAG_DIRECTORY; + } + + result = CreateSymbolicLinkW(dst->wide, src->wide, flags); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + + if (windows_has_symlink_unprivileged_flag && !result && + ERROR_INVALID_PARAMETER == GetLastError()) { + + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + /* This error might be caused by + SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported. + Try again, and update windows_has_symlink_unprivileged_flag if we + are successful this time. + + NOTE: There is a risk of a race condition here if there are other + conditions than the flag causing ERROR_INVALID_PARAMETER, and + another process (or thread) changes that condition in between our + calls to CreateSymbolicLink. + */ + flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE); + result = CreateSymbolicLinkW(dst->wide, src->wide, flags); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + + if (result || ERROR_INVALID_PARAMETER != GetLastError()) { + windows_has_symlink_unprivileged_flag = FALSE; + } + } + + if (!result) + return path_error2(src, dst); + +#else + + if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { + PyErr_SetString(PyExc_ValueError, + "symlink: src and dst must be the same type"); + return NULL; + } + + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_SYMLINKAT + if (dir_fd != DEFAULT_DIR_FD) { + if (HAVE_SYMLINKAT_RUNTIME) { + result = symlinkat(src->narrow, dir_fd, dst->narrow); + } else { + symlinkat_unavailable = 1; + } + } else +#endif + result = symlink(src->narrow, dst->narrow); + Py_END_ALLOW_THREADS + +#ifdef HAVE_SYMLINKAT + if (symlinkat_unavailable) { + argument_unavailable_error(NULL, "dir_fd"); + return NULL; + } +#endif + + if (result) + return path_error2(src, dst); +#endif + + Py_RETURN_NONE; +} +#endif /* HAVE_SYMLINK */ + + + + +static PyStructSequence_Field times_result_fields[] = { + {"user", "user time"}, + {"system", "system time"}, + {"children_user", "user time of children"}, + {"children_system", "system time of children"}, + {"elapsed", "elapsed time since an arbitrary point in the past"}, + {NULL} +}; + +PyDoc_STRVAR(times_result__doc__, +"times_result: Result from os.times().\n\n\ +This object may be accessed either as a tuple of\n\ + (user, system, children_user, children_system, elapsed),\n\ +or via the attributes user, system, children_user, children_system,\n\ +and elapsed.\n\ +\n\ +See os.times for more information."); + +static PyStructSequence_Desc times_result_desc = { + "times_result", /* name */ + times_result__doc__, /* doc */ + times_result_fields, + 5 +}; + +#ifdef MS_WINDOWS +#define HAVE_TIMES /* mandatory, for the method table */ +#endif + +#ifdef HAVE_TIMES + +static PyObject * +build_times_result(PyObject *module, double user, double system, + double children_user, double children_system, + double elapsed) +{ + PyObject *TimesResultType = get_posix_state(module)->TimesResultType; + PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType); + if (value == NULL) + return NULL; + +#define SET(i, field) \ + { \ + PyObject *o = PyFloat_FromDouble(field); \ + if (!o) { \ + Py_DECREF(value); \ + return NULL; \ + } \ + PyStructSequence_SET_ITEM(value, i, o); \ + } \ + + SET(0, user); + SET(1, system); + SET(2, children_user); + SET(3, children_system); + SET(4, elapsed); + +#undef SET + + return value; +} + + +#ifndef MS_WINDOWS +#define NEED_TICKS_PER_SECOND +static long ticks_per_second = -1; +#endif /* MS_WINDOWS */ + +/*[clinic input] +os.times + +Return a collection containing process timing information. + +The object returned behaves like a named tuple with these fields: + (utime, stime, cutime, cstime, elapsed_time) +All fields are floating point numbers. +[clinic start generated code]*/ + +static PyObject * +os_times_impl(PyObject *module) +/*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/ +#ifdef MS_WINDOWS +{ + FILETIME create, exit, kernel, user; + HANDLE hProc; + hProc = GetCurrentProcess(); + GetProcessTimes(hProc, &create, &exit, &kernel, &user); + /* The fields of a FILETIME structure are the hi and lo part + of a 64-bit value expressed in 100 nanosecond units. + 1e7 is one second in such units; 1e-7 the inverse. + 429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7. + */ + return build_times_result(module, + (double)(user.dwHighDateTime*429.4967296 + + user.dwLowDateTime*1e-7), + (double)(kernel.dwHighDateTime*429.4967296 + + kernel.dwLowDateTime*1e-7), + (double)0, + (double)0, + (double)0); +} +#else /* MS_WINDOWS */ +{ + + + struct tms t; + clock_t c; + errno = 0; + c = times(&t); + if (c == (clock_t) -1) + return posix_error(); + return build_times_result(module, + (double)t.tms_utime / ticks_per_second, + (double)t.tms_stime / ticks_per_second, + (double)t.tms_cutime / ticks_per_second, + (double)t.tms_cstime / ticks_per_second, + (double)c / ticks_per_second); +} +#endif /* MS_WINDOWS */ +#endif /* HAVE_TIMES */ + + +#ifdef HAVE_GETSID +/*[clinic input] +os.getsid + + pid: pid_t + / + +Call the system call getsid(pid) and return the result. +[clinic start generated code]*/ + +static PyObject * +os_getsid_impl(PyObject *module, pid_t pid) +/*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/ +{ + int sid; + sid = getsid(pid); + if (sid < 0) + return posix_error(); + return PyLong_FromLong((long)sid); +} +#endif /* HAVE_GETSID */ + + +#ifdef HAVE_SETSID +/*[clinic input] +os.setsid + +Call the system call setsid(). +[clinic start generated code]*/ + +static PyObject * +os_setsid_impl(PyObject *module) +/*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/ +{ + if (setsid() < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETSID */ + + +#ifdef HAVE_SETPGID +/*[clinic input] +os.setpgid + + pid: pid_t + pgrp: pid_t + / + +Call the system call setpgid(pid, pgrp). +[clinic start generated code]*/ + +static PyObject * +os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp) +/*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/ +{ + if (setpgid(pid, pgrp) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETPGID */ + + +#ifdef HAVE_TCGETPGRP +/*[clinic input] +os.tcgetpgrp + + fd: int + / + +Return the process group associated with the terminal specified by fd. +[clinic start generated code]*/ + +static PyObject * +os_tcgetpgrp_impl(PyObject *module, int fd) +/*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/ +{ + pid_t pgid = tcgetpgrp(fd); + if (pgid < 0) + return posix_error(); + return PyLong_FromPid(pgid); +} +#endif /* HAVE_TCGETPGRP */ + + +#ifdef HAVE_TCSETPGRP +/*[clinic input] +os.tcsetpgrp + + fd: int + pgid: pid_t + / + +Set the process group associated with the terminal specified by fd. +[clinic start generated code]*/ + +static PyObject * +os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid) +/*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/ +{ + if (tcsetpgrp(fd, pgid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_TCSETPGRP */ + +/* Functions acting on file descriptors */ + +#ifdef O_CLOEXEC +extern int _Py_open_cloexec_works; +#endif + + +/*[clinic input] +os.open -> int + path: path_t + flags: int + mode: int = 0o777 + * + dir_fd: dir_fd(requires='openat') = None + +# "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\ + +Open a file for low level IO. Returns a file descriptor (integer). + +If dir_fd is not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that directory. +dir_fd may not be implemented on your platform. + If it is unavailable, using it will raise a NotImplementedError. +[clinic start generated code]*/ + +static int +os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd) +/*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/ +{ + int fd; + int async_err = 0; +#ifdef HAVE_OPENAT + int openat_unavailable = 0; +#endif + +#ifdef O_CLOEXEC + int *atomic_flag_works = &_Py_open_cloexec_works; +#elif !defined(MS_WINDOWS) + int *atomic_flag_works = NULL; +#endif + +#ifdef MS_WINDOWS + flags |= O_NOINHERIT; +#elif defined(O_CLOEXEC) + flags |= O_CLOEXEC; +#endif + + if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) { + return -1; + } + + _Py_BEGIN_SUPPRESS_IPH + do { + Py_BEGIN_ALLOW_THREADS +#ifdef MS_WINDOWS + fd = _wopen(path->wide, flags, mode); +#else +#ifdef HAVE_OPENAT + if (dir_fd != DEFAULT_DIR_FD) { + if (HAVE_OPENAT_RUNTIME) { + fd = openat(dir_fd, path->narrow, flags, mode); + + } else { + openat_unavailable = 1; + fd = -1; + } + } else +#endif /* HAVE_OPENAT */ + fd = open(path->narrow, flags, mode); +#endif /* !MS_WINDOWS */ + Py_END_ALLOW_THREADS + } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + _Py_END_SUPPRESS_IPH + +#ifdef HAVE_OPENAT + if (openat_unavailable) { + argument_unavailable_error(NULL, "dir_fd"); + return -1; + } +#endif + + if (fd < 0) { + if (!async_err) + PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object); + return -1; + } + +#ifndef MS_WINDOWS + if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) { + close(fd); + return -1; + } +#endif + + return fd; +} + + +/*[clinic input] +os.close + + fd: int + +Close a file descriptor. +[clinic start generated code]*/ + +static PyObject * +os_close_impl(PyObject *module, int fd) +/*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/ +{ + int res; + /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/ + * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html + * for more details. + */ + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + res = close(fd); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error(); + Py_RETURN_NONE; +} + +/*[clinic input] +os.closerange + + fd_low: int + fd_high: int + / + +Closes all file descriptors in [fd_low, fd_high), ignoring errors. +[clinic start generated code]*/ + +static PyObject * +os_closerange_impl(PyObject *module, int fd_low, int fd_high) +/*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/ +{ + Py_BEGIN_ALLOW_THREADS + _Py_closerange(fd_low, fd_high - 1); + Py_END_ALLOW_THREADS + Py_RETURN_NONE; +} + + +/*[clinic input] +os.dup -> int + + fd: int + / + +Return a duplicate of a file descriptor. +[clinic start generated code]*/ + +static int +os_dup_impl(PyObject *module, int fd) +/*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/ +{ + return _Py_dup(fd); +} + +// dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS(). +// dup2.c provides working dup2() if and only if F_DUPFD is available. +#if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS)) +/*[clinic input] +os.dup2 -> int + fd: int + fd2: int + inheritable: bool=True + +Duplicate file descriptor. +[clinic start generated code]*/ + +static int +os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable) +/*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/ +{ + int res = 0; +#if defined(HAVE_DUP3) && \ + !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)) + /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */ + static int dup3_works = -1; +#endif + + if (fd < 0 || fd2 < 0) { + posix_error(); + return -1; + } + + /* dup2() can fail with EINTR if the target FD is already open, because it + * then has to be closed. See os_close_impl() for why we don't handle EINTR + * upon close(), and therefore below. + */ +#ifdef MS_WINDOWS + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + res = dup2(fd, fd2); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + if (res < 0) { + posix_error(); + return -1; + } + res = fd2; // msvcrt dup2 returns 0 on success. + + /* Character files like console cannot be make non-inheritable */ + if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) { + close(fd2); + return -1; + } + +#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC) + Py_BEGIN_ALLOW_THREADS + if (!inheritable) + res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2); + else + res = dup2(fd, fd2); + Py_END_ALLOW_THREADS + if (res < 0) { + posix_error(); + return -1; + } + +#else + +#ifdef HAVE_DUP3 + if (!inheritable && dup3_works != 0) { + Py_BEGIN_ALLOW_THREADS + res = dup3(fd, fd2, O_CLOEXEC); + Py_END_ALLOW_THREADS + if (res < 0) { + if (dup3_works == -1) + dup3_works = (errno != ENOSYS); + if (dup3_works) { + posix_error(); + return -1; + } + } + } + + if (inheritable || dup3_works == 0) + { +#endif + Py_BEGIN_ALLOW_THREADS + res = dup2(fd, fd2); + Py_END_ALLOW_THREADS + if (res < 0) { + posix_error(); + return -1; + } + + if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) { + close(fd2); + return -1; + } +#ifdef HAVE_DUP3 + } +#endif + +#endif + + return res; +} +#endif + + +#ifdef HAVE_LOCKF +/*[clinic input] +os.lockf + + fd: int + An open file descriptor. + command: int + One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST. + length: Py_off_t + The number of bytes to lock, starting at the current position. + / + +Apply, test or remove a POSIX lock on an open file descriptor. + +[clinic start generated code]*/ + +static PyObject * +os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length) +/*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/ +{ + int res; + + if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + res = lockf(fd, command, length); + Py_END_ALLOW_THREADS + + if (res < 0) + return posix_error(); + + Py_RETURN_NONE; +} +#endif /* HAVE_LOCKF */ + + +/*[clinic input] +os.lseek -> Py_off_t + + fd: int + position: Py_off_t + how: int + / + +Set the position of a file descriptor. Return the new position. + +Return the new cursor position in number of bytes +relative to the beginning of the file. +[clinic start generated code]*/ + +static Py_off_t +os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how) +/*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/ +{ + Py_off_t result; + +#ifdef SEEK_SET + /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ + switch (how) { + case 0: how = SEEK_SET; break; + case 1: how = SEEK_CUR; break; + case 2: how = SEEK_END; break; + } +#endif /* SEEK_END */ + + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH +#ifdef MS_WINDOWS + result = _lseeki64(fd, position, how); +#else + result = lseek(fd, position, how); +#endif + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + if (result < 0) + posix_error(); + + return result; +} + + +/*[clinic input] +os.read + fd: int + length: Py_ssize_t + / + +Read from a file descriptor. Returns a bytes object. +[clinic start generated code]*/ + +static PyObject * +os_read_impl(PyObject *module, int fd, Py_ssize_t length) +/*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/ +{ + Py_ssize_t n; + PyObject *buffer; + + if (length < 0) { + errno = EINVAL; + return posix_error(); + } + + length = Py_MIN(length, _PY_READ_MAX); + + buffer = PyBytes_FromStringAndSize((char *)NULL, length); + if (buffer == NULL) + return NULL; + + n = _Py_read(fd, PyBytes_AS_STRING(buffer), length); + if (n == -1) { + Py_DECREF(buffer); + return NULL; + } + + if (n != length) + _PyBytes_Resize(&buffer, n); + + return buffer; +} + +#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \ + || defined(__APPLE__))) \ + || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \ + || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2) +static int +iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type) +{ + Py_ssize_t i, j; + + *iov = PyMem_New(struct iovec, cnt); + if (*iov == NULL) { + PyErr_NoMemory(); + return -1; + } + + *buf = PyMem_New(Py_buffer, cnt); + if (*buf == NULL) { + PyMem_Free(*iov); + PyErr_NoMemory(); + return -1; + } + + for (i = 0; i < cnt; i++) { + PyObject *item = PySequence_GetItem(seq, i); + if (item == NULL) + goto fail; + if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) { + Py_DECREF(item); + goto fail; + } + Py_DECREF(item); + (*iov)[i].iov_base = (*buf)[i].buf; + (*iov)[i].iov_len = (*buf)[i].len; + } + return 0; + +fail: + PyMem_Free(*iov); + for (j = 0; j < i; j++) { + PyBuffer_Release(&(*buf)[j]); + } + PyMem_Free(*buf); + return -1; +} + +static void +iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt) +{ + int i; + PyMem_Free(iov); + for (i = 0; i < cnt; i++) { + PyBuffer_Release(&buf[i]); + } + PyMem_Free(buf); +} +#endif + + +#ifdef HAVE_READV +/*[clinic input] +os.readv -> Py_ssize_t + + fd: int + buffers: object + / + +Read from a file descriptor fd into an iterable of buffers. + +The buffers should be mutable buffers accepting bytes. +readv will transfer data into each buffer until it is full +and then move on to the next buffer in the sequence to hold +the rest of the data. + +readv returns the total number of bytes read, +which may be less than the total capacity of all the buffers. +[clinic start generated code]*/ + +static Py_ssize_t +os_readv_impl(PyObject *module, int fd, PyObject *buffers) +/*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/ +{ + Py_ssize_t cnt, n; + int async_err = 0; + struct iovec *iov; + Py_buffer *buf; + + if (!PySequence_Check(buffers)) { + PyErr_SetString(PyExc_TypeError, + "readv() arg 2 must be a sequence"); + return -1; + } + + cnt = PySequence_Size(buffers); + if (cnt < 0) + return -1; + + if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) + return -1; + + do { + Py_BEGIN_ALLOW_THREADS + n = readv(fd, iov, cnt); + Py_END_ALLOW_THREADS + } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + + iov_cleanup(iov, buf, cnt); + if (n < 0) { + if (!async_err) + posix_error(); + return -1; + } + + return n; +} +#endif /* HAVE_READV */ + + +#ifdef HAVE_PREAD +/*[clinic input] +os.pread + + fd: int + length: Py_ssize_t + offset: Py_off_t + / + +Read a number of bytes from a file descriptor starting at a particular offset. + +Read length bytes from file descriptor fd, starting at offset bytes from +the beginning of the file. The file offset remains unchanged. +[clinic start generated code]*/ + +static PyObject * +os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset) +/*[clinic end generated code: output=3f875c1eef82e32f input=85cb4a5589627144]*/ +{ + Py_ssize_t n; + int async_err = 0; + PyObject *buffer; + + if (length < 0) { + errno = EINVAL; + return posix_error(); + } + buffer = PyBytes_FromStringAndSize((char *)NULL, length); + if (buffer == NULL) + return NULL; + + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + n = pread(fd, PyBytes_AS_STRING(buffer), length, offset); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + + if (n < 0) { + Py_DECREF(buffer); + return (!async_err) ? posix_error() : NULL; + } + if (n != length) + _PyBytes_Resize(&buffer, n); + return buffer; +} +#endif /* HAVE_PREAD */ + +#if defined(HAVE_PREADV) || defined (HAVE_PREADV2) +/*[clinic input] +os.preadv -> Py_ssize_t + + fd: int + buffers: object + offset: Py_off_t + flags: int = 0 + / + +Reads from a file descriptor into a number of mutable bytes-like objects. + +Combines the functionality of readv() and pread(). As readv(), it will +transfer data into each buffer until it is full and then move on to the next +buffer in the sequence to hold the rest of the data. Its fourth argument, +specifies the file offset at which the input operation is to be performed. It +will return the total number of bytes read (which can be less than the total +capacity of all the objects). + +The flags argument contains a bitwise OR of zero or more of the following flags: + +- RWF_HIPRI +- RWF_NOWAIT + +Using non-zero flags requires Linux 4.6 or newer. +[clinic start generated code]*/ + +static Py_ssize_t +os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, + int flags) +/*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/ +{ + Py_ssize_t cnt, n; + int async_err = 0; + struct iovec *iov; + Py_buffer *buf; + + if (!PySequence_Check(buffers)) { + PyErr_SetString(PyExc_TypeError, + "preadv2() arg 2 must be a sequence"); + return -1; + } + + cnt = PySequence_Size(buffers); + if (cnt < 0) { + return -1; + } + +#ifndef HAVE_PREADV2 + if(flags != 0) { + argument_unavailable_error("preadv2", "flags"); + return -1; + } +#endif + + if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) { + return -1; + } +#ifdef HAVE_PREADV2 + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + n = preadv2(fd, iov, cnt, offset, flags); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); +#else + do { +#ifdef __APPLE__ +/* This entire function will be removed from the module dict when the API + * is not available. + */ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +#pragma clang diagnostic ignored "-Wunguarded-availability-new" +#endif + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + n = preadv(fd, iov, cnt, offset); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + +#ifdef __APPLE__ +#pragma clang diagnostic pop +#endif + +#endif + + iov_cleanup(iov, buf, cnt); + if (n < 0) { + if (!async_err) { + posix_error(); + } + return -1; + } + + return n; +} +#endif /* HAVE_PREADV */ + + +/*[clinic input] +os.write -> Py_ssize_t + + fd: int + data: Py_buffer + / + +Write a bytes object to a file descriptor. +[clinic start generated code]*/ + +static Py_ssize_t +os_write_impl(PyObject *module, int fd, Py_buffer *data) +/*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/ +{ + return _Py_write(fd, data->buf, data->len); +} + +#ifdef HAVE_SENDFILE +#ifdef __APPLE__ +/*[clinic input] +os.sendfile + + out_fd: int + in_fd: int + offset: Py_off_t + count as sbytes: Py_off_t + headers: object(c_default="NULL") = () + trailers: object(c_default="NULL") = () + flags: int = 0 + +Copy count bytes from file descriptor in_fd to file descriptor out_fd. +[clinic start generated code]*/ + +static PyObject * +os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset, + Py_off_t sbytes, PyObject *headers, PyObject *trailers, + int flags) +/*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/ +#elif defined(__FreeBSD__) || defined(__DragonFly__) +/*[clinic input] +os.sendfile + + out_fd: int + in_fd: int + offset: Py_off_t + count: Py_ssize_t + headers: object(c_default="NULL") = () + trailers: object(c_default="NULL") = () + flags: int = 0 + +Copy count bytes from file descriptor in_fd to file descriptor out_fd. +[clinic start generated code]*/ + +static PyObject * +os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset, + Py_ssize_t count, PyObject *headers, PyObject *trailers, + int flags) +/*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/ +#else +/*[clinic input] +os.sendfile + + out_fd: int + in_fd: int + offset as offobj: object + count: Py_ssize_t + +Copy count bytes from file descriptor in_fd to file descriptor out_fd. +[clinic start generated code]*/ + +static PyObject * +os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj, + Py_ssize_t count) +/*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/ +#endif +{ + Py_ssize_t ret; + int async_err = 0; + +#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) +#ifndef __APPLE__ + off_t sbytes; +#endif + Py_buffer *hbuf, *tbuf; + struct sf_hdtr sf; + + sf.headers = NULL; + sf.trailers = NULL; + + if (headers != NULL) { + if (!PySequence_Check(headers)) { + PyErr_SetString(PyExc_TypeError, + "sendfile() headers must be a sequence"); + return NULL; + } else { + Py_ssize_t i = PySequence_Size(headers); + if (i < 0) + return NULL; + if (i > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "sendfile() header is too large"); + return NULL; + } + if (i > 0) { + sf.hdr_cnt = (int)i; + if (iov_setup(&(sf.headers), &hbuf, + headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0) + return NULL; +#ifdef __APPLE__ + for (i = 0; i < sf.hdr_cnt; i++) { + Py_ssize_t blen = sf.headers[i].iov_len; +# define OFF_T_MAX 0x7fffffffffffffff + if (sbytes >= OFF_T_MAX - blen) { + PyErr_SetString(PyExc_OverflowError, + "sendfile() header is too large"); + return NULL; + } + sbytes += blen; + } +#endif + } + } + } + if (trailers != NULL) { + if (!PySequence_Check(trailers)) { + PyErr_SetString(PyExc_TypeError, + "sendfile() trailers must be a sequence"); + return NULL; + } else { + Py_ssize_t i = PySequence_Size(trailers); + if (i < 0) + return NULL; + if (i > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "sendfile() trailer is too large"); + return NULL; + } + if (i > 0) { + sf.trl_cnt = (int)i; + if (iov_setup(&(sf.trailers), &tbuf, + trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0) + return NULL; + } + } + } + + _Py_BEGIN_SUPPRESS_IPH + do { + Py_BEGIN_ALLOW_THREADS +#ifdef __APPLE__ + ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags); +#else + ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags); +#endif + Py_END_ALLOW_THREADS + } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + _Py_END_SUPPRESS_IPH + + if (sf.headers != NULL) + iov_cleanup(sf.headers, hbuf, sf.hdr_cnt); + if (sf.trailers != NULL) + iov_cleanup(sf.trailers, tbuf, sf.trl_cnt); + + if (ret < 0) { + if ((errno == EAGAIN) || (errno == EBUSY)) { + if (sbytes != 0) { + // some data has been sent + goto done; + } + else { + // no data has been sent; upper application is supposed + // to retry on EAGAIN or EBUSY + return posix_error(); + } + } + return (!async_err) ? posix_error() : NULL; + } + goto done; + +done: + #if !defined(HAVE_LARGEFILE_SUPPORT) + return Py_BuildValue("l", sbytes); + #else + return Py_BuildValue("L", sbytes); + #endif + +#else +#ifdef __linux__ + if (offobj == Py_None) { + do { + Py_BEGIN_ALLOW_THREADS + ret = sendfile(out_fd, in_fd, NULL, count); + Py_END_ALLOW_THREADS + } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (ret < 0) + return (!async_err) ? posix_error() : NULL; + return Py_BuildValue("n", ret); + } +#endif + off_t offset; + if (!Py_off_t_converter(offobj, &offset)) + return NULL; + +#if defined(__sun) && defined(__SVR4) + // On Solaris, sendfile raises EINVAL rather than returning 0 + // when the offset is equal or bigger than the in_fd size. + struct stat st; + + do { + Py_BEGIN_ALLOW_THREADS + ret = fstat(in_fd, &st); + Py_END_ALLOW_THREADS + } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (ret < 0) + return (!async_err) ? posix_error() : NULL; + + if (offset >= st.st_size) { + return Py_BuildValue("i", 0); + } + + // On illumos specifically sendfile() may perform a partial write but + // return -1/an error (in one confirmed case the destination socket + // had a 5 second timeout set and errno was EAGAIN) and it's on the client + // code to check if the offset parameter was modified by sendfile(). + // + // We need this variable to track said change. + off_t original_offset = offset; +#endif + + do { + Py_BEGIN_ALLOW_THREADS + ret = sendfile(out_fd, in_fd, &offset, count); +#if defined(__sun) && defined(__SVR4) + // This handles illumos-specific sendfile() partial write behavior, + // see a comment above for more details. + if (ret < 0 && offset != original_offset) { + ret = offset - original_offset; + } +#endif + Py_END_ALLOW_THREADS + } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (ret < 0) + return (!async_err) ? posix_error() : NULL; + return Py_BuildValue("n", ret); +#endif +} +#endif /* HAVE_SENDFILE */ + + +#if defined(__APPLE__) +/*[clinic input] +os._fcopyfile + + in_fd: int + out_fd: int + flags: int + / + +Efficiently copy content or metadata of 2 regular file descriptors (macOS). +[clinic start generated code]*/ + +static PyObject * +os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags) +/*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/ +{ + int ret; + + Py_BEGIN_ALLOW_THREADS + ret = fcopyfile(in_fd, out_fd, NULL, flags); + Py_END_ALLOW_THREADS + if (ret < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif + + +/*[clinic input] +os.fstat + + fd : int + +Perform a stat system call on the given file descriptor. + +Like stat(), but for an open file descriptor. +Equivalent to os.stat(fd). +[clinic start generated code]*/ + +static PyObject * +os_fstat_impl(PyObject *module, int fd) +/*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/ +{ + STRUCT_STAT st; + int res; + int async_err = 0; + + do { + Py_BEGIN_ALLOW_THREADS + res = FSTAT(fd, &st); + Py_END_ALLOW_THREADS + } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (res != 0) { +#ifdef MS_WINDOWS + return PyErr_SetFromWindowsErr(0); +#else + return (!async_err) ? posix_error() : NULL; +#endif + } + + return _pystat_fromstructstat(module, &st); +} + + +/*[clinic input] +os.isatty -> bool + fd: int + / + +Return True if the fd is connected to a terminal. + +Return True if the file descriptor is an open file descriptor +connected to the slave end of a terminal. +[clinic start generated code]*/ + +static int +os_isatty_impl(PyObject *module, int fd) +/*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/ +{ + int return_value; + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + return_value = isatty(fd); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + return return_value; +} + + +#ifdef HAVE_PIPE +/*[clinic input] +os.pipe + +Create a pipe. + +Returns a tuple of two file descriptors: + (read_fd, write_fd) +[clinic start generated code]*/ + +static PyObject * +os_pipe_impl(PyObject *module) +/*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/ +{ + int fds[2]; +#ifdef MS_WINDOWS + HANDLE read, write; + SECURITY_ATTRIBUTES attr; + BOOL ok; +#else + int res; +#endif + +#ifdef MS_WINDOWS + attr.nLength = sizeof(attr); + attr.lpSecurityDescriptor = NULL; + attr.bInheritHandle = FALSE; + + Py_BEGIN_ALLOW_THREADS + ok = CreatePipe(&read, &write, &attr, 0); + if (ok) { + fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY); + fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY); + if (fds[0] == -1 || fds[1] == -1) { + CloseHandle(read); + CloseHandle(write); + ok = 0; + } + } + Py_END_ALLOW_THREADS + + if (!ok) + return PyErr_SetFromWindowsErr(0); +#else + +#ifdef HAVE_PIPE2 + Py_BEGIN_ALLOW_THREADS + res = pipe2(fds, O_CLOEXEC); + Py_END_ALLOW_THREADS + + if (res != 0 && errno == ENOSYS) + { +#endif + Py_BEGIN_ALLOW_THREADS + res = pipe(fds); + Py_END_ALLOW_THREADS + + if (res == 0) { + if (_Py_set_inheritable(fds[0], 0, NULL) < 0) { + close(fds[0]); + close(fds[1]); + return NULL; + } + if (_Py_set_inheritable(fds[1], 0, NULL) < 0) { + close(fds[0]); + close(fds[1]); + return NULL; + } + } +#ifdef HAVE_PIPE2 + } +#endif + + if (res != 0) + return PyErr_SetFromErrno(PyExc_OSError); +#endif /* !MS_WINDOWS */ + return Py_BuildValue("(ii)", fds[0], fds[1]); +} +#endif /* HAVE_PIPE */ + + +#ifdef HAVE_PIPE2 +/*[clinic input] +os.pipe2 + + flags: int + / + +Create a pipe with flags set atomically. + +Returns a tuple of two file descriptors: + (read_fd, write_fd) + +flags can be constructed by ORing together one or more of these values: +O_NONBLOCK, O_CLOEXEC. +[clinic start generated code]*/ + +static PyObject * +os_pipe2_impl(PyObject *module, int flags) +/*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/ +{ + int fds[2]; + int res; + + res = pipe2(fds, flags); + if (res != 0) + return posix_error(); + return Py_BuildValue("(ii)", fds[0], fds[1]); +} +#endif /* HAVE_PIPE2 */ + + +#ifdef HAVE_WRITEV +/*[clinic input] +os.writev -> Py_ssize_t + fd: int + buffers: object + / + +Iterate over buffers, and write the contents of each to a file descriptor. + +Returns the total number of bytes written. +buffers must be a sequence of bytes-like objects. +[clinic start generated code]*/ + +static Py_ssize_t +os_writev_impl(PyObject *module, int fd, PyObject *buffers) +/*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/ +{ + Py_ssize_t cnt; + Py_ssize_t result; + int async_err = 0; + struct iovec *iov; + Py_buffer *buf; + + if (!PySequence_Check(buffers)) { + PyErr_SetString(PyExc_TypeError, + "writev() arg 2 must be a sequence"); + return -1; + } + cnt = PySequence_Size(buffers); + if (cnt < 0) + return -1; + + if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { + return -1; + } + + do { + Py_BEGIN_ALLOW_THREADS + result = writev(fd, iov, cnt); + Py_END_ALLOW_THREADS + } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + + iov_cleanup(iov, buf, cnt); + if (result < 0 && !async_err) + posix_error(); + + return result; +} +#endif /* HAVE_WRITEV */ + + +#ifdef HAVE_PWRITE +/*[clinic input] +os.pwrite -> Py_ssize_t + + fd: int + buffer: Py_buffer + offset: Py_off_t + / + +Write bytes to a file descriptor starting at a particular offset. + +Write buffer to fd, starting at offset bytes from the beginning of +the file. Returns the number of bytes writte. Does not change the +current file offset. +[clinic start generated code]*/ + +static Py_ssize_t +os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset) +/*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/ +{ + Py_ssize_t size; + int async_err = 0; + + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + + if (size < 0 && !async_err) + posix_error(); + return size; +} +#endif /* HAVE_PWRITE */ + +#if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2) +/*[clinic input] +os.pwritev -> Py_ssize_t + + fd: int + buffers: object + offset: Py_off_t + flags: int = 0 + / + +Writes the contents of bytes-like objects to a file descriptor at a given offset. + +Combines the functionality of writev() and pwrite(). All buffers must be a sequence +of bytes-like objects. Buffers are processed in array order. Entire contents of first +buffer is written before proceeding to second, and so on. The operating system may +set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used. +This function writes the contents of each object to the file descriptor and returns +the total number of bytes written. + +The flags argument contains a bitwise OR of zero or more of the following flags: + +- RWF_DSYNC +- RWF_SYNC +- RWF_APPEND + +Using non-zero flags requires Linux 4.7 or newer. +[clinic start generated code]*/ + +static Py_ssize_t +os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, + int flags) +/*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/ +{ + Py_ssize_t cnt; + Py_ssize_t result; + int async_err = 0; + struct iovec *iov; + Py_buffer *buf; + + if (!PySequence_Check(buffers)) { + PyErr_SetString(PyExc_TypeError, + "pwritev() arg 2 must be a sequence"); + return -1; + } + + cnt = PySequence_Size(buffers); + if (cnt < 0) { + return -1; + } + +#ifndef HAVE_PWRITEV2 + if(flags != 0) { + argument_unavailable_error("pwritev2", "flags"); + return -1; + } +#endif + + if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { + return -1; + } +#ifdef HAVE_PWRITEV2 + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + result = pwritev2(fd, iov, cnt, offset, flags); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); +#else + +#ifdef __APPLE__ +/* This entire function will be removed from the module dict when the API + * is not available. + */ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +#pragma clang diagnostic ignored "-Wunguarded-availability-new" +#endif + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + result = pwritev(fd, iov, cnt, offset); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + +#ifdef __APPLE__ +#pragma clang diagnostic pop +#endif + +#endif + + iov_cleanup(iov, buf, cnt); + if (result < 0) { + if (!async_err) { + posix_error(); + } + return -1; + } + + return result; +} +#endif /* HAVE_PWRITEV */ + +#ifdef HAVE_COPY_FILE_RANGE +/*[clinic input] + +os.copy_file_range + src: int + Source file descriptor. + dst: int + Destination file descriptor. + count: Py_ssize_t + Number of bytes to copy. + offset_src: object = None + Starting offset in src. + offset_dst: object = None + Starting offset in dst. + +Copy count bytes from one file descriptor to another. + +If offset_src is None, then src is read from the current position; +respectively for offset_dst. +[clinic start generated code]*/ + +static PyObject * +os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count, + PyObject *offset_src, PyObject *offset_dst) +/*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/ +{ + off_t offset_src_val, offset_dst_val; + off_t *p_offset_src = NULL; + off_t *p_offset_dst = NULL; + Py_ssize_t ret; + int async_err = 0; + /* The flags argument is provided to allow + * for future extensions and currently must be to 0. */ + int flags = 0; + + + if (count < 0) { + PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed"); + return NULL; + } + + if (offset_src != Py_None) { + if (!Py_off_t_converter(offset_src, &offset_src_val)) { + return NULL; + } + p_offset_src = &offset_src_val; + } + + if (offset_dst != Py_None) { + if (!Py_off_t_converter(offset_dst, &offset_dst_val)) { + return NULL; + } + p_offset_dst = &offset_dst_val; + } + + do { + Py_BEGIN_ALLOW_THREADS + ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags); + Py_END_ALLOW_THREADS + } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + + if (ret < 0) { + return (!async_err) ? posix_error() : NULL; + } + + return PyLong_FromSsize_t(ret); +} +#endif /* HAVE_COPY_FILE_RANGE*/ + +#if (defined(HAVE_SPLICE) && !defined(_AIX)) +/*[clinic input] + +os.splice + src: int + Source file descriptor. + dst: int + Destination file descriptor. + count: Py_ssize_t + Number of bytes to copy. + offset_src: object = None + Starting offset in src. + offset_dst: object = None + Starting offset in dst. + flags: unsigned_int = 0 + Flags to modify the semantics of the call. + +Transfer count bytes from one pipe to a descriptor or vice versa. + +If offset_src is None, then src is read from the current position; +respectively for offset_dst. The offset associated to the file +descriptor that refers to a pipe must be None. +[clinic start generated code]*/ + +static PyObject * +os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count, + PyObject *offset_src, PyObject *offset_dst, + unsigned int flags) +/*[clinic end generated code: output=d0386f25a8519dc5 input=047527c66c6d2e0a]*/ +{ + off_t offset_src_val, offset_dst_val; + off_t *p_offset_src = NULL; + off_t *p_offset_dst = NULL; + Py_ssize_t ret; + int async_err = 0; + + if (count < 0) { + PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed"); + return NULL; + } + + if (offset_src != Py_None) { + if (!Py_off_t_converter(offset_src, &offset_src_val)) { + return NULL; + } + p_offset_src = &offset_src_val; + } + + if (offset_dst != Py_None) { + if (!Py_off_t_converter(offset_dst, &offset_dst_val)) { + return NULL; + } + p_offset_dst = &offset_dst_val; + } + + do { + Py_BEGIN_ALLOW_THREADS + ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags); + Py_END_ALLOW_THREADS + } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + + if (ret < 0) { + return (!async_err) ? posix_error() : NULL; + } + + return PyLong_FromSsize_t(ret); +} +#endif /* HAVE_SPLICE*/ + +#ifdef HAVE_MKFIFO +/*[clinic input] +os.mkfifo + + path: path_t + mode: int=0o666 + * + dir_fd: dir_fd(requires='mkfifoat')=None + +Create a "fifo" (a POSIX named pipe). + +If dir_fd is not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that directory. +dir_fd may not be implemented on your platform. + If it is unavailable, using it will raise a NotImplementedError. +[clinic start generated code]*/ + +static PyObject * +os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd) +/*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/ +{ + int result; + int async_err = 0; +#ifdef HAVE_MKFIFOAT + int mkfifoat_unavailable = 0; +#endif + + do { + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_MKFIFOAT + if (dir_fd != DEFAULT_DIR_FD) { + if (HAVE_MKFIFOAT_RUNTIME) { + result = mkfifoat(dir_fd, path->narrow, mode); + + } else { + mkfifoat_unavailable = 1; + result = 0; + } + } else +#endif + result = mkfifo(path->narrow, mode); + Py_END_ALLOW_THREADS + } while (result != 0 && errno == EINTR && + !(async_err = PyErr_CheckSignals())); + +#ifdef HAVE_MKFIFOAT + if (mkfifoat_unavailable) { + argument_unavailable_error(NULL, "dir_fd"); + return NULL; + } +#endif + + if (result != 0) + return (!async_err) ? posix_error() : NULL; + + Py_RETURN_NONE; +} +#endif /* HAVE_MKFIFO */ + + +#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) +/*[clinic input] +os.mknod + + path: path_t + mode: int=0o600 + device: dev_t=0 + * + dir_fd: dir_fd(requires='mknodat')=None + +Create a node in the file system. + +Create a node in the file system (file, device special file or named pipe) +at path. mode specifies both the permissions to use and the +type of node to be created, being combined (bitwise OR) with one of +S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode, +device defines the newly created device special file (probably using +os.makedev()). Otherwise device is ignored. + +If dir_fd is not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that directory. +dir_fd may not be implemented on your platform. + If it is unavailable, using it will raise a NotImplementedError. +[clinic start generated code]*/ + +static PyObject * +os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device, + int dir_fd) +/*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/ +{ + int result; + int async_err = 0; +#ifdef HAVE_MKNODAT + int mknodat_unavailable = 0; +#endif + + do { + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_MKNODAT + if (dir_fd != DEFAULT_DIR_FD) { + if (HAVE_MKNODAT_RUNTIME) { + result = mknodat(dir_fd, path->narrow, mode, device); + + } else { + mknodat_unavailable = 1; + result = 0; + } + } else +#endif + result = mknod(path->narrow, mode, device); + Py_END_ALLOW_THREADS + } while (result != 0 && errno == EINTR && + !(async_err = PyErr_CheckSignals())); +#ifdef HAVE_MKNODAT + if (mknodat_unavailable) { + argument_unavailable_error(NULL, "dir_fd"); + return NULL; + } +#endif + if (result != 0) + return (!async_err) ? posix_error() : NULL; + + Py_RETURN_NONE; +} +#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */ + + +#ifdef HAVE_DEVICE_MACROS +/*[clinic input] +os.major -> unsigned_int + + device: dev_t + / + +Extracts a device major number from a raw device number. +[clinic start generated code]*/ + +static unsigned int +os_major_impl(PyObject *module, dev_t device) +/*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/ +{ + return major(device); +} + + +/*[clinic input] +os.minor -> unsigned_int + + device: dev_t + / + +Extracts a device minor number from a raw device number. +[clinic start generated code]*/ + +static unsigned int +os_minor_impl(PyObject *module, dev_t device) +/*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/ +{ + return minor(device); +} + + +/*[clinic input] +os.makedev -> dev_t + + major: int + minor: int + / + +Composes a raw device number from the major and minor device numbers. +[clinic start generated code]*/ + +static dev_t +os_makedev_impl(PyObject *module, int major, int minor) +/*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/ +{ + return makedev(major, minor); +} +#endif /* HAVE_DEVICE_MACROS */ + + +#if defined HAVE_FTRUNCATE || defined MS_WINDOWS +/*[clinic input] +os.ftruncate + + fd: int + length: Py_off_t + / + +Truncate a file, specified by file descriptor, to a specific length. +[clinic start generated code]*/ + +static PyObject * +os_ftruncate_impl(PyObject *module, int fd, Py_off_t length) +/*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/ +{ + int result; + int async_err = 0; + + if (PySys_Audit("os.truncate", "in", fd, length) < 0) { + return NULL; + } + + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH +#ifdef MS_WINDOWS + result = _chsize_s(fd, length); +#else + result = ftruncate(fd, length); +#endif + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (result != 0 && errno == EINTR && + !(async_err = PyErr_CheckSignals())); + if (result != 0) + return (!async_err) ? posix_error() : NULL; + Py_RETURN_NONE; +} +#endif /* HAVE_FTRUNCATE || MS_WINDOWS */ + + +#if defined HAVE_TRUNCATE || defined MS_WINDOWS +/*[clinic input] +os.truncate + path: path_t(allow_fd='PATH_HAVE_FTRUNCATE') + length: Py_off_t + +Truncate a file, specified by path, to a specific length. + +On some platforms, path may also be specified as an open file descriptor. + If this functionality is unavailable, using it raises an exception. +[clinic start generated code]*/ + +static PyObject * +os_truncate_impl(PyObject *module, path_t *path, Py_off_t length) +/*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/ +{ + int result; +#ifdef MS_WINDOWS + int fd; +#endif + + if (path->fd != -1) + return os_ftruncate_impl(module, path->fd, length); + + if (PySys_Audit("os.truncate", "On", path->object, length) < 0) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH +#ifdef MS_WINDOWS + fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT); + if (fd < 0) + result = -1; + else { + result = _chsize_s(fd, length); + close(fd); + if (result < 0) + errno = result; + } +#else + result = truncate(path->narrow, length); +#endif + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + if (result < 0) + return posix_path_error(path); + + Py_RETURN_NONE; +} +#endif /* HAVE_TRUNCATE || MS_WINDOWS */ + + +/* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise() + and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is + defined, which is the case in Python on AIX. AIX bug report: + http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */ +#if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__) +# define POSIX_FADVISE_AIX_BUG +#endif + + +#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) +/*[clinic input] +os.posix_fallocate + + fd: int + offset: Py_off_t + length: Py_off_t + / + +Ensure a file has allocated at least a particular number of bytes on disk. + +Ensure that the file specified by fd encompasses a range of bytes +starting at offset bytes from the beginning and continuing for length bytes. +[clinic start generated code]*/ + +static PyObject * +os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset, + Py_off_t length) +/*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/ +{ + int result; + int async_err = 0; + + do { + Py_BEGIN_ALLOW_THREADS + result = posix_fallocate(fd, offset, length); + Py_END_ALLOW_THREADS + } while (result == EINTR && !(async_err = PyErr_CheckSignals())); + + if (result == 0) + Py_RETURN_NONE; + + if (async_err) + return NULL; + + errno = result; + return posix_error(); +} +#endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */ + + +#if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG) +/*[clinic input] +os.posix_fadvise + + fd: int + offset: Py_off_t + length: Py_off_t + advice: int + / + +Announce an intention to access data in a specific pattern. + +Announce an intention to access data in a specific pattern, thus allowing +the kernel to make optimizations. +The advice applies to the region of the file specified by fd starting at +offset and continuing for length bytes. +advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL, +POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or +POSIX_FADV_DONTNEED. +[clinic start generated code]*/ + +static PyObject * +os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset, + Py_off_t length, int advice) +/*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/ +{ + int result; + int async_err = 0; + + do { + Py_BEGIN_ALLOW_THREADS + result = posix_fadvise(fd, offset, length, advice); + Py_END_ALLOW_THREADS + } while (result == EINTR && !(async_err = PyErr_CheckSignals())); + + if (result == 0) + Py_RETURN_NONE; + + if (async_err) + return NULL; + + errno = result; + return posix_error(); +} +#endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */ + + +#ifdef MS_WINDOWS +static PyObject* +win32_putenv(PyObject *name, PyObject *value) +{ + /* Search from index 1 because on Windows starting '=' is allowed for + defining hidden environment variables. */ + if (PyUnicode_GET_LENGTH(name) == 0 || + PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1) + { + PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); + return NULL; + } + PyObject *unicode; + if (value != NULL) { + unicode = PyUnicode_FromFormat("%U=%U", name, value); + } + else { + unicode = PyUnicode_FromFormat("%U=", name); + } + if (unicode == NULL) { + return NULL; + } + + Py_ssize_t size; + /* PyUnicode_AsWideCharString() rejects embedded null characters */ + wchar_t *env = PyUnicode_AsWideCharString(unicode, &size); + Py_DECREF(unicode); + + if (env == NULL) { + return NULL; + } + if (size > _MAX_ENV) { + PyErr_Format(PyExc_ValueError, + "the environment variable is longer than %u characters", + _MAX_ENV); + PyMem_Free(env); + return NULL; + } + + /* _wputenv() and SetEnvironmentVariableW() update the environment in the + Process Environment Block (PEB). _wputenv() also updates CRT 'environ' + and '_wenviron' variables, whereas SetEnvironmentVariableW() does not. + + Prefer _wputenv() to be compatible with C libraries using CRT + variables and CRT functions using these variables (ex: getenv()). */ + int err = _wputenv(env); + PyMem_Free(env); + + if (err) { + posix_error(); + return NULL; + } + + Py_RETURN_NONE; +} +#endif + + +#ifdef MS_WINDOWS +/*[clinic input] +os.putenv + + name: unicode + value: unicode + / + +Change or add an environment variable. +[clinic start generated code]*/ + +static PyObject * +os_putenv_impl(PyObject *module, PyObject *name, PyObject *value) +/*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/ +{ + if (PySys_Audit("os.putenv", "OO", name, value) < 0) { + return NULL; + } + return win32_putenv(name, value); +} +#else +/*[clinic input] +os.putenv + + name: FSConverter + value: FSConverter + / + +Change or add an environment variable. +[clinic start generated code]*/ + +static PyObject * +os_putenv_impl(PyObject *module, PyObject *name, PyObject *value) +/*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/ +{ + const char *name_string = PyBytes_AS_STRING(name); + const char *value_string = PyBytes_AS_STRING(value); + + if (strchr(name_string, '=') != NULL) { + PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); + return NULL; + } + + if (PySys_Audit("os.putenv", "OO", name, value) < 0) { + return NULL; + } + + if (setenv(name_string, value_string, 1)) { + return posix_error(); + } + Py_RETURN_NONE; +} +#endif /* !defined(MS_WINDOWS) */ + + +#ifdef MS_WINDOWS +/*[clinic input] +os.unsetenv + name: unicode + / + +Delete an environment variable. +[clinic start generated code]*/ + +static PyObject * +os_unsetenv_impl(PyObject *module, PyObject *name) +/*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/ +{ + if (PySys_Audit("os.unsetenv", "(O)", name) < 0) { + return NULL; + } + return win32_putenv(name, NULL); +} +#else +/*[clinic input] +os.unsetenv + name: FSConverter + / + +Delete an environment variable. +[clinic start generated code]*/ + +static PyObject * +os_unsetenv_impl(PyObject *module, PyObject *name) +/*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/ +{ + if (PySys_Audit("os.unsetenv", "(O)", name) < 0) { + return NULL; + } +#ifdef HAVE_BROKEN_UNSETENV + unsetenv(PyBytes_AS_STRING(name)); +#else + int err = unsetenv(PyBytes_AS_STRING(name)); + if (err) { + return posix_error(); + } +#endif + + Py_RETURN_NONE; +} +#endif /* !MS_WINDOWS */ + + +/*[clinic input] +os.strerror + + code: int + / + +Translate an error code to a message string. +[clinic start generated code]*/ + +static PyObject * +os_strerror_impl(PyObject *module, int code) +/*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/ +{ + char *message = strerror(code); + if (message == NULL) { + PyErr_SetString(PyExc_ValueError, + "strerror() argument out of range"); + return NULL; + } + return PyUnicode_DecodeLocale(message, "surrogateescape"); +} + + +#ifdef HAVE_SYS_WAIT_H +#ifdef WCOREDUMP +/*[clinic input] +os.WCOREDUMP -> bool + + status: int + / + +Return True if the process returning status was dumped to a core file. +[clinic start generated code]*/ + +static int +os_WCOREDUMP_impl(PyObject *module, int status) +/*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WCOREDUMP(wait_status); +} +#endif /* WCOREDUMP */ + + +#ifdef WIFCONTINUED +/*[clinic input] +os.WIFCONTINUED -> bool + + status: int + +Return True if a particular process was continued from a job control stop. + +Return True if the process returning status was continued from a +job control stop. +[clinic start generated code]*/ + +static int +os_WIFCONTINUED_impl(PyObject *module, int status) +/*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WIFCONTINUED(wait_status); +} +#endif /* WIFCONTINUED */ + + +#ifdef WIFSTOPPED +/*[clinic input] +os.WIFSTOPPED -> bool + + status: int + +Return True if the process returning status was stopped. +[clinic start generated code]*/ + +static int +os_WIFSTOPPED_impl(PyObject *module, int status) +/*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WIFSTOPPED(wait_status); +} +#endif /* WIFSTOPPED */ + + +#ifdef WIFSIGNALED +/*[clinic input] +os.WIFSIGNALED -> bool + + status: int + +Return True if the process returning status was terminated by a signal. +[clinic start generated code]*/ + +static int +os_WIFSIGNALED_impl(PyObject *module, int status) +/*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WIFSIGNALED(wait_status); +} +#endif /* WIFSIGNALED */ + + +#ifdef WIFEXITED +/*[clinic input] +os.WIFEXITED -> bool + + status: int + +Return True if the process returning status exited via the exit() system call. +[clinic start generated code]*/ + +static int +os_WIFEXITED_impl(PyObject *module, int status) +/*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WIFEXITED(wait_status); +} +#endif /* WIFEXITED */ + + +#ifdef WEXITSTATUS +/*[clinic input] +os.WEXITSTATUS -> int + + status: int + +Return the process return code from status. +[clinic start generated code]*/ + +static int +os_WEXITSTATUS_impl(PyObject *module, int status) +/*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WEXITSTATUS(wait_status); +} +#endif /* WEXITSTATUS */ + + +#ifdef WTERMSIG +/*[clinic input] +os.WTERMSIG -> int + + status: int + +Return the signal that terminated the process that provided the status value. +[clinic start generated code]*/ + +static int +os_WTERMSIG_impl(PyObject *module, int status) +/*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WTERMSIG(wait_status); +} +#endif /* WTERMSIG */ + + +#ifdef WSTOPSIG +/*[clinic input] +os.WSTOPSIG -> int + + status: int + +Return the signal that stopped the process that provided the status value. +[clinic start generated code]*/ + +static int +os_WSTOPSIG_impl(PyObject *module, int status) +/*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WSTOPSIG(wait_status); +} +#endif /* WSTOPSIG */ +#endif /* HAVE_SYS_WAIT_H */ + + +#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) +#ifdef _SCO_DS +/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the + needed definitions in sys/statvfs.h */ +#define _SVID3 +#endif +#include + +static PyObject* +_pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) { + PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType; + PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType); + if (v == NULL) + return NULL; + +#if !defined(HAVE_LARGEFILE_SUPPORT) + PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize)); + PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize)); + PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks)); + PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree)); + PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail)); + PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files)); + PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree)); + PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail)); + PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag)); + PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax)); +#else + PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize)); + PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize)); + PyStructSequence_SET_ITEM(v, 2, + PyLong_FromLongLong((long long) st.f_blocks)); + PyStructSequence_SET_ITEM(v, 3, + PyLong_FromLongLong((long long) st.f_bfree)); + PyStructSequence_SET_ITEM(v, 4, + PyLong_FromLongLong((long long) st.f_bavail)); + PyStructSequence_SET_ITEM(v, 5, + PyLong_FromLongLong((long long) st.f_files)); + PyStructSequence_SET_ITEM(v, 6, + PyLong_FromLongLong((long long) st.f_ffree)); + PyStructSequence_SET_ITEM(v, 7, + PyLong_FromLongLong((long long) st.f_favail)); + PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag)); + PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax)); +#endif +/* The _ALL_SOURCE feature test macro defines f_fsid as a structure + * (issue #32390). */ +#if defined(_AIX) && defined(_ALL_SOURCE) + PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0])); +#else + PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid)); +#endif + if (PyErr_Occurred()) { + Py_DECREF(v); + return NULL; + } + + return v; +} + + +/*[clinic input] +os.fstatvfs + fd: int + / + +Perform an fstatvfs system call on the given fd. + +Equivalent to statvfs(fd). +[clinic start generated code]*/ + +static PyObject * +os_fstatvfs_impl(PyObject *module, int fd) +/*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/ +{ + int result; + int async_err = 0; + struct statvfs st; + + do { + Py_BEGIN_ALLOW_THREADS + result = fstatvfs(fd, &st); + Py_END_ALLOW_THREADS + } while (result != 0 && errno == EINTR && + !(async_err = PyErr_CheckSignals())); + if (result != 0) + return (!async_err) ? posix_error() : NULL; + + return _pystatvfs_fromstructstatvfs(module, st); +} +#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */ + + +#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) +#include +/*[clinic input] +os.statvfs + + path: path_t(allow_fd='PATH_HAVE_FSTATVFS') + +Perform a statvfs system call on the given path. + +path may always be specified as a string. +On some platforms, path may also be specified as an open file descriptor. + If this functionality is unavailable, using it raises an exception. +[clinic start generated code]*/ + +static PyObject * +os_statvfs_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/ +{ + int result; + struct statvfs st; + + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_FSTATVFS + if (path->fd != -1) { + result = fstatvfs(path->fd, &st); + } + else +#endif + result = statvfs(path->narrow, &st); + Py_END_ALLOW_THREADS + + if (result) { + return path_error(path); + } + + return _pystatvfs_fromstructstatvfs(module, st); +} +#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */ + + +#ifdef MS_WINDOWS +/*[clinic input] +os._getdiskusage + + path: path_t + +Return disk usage statistics about the given path as a (total, free) tuple. +[clinic start generated code]*/ + +static PyObject * +os__getdiskusage_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/ +{ + BOOL retval; + ULARGE_INTEGER _, total, free; + DWORD err = 0; + + Py_BEGIN_ALLOW_THREADS + retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free); + Py_END_ALLOW_THREADS + if (retval == 0) { + if (GetLastError() == ERROR_DIRECTORY) { + wchar_t *dir_path = NULL; + + dir_path = PyMem_New(wchar_t, path->length + 1); + if (dir_path == NULL) { + return PyErr_NoMemory(); + } + + wcscpy_s(dir_path, path->length + 1, path->wide); + + if (_dirnameW(dir_path) != -1) { + Py_BEGIN_ALLOW_THREADS + retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free); + Py_END_ALLOW_THREADS + } + /* Record the last error in case it's modified by PyMem_Free. */ + err = GetLastError(); + PyMem_Free(dir_path); + if (retval) { + goto success; + } + } + return PyErr_SetFromWindowsErr(err); + } + +success: + return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart); +} +#endif /* MS_WINDOWS */ + + +/* This is used for fpathconf(), pathconf(), confstr() and sysconf(). + * It maps strings representing configuration variable names to + * integer values, allowing those functions to be called with the + * magic names instead of polluting the module's namespace with tons of + * rarely-used constants. There are three separate tables that use + * these definitions. + * + * This code is always included, even if none of the interfaces that + * need it are included. The #if hackery needed to avoid it would be + * sufficiently pervasive that it's not worth the loss of readability. + */ +struct constdef { + const char *name; + int value; +}; + +static int +conv_confname(PyObject *arg, int *valuep, struct constdef *table, + size_t tablesize) +{ + if (PyLong_Check(arg)) { + int value = _PyLong_AsInt(arg); + if (value == -1 && PyErr_Occurred()) + return 0; + *valuep = value; + return 1; + } + else { + /* look up the value in the table using a binary search */ + size_t lo = 0; + size_t mid; + size_t hi = tablesize; + int cmp; + const char *confname; + if (!PyUnicode_Check(arg)) { + PyErr_SetString(PyExc_TypeError, + "configuration names must be strings or integers"); + return 0; + } + confname = PyUnicode_AsUTF8(arg); + if (confname == NULL) + return 0; + while (lo < hi) { + mid = (lo + hi) / 2; + cmp = strcmp(confname, table[mid].name); + if (cmp < 0) + hi = mid; + else if (cmp > 0) + lo = mid + 1; + else { + *valuep = table[mid].value; + return 1; + } + } + PyErr_SetString(PyExc_ValueError, "unrecognized configuration name"); + return 0; + } +} + + +#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF) +static struct constdef posix_constants_pathconf[] = { +#ifdef _PC_ABI_AIO_XFER_MAX + {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX}, +#endif +#ifdef _PC_ABI_ASYNC_IO + {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO}, +#endif +#ifdef _PC_ASYNC_IO + {"PC_ASYNC_IO", _PC_ASYNC_IO}, +#endif +#ifdef _PC_CHOWN_RESTRICTED + {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED}, +#endif +#ifdef _PC_FILESIZEBITS + {"PC_FILESIZEBITS", _PC_FILESIZEBITS}, +#endif +#ifdef _PC_LAST + {"PC_LAST", _PC_LAST}, +#endif +#ifdef _PC_LINK_MAX + {"PC_LINK_MAX", _PC_LINK_MAX}, +#endif +#ifdef _PC_MAX_CANON + {"PC_MAX_CANON", _PC_MAX_CANON}, +#endif +#ifdef _PC_MAX_INPUT + {"PC_MAX_INPUT", _PC_MAX_INPUT}, +#endif +#ifdef _PC_NAME_MAX + {"PC_NAME_MAX", _PC_NAME_MAX}, +#endif +#ifdef _PC_NO_TRUNC + {"PC_NO_TRUNC", _PC_NO_TRUNC}, +#endif +#ifdef _PC_PATH_MAX + {"PC_PATH_MAX", _PC_PATH_MAX}, +#endif +#ifdef _PC_PIPE_BUF + {"PC_PIPE_BUF", _PC_PIPE_BUF}, +#endif +#ifdef _PC_PRIO_IO + {"PC_PRIO_IO", _PC_PRIO_IO}, +#endif +#ifdef _PC_SOCK_MAXBUF + {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF}, +#endif +#ifdef _PC_SYNC_IO + {"PC_SYNC_IO", _PC_SYNC_IO}, +#endif +#ifdef _PC_VDISABLE + {"PC_VDISABLE", _PC_VDISABLE}, +#endif +#ifdef _PC_ACL_ENABLED + {"PC_ACL_ENABLED", _PC_ACL_ENABLED}, +#endif +#ifdef _PC_MIN_HOLE_SIZE + {"PC_MIN_HOLE_SIZE", _PC_MIN_HOLE_SIZE}, +#endif +#ifdef _PC_ALLOC_SIZE_MIN + {"PC_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN}, +#endif +#ifdef _PC_REC_INCR_XFER_SIZE + {"PC_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE}, +#endif +#ifdef _PC_REC_MAX_XFER_SIZE + {"PC_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE}, +#endif +#ifdef _PC_REC_MIN_XFER_SIZE + {"PC_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE}, +#endif +#ifdef _PC_REC_XFER_ALIGN + {"PC_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN}, +#endif +#ifdef _PC_SYMLINK_MAX + {"PC_SYMLINK_MAX", _PC_SYMLINK_MAX}, +#endif +#ifdef _PC_XATTR_ENABLED + {"PC_XATTR_ENABLED", _PC_XATTR_ENABLED}, +#endif +#ifdef _PC_XATTR_EXISTS + {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS}, +#endif +#ifdef _PC_TIMESTAMP_RESOLUTION + {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION}, +#endif +}; + +static int +conv_path_confname(PyObject *arg, int *valuep) +{ + return conv_confname(arg, valuep, posix_constants_pathconf, + sizeof(posix_constants_pathconf) + / sizeof(struct constdef)); +} +#endif + + +#ifdef HAVE_FPATHCONF +/*[clinic input] +os.fpathconf -> long + + fd: fildes + name: path_confname + / + +Return the configuration limit name for the file descriptor fd. + +If there is no limit, return -1. +[clinic start generated code]*/ + +static long +os_fpathconf_impl(PyObject *module, int fd, int name) +/*[clinic end generated code: output=d5b7042425fc3e21 input=5b8d2471cfaae186]*/ +{ + long limit; + + errno = 0; + limit = fpathconf(fd, name); + if (limit == -1 && errno != 0) + posix_error(); + + return limit; +} +#endif /* HAVE_FPATHCONF */ + + +#ifdef HAVE_PATHCONF +/*[clinic input] +os.pathconf -> long + path: path_t(allow_fd='PATH_HAVE_FPATHCONF') + name: path_confname + +Return the configuration limit name for the file or directory path. + +If there is no limit, return -1. +On some platforms, path may also be specified as an open file descriptor. + If this functionality is unavailable, using it raises an exception. +[clinic start generated code]*/ + +static long +os_pathconf_impl(PyObject *module, path_t *path, int name) +/*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/ +{ + long limit; + + errno = 0; +#ifdef HAVE_FPATHCONF + if (path->fd != -1) + limit = fpathconf(path->fd, name); + else +#endif + limit = pathconf(path->narrow, name); + if (limit == -1 && errno != 0) { + if (errno == EINVAL) + /* could be a path or name problem */ + posix_error(); + else + path_error(path); + } + + return limit; +} +#endif /* HAVE_PATHCONF */ + +#ifdef HAVE_CONFSTR +static struct constdef posix_constants_confstr[] = { +#ifdef _CS_ARCHITECTURE + {"CS_ARCHITECTURE", _CS_ARCHITECTURE}, +#endif +#ifdef _CS_GNU_LIBC_VERSION + {"CS_GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION}, +#endif +#ifdef _CS_GNU_LIBPTHREAD_VERSION + {"CS_GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION}, +#endif +#ifdef _CS_HOSTNAME + {"CS_HOSTNAME", _CS_HOSTNAME}, +#endif +#ifdef _CS_HW_PROVIDER + {"CS_HW_PROVIDER", _CS_HW_PROVIDER}, +#endif +#ifdef _CS_HW_SERIAL + {"CS_HW_SERIAL", _CS_HW_SERIAL}, +#endif +#ifdef _CS_INITTAB_NAME + {"CS_INITTAB_NAME", _CS_INITTAB_NAME}, +#endif +#ifdef _CS_LFS64_CFLAGS + {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS}, +#endif +#ifdef _CS_LFS64_LDFLAGS + {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS}, +#endif +#ifdef _CS_LFS64_LIBS + {"CS_LFS64_LIBS", _CS_LFS64_LIBS}, +#endif +#ifdef _CS_LFS64_LINTFLAGS + {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS}, +#endif +#ifdef _CS_LFS_CFLAGS + {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS}, +#endif +#ifdef _CS_LFS_LDFLAGS + {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS}, +#endif +#ifdef _CS_LFS_LIBS + {"CS_LFS_LIBS", _CS_LFS_LIBS}, +#endif +#ifdef _CS_LFS_LINTFLAGS + {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS}, +#endif +#ifdef _CS_MACHINE + {"CS_MACHINE", _CS_MACHINE}, +#endif +#ifdef _CS_PATH + {"CS_PATH", _CS_PATH}, +#endif +#ifdef _CS_RELEASE + {"CS_RELEASE", _CS_RELEASE}, +#endif +#ifdef _CS_SRPC_DOMAIN + {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN}, +#endif +#ifdef _CS_SYSNAME + {"CS_SYSNAME", _CS_SYSNAME}, +#endif +#ifdef _CS_VERSION + {"CS_VERSION", _CS_VERSION}, +#endif +#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS + {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS}, +#endif +#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS + {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS}, +#endif +#ifdef _CS_XBS5_ILP32_OFF32_LIBS + {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS}, +#endif +#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS + {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS}, +#endif +#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS + {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS}, +#endif +#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS + {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS}, +#endif +#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS + {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS}, +#endif +#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS + {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS}, +#endif +#ifdef _CS_XBS5_LP64_OFF64_CFLAGS + {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS}, +#endif +#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS + {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS}, +#endif +#ifdef _CS_XBS5_LP64_OFF64_LIBS + {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS}, +#endif +#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS + {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS}, +#endif +#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS + {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS}, +#endif +#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS + {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS}, +#endif +#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS + {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS}, +#endif +#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS + {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS}, +#endif +#ifdef _MIPS_CS_AVAIL_PROCESSORS + {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS}, +#endif +#ifdef _MIPS_CS_BASE + {"MIPS_CS_BASE", _MIPS_CS_BASE}, +#endif +#ifdef _MIPS_CS_HOSTID + {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID}, +#endif +#ifdef _MIPS_CS_HW_NAME + {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME}, +#endif +#ifdef _MIPS_CS_NUM_PROCESSORS + {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS}, +#endif +#ifdef _MIPS_CS_OSREL_MAJ + {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ}, +#endif +#ifdef _MIPS_CS_OSREL_MIN + {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN}, +#endif +#ifdef _MIPS_CS_OSREL_PATCH + {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH}, +#endif +#ifdef _MIPS_CS_OS_NAME + {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME}, +#endif +#ifdef _MIPS_CS_OS_PROVIDER + {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER}, +#endif +#ifdef _MIPS_CS_PROCESSORS + {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS}, +#endif +#ifdef _MIPS_CS_SERIAL + {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL}, +#endif +#ifdef _MIPS_CS_VENDOR + {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR}, +#endif +}; + +static int +conv_confstr_confname(PyObject *arg, int *valuep) +{ + return conv_confname(arg, valuep, posix_constants_confstr, + sizeof(posix_constants_confstr) + / sizeof(struct constdef)); +} + + +/*[clinic input] +os.confstr + + name: confstr_confname + / + +Return a string-valued system configuration variable. +[clinic start generated code]*/ + +static PyObject * +os_confstr_impl(PyObject *module, int name) +/*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/ +{ + PyObject *result = NULL; + char buffer[255]; + size_t len; + + errno = 0; + len = confstr(name, buffer, sizeof(buffer)); + if (len == 0) { + if (errno) { + posix_error(); + return NULL; + } + else { + Py_RETURN_NONE; + } + } + + if (len >= sizeof(buffer)) { + size_t len2; + char *buf = PyMem_Malloc(len); + if (buf == NULL) + return PyErr_NoMemory(); + len2 = confstr(name, buf, len); + assert(len == len2); + result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1); + PyMem_Free(buf); + } + else + result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1); + return result; +} +#endif /* HAVE_CONFSTR */ + + +#ifdef HAVE_SYSCONF +static struct constdef posix_constants_sysconf[] = { +#ifdef _SC_2_CHAR_TERM + {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM}, +#endif +#ifdef _SC_2_C_BIND + {"SC_2_C_BIND", _SC_2_C_BIND}, +#endif +#ifdef _SC_2_C_DEV + {"SC_2_C_DEV", _SC_2_C_DEV}, +#endif +#ifdef _SC_2_C_VERSION + {"SC_2_C_VERSION", _SC_2_C_VERSION}, +#endif +#ifdef _SC_2_FORT_DEV + {"SC_2_FORT_DEV", _SC_2_FORT_DEV}, +#endif +#ifdef _SC_2_FORT_RUN + {"SC_2_FORT_RUN", _SC_2_FORT_RUN}, +#endif +#ifdef _SC_2_LOCALEDEF + {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF}, +#endif +#ifdef _SC_2_SW_DEV + {"SC_2_SW_DEV", _SC_2_SW_DEV}, +#endif +#ifdef _SC_2_UPE + {"SC_2_UPE", _SC_2_UPE}, +#endif +#ifdef _SC_2_VERSION + {"SC_2_VERSION", _SC_2_VERSION}, +#endif +#ifdef _SC_ABI_ASYNCHRONOUS_IO + {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO}, +#endif +#ifdef _SC_ACL + {"SC_ACL", _SC_ACL}, +#endif +#ifdef _SC_AIO_LISTIO_MAX + {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX}, +#endif +#ifdef _SC_AIO_MAX + {"SC_AIO_MAX", _SC_AIO_MAX}, +#endif +#ifdef _SC_AIO_PRIO_DELTA_MAX + {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX}, +#endif +#ifdef _SC_ARG_MAX + {"SC_ARG_MAX", _SC_ARG_MAX}, +#endif +#ifdef _SC_ASYNCHRONOUS_IO + {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO}, +#endif +#ifdef _SC_ATEXIT_MAX + {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX}, +#endif +#ifdef _SC_AUDIT + {"SC_AUDIT", _SC_AUDIT}, +#endif +#ifdef _SC_AVPHYS_PAGES + {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES}, +#endif +#ifdef _SC_BC_BASE_MAX + {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX}, +#endif +#ifdef _SC_BC_DIM_MAX + {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX}, +#endif +#ifdef _SC_BC_SCALE_MAX + {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX}, +#endif +#ifdef _SC_BC_STRING_MAX + {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX}, +#endif +#ifdef _SC_CAP + {"SC_CAP", _SC_CAP}, +#endif +#ifdef _SC_CHARCLASS_NAME_MAX + {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX}, +#endif +#ifdef _SC_CHAR_BIT + {"SC_CHAR_BIT", _SC_CHAR_BIT}, +#endif +#ifdef _SC_CHAR_MAX + {"SC_CHAR_MAX", _SC_CHAR_MAX}, +#endif +#ifdef _SC_CHAR_MIN + {"SC_CHAR_MIN", _SC_CHAR_MIN}, +#endif +#ifdef _SC_CHILD_MAX + {"SC_CHILD_MAX", _SC_CHILD_MAX}, +#endif +#ifdef _SC_CLK_TCK + {"SC_CLK_TCK", _SC_CLK_TCK}, +#endif +#ifdef _SC_COHER_BLKSZ + {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ}, +#endif +#ifdef _SC_COLL_WEIGHTS_MAX + {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX}, +#endif +#ifdef _SC_DCACHE_ASSOC + {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC}, +#endif +#ifdef _SC_DCACHE_BLKSZ + {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ}, +#endif +#ifdef _SC_DCACHE_LINESZ + {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ}, +#endif +#ifdef _SC_DCACHE_SZ + {"SC_DCACHE_SZ", _SC_DCACHE_SZ}, +#endif +#ifdef _SC_DCACHE_TBLKSZ + {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ}, +#endif +#ifdef _SC_DELAYTIMER_MAX + {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX}, +#endif +#ifdef _SC_EQUIV_CLASS_MAX + {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX}, +#endif +#ifdef _SC_EXPR_NEST_MAX + {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX}, +#endif +#ifdef _SC_FSYNC + {"SC_FSYNC", _SC_FSYNC}, +#endif +#ifdef _SC_GETGR_R_SIZE_MAX + {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX}, +#endif +#ifdef _SC_GETPW_R_SIZE_MAX + {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX}, +#endif +#ifdef _SC_ICACHE_ASSOC + {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC}, +#endif +#ifdef _SC_ICACHE_BLKSZ + {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ}, +#endif +#ifdef _SC_ICACHE_LINESZ + {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ}, +#endif +#ifdef _SC_ICACHE_SZ + {"SC_ICACHE_SZ", _SC_ICACHE_SZ}, +#endif +#ifdef _SC_INF + {"SC_INF", _SC_INF}, +#endif +#ifdef _SC_INT_MAX + {"SC_INT_MAX", _SC_INT_MAX}, +#endif +#ifdef _SC_INT_MIN + {"SC_INT_MIN", _SC_INT_MIN}, +#endif +#ifdef _SC_IOV_MAX + {"SC_IOV_MAX", _SC_IOV_MAX}, +#endif +#ifdef _SC_IP_SECOPTS + {"SC_IP_SECOPTS", _SC_IP_SECOPTS}, +#endif +#ifdef _SC_JOB_CONTROL + {"SC_JOB_CONTROL", _SC_JOB_CONTROL}, +#endif +#ifdef _SC_KERN_POINTERS + {"SC_KERN_POINTERS", _SC_KERN_POINTERS}, +#endif +#ifdef _SC_KERN_SIM + {"SC_KERN_SIM", _SC_KERN_SIM}, +#endif +#ifdef _SC_LINE_MAX + {"SC_LINE_MAX", _SC_LINE_MAX}, +#endif +#ifdef _SC_LOGIN_NAME_MAX + {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX}, +#endif +#ifdef _SC_LOGNAME_MAX + {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX}, +#endif +#ifdef _SC_LONG_BIT + {"SC_LONG_BIT", _SC_LONG_BIT}, +#endif +#ifdef _SC_MAC + {"SC_MAC", _SC_MAC}, +#endif +#ifdef _SC_MAPPED_FILES + {"SC_MAPPED_FILES", _SC_MAPPED_FILES}, +#endif +#ifdef _SC_MAXPID + {"SC_MAXPID", _SC_MAXPID}, +#endif +#ifdef _SC_MB_LEN_MAX + {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX}, +#endif +#ifdef _SC_MEMLOCK + {"SC_MEMLOCK", _SC_MEMLOCK}, +#endif +#ifdef _SC_MEMLOCK_RANGE + {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE}, +#endif +#ifdef _SC_MEMORY_PROTECTION + {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION}, +#endif +#ifdef _SC_MESSAGE_PASSING + {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING}, +#endif +#ifdef _SC_MMAP_FIXED_ALIGNMENT + {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT}, +#endif +#ifdef _SC_MQ_OPEN_MAX + {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX}, +#endif +#ifdef _SC_MQ_PRIO_MAX + {"SC_MQ_PRIO_MAX", _SC_MQ_PRIO_MAX}, +#endif +#ifdef _SC_NACLS_MAX + {"SC_NACLS_MAX", _SC_NACLS_MAX}, +#endif +#ifdef _SC_NGROUPS_MAX + {"SC_NGROUPS_MAX", _SC_NGROUPS_MAX}, +#endif +#ifdef _SC_NL_ARGMAX + {"SC_NL_ARGMAX", _SC_NL_ARGMAX}, +#endif +#ifdef _SC_NL_LANGMAX + {"SC_NL_LANGMAX", _SC_NL_LANGMAX}, +#endif +#ifdef _SC_NL_MSGMAX + {"SC_NL_MSGMAX", _SC_NL_MSGMAX}, +#endif +#ifdef _SC_NL_NMAX + {"SC_NL_NMAX", _SC_NL_NMAX}, +#endif +#ifdef _SC_NL_SETMAX + {"SC_NL_SETMAX", _SC_NL_SETMAX}, +#endif +#ifdef _SC_NL_TEXTMAX + {"SC_NL_TEXTMAX", _SC_NL_TEXTMAX}, +#endif +#ifdef _SC_NPROCESSORS_CONF + {"SC_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF}, +#endif +#ifdef _SC_NPROCESSORS_ONLN + {"SC_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN}, +#endif +#ifdef _SC_NPROC_CONF + {"SC_NPROC_CONF", _SC_NPROC_CONF}, +#endif +#ifdef _SC_NPROC_ONLN + {"SC_NPROC_ONLN", _SC_NPROC_ONLN}, +#endif +#ifdef _SC_NZERO + {"SC_NZERO", _SC_NZERO}, +#endif +#ifdef _SC_OPEN_MAX + {"SC_OPEN_MAX", _SC_OPEN_MAX}, +#endif +#ifdef _SC_PAGESIZE + {"SC_PAGESIZE", _SC_PAGESIZE}, +#endif +#ifdef _SC_PAGE_SIZE + {"SC_PAGE_SIZE", _SC_PAGE_SIZE}, +#endif +#ifdef _SC_AIX_REALMEM + {"SC_AIX_REALMEM", _SC_AIX_REALMEM}, +#endif +#ifdef _SC_PASS_MAX + {"SC_PASS_MAX", _SC_PASS_MAX}, +#endif +#ifdef _SC_PHYS_PAGES + {"SC_PHYS_PAGES", _SC_PHYS_PAGES}, +#endif +#ifdef _SC_PII + {"SC_PII", _SC_PII}, +#endif +#ifdef _SC_PII_INTERNET + {"SC_PII_INTERNET", _SC_PII_INTERNET}, +#endif +#ifdef _SC_PII_INTERNET_DGRAM + {"SC_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM}, +#endif +#ifdef _SC_PII_INTERNET_STREAM + {"SC_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM}, +#endif +#ifdef _SC_PII_OSI + {"SC_PII_OSI", _SC_PII_OSI}, +#endif +#ifdef _SC_PII_OSI_CLTS + {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS}, +#endif +#ifdef _SC_PII_OSI_COTS + {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS}, +#endif +#ifdef _SC_PII_OSI_M + {"SC_PII_OSI_M", _SC_PII_OSI_M}, +#endif +#ifdef _SC_PII_SOCKET + {"SC_PII_SOCKET", _SC_PII_SOCKET}, +#endif +#ifdef _SC_PII_XTI + {"SC_PII_XTI", _SC_PII_XTI}, +#endif +#ifdef _SC_POLL + {"SC_POLL", _SC_POLL}, +#endif +#ifdef _SC_PRIORITIZED_IO + {"SC_PRIORITIZED_IO", _SC_PRIORITIZED_IO}, +#endif +#ifdef _SC_PRIORITY_SCHEDULING + {"SC_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING}, +#endif +#ifdef _SC_REALTIME_SIGNALS + {"SC_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS}, +#endif +#ifdef _SC_RE_DUP_MAX + {"SC_RE_DUP_MAX", _SC_RE_DUP_MAX}, +#endif +#ifdef _SC_RTSIG_MAX + {"SC_RTSIG_MAX", _SC_RTSIG_MAX}, +#endif +#ifdef _SC_SAVED_IDS + {"SC_SAVED_IDS", _SC_SAVED_IDS}, +#endif +#ifdef _SC_SCHAR_MAX + {"SC_SCHAR_MAX", _SC_SCHAR_MAX}, +#endif +#ifdef _SC_SCHAR_MIN + {"SC_SCHAR_MIN", _SC_SCHAR_MIN}, +#endif +#ifdef _SC_SELECT + {"SC_SELECT", _SC_SELECT}, +#endif +#ifdef _SC_SEMAPHORES + {"SC_SEMAPHORES", _SC_SEMAPHORES}, +#endif +#ifdef _SC_SEM_NSEMS_MAX + {"SC_SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX}, +#endif +#ifdef _SC_SEM_VALUE_MAX + {"SC_SEM_VALUE_MAX", _SC_SEM_VALUE_MAX}, +#endif +#ifdef _SC_SHARED_MEMORY_OBJECTS + {"SC_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS}, +#endif +#ifdef _SC_SHRT_MAX + {"SC_SHRT_MAX", _SC_SHRT_MAX}, +#endif +#ifdef _SC_SHRT_MIN + {"SC_SHRT_MIN", _SC_SHRT_MIN}, +#endif +#ifdef _SC_SIGQUEUE_MAX + {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX}, +#endif +#ifdef _SC_SIGRT_MAX + {"SC_SIGRT_MAX", _SC_SIGRT_MAX}, +#endif +#ifdef _SC_SIGRT_MIN + {"SC_SIGRT_MIN", _SC_SIGRT_MIN}, +#endif +#ifdef _SC_SOFTPOWER + {"SC_SOFTPOWER", _SC_SOFTPOWER}, +#endif +#ifdef _SC_SPLIT_CACHE + {"SC_SPLIT_CACHE", _SC_SPLIT_CACHE}, +#endif +#ifdef _SC_SSIZE_MAX + {"SC_SSIZE_MAX", _SC_SSIZE_MAX}, +#endif +#ifdef _SC_STACK_PROT + {"SC_STACK_PROT", _SC_STACK_PROT}, +#endif +#ifdef _SC_STREAM_MAX + {"SC_STREAM_MAX", _SC_STREAM_MAX}, +#endif +#ifdef _SC_SYNCHRONIZED_IO + {"SC_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO}, +#endif +#ifdef _SC_THREADS + {"SC_THREADS", _SC_THREADS}, +#endif +#ifdef _SC_THREAD_ATTR_STACKADDR + {"SC_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR}, +#endif +#ifdef _SC_THREAD_ATTR_STACKSIZE + {"SC_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE}, +#endif +#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS + {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS}, +#endif +#ifdef _SC_THREAD_KEYS_MAX + {"SC_THREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX}, +#endif +#ifdef _SC_THREAD_PRIORITY_SCHEDULING + {"SC_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING}, +#endif +#ifdef _SC_THREAD_PRIO_INHERIT + {"SC_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT}, +#endif +#ifdef _SC_THREAD_PRIO_PROTECT + {"SC_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT}, +#endif +#ifdef _SC_THREAD_PROCESS_SHARED + {"SC_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED}, +#endif +#ifdef _SC_THREAD_SAFE_FUNCTIONS + {"SC_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS}, +#endif +#ifdef _SC_THREAD_STACK_MIN + {"SC_THREAD_STACK_MIN", _SC_THREAD_STACK_MIN}, +#endif +#ifdef _SC_THREAD_THREADS_MAX + {"SC_THREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX}, +#endif +#ifdef _SC_TIMERS + {"SC_TIMERS", _SC_TIMERS}, +#endif +#ifdef _SC_TIMER_MAX + {"SC_TIMER_MAX", _SC_TIMER_MAX}, +#endif +#ifdef _SC_TTY_NAME_MAX + {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX}, +#endif +#ifdef _SC_TZNAME_MAX + {"SC_TZNAME_MAX", _SC_TZNAME_MAX}, +#endif +#ifdef _SC_T_IOV_MAX + {"SC_T_IOV_MAX", _SC_T_IOV_MAX}, +#endif +#ifdef _SC_UCHAR_MAX + {"SC_UCHAR_MAX", _SC_UCHAR_MAX}, +#endif +#ifdef _SC_UINT_MAX + {"SC_UINT_MAX", _SC_UINT_MAX}, +#endif +#ifdef _SC_UIO_MAXIOV + {"SC_UIO_MAXIOV", _SC_UIO_MAXIOV}, +#endif +#ifdef _SC_ULONG_MAX + {"SC_ULONG_MAX", _SC_ULONG_MAX}, +#endif +#ifdef _SC_USHRT_MAX + {"SC_USHRT_MAX", _SC_USHRT_MAX}, +#endif +#ifdef _SC_VERSION + {"SC_VERSION", _SC_VERSION}, +#endif +#ifdef _SC_WORD_BIT + {"SC_WORD_BIT", _SC_WORD_BIT}, +#endif +#ifdef _SC_XBS5_ILP32_OFF32 + {"SC_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32}, +#endif +#ifdef _SC_XBS5_ILP32_OFFBIG + {"SC_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG}, +#endif +#ifdef _SC_XBS5_LP64_OFF64 + {"SC_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64}, +#endif +#ifdef _SC_XBS5_LPBIG_OFFBIG + {"SC_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG}, +#endif +#ifdef _SC_XOPEN_CRYPT + {"SC_XOPEN_CRYPT", _SC_XOPEN_CRYPT}, +#endif +#ifdef _SC_XOPEN_ENH_I18N + {"SC_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N}, +#endif +#ifdef _SC_XOPEN_LEGACY + {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY}, +#endif +#ifdef _SC_XOPEN_REALTIME + {"SC_XOPEN_REALTIME", _SC_XOPEN_REALTIME}, +#endif +#ifdef _SC_XOPEN_REALTIME_THREADS + {"SC_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS}, +#endif +#ifdef _SC_XOPEN_SHM + {"SC_XOPEN_SHM", _SC_XOPEN_SHM}, +#endif +#ifdef _SC_XOPEN_UNIX + {"SC_XOPEN_UNIX", _SC_XOPEN_UNIX}, +#endif +#ifdef _SC_XOPEN_VERSION + {"SC_XOPEN_VERSION", _SC_XOPEN_VERSION}, +#endif +#ifdef _SC_XOPEN_XCU_VERSION + {"SC_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION}, +#endif +#ifdef _SC_XOPEN_XPG2 + {"SC_XOPEN_XPG2", _SC_XOPEN_XPG2}, +#endif +#ifdef _SC_XOPEN_XPG3 + {"SC_XOPEN_XPG3", _SC_XOPEN_XPG3}, +#endif +#ifdef _SC_XOPEN_XPG4 + {"SC_XOPEN_XPG4", _SC_XOPEN_XPG4}, +#endif +#ifdef _SC_MINSIGSTKSZ + {"SC_MINSIGSTKSZ", _SC_MINSIGSTKSZ}, +#endif +}; + +static int +conv_sysconf_confname(PyObject *arg, int *valuep) +{ + return conv_confname(arg, valuep, posix_constants_sysconf, + sizeof(posix_constants_sysconf) + / sizeof(struct constdef)); +} + + +/*[clinic input] +os.sysconf -> long + name: sysconf_confname + / + +Return an integer-valued system configuration variable. +[clinic start generated code]*/ + +static long +os_sysconf_impl(PyObject *module, int name) +/*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/ +{ + long value; + + errno = 0; + value = sysconf(name); + if (value == -1 && errno != 0) + posix_error(); + return value; +} +#endif /* HAVE_SYSCONF */ + + +/* This code is used to ensure that the tables of configuration value names + * are in sorted order as required by conv_confname(), and also to build + * the exported dictionaries that are used to publish information about the + * names available on the host platform. + * + * Sorting the table at runtime ensures that the table is properly ordered + * when used, even for platforms we're not able to test on. It also makes + * it easier to add additional entries to the tables. + */ + +static int +cmp_constdefs(const void *v1, const void *v2) +{ + const struct constdef *c1 = + (const struct constdef *) v1; + const struct constdef *c2 = + (const struct constdef *) v2; + + return strcmp(c1->name, c2->name); +} + +static int +setup_confname_table(struct constdef *table, size_t tablesize, + const char *tablename, PyObject *module) +{ + PyObject *d = NULL; + size_t i; + + qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs); + d = PyDict_New(); + if (d == NULL) + return -1; + + for (i=0; i < tablesize; ++i) { + PyObject *o = PyLong_FromLong(table[i].value); + if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) { + Py_XDECREF(o); + Py_DECREF(d); + return -1; + } + Py_DECREF(o); + } + return PyModule_AddObject(module, tablename, d); +} + +/* Return -1 on failure, 0 on success. */ +static int +setup_confname_tables(PyObject *module) +{ +#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF) + if (setup_confname_table(posix_constants_pathconf, + sizeof(posix_constants_pathconf) + / sizeof(struct constdef), + "pathconf_names", module)) + return -1; +#endif +#ifdef HAVE_CONFSTR + if (setup_confname_table(posix_constants_confstr, + sizeof(posix_constants_confstr) + / sizeof(struct constdef), + "confstr_names", module)) + return -1; +#endif +#ifdef HAVE_SYSCONF + if (setup_confname_table(posix_constants_sysconf, + sizeof(posix_constants_sysconf) + / sizeof(struct constdef), + "sysconf_names", module)) + return -1; +#endif + return 0; +} + + +/*[clinic input] +os.abort + +Abort the interpreter immediately. + +This function 'dumps core' or otherwise fails in the hardest way possible +on the hosting operating system. This function never returns. +[clinic start generated code]*/ + +static PyObject * +os_abort_impl(PyObject *module) +/*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/ +{ + abort(); + /*NOTREACHED*/ +#ifndef __clang__ + /* Issue #28152: abort() is declared with __attribute__((__noreturn__)). + GCC emits a warning without "return NULL;" (compiler bug?), but Clang + is smarter and emits a warning on the return. */ + Py_FatalError("abort() called from Python code didn't abort!"); + return NULL; +#endif +} + +#ifdef MS_WINDOWS +/* Grab ShellExecute dynamically from shell32 */ +static int has_ShellExecute = -1; +static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR, + LPCWSTR, INT); +static int +check_ShellExecute() +{ + HINSTANCE hShell32; + + /* only recheck */ + if (-1 == has_ShellExecute) { + Py_BEGIN_ALLOW_THREADS + /* Security note: this call is not vulnerable to "DLL hijacking". + SHELL32 is part of "KnownDLLs" and so Windows always load + the system SHELL32.DLL, even if there is another SHELL32.DLL + in the DLL search path. */ + hShell32 = LoadLibraryW(L"SHELL32"); + if (hShell32) { + *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32, + "ShellExecuteW"); + has_ShellExecute = Py_ShellExecuteW != NULL; + } else { + has_ShellExecute = 0; + } + Py_END_ALLOW_THREADS + } + return has_ShellExecute; +} + + +/*[clinic input] +os.startfile + filepath: path_t + operation: Py_UNICODE = NULL + arguments: Py_UNICODE = NULL + cwd: path_t(nullable=True) = None + show_cmd: int = 1 + +Start a file with its associated application. + +When "operation" is not specified or "open", this acts like +double-clicking the file in Explorer, or giving the file name as an +argument to the DOS "start" command: the file is opened with whatever +application (if any) its extension is associated. +When another "operation" is given, it specifies what should be done with +the file. A typical operation is "print". + +"arguments" is passed to the application, but should be omitted if the +file is a document. + +"cwd" is the working directory for the operation. If "filepath" is +relative, it will be resolved against this directory. This argument +should usually be an absolute path. + +"show_cmd" can be used to override the recommended visibility option. +See the Windows ShellExecute documentation for values. + +startfile returns as soon as the associated application is launched. +There is no option to wait for the application to close, and no way +to retrieve the application's exit status. + +The filepath is relative to the current directory. If you want to use +an absolute path, make sure the first character is not a slash ("/"); +the underlying Win32 ShellExecute function doesn't work if it is. +[clinic start generated code]*/ + +static PyObject * +os_startfile_impl(PyObject *module, path_t *filepath, + const Py_UNICODE *operation, const Py_UNICODE *arguments, + path_t *cwd, int show_cmd) +/*[clinic end generated code: output=3baa4f9795841880 input=8248997b80669622]*/ +{ + HINSTANCE rc; + + if(!check_ShellExecute()) { + /* If the OS doesn't have ShellExecute, return a + NotImplementedError. */ + return PyErr_Format(PyExc_NotImplementedError, + "startfile not available on this platform"); + } + + if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) { + return NULL; + } + if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation, + arguments, cwd->object ? cwd->object : Py_None, + show_cmd) < 0) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide, + arguments, cwd->wide, show_cmd); + Py_END_ALLOW_THREADS + + if (rc <= (HINSTANCE)32) { + win32_error_object("startfile", filepath->object); + return NULL; + } + Py_RETURN_NONE; +} +#endif /* MS_WINDOWS */ + + +#ifdef HAVE_GETLOADAVG +/*[clinic input] +os.getloadavg + +Return average recent system load information. + +Return the number of processes in the system run queue averaged over +the last 1, 5, and 15 minutes as a tuple of three floats. +Raises OSError if the load average was unobtainable. +[clinic start generated code]*/ + +static PyObject * +os_getloadavg_impl(PyObject *module) +/*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/ +{ + double loadavg[3]; + if (getloadavg(loadavg, 3)!=3) { + PyErr_SetString(PyExc_OSError, "Load averages are unobtainable"); + return NULL; + } else + return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]); +} +#endif /* HAVE_GETLOADAVG */ + + +/*[clinic input] +os.device_encoding + fd: int + +Return a string describing the encoding of a terminal's file descriptor. + +The file descriptor must be attached to a terminal. +If the device is not a terminal, return None. +[clinic start generated code]*/ + +static PyObject * +os_device_encoding_impl(PyObject *module, int fd) +/*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/ +{ + return _Py_device_encoding(fd); +} + + +#ifdef HAVE_SETRESUID +/*[clinic input] +os.setresuid + + ruid: uid_t + euid: uid_t + suid: uid_t + / + +Set the current process's real, effective, and saved user ids. +[clinic start generated code]*/ + +static PyObject * +os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid) +/*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/ +{ + if (setresuid(ruid, euid, suid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETRESUID */ + + +#ifdef HAVE_SETRESGID +/*[clinic input] +os.setresgid + + rgid: gid_t + egid: gid_t + sgid: gid_t + / + +Set the current process's real, effective, and saved group ids. +[clinic start generated code]*/ + +static PyObject * +os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid) +/*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/ +{ + if (setresgid(rgid, egid, sgid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETRESGID */ + + +#ifdef HAVE_GETRESUID +/*[clinic input] +os.getresuid + +Return a tuple of the current process's real, effective, and saved user ids. +[clinic start generated code]*/ + +static PyObject * +os_getresuid_impl(PyObject *module) +/*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/ +{ + uid_t ruid, euid, suid; + if (getresuid(&ruid, &euid, &suid) < 0) + return posix_error(); + return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid), + _PyLong_FromUid(euid), + _PyLong_FromUid(suid)); +} +#endif /* HAVE_GETRESUID */ + + +#ifdef HAVE_GETRESGID +/*[clinic input] +os.getresgid + +Return a tuple of the current process's real, effective, and saved group ids. +[clinic start generated code]*/ + +static PyObject * +os_getresgid_impl(PyObject *module) +/*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/ +{ + gid_t rgid, egid, sgid; + if (getresgid(&rgid, &egid, &sgid) < 0) + return posix_error(); + return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid), + _PyLong_FromGid(egid), + _PyLong_FromGid(sgid)); +} +#endif /* HAVE_GETRESGID */ + + +#ifdef USE_XATTRS +/*[clinic input] +os.getxattr + + path: path_t(allow_fd=True) + attribute: path_t + * + follow_symlinks: bool = True + +Return the value of extended attribute attribute on path. + +path may be either a string, a path-like object, or an open file descriptor. +If follow_symlinks is False, and the last element of the path is a symbolic + link, getxattr will examine the symbolic link itself instead of the file + the link points to. + +[clinic start generated code]*/ + +static PyObject * +os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute, + int follow_symlinks) +/*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/ +{ + Py_ssize_t i; + PyObject *buffer = NULL; + + if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks)) + return NULL; + + if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) { + return NULL; + } + + for (i = 0; ; i++) { + void *ptr; + ssize_t result; + static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0}; + Py_ssize_t buffer_size = buffer_sizes[i]; + if (!buffer_size) { + path_error(path); + return NULL; + } + buffer = PyBytes_FromStringAndSize(NULL, buffer_size); + if (!buffer) + return NULL; + ptr = PyBytes_AS_STRING(buffer); + + Py_BEGIN_ALLOW_THREADS; + if (path->fd >= 0) + result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size); + else if (follow_symlinks) + result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size); + else + result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size); + Py_END_ALLOW_THREADS; + + if (result < 0) { + Py_DECREF(buffer); + if (errno == ERANGE) + continue; + path_error(path); + return NULL; + } + + if (result != buffer_size) { + /* Can only shrink. */ + _PyBytes_Resize(&buffer, result); + } + break; + } + + return buffer; +} + + +/*[clinic input] +os.setxattr + + path: path_t(allow_fd=True) + attribute: path_t + value: Py_buffer + flags: int = 0 + * + follow_symlinks: bool = True + +Set extended attribute attribute on path to value. + +path may be either a string, a path-like object, or an open file descriptor. +If follow_symlinks is False, and the last element of the path is a symbolic + link, setxattr will modify the symbolic link itself instead of the file + the link points to. + +[clinic start generated code]*/ + +static PyObject * +os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute, + Py_buffer *value, int flags, int follow_symlinks) +/*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/ +{ + ssize_t result; + + if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks)) + return NULL; + + if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object, + value->buf, value->len, flags) < 0) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS; + if (path->fd > -1) + result = fsetxattr(path->fd, attribute->narrow, + value->buf, value->len, flags); + else if (follow_symlinks) + result = setxattr(path->narrow, attribute->narrow, + value->buf, value->len, flags); + else + result = lsetxattr(path->narrow, attribute->narrow, + value->buf, value->len, flags); + Py_END_ALLOW_THREADS; + + if (result) { + path_error(path); + return NULL; + } + + Py_RETURN_NONE; +} + + +/*[clinic input] +os.removexattr + + path: path_t(allow_fd=True) + attribute: path_t + * + follow_symlinks: bool = True + +Remove extended attribute attribute on path. + +path may be either a string, a path-like object, or an open file descriptor. +If follow_symlinks is False, and the last element of the path is a symbolic + link, removexattr will modify the symbolic link itself instead of the file + the link points to. + +[clinic start generated code]*/ + +static PyObject * +os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute, + int follow_symlinks) +/*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/ +{ + ssize_t result; + + if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks)) + return NULL; + + if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS; + if (path->fd > -1) + result = fremovexattr(path->fd, attribute->narrow); + else if (follow_symlinks) + result = removexattr(path->narrow, attribute->narrow); + else + result = lremovexattr(path->narrow, attribute->narrow); + Py_END_ALLOW_THREADS; + + if (result) { + return path_error(path); + } + + Py_RETURN_NONE; +} + + +/*[clinic input] +os.listxattr + + path: path_t(allow_fd=True, nullable=True) = None + * + follow_symlinks: bool = True + +Return a list of extended attributes on path. + +path may be either None, a string, a path-like object, or an open file descriptor. +if path is None, listxattr will examine the current directory. +If follow_symlinks is False, and the last element of the path is a symbolic + link, listxattr will examine the symbolic link itself instead of the file + the link points to. +[clinic start generated code]*/ + +static PyObject * +os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks) +/*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/ +{ + Py_ssize_t i; + PyObject *result = NULL; + const char *name; + char *buffer = NULL; + + if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks)) + goto exit; + + if (PySys_Audit("os.listxattr", "(O)", + path->object ? path->object : Py_None) < 0) { + return NULL; + } + + name = path->narrow ? path->narrow : "."; + + for (i = 0; ; i++) { + const char *start, *trace, *end; + ssize_t length; + static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 }; + Py_ssize_t buffer_size = buffer_sizes[i]; + if (!buffer_size) { + /* ERANGE */ + path_error(path); + break; + } + buffer = PyMem_Malloc(buffer_size); + if (!buffer) { + PyErr_NoMemory(); + break; + } + + Py_BEGIN_ALLOW_THREADS; + if (path->fd > -1) + length = flistxattr(path->fd, buffer, buffer_size); + else if (follow_symlinks) + length = listxattr(name, buffer, buffer_size); + else + length = llistxattr(name, buffer, buffer_size); + Py_END_ALLOW_THREADS; + + if (length < 0) { + if (errno == ERANGE) { + PyMem_Free(buffer); + buffer = NULL; + continue; + } + path_error(path); + break; + } + + result = PyList_New(0); + if (!result) { + goto exit; + } + + end = buffer + length; + for (trace = start = buffer; trace != end; trace++) { + if (!*trace) { + int error; + PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start, + trace - start); + if (!attribute) { + Py_DECREF(result); + result = NULL; + goto exit; + } + error = PyList_Append(result, attribute); + Py_DECREF(attribute); + if (error) { + Py_DECREF(result); + result = NULL; + goto exit; + } + start = trace + 1; + } + } + break; + } +exit: + if (buffer) + PyMem_Free(buffer); + return result; +} +#endif /* USE_XATTRS */ + + +/*[clinic input] +os.urandom + + size: Py_ssize_t + / + +Return a bytes object containing random bytes suitable for cryptographic use. +[clinic start generated code]*/ + +static PyObject * +os_urandom_impl(PyObject *module, Py_ssize_t size) +/*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/ +{ + PyObject *bytes; + int result; + + if (size < 0) + return PyErr_Format(PyExc_ValueError, + "negative argument not allowed"); + bytes = PyBytes_FromStringAndSize(NULL, size); + if (bytes == NULL) + return NULL; + + result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes)); + if (result == -1) { + Py_DECREF(bytes); + return NULL; + } + return bytes; +} + +#ifdef HAVE_MEMFD_CREATE +/*[clinic input] +os.memfd_create + + name: FSConverter + flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC + +[clinic start generated code]*/ + +static PyObject * +os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags) +/*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/ +{ + int fd; + const char *bytes = PyBytes_AS_STRING(name); + Py_BEGIN_ALLOW_THREADS + fd = memfd_create(bytes, flags); + Py_END_ALLOW_THREADS + if (fd == -1) { + return PyErr_SetFromErrno(PyExc_OSError); + } + return PyLong_FromLong(fd); +} +#endif + +#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC) +/*[clinic input] +os.eventfd + + initval: unsigned_int + flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC + +Creates and returns an event notification file descriptor. +[clinic start generated code]*/ + +static PyObject * +os_eventfd_impl(PyObject *module, unsigned int initval, int flags) +/*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/ + +{ + /* initval is limited to uint32_t, internal counter is uint64_t */ + int fd; + Py_BEGIN_ALLOW_THREADS + fd = eventfd(initval, flags); + Py_END_ALLOW_THREADS + if (fd == -1) { + return PyErr_SetFromErrno(PyExc_OSError); + } + return PyLong_FromLong(fd); +} + +/*[clinic input] +os.eventfd_read + + fd: fildes + +Read eventfd value +[clinic start generated code]*/ + +static PyObject * +os_eventfd_read_impl(PyObject *module, int fd) +/*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/ +{ + eventfd_t value; + int result; + Py_BEGIN_ALLOW_THREADS + result = eventfd_read(fd, &value); + Py_END_ALLOW_THREADS + if (result == -1) { + return PyErr_SetFromErrno(PyExc_OSError); + } + return PyLong_FromUnsignedLongLong(value); +} + +/*[clinic input] +os.eventfd_write + + fd: fildes + value: unsigned_long_long + +Write eventfd value. +[clinic start generated code]*/ + +static PyObject * +os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value) +/*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/ +{ + int result; + Py_BEGIN_ALLOW_THREADS + result = eventfd_write(fd, value); + Py_END_ALLOW_THREADS + if (result == -1) { + return PyErr_SetFromErrno(PyExc_OSError); + } + Py_RETURN_NONE; +} +#endif /* HAVE_EVENTFD && EFD_CLOEXEC */ + +/* Terminal size querying */ + +PyDoc_STRVAR(TerminalSize_docstring, + "A tuple of (columns, lines) for holding terminal window size"); + +static PyStructSequence_Field TerminalSize_fields[] = { + {"columns", "width of the terminal window in characters"}, + {"lines", "height of the terminal window in characters"}, + {NULL, NULL} +}; + +static PyStructSequence_Desc TerminalSize_desc = { + "os.terminal_size", + TerminalSize_docstring, + TerminalSize_fields, + 2, +}; + +#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) +/*[clinic input] +os.get_terminal_size + + fd: int(c_default="fileno(stdout)", py_default="") = -1 + / + +Return the size of the terminal window as (columns, lines). + +The optional argument fd (default standard output) specifies +which file descriptor should be queried. + +If the file descriptor is not connected to a terminal, an OSError +is thrown. + +This function will only be defined if an implementation is +available for this system. + +shutil.get_terminal_size is the high-level function which should +normally be used, os.get_terminal_size is the low-level implementation. +[clinic start generated code]*/ + +static PyObject * +os_get_terminal_size_impl(PyObject *module, int fd) +/*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/ +{ + int columns, lines; + PyObject *termsize; + + /* Under some conditions stdout may not be connected and + * fileno(stdout) may point to an invalid file descriptor. For example + * GUI apps don't have valid standard streams by default. + * + * If this happens, and the optional fd argument is not present, + * the ioctl below will fail returning EBADF. This is what we want. + */ + +#ifdef TERMSIZE_USE_IOCTL + { + struct winsize w; + if (ioctl(fd, TIOCGWINSZ, &w)) + return PyErr_SetFromErrno(PyExc_OSError); + columns = w.ws_col; + lines = w.ws_row; + } +#endif /* TERMSIZE_USE_IOCTL */ + +#ifdef TERMSIZE_USE_CONIO + { + HANDLE handle; + CONSOLE_SCREEN_BUFFER_INFO csbi; + handle = _Py_get_osfhandle(fd); + if (handle == INVALID_HANDLE_VALUE) + return NULL; + + if (!GetConsoleScreenBufferInfo(handle, &csbi)) + return PyErr_SetFromWindowsErr(0); + + columns = csbi.srWindow.Right - csbi.srWindow.Left + 1; + lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; + } +#endif /* TERMSIZE_USE_CONIO */ + + PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType; + termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType); + if (termsize == NULL) + return NULL; + PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns)); + PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines)); + if (PyErr_Occurred()) { + Py_DECREF(termsize); + return NULL; + } + return termsize; +} +#endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */ + + +/*[clinic input] +os.cpu_count + +Return the number of CPUs in the system; return None if indeterminable. + +This number is not equivalent to the number of CPUs the current process can +use. The number of usable CPUs can be obtained with +``len(os.sched_getaffinity(0))`` +[clinic start generated code]*/ + +static PyObject * +os_cpu_count_impl(PyObject *module) +/*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/ +{ + int ncpu = 0; +#ifdef MS_WINDOWS + ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS); +#elif defined(__hpux) + ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL); +#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) + ncpu = sysconf(_SC_NPROCESSORS_ONLN); +#elif defined(__VXWORKS__) + ncpu = _Py_popcount32(vxCpuEnabledGet()); +#elif defined(__DragonFly__) || \ + defined(__OpenBSD__) || \ + defined(__FreeBSD__) || \ + defined(__NetBSD__) || \ + defined(__APPLE__) + int mib[2]; + size_t len = sizeof(ncpu); + mib[0] = CTL_HW; + mib[1] = HW_NCPU; + if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) + ncpu = 0; +#endif + if (ncpu >= 1) + return PyLong_FromLong(ncpu); + else + Py_RETURN_NONE; +} + + +/*[clinic input] +os.get_inheritable -> bool + + fd: int + / + +Get the close-on-exe flag of the specified file descriptor. +[clinic start generated code]*/ + +static int +os_get_inheritable_impl(PyObject *module, int fd) +/*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/ +{ + int return_value; + _Py_BEGIN_SUPPRESS_IPH + return_value = _Py_get_inheritable(fd); + _Py_END_SUPPRESS_IPH + return return_value; +} + + +/*[clinic input] +os.set_inheritable + fd: int + inheritable: int + / + +Set the inheritable flag of the specified file descriptor. +[clinic start generated code]*/ + +static PyObject * +os_set_inheritable_impl(PyObject *module, int fd, int inheritable) +/*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/ +{ + int result; + + _Py_BEGIN_SUPPRESS_IPH + result = _Py_set_inheritable(fd, inheritable, NULL); + _Py_END_SUPPRESS_IPH + if (result < 0) + return NULL; + Py_RETURN_NONE; +} + + +#ifdef MS_WINDOWS +/*[clinic input] +os.get_handle_inheritable -> bool + handle: intptr_t + / + +Get the close-on-exe flag of the specified file descriptor. +[clinic start generated code]*/ + +static int +os_get_handle_inheritable_impl(PyObject *module, intptr_t handle) +/*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/ +{ + DWORD flags; + + if (!GetHandleInformation((HANDLE)handle, &flags)) { + PyErr_SetFromWindowsErr(0); + return -1; + } + + return flags & HANDLE_FLAG_INHERIT; +} + + +/*[clinic input] +os.set_handle_inheritable + handle: intptr_t + inheritable: bool + / + +Set the inheritable flag of the specified handle. +[clinic start generated code]*/ + +static PyObject * +os_set_handle_inheritable_impl(PyObject *module, intptr_t handle, + int inheritable) +/*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/ +{ + DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0; + if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) { + PyErr_SetFromWindowsErr(0); + return NULL; + } + Py_RETURN_NONE; +} +#endif /* MS_WINDOWS */ + +#ifndef MS_WINDOWS +/*[clinic input] +os.get_blocking -> bool + fd: int + / + +Get the blocking mode of the file descriptor. + +Return False if the O_NONBLOCK flag is set, True if the flag is cleared. +[clinic start generated code]*/ + +static int +os_get_blocking_impl(PyObject *module, int fd) +/*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/ +{ + int blocking; + + _Py_BEGIN_SUPPRESS_IPH + blocking = _Py_get_blocking(fd); + _Py_END_SUPPRESS_IPH + return blocking; +} + +/*[clinic input] +os.set_blocking + fd: int + blocking: bool(accept={int}) + / + +Set the blocking mode of the specified file descriptor. + +Set the O_NONBLOCK flag if blocking is False, +clear the O_NONBLOCK flag otherwise. +[clinic start generated code]*/ + +static PyObject * +os_set_blocking_impl(PyObject *module, int fd, int blocking) +/*[clinic end generated code: output=384eb43aa0762a9d input=bf5c8efdc5860ff3]*/ +{ + int result; + + _Py_BEGIN_SUPPRESS_IPH + result = _Py_set_blocking(fd, blocking); + _Py_END_SUPPRESS_IPH + if (result < 0) + return NULL; + Py_RETURN_NONE; +} +#endif /* !MS_WINDOWS */ + + +/*[clinic input] +class os.DirEntry "DirEntry *" "DirEntryType" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/ + +typedef struct { + PyObject_HEAD + PyObject *name; + PyObject *path; + PyObject *stat; + PyObject *lstat; +#ifdef MS_WINDOWS + struct _Py_stat_struct win32_lstat; + uint64_t win32_file_index; + int got_file_index; +#else /* POSIX */ +#ifdef HAVE_DIRENT_D_TYPE + unsigned char d_type; +#endif + ino_t d_ino; + int dir_fd; +#endif +} DirEntry; + +static void +DirEntry_dealloc(DirEntry *entry) +{ + PyTypeObject *tp = Py_TYPE(entry); + Py_XDECREF(entry->name); + Py_XDECREF(entry->path); + Py_XDECREF(entry->stat); + Py_XDECREF(entry->lstat); + freefunc free_func = PyType_GetSlot(tp, Py_tp_free); + free_func(entry); + Py_DECREF(tp); +} + +/* Forward reference */ +static int +DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self, + int follow_symlinks, unsigned short mode_bits); + +/*[clinic input] +os.DirEntry.is_symlink -> bool + defining_class: defining_class + / + +Return True if the entry is a symbolic link; cached per entry. +[clinic start generated code]*/ + +static int +os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class) +/*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/ +{ +#ifdef MS_WINDOWS + return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK; +#elif defined(HAVE_DIRENT_D_TYPE) + /* POSIX */ + if (self->d_type != DT_UNKNOWN) + return self->d_type == DT_LNK; + else + return DirEntry_test_mode(defining_class, self, 0, S_IFLNK); +#else + /* POSIX without d_type */ + return DirEntry_test_mode(defining_class, self, 0, S_IFLNK); +#endif +} + +/*[clinic input] +os.DirEntry.is_junction -> bool + defining_class: defining_class + / + +Return True if the entry is a junction; cached per entry. +[clinic start generated code]*/ + +static int +os_DirEntry_is_junction_impl(DirEntry *self, PyTypeObject *defining_class) +/*[clinic end generated code: output=7061a07b0ef2cd1f input=475cd36fb7d4723f]*/ +{ +#ifdef MS_WINDOWS + return self->win32_lstat.st_reparse_tag == IO_REPARSE_TAG_MOUNT_POINT; +#else + return 0; +#endif +} + +static PyObject * +DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks) +{ + int result; + STRUCT_STAT st; + PyObject *ub; + +#ifdef MS_WINDOWS + if (!PyUnicode_FSDecoder(self->path, &ub)) + return NULL; + wchar_t *path = PyUnicode_AsWideCharString(ub, NULL); + Py_DECREF(ub); +#else /* POSIX */ + if (!PyUnicode_FSConverter(self->path, &ub)) + return NULL; + const char *path = PyBytes_AS_STRING(ub); + if (self->dir_fd != DEFAULT_DIR_FD) { +#ifdef HAVE_FSTATAT + if (HAVE_FSTATAT_RUNTIME) { + Py_BEGIN_ALLOW_THREADS + result = fstatat(self->dir_fd, path, &st, + follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); + Py_END_ALLOW_THREADS + } else + +#endif /* HAVE_FSTATAT */ + { + Py_DECREF(ub); + PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat"); + return NULL; + } + } + else +#endif + { + Py_BEGIN_ALLOW_THREADS + if (follow_symlinks) { + result = STAT(path, &st); + } + else { + result = LSTAT(path, &st); + } + Py_END_ALLOW_THREADS + } +#if defined(MS_WINDOWS) + PyMem_Free(path); +#else + Py_DECREF(ub); +#endif + + if (result != 0) + return path_object_error(self->path); + + return _pystat_fromstructstat(module, &st); +} + +static PyObject * +DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self) +{ + if (!self->lstat) { + PyObject *module = PyType_GetModule(defining_class); +#ifdef MS_WINDOWS + self->lstat = _pystat_fromstructstat(module, &self->win32_lstat); +#else /* POSIX */ + self->lstat = DirEntry_fetch_stat(module, self, 0); +#endif + } + return Py_XNewRef(self->lstat); +} + +/*[clinic input] +os.DirEntry.stat + defining_class: defining_class + / + * + follow_symlinks: bool = True + +Return stat_result object for the entry; cached per entry. +[clinic start generated code]*/ + +static PyObject * +os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class, + int follow_symlinks) +/*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/ +{ + if (!follow_symlinks) { + return DirEntry_get_lstat(defining_class, self); + } + + if (!self->stat) { + int result = os_DirEntry_is_symlink_impl(self, defining_class); + if (result == -1) { + return NULL; + } + if (result) { + PyObject *module = PyType_GetModule(defining_class); + self->stat = DirEntry_fetch_stat(module, self, 1); + } + else { + self->stat = DirEntry_get_lstat(defining_class, self); + } + } + + return Py_XNewRef(self->stat); +} + +/* Set exception and return -1 on error, 0 for False, 1 for True */ +static int +DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self, + int follow_symlinks, unsigned short mode_bits) +{ + PyObject *stat = NULL; + PyObject *st_mode = NULL; + long mode; + int result; +#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE) + int is_symlink; + int need_stat; +#endif +#ifdef MS_WINDOWS + unsigned long dir_bits; +#endif + +#ifdef MS_WINDOWS + is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK; + need_stat = follow_symlinks && is_symlink; +#elif defined(HAVE_DIRENT_D_TYPE) + is_symlink = self->d_type == DT_LNK; + need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink); +#endif + +#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE) + if (need_stat) { +#endif + stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks); + if (!stat) { + if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) { + /* If file doesn't exist (anymore), then return False + (i.e., say it's not a file/directory) */ + PyErr_Clear(); + return 0; + } + goto error; + } + _posixstate* state = get_posix_state(PyType_GetModule(defining_class)); + st_mode = PyObject_GetAttr(stat, state->st_mode); + if (!st_mode) + goto error; + + mode = PyLong_AsLong(st_mode); + if (mode == -1 && PyErr_Occurred()) + goto error; + Py_CLEAR(st_mode); + Py_CLEAR(stat); + result = (mode & S_IFMT) == mode_bits; +#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE) + } + else if (is_symlink) { + assert(mode_bits != S_IFLNK); + result = 0; + } + else { + assert(mode_bits == S_IFDIR || mode_bits == S_IFREG); +#ifdef MS_WINDOWS + dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY; + if (mode_bits == S_IFDIR) + result = dir_bits != 0; + else + result = dir_bits == 0; +#else /* POSIX */ + if (mode_bits == S_IFDIR) + result = self->d_type == DT_DIR; + else + result = self->d_type == DT_REG; +#endif + } +#endif + + return result; + +error: + Py_XDECREF(st_mode); + Py_XDECREF(stat); + return -1; +} + +/*[clinic input] +os.DirEntry.is_dir -> bool + defining_class: defining_class + / + * + follow_symlinks: bool = True + +Return True if the entry is a directory; cached per entry. +[clinic start generated code]*/ + +static int +os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class, + int follow_symlinks) +/*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/ +{ + return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR); +} + +/*[clinic input] +os.DirEntry.is_file -> bool + defining_class: defining_class + / + * + follow_symlinks: bool = True + +Return True if the entry is a file; cached per entry. +[clinic start generated code]*/ + +static int +os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class, + int follow_symlinks) +/*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/ +{ + return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG); +} + +/*[clinic input] +os.DirEntry.inode + +Return inode of the entry; cached per entry. +[clinic start generated code]*/ + +static PyObject * +os_DirEntry_inode_impl(DirEntry *self) +/*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/ +{ +#ifdef MS_WINDOWS + if (!self->got_file_index) { + PyObject *unicode; + STRUCT_STAT stat; + int result; + + if (!PyUnicode_FSDecoder(self->path, &unicode)) + return NULL; + wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL); + Py_DECREF(unicode); + result = LSTAT(path, &stat); + PyMem_Free(path); + + if (result != 0) + return path_object_error(self->path); + + self->win32_file_index = stat.st_ino; + self->got_file_index = 1; + } + static_assert(sizeof(unsigned long long) >= sizeof(self->win32_file_index), + "DirEntry.win32_file_index is larger than unsigned long long"); + return PyLong_FromUnsignedLongLong(self->win32_file_index); +#else /* POSIX */ + static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino), + "DirEntry.d_ino is larger than unsigned long long"); + return PyLong_FromUnsignedLongLong(self->d_ino); +#endif +} + +static PyObject * +DirEntry_repr(DirEntry *self) +{ + return PyUnicode_FromFormat("", self->name); +} + +/*[clinic input] +os.DirEntry.__fspath__ + +Returns the path for the entry. +[clinic start generated code]*/ + +static PyObject * +os_DirEntry___fspath___impl(DirEntry *self) +/*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/ +{ + return Py_NewRef(self->path); +} + +static PyMemberDef DirEntry_members[] = { + {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY, + "the entry's base filename, relative to scandir() \"path\" argument"}, + {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY, + "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"}, + {NULL} +}; + +#include "clinic/posixmodule.c.h" + +static PyMethodDef DirEntry_methods[] = { + OS_DIRENTRY_IS_DIR_METHODDEF + OS_DIRENTRY_IS_FILE_METHODDEF + OS_DIRENTRY_IS_SYMLINK_METHODDEF + OS_DIRENTRY_IS_JUNCTION_METHODDEF + OS_DIRENTRY_STAT_METHODDEF + OS_DIRENTRY_INODE_METHODDEF + OS_DIRENTRY___FSPATH___METHODDEF + {"__class_getitem__", Py_GenericAlias, + METH_O|METH_CLASS, PyDoc_STR("See PEP 585")}, + {NULL} +}; + +static PyType_Slot DirEntryType_slots[] = { + {Py_tp_dealloc, DirEntry_dealloc}, + {Py_tp_repr, DirEntry_repr}, + {Py_tp_methods, DirEntry_methods}, + {Py_tp_members, DirEntry_members}, + {0, 0}, +}; + +static PyType_Spec DirEntryType_spec = { + MODNAME ".DirEntry", + sizeof(DirEntry), + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, + DirEntryType_slots +}; + + +#ifdef MS_WINDOWS + +static wchar_t * +join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename) +{ + Py_ssize_t path_len; + Py_ssize_t size; + wchar_t *result; + wchar_t ch; + + if (!path_wide) { /* Default arg: "." */ + path_wide = L"."; + path_len = 1; + } + else { + path_len = wcslen(path_wide); + } + + /* The +1's are for the path separator and the NUL */ + size = path_len + 1 + wcslen(filename) + 1; + result = PyMem_New(wchar_t, size); + if (!result) { + PyErr_NoMemory(); + return NULL; + } + wcscpy(result, path_wide); + if (path_len > 0) { + ch = result[path_len - 1]; + if (ch != SEP && ch != ALTSEP && ch != L':') + result[path_len++] = SEP; + wcscpy(result + path_len, filename); + } + return result; +} + +static PyObject * +DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW) +{ + DirEntry *entry; + BY_HANDLE_FILE_INFORMATION file_info; + ULONG reparse_tag; + wchar_t *joined_path; + + PyObject *DirEntryType = get_posix_state(module)->DirEntryType; + entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType); + if (!entry) + return NULL; + entry->name = NULL; + entry->path = NULL; + entry->stat = NULL; + entry->lstat = NULL; + entry->got_file_index = 0; + + entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1); + if (!entry->name) + goto error; + if (path->narrow) { + Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name)); + if (!entry->name) + goto error; + } + + joined_path = join_path_filenameW(path->wide, dataW->cFileName); + if (!joined_path) + goto error; + + entry->path = PyUnicode_FromWideChar(joined_path, -1); + PyMem_Free(joined_path); + if (!entry->path) + goto error; + if (path->narrow) { + Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path)); + if (!entry->path) + goto error; + } + + find_data_to_file_info(dataW, &file_info, &reparse_tag); + _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat); + + return (PyObject *)entry; + +error: + Py_DECREF(entry); + return NULL; +} + +#else /* POSIX */ + +static char * +join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len) +{ + Py_ssize_t path_len; + Py_ssize_t size; + char *result; + + if (!path_narrow) { /* Default arg: "." */ + path_narrow = "."; + path_len = 1; + } + else { + path_len = strlen(path_narrow); + } + + if (filename_len == -1) + filename_len = strlen(filename); + + /* The +1's are for the path separator and the NUL */ + size = path_len + 1 + filename_len + 1; + result = PyMem_New(char, size); + if (!result) { + PyErr_NoMemory(); + return NULL; + } + strcpy(result, path_narrow); + if (path_len > 0 && result[path_len - 1] != '/') + result[path_len++] = '/'; + strcpy(result + path_len, filename); + return result; +} + +static PyObject * +DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name, + Py_ssize_t name_len, ino_t d_ino +#ifdef HAVE_DIRENT_D_TYPE + , unsigned char d_type +#endif + ) +{ + DirEntry *entry; + char *joined_path; + + PyObject *DirEntryType = get_posix_state(module)->DirEntryType; + entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType); + if (!entry) + return NULL; + entry->name = NULL; + entry->path = NULL; + entry->stat = NULL; + entry->lstat = NULL; + + if (path->fd != -1) { + entry->dir_fd = path->fd; + joined_path = NULL; + } + else { + entry->dir_fd = DEFAULT_DIR_FD; + joined_path = join_path_filename(path->narrow, name, name_len); + if (!joined_path) + goto error; + } + + if (!path->narrow || !PyBytes_Check(path->object)) { + entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len); + if (joined_path) + entry->path = PyUnicode_DecodeFSDefault(joined_path); + } + else { + entry->name = PyBytes_FromStringAndSize(name, name_len); + if (joined_path) + entry->path = PyBytes_FromString(joined_path); + } + PyMem_Free(joined_path); + if (!entry->name) + goto error; + + if (path->fd != -1) { + entry->path = Py_NewRef(entry->name); + } + else if (!entry->path) + goto error; + +#ifdef HAVE_DIRENT_D_TYPE + entry->d_type = d_type; +#endif + entry->d_ino = d_ino; + + return (PyObject *)entry; + +error: + Py_XDECREF(entry); + return NULL; +} + +#endif + + +typedef struct { + PyObject_HEAD + path_t path; +#ifdef MS_WINDOWS + HANDLE handle; + WIN32_FIND_DATAW file_data; + int first_time; +#else /* POSIX */ + DIR *dirp; +#endif +#ifdef HAVE_FDOPENDIR + int fd; +#endif +} ScandirIterator; + +#ifdef MS_WINDOWS + +static int +ScandirIterator_is_closed(ScandirIterator *iterator) +{ + return iterator->handle == INVALID_HANDLE_VALUE; +} + +static void +ScandirIterator_closedir(ScandirIterator *iterator) +{ + HANDLE handle = iterator->handle; + + if (handle == INVALID_HANDLE_VALUE) + return; + + iterator->handle = INVALID_HANDLE_VALUE; + Py_BEGIN_ALLOW_THREADS + FindClose(handle); + Py_END_ALLOW_THREADS +} + +static PyObject * +ScandirIterator_iternext(ScandirIterator *iterator) +{ + WIN32_FIND_DATAW *file_data = &iterator->file_data; + BOOL success; + PyObject *entry; + + /* Happens if the iterator is iterated twice, or closed explicitly */ + if (iterator->handle == INVALID_HANDLE_VALUE) + return NULL; + + while (1) { + if (!iterator->first_time) { + Py_BEGIN_ALLOW_THREADS + success = FindNextFileW(iterator->handle, file_data); + Py_END_ALLOW_THREADS + if (!success) { + /* Error or no more files */ + if (GetLastError() != ERROR_NO_MORE_FILES) + path_error(&iterator->path); + break; + } + } + iterator->first_time = 0; + + /* Skip over . and .. */ + if (wcscmp(file_data->cFileName, L".") != 0 && + wcscmp(file_data->cFileName, L"..") != 0) + { + PyObject *module = PyType_GetModule(Py_TYPE(iterator)); + entry = DirEntry_from_find_data(module, &iterator->path, file_data); + if (!entry) + break; + return entry; + } + + /* Loop till we get a non-dot directory or finish iterating */ + } + + /* Error or no more files */ + ScandirIterator_closedir(iterator); + return NULL; +} + +#else /* POSIX */ + +static int +ScandirIterator_is_closed(ScandirIterator *iterator) +{ + return !iterator->dirp; +} + +static void +ScandirIterator_closedir(ScandirIterator *iterator) +{ + DIR *dirp = iterator->dirp; + + if (!dirp) + return; + + iterator->dirp = NULL; + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_FDOPENDIR + if (iterator->path.fd != -1) + rewinddir(dirp); +#endif + closedir(dirp); + Py_END_ALLOW_THREADS + return; +} + +static PyObject * +ScandirIterator_iternext(ScandirIterator *iterator) +{ + struct dirent *direntp; + Py_ssize_t name_len; + int is_dot; + PyObject *entry; + + /* Happens if the iterator is iterated twice, or closed explicitly */ + if (!iterator->dirp) + return NULL; + + while (1) { + errno = 0; + Py_BEGIN_ALLOW_THREADS + direntp = readdir(iterator->dirp); + Py_END_ALLOW_THREADS + + if (!direntp) { + /* Error or no more files */ + if (errno != 0) + path_error(&iterator->path); + break; + } + + /* Skip over . and .. */ + name_len = NAMLEN(direntp); + is_dot = direntp->d_name[0] == '.' && + (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2)); + if (!is_dot) { + PyObject *module = PyType_GetModule(Py_TYPE(iterator)); + entry = DirEntry_from_posix_info(module, + &iterator->path, direntp->d_name, + name_len, direntp->d_ino +#ifdef HAVE_DIRENT_D_TYPE + , direntp->d_type +#endif + ); + if (!entry) + break; + return entry; + } + + /* Loop till we get a non-dot directory or finish iterating */ + } + + /* Error or no more files */ + ScandirIterator_closedir(iterator); + return NULL; +} + +#endif + +static PyObject * +ScandirIterator_close(ScandirIterator *self, PyObject *args) +{ + ScandirIterator_closedir(self); + Py_RETURN_NONE; +} + +static PyObject * +ScandirIterator_enter(PyObject *self, PyObject *args) +{ + return Py_NewRef(self); +} + +static PyObject * +ScandirIterator_exit(ScandirIterator *self, PyObject *args) +{ + ScandirIterator_closedir(self); + Py_RETURN_NONE; +} + +static void +ScandirIterator_finalize(ScandirIterator *iterator) +{ + PyObject *error_type, *error_value, *error_traceback; + + /* Save the current exception, if any. */ + PyErr_Fetch(&error_type, &error_value, &error_traceback); + + if (!ScandirIterator_is_closed(iterator)) { + ScandirIterator_closedir(iterator); + + if (PyErr_ResourceWarning((PyObject *)iterator, 1, + "unclosed scandir iterator %R", iterator)) { + /* Spurious errors can appear at shutdown */ + if (PyErr_ExceptionMatches(PyExc_Warning)) { + PyErr_WriteUnraisable((PyObject *) iterator); + } + } + } + + path_cleanup(&iterator->path); + + /* Restore the saved exception. */ + PyErr_Restore(error_type, error_value, error_traceback); +} + +static void +ScandirIterator_dealloc(ScandirIterator *iterator) +{ + PyTypeObject *tp = Py_TYPE(iterator); + if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0) + return; + + freefunc free_func = PyType_GetSlot(tp, Py_tp_free); + free_func(iterator); + Py_DECREF(tp); +} + +static PyMethodDef ScandirIterator_methods[] = { + {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS}, + {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS}, + {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS}, + {NULL} +}; + +static PyType_Slot ScandirIteratorType_slots[] = { + {Py_tp_dealloc, ScandirIterator_dealloc}, + {Py_tp_finalize, ScandirIterator_finalize}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, ScandirIterator_iternext}, + {Py_tp_methods, ScandirIterator_methods}, + {0, 0}, +}; + +static PyType_Spec ScandirIteratorType_spec = { + MODNAME ".ScandirIterator", + sizeof(ScandirIterator), + 0, + // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since + // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance. + (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE + | Py_TPFLAGS_DISALLOW_INSTANTIATION), + ScandirIteratorType_slots +}; + +/*[clinic input] +os.scandir + + path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None + +Return an iterator of DirEntry objects for given path. + +path can be specified as either str, bytes, or a path-like object. If path +is bytes, the names of yielded DirEntry objects will also be bytes; in +all other circumstances they will be str. + +If path is None, uses the path='.'. +[clinic start generated code]*/ + +static PyObject * +os_scandir_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/ +{ + ScandirIterator *iterator; +#ifdef MS_WINDOWS + wchar_t *path_strW; +#else + const char *path_str; +#ifdef HAVE_FDOPENDIR + int fd = -1; +#endif +#endif + + if (PySys_Audit("os.scandir", "O", + path->object ? path->object : Py_None) < 0) { + return NULL; + } + + PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType; + iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType); + if (!iterator) + return NULL; + +#ifdef MS_WINDOWS + iterator->handle = INVALID_HANDLE_VALUE; +#else + iterator->dirp = NULL; +#endif + + /* Move the ownership to iterator->path */ + memcpy(&iterator->path, path, sizeof(path_t)); + memset(path, 0, sizeof(path_t)); + +#ifdef MS_WINDOWS + iterator->first_time = 1; + + path_strW = join_path_filenameW(iterator->path.wide, L"*.*"); + if (!path_strW) + goto error; + + Py_BEGIN_ALLOW_THREADS + iterator->handle = FindFirstFileW(path_strW, &iterator->file_data); + Py_END_ALLOW_THREADS + + PyMem_Free(path_strW); + + if (iterator->handle == INVALID_HANDLE_VALUE) { + path_error(&iterator->path); + goto error; + } +#else /* POSIX */ + errno = 0; +#ifdef HAVE_FDOPENDIR + if (iterator->path.fd != -1) { + if (HAVE_FDOPENDIR_RUNTIME) { + /* closedir() closes the FD, so we duplicate it */ + fd = _Py_dup(iterator->path.fd); + if (fd == -1) + goto error; + + Py_BEGIN_ALLOW_THREADS + iterator->dirp = fdopendir(fd); + Py_END_ALLOW_THREADS + } else { + PyErr_SetString(PyExc_TypeError, + "scandir: path should be string, bytes, os.PathLike or None, not int"); + return NULL; + } + } + else +#endif + { + if (iterator->path.narrow) + path_str = iterator->path.narrow; + else + path_str = "."; + + Py_BEGIN_ALLOW_THREADS + iterator->dirp = opendir(path_str); + Py_END_ALLOW_THREADS + } + + if (!iterator->dirp) { + path_error(&iterator->path); +#ifdef HAVE_FDOPENDIR + if (fd != -1) { + Py_BEGIN_ALLOW_THREADS + close(fd); + Py_END_ALLOW_THREADS + } +#endif + goto error; + } +#endif + + return (PyObject *)iterator; + +error: + Py_DECREF(iterator); + return NULL; +} + +/* + Return the file system path representation of the object. + + If the object is str or bytes, then allow it to pass through with + an incremented refcount. If the object defines __fspath__(), then + return the result of that method. All other types raise a TypeError. +*/ +PyObject * +PyOS_FSPath(PyObject *path) +{ + /* For error message reasons, this function is manually inlined in + path_converter(). */ + PyObject *func = NULL; + PyObject *path_repr = NULL; + + if (PyUnicode_Check(path) || PyBytes_Check(path)) { + return Py_NewRef(path); + } + + func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__)); + if (NULL == func) { + return PyErr_Format(PyExc_TypeError, + "expected str, bytes or os.PathLike object, " + "not %.200s", + _PyType_Name(Py_TYPE(path))); + } + + path_repr = _PyObject_CallNoArgs(func); + Py_DECREF(func); + if (NULL == path_repr) { + return NULL; + } + + if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) { + PyErr_Format(PyExc_TypeError, + "expected %.200s.__fspath__() to return str or bytes, " + "not %.200s", _PyType_Name(Py_TYPE(path)), + _PyType_Name(Py_TYPE(path_repr))); + Py_DECREF(path_repr); + return NULL; + } + + return path_repr; +} + +/*[clinic input] +os.fspath + + path: object + +Return the file system path representation of the object. + +If the object is str or bytes, then allow it to pass through as-is. If the +object defines __fspath__(), then return the result of that method. All other +types raise a TypeError. +[clinic start generated code]*/ + +static PyObject * +os_fspath_impl(PyObject *module, PyObject *path) +/*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/ +{ + return PyOS_FSPath(path); +} + +#ifdef HAVE_GETRANDOM_SYSCALL +/*[clinic input] +os.getrandom + + size: Py_ssize_t + flags: int=0 + +Obtain a series of random bytes. +[clinic start generated code]*/ + +static PyObject * +os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags) +/*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/ +{ + PyObject *bytes; + Py_ssize_t n; + + if (size < 0) { + errno = EINVAL; + return posix_error(); + } + + bytes = PyBytes_FromStringAndSize(NULL, size); + if (bytes == NULL) { + PyErr_NoMemory(); + return NULL; + } + + while (1) { + n = syscall(SYS_getrandom, + PyBytes_AS_STRING(bytes), + PyBytes_GET_SIZE(bytes), + flags); + if (n < 0 && errno == EINTR) { + if (PyErr_CheckSignals() < 0) { + goto error; + } + + /* getrandom() was interrupted by a signal: retry */ + continue; + } + break; + } + + if (n < 0) { + PyErr_SetFromErrno(PyExc_OSError); + goto error; + } + + if (n != size) { + _PyBytes_Resize(&bytes, n); + } + + return bytes; + +error: + Py_DECREF(bytes); + return NULL; +} +#endif /* HAVE_GETRANDOM_SYSCALL */ + +#ifdef MS_WINDOWS +/* bpo-36085: Helper functions for managing DLL search directories + * on win32 + */ + +typedef DLL_DIRECTORY_COOKIE (WINAPI *PAddDllDirectory)(PCWSTR newDirectory); +typedef BOOL (WINAPI *PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie); + +/*[clinic input] +os._add_dll_directory + + path: path_t + +Add a path to the DLL search path. + +This search path is used when resolving dependencies for imported +extension modules (the module itself is resolved through sys.path), +and also by ctypes. + +Returns an opaque value that may be passed to os.remove_dll_directory +to remove this directory from the search path. +[clinic start generated code]*/ + +static PyObject * +os__add_dll_directory_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/ +{ + HMODULE hKernel32; + PAddDllDirectory AddDllDirectory; + DLL_DIRECTORY_COOKIE cookie = 0; + DWORD err = 0; + + if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) { + return NULL; + } + + /* For Windows 7, we have to load this. As this will be a fairly + infrequent operation, just do it each time. Kernel32 is always + loaded. */ + Py_BEGIN_ALLOW_THREADS + if (!(hKernel32 = GetModuleHandleW(L"kernel32")) || + !(AddDllDirectory = (PAddDllDirectory)GetProcAddress( + hKernel32, "AddDllDirectory")) || + !(cookie = (*AddDllDirectory)(path->wide))) { + err = GetLastError(); + } + Py_END_ALLOW_THREADS + + if (err) { + return win32_error_object_err("add_dll_directory", + path->object, err); + } + + return PyCapsule_New(cookie, "DLL directory cookie", NULL); +} + +/*[clinic input] +os._remove_dll_directory + + cookie: object + +Removes a path from the DLL search path. + +The parameter is an opaque value that was returned from +os.add_dll_directory. You can only remove directories that you added +yourself. +[clinic start generated code]*/ + +static PyObject * +os__remove_dll_directory_impl(PyObject *module, PyObject *cookie) +/*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/ +{ + HMODULE hKernel32; + PRemoveDllDirectory RemoveDllDirectory; + DLL_DIRECTORY_COOKIE cookieValue; + DWORD err = 0; + + if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) { + PyErr_SetString(PyExc_TypeError, + "Provided cookie was not returned from os.add_dll_directory"); + return NULL; + } + + cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer( + cookie, "DLL directory cookie"); + + /* For Windows 7, we have to load this. As this will be a fairly + infrequent operation, just do it each time. Kernel32 is always + loaded. */ + Py_BEGIN_ALLOW_THREADS + if (!(hKernel32 = GetModuleHandleW(L"kernel32")) || + !(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress( + hKernel32, "RemoveDllDirectory")) || + !(*RemoveDllDirectory)(cookieValue)) { + err = GetLastError(); + } + Py_END_ALLOW_THREADS + + if (err) { + return win32_error_object_err("remove_dll_directory", + NULL, err); + } + + if (PyCapsule_SetName(cookie, NULL)) { + return NULL; + } + + Py_RETURN_NONE; +} + +#endif + + +/* Only check if WIFEXITED is available: expect that it comes + with WEXITSTATUS, WIFSIGNALED, etc. + + os.waitstatus_to_exitcode() is implemented in C and not in Python, so + subprocess can safely call it during late Python finalization without + risking that used os attributes were set to None by finalize_modules(). */ +#if defined(WIFEXITED) || defined(MS_WINDOWS) +/*[clinic input] +os.waitstatus_to_exitcode + + status as status_obj: object + +Convert a wait status to an exit code. + +On Unix: + +* If WIFEXITED(status) is true, return WEXITSTATUS(status). +* If WIFSIGNALED(status) is true, return -WTERMSIG(status). +* Otherwise, raise a ValueError. + +On Windows, return status shifted right by 8 bits. + +On Unix, if the process is being traced or if waitpid() was called with +WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true. +This function must not be called if WIFSTOPPED(status) is true. +[clinic start generated code]*/ + +static PyObject * +os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj) +/*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/ +{ +#ifndef MS_WINDOWS + int status = _PyLong_AsInt(status_obj); + if (status == -1 && PyErr_Occurred()) { + return NULL; + } + + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + int exitcode; + if (WIFEXITED(wait_status)) { + exitcode = WEXITSTATUS(wait_status); + /* Sanity check to provide warranty on the function behavior. + It should not occur in practice */ + if (exitcode < 0) { + PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode); + return NULL; + } + } + else if (WIFSIGNALED(wait_status)) { + int signum = WTERMSIG(wait_status); + /* Sanity check to provide warranty on the function behavior. + It should not occurs in practice */ + if (signum <= 0) { + PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum); + return NULL; + } + exitcode = -signum; + } else if (WIFSTOPPED(wait_status)) { + /* Status only received if the process is being traced + or if waitpid() was called with WUNTRACED option. */ + int signum = WSTOPSIG(wait_status); + PyErr_Format(PyExc_ValueError, + "process stopped by delivery of signal %i", + signum); + return NULL; + } + else { + PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status); + return NULL; + } + return PyLong_FromLong(exitcode); +#else + /* Windows implementation: see os.waitpid() implementation + which uses _cwait(). */ + unsigned long long status = PyLong_AsUnsignedLongLong(status_obj); + if (status == (unsigned long long)-1 && PyErr_Occurred()) { + return NULL; + } + + unsigned long long exitcode = (status >> 8); + /* ExitProcess() accepts an UINT type: + reject exit code which doesn't fit in an UINT */ + if (exitcode > UINT_MAX) { + PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode); + return NULL; + } + return PyLong_FromUnsignedLong((unsigned long)exitcode); +#endif +} +#endif + + +static PyMethodDef posix_methods[] = { + + OS_STAT_METHODDEF + OS_ACCESS_METHODDEF + OS_TTYNAME_METHODDEF + OS_CHDIR_METHODDEF + OS_CHFLAGS_METHODDEF + OS_CHMOD_METHODDEF + OS_FCHMOD_METHODDEF + OS_LCHMOD_METHODDEF + OS_CHOWN_METHODDEF + OS_FCHOWN_METHODDEF + OS_LCHOWN_METHODDEF + OS_LCHFLAGS_METHODDEF + OS_CHROOT_METHODDEF + OS_CTERMID_METHODDEF + OS_GETCWD_METHODDEF + OS_GETCWDB_METHODDEF + OS_LINK_METHODDEF + OS_LISTDIR_METHODDEF + OS_LSTAT_METHODDEF + OS_MKDIR_METHODDEF + OS_NICE_METHODDEF + OS_GETPRIORITY_METHODDEF + OS_SETPRIORITY_METHODDEF + OS_POSIX_SPAWN_METHODDEF + OS_POSIX_SPAWNP_METHODDEF + OS_READLINK_METHODDEF + OS_COPY_FILE_RANGE_METHODDEF + OS_SPLICE_METHODDEF + OS_RENAME_METHODDEF + OS_REPLACE_METHODDEF + OS_RMDIR_METHODDEF + OS_SYMLINK_METHODDEF + OS_SYSTEM_METHODDEF + OS_UMASK_METHODDEF + OS_UNAME_METHODDEF + OS_UNLINK_METHODDEF + OS_REMOVE_METHODDEF + OS_UTIME_METHODDEF + OS_TIMES_METHODDEF + OS__EXIT_METHODDEF + OS__FCOPYFILE_METHODDEF + OS_EXECV_METHODDEF + OS_EXECVE_METHODDEF + OS_SPAWNV_METHODDEF + OS_SPAWNVE_METHODDEF + OS_FORK1_METHODDEF + OS_FORK_METHODDEF + OS_REGISTER_AT_FORK_METHODDEF + OS_SCHED_GET_PRIORITY_MAX_METHODDEF + OS_SCHED_GET_PRIORITY_MIN_METHODDEF + OS_SCHED_GETPARAM_METHODDEF + OS_SCHED_GETSCHEDULER_METHODDEF + OS_SCHED_RR_GET_INTERVAL_METHODDEF + OS_SCHED_SETPARAM_METHODDEF + OS_SCHED_SETSCHEDULER_METHODDEF + OS_SCHED_YIELD_METHODDEF + OS_SCHED_SETAFFINITY_METHODDEF + OS_SCHED_GETAFFINITY_METHODDEF + OS_OPENPTY_METHODDEF + OS_LOGIN_TTY_METHODDEF + OS_FORKPTY_METHODDEF + OS_GETEGID_METHODDEF + OS_GETEUID_METHODDEF + OS_GETGID_METHODDEF + OS_GETGROUPLIST_METHODDEF + OS_GETGROUPS_METHODDEF + OS_GETPID_METHODDEF + OS_GETPGRP_METHODDEF + OS_GETPPID_METHODDEF + OS_GETUID_METHODDEF + OS_GETLOGIN_METHODDEF + OS_KILL_METHODDEF + OS_KILLPG_METHODDEF + OS_PLOCK_METHODDEF + OS_STARTFILE_METHODDEF + OS_SETUID_METHODDEF + OS_SETEUID_METHODDEF + OS_SETREUID_METHODDEF + OS_SETGID_METHODDEF + OS_SETEGID_METHODDEF + OS_SETREGID_METHODDEF + OS_SETGROUPS_METHODDEF + OS_INITGROUPS_METHODDEF + OS_GETPGID_METHODDEF + OS_SETPGRP_METHODDEF + OS_WAIT_METHODDEF + OS_WAIT3_METHODDEF + OS_WAIT4_METHODDEF + OS_WAITID_METHODDEF + OS_WAITPID_METHODDEF + OS_PIDFD_OPEN_METHODDEF + OS_GETSID_METHODDEF + OS_SETSID_METHODDEF + OS_SETPGID_METHODDEF + OS_TCGETPGRP_METHODDEF + OS_TCSETPGRP_METHODDEF + OS_OPEN_METHODDEF + OS_CLOSE_METHODDEF + OS_CLOSERANGE_METHODDEF + OS_DEVICE_ENCODING_METHODDEF + OS_DUP_METHODDEF + OS_DUP2_METHODDEF + OS_LOCKF_METHODDEF + OS_LSEEK_METHODDEF + OS_READ_METHODDEF + OS_READV_METHODDEF + OS_PREAD_METHODDEF + OS_PREADV_METHODDEF + OS_WRITE_METHODDEF + OS_WRITEV_METHODDEF + OS_PWRITE_METHODDEF + OS_PWRITEV_METHODDEF + OS_SENDFILE_METHODDEF + OS_FSTAT_METHODDEF + OS_ISATTY_METHODDEF + OS_PIPE_METHODDEF + OS_PIPE2_METHODDEF + OS_MKFIFO_METHODDEF + OS_MKNOD_METHODDEF + OS_MAJOR_METHODDEF + OS_MINOR_METHODDEF + OS_MAKEDEV_METHODDEF + OS_FTRUNCATE_METHODDEF + OS_TRUNCATE_METHODDEF + OS_POSIX_FALLOCATE_METHODDEF + OS_POSIX_FADVISE_METHODDEF + OS_PUTENV_METHODDEF + OS_UNSETENV_METHODDEF + OS_STRERROR_METHODDEF + OS_FCHDIR_METHODDEF + OS_FSYNC_METHODDEF + OS_SYNC_METHODDEF + OS_FDATASYNC_METHODDEF + OS_WCOREDUMP_METHODDEF + OS_WIFCONTINUED_METHODDEF + OS_WIFSTOPPED_METHODDEF + OS_WIFSIGNALED_METHODDEF + OS_WIFEXITED_METHODDEF + OS_WEXITSTATUS_METHODDEF + OS_WTERMSIG_METHODDEF + OS_WSTOPSIG_METHODDEF + OS_FSTATVFS_METHODDEF + OS_STATVFS_METHODDEF + OS_CONFSTR_METHODDEF + OS_SYSCONF_METHODDEF + OS_FPATHCONF_METHODDEF + OS_PATHCONF_METHODDEF + OS_ABORT_METHODDEF + OS__GETFULLPATHNAME_METHODDEF + OS__GETDISKUSAGE_METHODDEF + OS__GETFINALPATHNAME_METHODDEF + OS__GETVOLUMEPATHNAME_METHODDEF + OS__PATH_SPLITROOT_METHODDEF + OS__PATH_NORMPATH_METHODDEF + OS_GETLOADAVG_METHODDEF + OS_URANDOM_METHODDEF + OS_SETRESUID_METHODDEF + OS_SETRESGID_METHODDEF + OS_GETRESUID_METHODDEF + OS_GETRESGID_METHODDEF + + OS_GETXATTR_METHODDEF + OS_SETXATTR_METHODDEF + OS_REMOVEXATTR_METHODDEF + OS_LISTXATTR_METHODDEF + + OS_GET_TERMINAL_SIZE_METHODDEF + OS_CPU_COUNT_METHODDEF + OS_GET_INHERITABLE_METHODDEF + OS_SET_INHERITABLE_METHODDEF + OS_GET_HANDLE_INHERITABLE_METHODDEF + OS_SET_HANDLE_INHERITABLE_METHODDEF + OS_GET_BLOCKING_METHODDEF + OS_SET_BLOCKING_METHODDEF + OS_SCANDIR_METHODDEF + OS_FSPATH_METHODDEF + OS_GETRANDOM_METHODDEF + OS_MEMFD_CREATE_METHODDEF + OS_EVENTFD_METHODDEF + OS_EVENTFD_READ_METHODDEF + OS_EVENTFD_WRITE_METHODDEF + OS__ADD_DLL_DIRECTORY_METHODDEF + OS__REMOVE_DLL_DIRECTORY_METHODDEF + OS_WAITSTATUS_TO_EXITCODE_METHODDEF + OS_SETNS_METHODDEF + OS_UNSHARE_METHODDEF + {NULL, NULL} /* Sentinel */ +}; + +static int +all_ins(PyObject *m) +{ +#ifdef F_OK + if (PyModule_AddIntMacro(m, F_OK)) return -1; +#endif +#ifdef R_OK + if (PyModule_AddIntMacro(m, R_OK)) return -1; +#endif +#ifdef W_OK + if (PyModule_AddIntMacro(m, W_OK)) return -1; +#endif +#ifdef X_OK + if (PyModule_AddIntMacro(m, X_OK)) return -1; +#endif +#ifdef NGROUPS_MAX + if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1; +#endif +#ifdef TMP_MAX + if (PyModule_AddIntMacro(m, TMP_MAX)) return -1; +#endif +#ifdef WCONTINUED + if (PyModule_AddIntMacro(m, WCONTINUED)) return -1; +#endif +#ifdef WNOHANG + if (PyModule_AddIntMacro(m, WNOHANG)) return -1; +#endif +#ifdef WUNTRACED + if (PyModule_AddIntMacro(m, WUNTRACED)) return -1; +#endif +#ifdef O_RDONLY + if (PyModule_AddIntMacro(m, O_RDONLY)) return -1; +#endif +#ifdef O_WRONLY + if (PyModule_AddIntMacro(m, O_WRONLY)) return -1; +#endif +#ifdef O_RDWR + if (PyModule_AddIntMacro(m, O_RDWR)) return -1; +#endif +#ifdef O_NDELAY + if (PyModule_AddIntMacro(m, O_NDELAY)) return -1; +#endif +#ifdef O_NONBLOCK + if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1; +#endif +#ifdef O_APPEND + if (PyModule_AddIntMacro(m, O_APPEND)) return -1; +#endif +#ifdef O_DSYNC + if (PyModule_AddIntMacro(m, O_DSYNC)) return -1; +#endif +#ifdef O_RSYNC + if (PyModule_AddIntMacro(m, O_RSYNC)) return -1; +#endif +#ifdef O_SYNC + if (PyModule_AddIntMacro(m, O_SYNC)) return -1; +#endif +#ifdef O_NOCTTY + if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1; +#endif +#ifdef O_CREAT + if (PyModule_AddIntMacro(m, O_CREAT)) return -1; +#endif +#ifdef O_EXCL + if (PyModule_AddIntMacro(m, O_EXCL)) return -1; +#endif +#ifdef O_TRUNC + if (PyModule_AddIntMacro(m, O_TRUNC)) return -1; +#endif +#ifdef O_BINARY + if (PyModule_AddIntMacro(m, O_BINARY)) return -1; +#endif +#ifdef O_TEXT + if (PyModule_AddIntMacro(m, O_TEXT)) return -1; +#endif +#ifdef O_XATTR + if (PyModule_AddIntMacro(m, O_XATTR)) return -1; +#endif +#ifdef O_LARGEFILE + if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1; +#endif +#ifndef __GNU__ +#ifdef O_SHLOCK + if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1; +#endif +#ifdef O_EXLOCK + if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1; +#endif +#endif +#ifdef O_EXEC + if (PyModule_AddIntMacro(m, O_EXEC)) return -1; +#endif +#ifdef O_SEARCH + if (PyModule_AddIntMacro(m, O_SEARCH)) return -1; +#endif +#ifdef O_PATH + if (PyModule_AddIntMacro(m, O_PATH)) return -1; +#endif +#ifdef O_TTY_INIT + if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1; +#endif +#ifdef O_TMPFILE + if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1; +#endif +#ifdef PRIO_PROCESS + if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1; +#endif +#ifdef PRIO_PGRP + if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1; +#endif +#ifdef PRIO_USER + if (PyModule_AddIntMacro(m, PRIO_USER)) return -1; +#endif +#ifdef O_CLOEXEC + if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1; +#endif +#ifdef O_ACCMODE + if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1; +#endif +#ifdef O_EVTONLY + if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1; +#endif +#ifdef O_FSYNC + if (PyModule_AddIntMacro(m, O_FSYNC)) return -1; +#endif +#ifdef O_SYMLINK + if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1; +#endif + +#ifdef SEEK_HOLE + if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1; +#endif +#ifdef SEEK_DATA + if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1; +#endif + +/* MS Windows */ +#ifdef O_NOINHERIT + /* Don't inherit in child processes. */ + if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1; +#endif +#ifdef _O_SHORT_LIVED + /* Optimize for short life (keep in memory). */ + /* MS forgot to define this one with a non-underscore form too. */ + if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1; +#endif +#ifdef O_TEMPORARY + /* Automatically delete when last handle is closed. */ + if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1; +#endif +#ifdef O_RANDOM + /* Optimize for random access. */ + if (PyModule_AddIntMacro(m, O_RANDOM)) return -1; +#endif +#ifdef O_SEQUENTIAL + /* Optimize for sequential access. */ + if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1; +#endif + +/* GNU extensions. */ +#ifdef O_ASYNC + /* Send a SIGIO signal whenever input or output + becomes available on file descriptor */ + if (PyModule_AddIntMacro(m, O_ASYNC)) return -1; +#endif +#ifdef O_DIRECT + /* Direct disk access. */ + if (PyModule_AddIntMacro(m, O_DIRECT)) return -1; +#endif +#ifdef O_DIRECTORY + /* Must be a directory. */ + if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1; +#endif +#ifdef O_NOFOLLOW + /* Do not follow links. */ + if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1; +#endif +#ifdef O_NOFOLLOW_ANY + if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1; +#endif +#ifdef O_NOLINKS + /* Fails if link count of the named file is greater than 1 */ + if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1; +#endif +#ifdef O_NOATIME + /* Do not update the access time. */ + if (PyModule_AddIntMacro(m, O_NOATIME)) return -1; +#endif + + /* These come from sysexits.h */ +#ifdef EX_OK + if (PyModule_AddIntMacro(m, EX_OK)) return -1; +#endif /* EX_OK */ +#ifdef EX_USAGE + if (PyModule_AddIntMacro(m, EX_USAGE)) return -1; +#endif /* EX_USAGE */ +#ifdef EX_DATAERR + if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1; +#endif /* EX_DATAERR */ +#ifdef EX_NOINPUT + if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1; +#endif /* EX_NOINPUT */ +#ifdef EX_NOUSER + if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1; +#endif /* EX_NOUSER */ +#ifdef EX_NOHOST + if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1; +#endif /* EX_NOHOST */ +#ifdef EX_UNAVAILABLE + if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1; +#endif /* EX_UNAVAILABLE */ +#ifdef EX_SOFTWARE + if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1; +#endif /* EX_SOFTWARE */ +#ifdef EX_OSERR + if (PyModule_AddIntMacro(m, EX_OSERR)) return -1; +#endif /* EX_OSERR */ +#ifdef EX_OSFILE + if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1; +#endif /* EX_OSFILE */ +#ifdef EX_CANTCREAT + if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1; +#endif /* EX_CANTCREAT */ +#ifdef EX_IOERR + if (PyModule_AddIntMacro(m, EX_IOERR)) return -1; +#endif /* EX_IOERR */ +#ifdef EX_TEMPFAIL + if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1; +#endif /* EX_TEMPFAIL */ +#ifdef EX_PROTOCOL + if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1; +#endif /* EX_PROTOCOL */ +#ifdef EX_NOPERM + if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1; +#endif /* EX_NOPERM */ +#ifdef EX_CONFIG + if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1; +#endif /* EX_CONFIG */ +#ifdef EX_NOTFOUND + if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1; +#endif /* EX_NOTFOUND */ + + /* statvfs */ +#ifdef ST_RDONLY + if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1; +#endif /* ST_RDONLY */ +#ifdef ST_NOSUID + if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1; +#endif /* ST_NOSUID */ + + /* GNU extensions */ +#ifdef ST_NODEV + if (PyModule_AddIntMacro(m, ST_NODEV)) return -1; +#endif /* ST_NODEV */ +#ifdef ST_NOEXEC + if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1; +#endif /* ST_NOEXEC */ +#ifdef ST_SYNCHRONOUS + if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1; +#endif /* ST_SYNCHRONOUS */ +#ifdef ST_MANDLOCK + if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1; +#endif /* ST_MANDLOCK */ +#ifdef ST_WRITE + if (PyModule_AddIntMacro(m, ST_WRITE)) return -1; +#endif /* ST_WRITE */ +#ifdef ST_APPEND + if (PyModule_AddIntMacro(m, ST_APPEND)) return -1; +#endif /* ST_APPEND */ +#ifdef ST_NOATIME + if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1; +#endif /* ST_NOATIME */ +#ifdef ST_NODIRATIME + if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1; +#endif /* ST_NODIRATIME */ +#ifdef ST_RELATIME + if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1; +#endif /* ST_RELATIME */ + + /* FreeBSD sendfile() constants */ +#ifdef SF_NODISKIO + if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1; +#endif + /* is obsolete since the 11.x release */ +#ifdef SF_MNOWAIT + if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1; +#endif +#ifdef SF_SYNC + if (PyModule_AddIntMacro(m, SF_SYNC)) return -1; +#endif +#ifdef SF_NOCACHE + if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1; +#endif + + /* constants for posix_fadvise */ +#ifdef POSIX_FADV_NORMAL + if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1; +#endif +#ifdef POSIX_FADV_SEQUENTIAL + if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1; +#endif +#ifdef POSIX_FADV_RANDOM + if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1; +#endif +#ifdef POSIX_FADV_NOREUSE + if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1; +#endif +#ifdef POSIX_FADV_WILLNEED + if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1; +#endif +#ifdef POSIX_FADV_DONTNEED + if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1; +#endif + + /* constants for waitid */ +#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID) + if (PyModule_AddIntMacro(m, P_PID)) return -1; + if (PyModule_AddIntMacro(m, P_PGID)) return -1; + if (PyModule_AddIntMacro(m, P_ALL)) return -1; +#ifdef P_PIDFD + if (PyModule_AddIntMacro(m, P_PIDFD)) return -1; +#endif +#ifdef PIDFD_NONBLOCK + if (PyModule_AddIntMacro(m, PIDFD_NONBLOCK)) return -1; +#endif +#endif +#ifdef WEXITED + if (PyModule_AddIntMacro(m, WEXITED)) return -1; +#endif +#ifdef WNOWAIT + if (PyModule_AddIntMacro(m, WNOWAIT)) return -1; +#endif +#ifdef WSTOPPED + if (PyModule_AddIntMacro(m, WSTOPPED)) return -1; +#endif +#ifdef CLD_EXITED + if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1; +#endif +#ifdef CLD_KILLED + if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1; +#endif +#ifdef CLD_DUMPED + if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1; +#endif +#ifdef CLD_TRAPPED + if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1; +#endif +#ifdef CLD_STOPPED + if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1; +#endif +#ifdef CLD_CONTINUED + if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1; +#endif + + /* constants for lockf */ +#ifdef F_LOCK + if (PyModule_AddIntMacro(m, F_LOCK)) return -1; +#endif +#ifdef F_TLOCK + if (PyModule_AddIntMacro(m, F_TLOCK)) return -1; +#endif +#ifdef F_ULOCK + if (PyModule_AddIntMacro(m, F_ULOCK)) return -1; +#endif +#ifdef F_TEST + if (PyModule_AddIntMacro(m, F_TEST)) return -1; +#endif + +#ifdef RWF_DSYNC + if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1; +#endif +#ifdef RWF_HIPRI + if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1; +#endif +#ifdef RWF_SYNC + if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1; +#endif +#ifdef RWF_NOWAIT + if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1; +#endif +#ifdef RWF_APPEND + if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1; +#endif + +/* constants for splice */ +#if defined(HAVE_SPLICE) && defined(__linux__) + if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1; + if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1; + if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1; +#endif + +/* constants for posix_spawn */ +#ifdef HAVE_POSIX_SPAWN + if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1; + if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1; + if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1; +#endif + +#if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN) + if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1; + if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1; + if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1; +#endif +#ifdef HAVE_SPAWNV + if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1; + if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1; +#endif + +#ifdef HAVE_SCHED_H +#ifdef SCHED_OTHER + if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1; +#endif +#ifdef SCHED_FIFO + if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1; +#endif +#ifdef SCHED_RR + if (PyModule_AddIntMacro(m, SCHED_RR)) return -1; +#endif +#ifdef SCHED_SPORADIC + if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1; +#endif +#ifdef SCHED_BATCH + if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1; +#endif +#ifdef SCHED_IDLE + if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1; +#endif +#ifdef SCHED_RESET_ON_FORK + if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1; +#endif +#ifdef SCHED_SYS + if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1; +#endif +#ifdef SCHED_IA + if (PyModule_AddIntMacro(m, SCHED_IA)) return -1; +#endif +#ifdef SCHED_FSS + if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1; +#endif +#ifdef SCHED_FX + if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1; +#endif + +/* constants for namespaces */ +#if defined(HAVE_SETNS) || defined(HAVE_UNSHARE) +#ifdef CLONE_FS + if (PyModule_AddIntMacro(m, CLONE_FS)) return -1; +#endif +#ifdef CLONE_FILES + if (PyModule_AddIntMacro(m, CLONE_FILES)) return -1; +#endif +#ifdef CLONE_NEWNS + if (PyModule_AddIntMacro(m, CLONE_NEWNS)) return -1; +#endif +#ifdef CLONE_NEWCGROUP + if (PyModule_AddIntMacro(m, CLONE_NEWCGROUP)) return -1; +#endif +#ifdef CLONE_NEWUTS + if (PyModule_AddIntMacro(m, CLONE_NEWUTS)) return -1; +#endif +#ifdef CLONE_NEWIPC + if (PyModule_AddIntMacro(m, CLONE_NEWIPC)) return -1; +#endif +#ifdef CLONE_NEWUSER + if (PyModule_AddIntMacro(m, CLONE_NEWUSER)) return -1; +#endif +#ifdef CLONE_NEWPID + if (PyModule_AddIntMacro(m, CLONE_NEWPID)) return -1; +#endif +#ifdef CLONE_NEWNET + if (PyModule_AddIntMacro(m, CLONE_NEWNET)) return -1; +#endif +#ifdef CLONE_NEWTIME + if (PyModule_AddIntMacro(m, CLONE_NEWTIME)) return -1; +#endif +#ifdef CLONE_SYSVSEM + if (PyModule_AddIntMacro(m, CLONE_SYSVSEM)) return -1; +#endif +#ifdef CLONE_THREAD + if (PyModule_AddIntMacro(m, CLONE_THREAD)) return -1; +#endif +#ifdef CLONE_SIGHAND + if (PyModule_AddIntMacro(m, CLONE_SIGHAND)) return -1; +#endif +#ifdef CLONE_VM + if (PyModule_AddIntMacro(m, CLONE_VM)) return -1; +#endif +#endif + +#endif + +#ifdef USE_XATTRS + if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1; + if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1; + if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1; +#endif + +#if HAVE_DECL_RTLD_LAZY + if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1; +#endif +#if HAVE_DECL_RTLD_NOW + if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1; +#endif +#if HAVE_DECL_RTLD_GLOBAL + if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1; +#endif +#if HAVE_DECL_RTLD_LOCAL + if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1; +#endif +#if HAVE_DECL_RTLD_NODELETE + if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1; +#endif +#if HAVE_DECL_RTLD_NOLOAD + if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1; +#endif +#if HAVE_DECL_RTLD_DEEPBIND + if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1; +#endif +#if HAVE_DECL_RTLD_MEMBER + if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1; +#endif + +#ifdef HAVE_GETRANDOM_SYSCALL + if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1; + if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1; +#endif +#ifdef HAVE_MEMFD_CREATE + if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1; + if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1; +#ifdef MFD_HUGETLB + if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1; +#endif +#ifdef MFD_HUGE_SHIFT + if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1; +#endif +#ifdef MFD_HUGE_MASK + if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1; +#endif +#ifdef MFD_HUGE_64KB + if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1; +#endif +#ifdef MFD_HUGE_512KB + if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1; +#endif +#ifdef MFD_HUGE_1MB + if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1; +#endif +#ifdef MFD_HUGE_2MB + if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1; +#endif +#ifdef MFD_HUGE_8MB + if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1; +#endif +#ifdef MFD_HUGE_16MB + if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1; +#endif +#ifdef MFD_HUGE_32MB + if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1; +#endif +#ifdef MFD_HUGE_256MB + if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1; +#endif +#ifdef MFD_HUGE_512MB + if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1; +#endif +#ifdef MFD_HUGE_1GB + if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1; +#endif +#ifdef MFD_HUGE_2GB + if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1; +#endif +#ifdef MFD_HUGE_16GB + if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1; +#endif +#endif /* HAVE_MEMFD_CREATE */ + +#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC) + if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1; +#ifdef EFD_NONBLOCK + if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1; +#endif +#ifdef EFD_SEMAPHORE + if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1; +#endif +#endif /* HAVE_EVENTFD && EFD_CLOEXEC */ + +#if defined(__APPLE__) + if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1; + if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1; + if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1; + if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1; +#endif + +#ifdef MS_WINDOWS + if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1; + if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1; + if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1; + if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1; + if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1; +#endif + + return 0; +} + + + +#define PROBE(name, test) \ + static int name(void) \ + { \ + if (test) { \ + return 1; \ + } else { \ + return 0; \ + } \ + } + +#ifdef HAVE_FSTATAT +PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME) +#endif + +#ifdef HAVE_FACCESSAT +PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME) +#endif + +#ifdef HAVE_FCHMODAT +PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME) +#endif + +#ifdef HAVE_FCHOWNAT +PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME) +#endif + +#ifdef HAVE_LINKAT +PROBE(probe_linkat, HAVE_LINKAT_RUNTIME) +#endif + +#ifdef HAVE_FDOPENDIR +PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME) +#endif + +#ifdef HAVE_MKDIRAT +PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME) +#endif + +#ifdef HAVE_MKFIFOAT +PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME) +#endif + +#ifdef HAVE_MKNODAT +PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME) +#endif + +#ifdef HAVE_RENAMEAT +PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME) +#endif + +#ifdef HAVE_UNLINKAT +PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME) +#endif + +#ifdef HAVE_OPENAT +PROBE(probe_openat, HAVE_OPENAT_RUNTIME) +#endif + +#ifdef HAVE_READLINKAT +PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME) +#endif + +#ifdef HAVE_SYMLINKAT +PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME) +#endif + +#ifdef HAVE_FUTIMENS +PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME) +#endif + +#ifdef HAVE_UTIMENSAT +PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME) +#endif + + + + +static const struct have_function { + const char * const label; + int (*probe)(void); +} have_functions[] = { + +#ifdef HAVE_EVENTFD + {"HAVE_EVENTFD", NULL}, +#endif + +#ifdef HAVE_FACCESSAT + { "HAVE_FACCESSAT", probe_faccessat }, +#endif + +#ifdef HAVE_FCHDIR + { "HAVE_FCHDIR", NULL }, +#endif + +#ifdef HAVE_FCHMOD + { "HAVE_FCHMOD", NULL }, +#endif + +#ifdef HAVE_FCHMODAT + { "HAVE_FCHMODAT", probe_fchmodat }, +#endif + +#ifdef HAVE_FCHOWN + { "HAVE_FCHOWN", NULL }, +#endif + +#ifdef HAVE_FCHOWNAT + { "HAVE_FCHOWNAT", probe_fchownat }, +#endif + +#ifdef HAVE_FEXECVE + { "HAVE_FEXECVE", NULL }, +#endif + +#ifdef HAVE_FDOPENDIR + { "HAVE_FDOPENDIR", probe_fdopendir }, +#endif + +#ifdef HAVE_FPATHCONF + { "HAVE_FPATHCONF", NULL }, +#endif + +#ifdef HAVE_FSTATAT + { "HAVE_FSTATAT", probe_fstatat }, +#endif + +#ifdef HAVE_FSTATVFS + { "HAVE_FSTATVFS", NULL }, +#endif + +#if defined HAVE_FTRUNCATE || defined MS_WINDOWS + { "HAVE_FTRUNCATE", NULL }, +#endif + +#ifdef HAVE_FUTIMENS + { "HAVE_FUTIMENS", probe_futimens }, +#endif + +#ifdef HAVE_FUTIMES + { "HAVE_FUTIMES", NULL }, +#endif + +#ifdef HAVE_FUTIMESAT + { "HAVE_FUTIMESAT", NULL }, +#endif + +#ifdef HAVE_LINKAT + { "HAVE_LINKAT", probe_linkat }, +#endif + +#ifdef HAVE_LCHFLAGS + { "HAVE_LCHFLAGS", NULL }, +#endif + +#ifdef HAVE_LCHMOD + { "HAVE_LCHMOD", NULL }, +#endif + +#ifdef HAVE_LCHOWN + { "HAVE_LCHOWN", NULL }, +#endif + +#ifdef HAVE_LSTAT + { "HAVE_LSTAT", NULL }, +#endif + +#ifdef HAVE_LUTIMES + { "HAVE_LUTIMES", NULL }, +#endif + +#ifdef HAVE_MEMFD_CREATE + { "HAVE_MEMFD_CREATE", NULL }, +#endif + +#ifdef HAVE_MKDIRAT + { "HAVE_MKDIRAT", probe_mkdirat }, +#endif + +#ifdef HAVE_MKFIFOAT + { "HAVE_MKFIFOAT", probe_mkfifoat }, +#endif + +#ifdef HAVE_MKNODAT + { "HAVE_MKNODAT", probe_mknodat }, +#endif + +#ifdef HAVE_OPENAT + { "HAVE_OPENAT", probe_openat }, +#endif + +#ifdef HAVE_READLINKAT + { "HAVE_READLINKAT", probe_readlinkat }, +#endif + +#ifdef HAVE_RENAMEAT + { "HAVE_RENAMEAT", probe_renameat }, +#endif + +#ifdef HAVE_SYMLINKAT + { "HAVE_SYMLINKAT", probe_symlinkat }, +#endif + +#ifdef HAVE_UNLINKAT + { "HAVE_UNLINKAT", probe_unlinkat }, +#endif + +#ifdef HAVE_UTIMENSAT + { "HAVE_UTIMENSAT", probe_utimensat }, +#endif + +#ifdef MS_WINDOWS + { "MS_WINDOWS", NULL }, +#endif + + { NULL, NULL } +}; + + +static int +posixmodule_exec(PyObject *m) +{ + _posixstate *state = get_posix_state(m); + +#if defined(HAVE_PWRITEV) + if (HAVE_PWRITEV_RUNTIME) {} else { + PyObject* dct = PyModule_GetDict(m); + + if (dct == NULL) { + return -1; + } + + if (PyDict_DelItemString(dct, "pwritev") == -1) { + PyErr_Clear(); + } + if (PyDict_DelItemString(dct, "preadv") == -1) { + PyErr_Clear(); + } + } +#endif + + /* Initialize environ dictionary */ + PyObject *v = convertenviron(); + Py_XINCREF(v); + if (v == NULL || PyModule_AddObject(m, "environ", v) != 0) + return -1; + Py_DECREF(v); + + if (all_ins(m)) + return -1; + + if (setup_confname_tables(m)) + return -1; + + PyModule_AddObject(m, "error", Py_NewRef(PyExc_OSError)); + +#if defined(HAVE_WAITID) && !defined(__APPLE__) + waitid_result_desc.name = MODNAME ".waitid_result"; + PyObject *WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc); + if (WaitidResultType == NULL) { + return -1; + } + PyModule_AddObject(m, "waitid_result", Py_NewRef(WaitidResultType)); + state->WaitidResultType = WaitidResultType; +#endif + + stat_result_desc.name = "os.stat_result"; /* see issue #19209 */ + stat_result_desc.fields[7].name = PyStructSequence_UnnamedField; + stat_result_desc.fields[8].name = PyStructSequence_UnnamedField; + stat_result_desc.fields[9].name = PyStructSequence_UnnamedField; + PyObject *StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc); + if (StatResultType == NULL) { + return -1; + } + PyModule_AddObject(m, "stat_result", Py_NewRef(StatResultType)); + state->StatResultType = StatResultType; + structseq_new = ((PyTypeObject *)StatResultType)->tp_new; + ((PyTypeObject *)StatResultType)->tp_new = statresult_new; + + statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */ + PyObject *StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc); + if (StatVFSResultType == NULL) { + return -1; + } + PyModule_AddObject(m, "statvfs_result", Py_NewRef(StatVFSResultType)); + state->StatVFSResultType = StatVFSResultType; +#ifdef NEED_TICKS_PER_SECOND +# if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK) + ticks_per_second = sysconf(_SC_CLK_TCK); +# elif defined(HZ) + ticks_per_second = HZ; +# else + ticks_per_second = 60; /* magic fallback value; may be bogus */ +# endif +#endif + +#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) + sched_param_desc.name = MODNAME ".sched_param"; + PyObject *SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc); + if (SchedParamType == NULL) { + return -1; + } + PyModule_AddObject(m, "sched_param", Py_NewRef(SchedParamType)); + state->SchedParamType = SchedParamType; + ((PyTypeObject *)SchedParamType)->tp_new = os_sched_param; +#endif + + /* initialize TerminalSize_info */ + PyObject *TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc); + if (TerminalSizeType == NULL) { + return -1; + } + PyModule_AddObject(m, "terminal_size", Py_NewRef(TerminalSizeType)); + state->TerminalSizeType = TerminalSizeType; + + /* initialize scandir types */ + PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL); + if (ScandirIteratorType == NULL) { + return -1; + } + state->ScandirIteratorType = ScandirIteratorType; + + PyObject *DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL); + if (DirEntryType == NULL) { + return -1; + } + PyModule_AddObject(m, "DirEntry", Py_NewRef(DirEntryType)); + state->DirEntryType = DirEntryType; + + times_result_desc.name = MODNAME ".times_result"; + PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(×_result_desc); + if (TimesResultType == NULL) { + return -1; + } + PyModule_AddObject(m, "times_result", Py_NewRef(TimesResultType)); + state->TimesResultType = TimesResultType; + + PyTypeObject *UnameResultType = PyStructSequence_NewType(&uname_result_desc); + if (UnameResultType == NULL) { + return -1; + } + ; + PyModule_AddObject(m, "uname_result", Py_NewRef(UnameResultType)); + state->UnameResultType = (PyObject *)UnameResultType; + + if ((state->billion = PyLong_FromLong(1000000000)) == NULL) + return -1; +#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) + state->struct_rusage = PyUnicode_InternFromString("struct_rusage"); + if (state->struct_rusage == NULL) + return -1; +#endif + state->st_mode = PyUnicode_InternFromString("st_mode"); + if (state->st_mode == NULL) + return -1; + + /* suppress "function not used" warnings */ + { + int ignored; + fd_specified("", -1); + follow_symlinks_specified("", 1); + dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1); + dir_fd_converter(Py_None, &ignored); + dir_fd_unavailable(Py_None, &ignored); + } + + /* + * provide list of locally available functions + * so os.py can populate support_* lists + */ + PyObject *list = PyList_New(0); + if (!list) { + return -1; + } + for (const struct have_function *trace = have_functions; trace->label; trace++) { + PyObject *unicode; + if (trace->probe && !trace->probe()) continue; + unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL); + if (!unicode) + return -1; + if (PyList_Append(list, unicode)) + return -1; + Py_DECREF(unicode); + } + + PyModule_AddObject(m, "_have_functions", list); + + return 0; +} + + +static PyModuleDef_Slot posixmodile_slots[] = { + {Py_mod_exec, posixmodule_exec}, + {0, NULL} +}; + +static struct PyModuleDef posixmodule = { + PyModuleDef_HEAD_INIT, + .m_name = MODNAME, + .m_doc = posix__doc__, + .m_size = sizeof(_posixstate), + .m_methods = posix_methods, + .m_slots = posixmodile_slots, + .m_traverse = _posix_traverse, + .m_clear = _posix_clear, + .m_free = _posix_free, +}; + +PyMODINIT_FUNC +INITFUNC(void) +{ + return PyModuleDef_Init(&posixmodule); +} + +#ifdef __cplusplus +} +#endif diff --git a/Programs/test_frozenmain.h b/Programs/test_frozenmain.h index f2cf1978367eab..96be3ce3c25c3f 100644 --- a/Programs/test_frozenmain.h +++ b/Programs/test_frozenmain.h @@ -1,42 +1,42 @@ -// Auto-generated by Programs/freeze_test_frozenmain.py -unsigned char M_test_frozenmain[] = { - 227,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0, - 0,0,0,0,0,243,184,0,0,0,151,0,100,0,100,1, - 108,0,90,0,100,0,100,1,108,1,90,1,2,0,101,2, - 100,2,171,1,0,0,0,0,0,0,0,0,1,0,2,0, - 101,2,100,3,101,0,106,6,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,171,2,0,0,0,0, - 0,0,0,0,1,0,2,0,101,1,106,8,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,171,0, - 0,0,0,0,0,0,0,0,100,4,25,0,0,0,0,0, - 0,0,0,0,90,5,100,5,68,0,93,23,0,0,90,6, - 2,0,101,2,100,6,101,6,155,0,100,7,101,5,101,6, - 25,0,0,0,0,0,0,0,0,0,155,0,157,4,171,1, - 0,0,0,0,0,0,0,0,1,0,140,25,4,0,100,1, - 83,0,41,8,233,0,0,0,0,78,122,18,70,114,111,122, - 101,110,32,72,101,108,108,111,32,87,111,114,108,100,122,8, - 115,121,115,46,97,114,103,118,218,6,99,111,110,102,105,103, - 41,5,218,12,112,114,111,103,114,97,109,95,110,97,109,101, - 218,10,101,120,101,99,117,116,97,98,108,101,218,15,117,115, - 101,95,101,110,118,105,114,111,110,109,101,110,116,218,17,99, - 111,110,102,105,103,117,114,101,95,99,95,115,116,100,105,111, - 218,14,98,117,102,102,101,114,101,100,95,115,116,100,105,111, - 122,7,99,111,110,102,105,103,32,122,2,58,32,41,7,218, - 3,115,121,115,218,17,95,116,101,115,116,105,110,116,101,114, - 110,97,108,99,97,112,105,218,5,112,114,105,110,116,218,4, - 97,114,103,118,218,11,103,101,116,95,99,111,110,102,105,103, - 115,114,3,0,0,0,218,3,107,101,121,169,0,243,0,0, - 0,0,250,18,116,101,115,116,95,102,114,111,122,101,110,109, - 97,105,110,46,112,121,250,8,60,109,111,100,117,108,101,62, - 114,18,0,0,0,1,0,0,0,115,154,0,0,0,240,3, - 1,1,1,240,8,0,1,11,128,10,128,10,128,10,216,0, - 24,208,0,24,208,0,24,208,0,24,224,0,5,128,5,208, - 6,26,212,0,27,208,0,27,216,0,5,128,5,128,106,144, - 35,151,40,145,40,212,0,27,208,0,27,216,9,38,208,9, - 26,215,9,38,209,9,38,212,9,40,168,24,212,9,50,128, - 6,240,2,6,12,2,240,0,7,1,42,241,0,7,1,42, - 128,67,240,14,0,5,10,128,69,208,10,40,144,67,208,10, - 40,208,10,40,152,54,160,35,156,59,208,10,40,208,10,40, - 212,4,41,208,4,41,208,4,41,240,15,7,1,42,240,0, - 7,1,42,240,0,7,1,42,114,16,0,0,0, -}; +// Auto-generated by Programs/freeze_test_frozenmain.py +unsigned char M_test_frozenmain[] = { + 227,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0, + 0,0,0,0,0,243,184,0,0,0,151,0,100,0,100,1, + 108,0,90,0,100,0,100,1,108,1,90,1,2,0,101,2, + 100,2,171,1,0,0,0,0,0,0,0,0,1,0,2,0, + 101,2,100,3,101,0,106,6,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,171,2,0,0,0,0, + 0,0,0,0,1,0,2,0,101,1,106,8,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,171,0, + 0,0,0,0,0,0,0,0,100,4,25,0,0,0,0,0, + 0,0,0,0,90,5,100,5,68,0,93,23,0,0,90,6, + 2,0,101,2,100,6,101,6,155,0,100,7,101,5,101,6, + 25,0,0,0,0,0,0,0,0,0,155,0,157,4,171,1, + 0,0,0,0,0,0,0,0,1,0,140,25,4,0,100,1, + 83,0,41,8,233,0,0,0,0,78,122,18,70,114,111,122, + 101,110,32,72,101,108,108,111,32,87,111,114,108,100,122,8, + 115,121,115,46,97,114,103,118,218,6,99,111,110,102,105,103, + 41,5,218,12,112,114,111,103,114,97,109,95,110,97,109,101, + 218,10,101,120,101,99,117,116,97,98,108,101,218,15,117,115, + 101,95,101,110,118,105,114,111,110,109,101,110,116,218,17,99, + 111,110,102,105,103,117,114,101,95,99,95,115,116,100,105,111, + 218,14,98,117,102,102,101,114,101,100,95,115,116,100,105,111, + 122,7,99,111,110,102,105,103,32,122,2,58,32,41,7,218, + 3,115,121,115,218,17,95,116,101,115,116,105,110,116,101,114, + 110,97,108,99,97,112,105,218,5,112,114,105,110,116,218,4, + 97,114,103,118,218,11,103,101,116,95,99,111,110,102,105,103, + 115,114,3,0,0,0,218,3,107,101,121,169,0,243,0,0, + 0,0,250,18,116,101,115,116,95,102,114,111,122,101,110,109, + 97,105,110,46,112,121,250,8,60,109,111,100,117,108,101,62, + 114,18,0,0,0,1,0,0,0,115,154,0,0,0,240,3, + 1,1,1,240,8,0,1,11,128,10,128,10,128,10,216,0, + 24,208,0,24,208,0,24,208,0,24,224,0,5,128,5,208, + 6,26,212,0,27,208,0,27,216,0,5,128,5,128,106,144, + 35,151,40,145,40,212,0,27,208,0,27,216,9,38,208,9, + 26,215,9,38,209,9,38,212,9,40,168,24,212,9,50,128, + 6,240,2,6,12,2,240,0,7,1,42,241,0,7,1,42, + 128,67,240,14,0,5,10,128,69,208,10,40,144,67,208,10, + 40,208,10,40,152,54,160,35,156,59,208,10,40,208,10,40, + 212,4,41,208,4,41,208,4,41,240,15,7,1,42,240,0, + 7,1,42,240,0,7,1,42,114,16,0,0,0, +}; From 4a9330a9719ad5eeb533dd66c170d004dd7a4e46 Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Thu, 17 Nov 2022 22:02:41 -0800 Subject: [PATCH 24/35] update docs --- Doc/library/os.rst | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 0f0fb55e315c95..e2c00808324a30 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -2738,6 +2738,17 @@ features: This method can raise :exc:`OSError`, such as :exc:`PermissionError`, but :exc:`FileNotFoundError` is caught and not raised. + .. method:: is_junction() + + Return ``True`` if this entry is a junction (even if broken); + return ``False`` if the entry points to a directory or any kind of file, + or if it doesn't exist anymore. + + The result is cached on the ``os.DirEntry`` object. Call + :func:`os.path.is_junction` to fetch up-to-date information. + + .. versionadded:: 3.12 + .. method:: stat(*, follow_symlinks=True) Return a :class:`stat_result` object for this entry. This method @@ -2760,8 +2771,8 @@ features: Note that there is a nice correspondence between several attributes and methods of ``os.DirEntry`` and of :class:`pathlib.Path`. In particular, the ``name`` attribute has the same - meaning, as do the ``is_dir()``, ``is_file()``, ``is_symlink()`` - and ``stat()`` methods. + meaning, as do the ``is_dir()``, ``is_file()``, ``is_symlink()``, + ``is_junction()``, and ``stat()`` methods. .. versionadded:: 3.5 From aa27ead52770585f3f2e6823179d006c183ccf3e Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Thu, 17 Nov 2022 22:11:52 -0800 Subject: [PATCH 25/35] fix mistype --- Doc/library/os.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst index e2c00808324a30..baa2b1dad7de6d 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -2745,7 +2745,7 @@ features: or if it doesn't exist anymore. The result is cached on the ``os.DirEntry`` object. Call - :func:`os.path.is_junction` to fetch up-to-date information. + :func:`os.path.isjunction` to fetch up-to-date information. .. versionadded:: 3.12 From 8b6d55d938f67e4592d191ec03be81735ebc1ccc Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Thu, 17 Nov 2022 22:43:15 -0800 Subject: [PATCH 26/35] Add test for DirEntry is_junction() --- Lib/test/test_os.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index cb78e8cb77de1c..b5f40f609aaf3f 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -4158,6 +4158,8 @@ def check_entry(self, entry, name, is_dir, is_file, is_symlink): self.assertEqual(entry.is_file(follow_symlinks=False), stat.S_ISREG(entry_lstat.st_mode)) + self.assertEqual(entry.is_junction(), os.path.isjunction(entry.path)) + self.assert_stat_equal(entry.stat(), entry_stat, os.name == 'nt' and not is_symlink) @@ -4206,6 +4208,21 @@ def test_attributes(self): entry = entries['symlink_file.txt'] self.check_entry(entry, 'symlink_file.txt', False, True, True) + @unittest.skipIf(sys.platform != 'win32', "Can only test junctions with creation on win32.") + def test_attributes_junctions(self): + dirname = os.path.join(self.path, "tgtdir") + os.mkdir(dirname) + + import _winapi + try: + _winapi.CreateJunction(os.path.join(self.path, "srcjunc"), dirname) + except OSError: + raise unittest.SkipTest('creating the test junction failed') + + entries = self.get_entries(['srcjunc', 'tgtdir']) + self.assertEqual(entries['srcjunc'].is_junction(), True) + self.assertEqual(entries['tgtdir'].is_junction(), False) + def get_entry(self, name): path = self.bytes_path if isinstance(name, bytes) else self.path entries = list(os.scandir(path)) From f3e6483e0c0794c232bd7f8da3d138298fbd26c2 Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Thu, 17 Nov 2022 23:22:55 -0800 Subject: [PATCH 27/35] rekick ci From 4e448f7a4409ac1192d37f25024fc5941f790824 Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Fri, 18 Nov 2022 09:27:51 -0800 Subject: [PATCH 28/35] Update Doc/library/os.rst Co-authored-by: Eryk Sun --- Doc/library/os.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst index baa2b1dad7de6d..cd8609e9bd7dc6 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -2741,8 +2741,8 @@ features: .. method:: is_junction() Return ``True`` if this entry is a junction (even if broken); - return ``False`` if the entry points to a directory or any kind of file, - or if it doesn't exist anymore. + return ``False`` if the entry points to a regular directory or file, a + symlink, or if it doesn't exist anymore. The result is cached on the ``os.DirEntry`` object. Call :func:`os.path.isjunction` to fetch up-to-date information. From 25f48bea10a48c0e8de00ecc952d3458383a3b63 Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Fri, 18 Nov 2022 09:46:38 -0800 Subject: [PATCH 29/35] Update Doc/library/os.rst Co-authored-by: Eryk Sun --- Doc/library/os.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst index cd8609e9bd7dc6..4360a1a73de07e 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -2741,8 +2741,8 @@ features: .. method:: is_junction() Return ``True`` if this entry is a junction (even if broken); - return ``False`` if the entry points to a regular directory or file, a - symlink, or if it doesn't exist anymore. + return ``False`` if the entry points to a regular directory, any kind + of file, a symlink, or if it doesn't exist anymore. The result is cached on the ``os.DirEntry`` object. Call :func:`os.path.isjunction` to fetch up-to-date information. From 2dea623b12cfd8f59b7baa04af8da915befddeb2 Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Fri, 18 Nov 2022 16:27:24 -0800 Subject: [PATCH 30/35] Update Lib/test/test_os.py Co-authored-by: Eryk Sun --- Lib/test/test_os.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index b5f40f609aaf3f..94db8bb7737acd 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -4215,7 +4215,7 @@ def test_attributes_junctions(self): import _winapi try: - _winapi.CreateJunction(os.path.join(self.path, "srcjunc"), dirname) + _winapi.CreateJunction(dirname, os.path.join(self.path, "srcjunc")) except OSError: raise unittest.SkipTest('creating the test junction failed') From 5b6ee7d3cb78afa76c9a331315af763fa9bb727f Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Fri, 18 Nov 2022 16:49:52 -0800 Subject: [PATCH 31/35] kick ci From dfeb40b6b5e30410be861f21ac3702036a24aef2 Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Mon, 21 Nov 2022 18:33:50 -0800 Subject: [PATCH 32/35] Remove _rmtree_is_dir() since we can now just check if the entry is a dir and not a junction across the board --- Lib/shutil.py | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/Lib/shutil.py b/Lib/shutil.py index f5687e3b346ef2..6544c56735d622 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -565,18 +565,6 @@ def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, dirs_exist_ok=dirs_exist_ok) if hasattr(os.stat_result, 'st_file_attributes'): - # Special handling for directory junctions to make them behave like - # symlinks for shutil.rmtree, since in general they do not appear as - # regular links. - def _rmtree_isdir(entry): - try: - st = entry.stat(follow_symlinks=False) - return (stat.S_ISDIR(st.st_mode) and not - (st.st_file_attributes & stat.FILE_ATTRIBUTE_REPARSE_POINT - and st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT)) - except OSError: - return False - def _rmtree_islink(path): try: st = os.lstat(path) @@ -586,12 +574,6 @@ def _rmtree_islink(path): except OSError: return False else: - def _rmtree_isdir(entry): - try: - return entry.is_dir(follow_symlinks=False) - except OSError: - return False - def _rmtree_islink(path): return os.path.islink(path) @@ -605,7 +587,7 @@ def _rmtree_unsafe(path, onerror): entries = [] for entry in entries: fullname = entry.path - if _rmtree_isdir(entry): + if entry.is_dir(follow_symlinks=False) and not entry.is_junction(): try: if entry.is_symlink(): # This can only happen if someone replaces From 8a90cbacd929b3a2945661506328cb5dd529e4c0 Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Mon, 21 Nov 2022 19:48:16 -0800 Subject: [PATCH 33/35] Update Lib/shutil.py Co-authored-by: Eryk Sun --- Lib/shutil.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Lib/shutil.py b/Lib/shutil.py index 6544c56735d622..0877fe3694eb4c 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -587,7 +587,11 @@ def _rmtree_unsafe(path, onerror): entries = [] for entry in entries: fullname = entry.path - if entry.is_dir(follow_symlinks=False) and not entry.is_junction(): + try: + is_dir = (entry.is_dir(follow_symlinks=False) and + not entry.is_junction()) + except OSError: + is_dir = False try: if entry.is_symlink(): # This can only happen if someone replaces From 296992b7a7982691a661a2876c8dac640002b237 Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Mon, 21 Nov 2022 19:52:13 -0800 Subject: [PATCH 34/35] update from suggestion --- Lib/shutil.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Lib/shutil.py b/Lib/shutil.py index 0877fe3694eb4c..42076595e33b8a 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -592,6 +592,8 @@ def _rmtree_unsafe(path, onerror): not entry.is_junction()) except OSError: is_dir = False + + if is_dir: try: if entry.is_symlink(): # This can only happen if someone replaces From f3372dbbd6b4cfeab4447d953dcfd281757aecdf Mon Sep 17 00:00:00 2001 From: Charles Machalow Date: Mon, 21 Nov 2022 20:45:44 -0800 Subject: [PATCH 35/35] Update Lib/shutil.py Co-authored-by: Eryk Sun --- Lib/shutil.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Lib/shutil.py b/Lib/shutil.py index 42076595e33b8a..f372406a6c51a8 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -588,12 +588,11 @@ def _rmtree_unsafe(path, onerror): for entry in entries: fullname = entry.path try: - is_dir = (entry.is_dir(follow_symlinks=False) and - not entry.is_junction()) + is_dir = entry.is_dir(follow_symlinks=False) except OSError: is_dir = False - if is_dir: + if is_dir and not entry.is_junction(): try: if entry.is_symlink(): # This can only happen if someone replaces