Skip to content

Commit c8d85a6

Browse files
committed
gh-157899: added iOS as supported platform for calling os.readlink with a FD referring to a symlink.
Also some code/test cleanup.
1 parent 9bf9236 commit c8d85a6

8 files changed

Lines changed: 68 additions & 86 deletions

File tree

‎Doc/library/os.rst‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2802,11 +2802,11 @@ features:
28022802
This function can also support :ref:`paths relative to directory descriptors
28032803
<dir_fd>`.
28042804

2805-
On Linux, Android and macOS, *path* can also be a file descriptor referring
2805+
On Linux, Android, macOS and iOS, *path* can also be a file descriptor referring
28062806
to a symbolic link. In that case, *dir_fd* must be ``None``.
28072807
(On Linux and Android, such a file descriptor must be obtained through
28082808
:func:`os.open` with ``os.O_RDONLY | os.O_PATH | os.O_NOFOLLOW``.
2809-
On macOS, :func:`os.open` must be called with
2809+
On macOS and iOS, :func:`os.open` must be called with
28102810
``os.O_RDONLY | os.O_SYMLINK``.)
28112811
On other operating systems, a ``NotImplementedError`` is raised if *path*
28122812
is an integer.
@@ -2840,7 +2840,7 @@ features:
28402840

28412841
.. versionchanged:: next
28422842
Accepts file descriptors pointing to symbolic links as *path* on
2843-
Linux, Android and macOS.
2843+
Linux, Android, macOS and iOS.
28442844

28452845
.. function:: remove(path, *, dir_fd=None)
28462846

‎Doc/whatsnew/3.16.rst‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ os
547547
(Contributed by Md Arif in :gh:`152936`.)
548548

549549
* :func:`os.readlink` now accepts a file descriptor referring to a symlink on
550-
Linux, Android and macOS.
550+
Linux, Android, macOS and iOS.
551551
(Contributed by OOTS in :gh:`157899`.)
552552

553553

‎Lib/test/test_os/test_posix.py‎

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1882,19 +1882,16 @@ def test_readlink_dir_fd(self):
18821882
self.assertEqual(posix.readlink(name, dir_fd=dir_fd), 'symlink')
18831883

18841884

1885-
_support_readlink_with_fd = hasattr(os, 'readlink') and (
1886-
"HAVE_FREADLINK" in posix._have_functions # macOS
1887-
or (
1888-
os.readlink in os.supports_dir_fd
1889-
and sys.platform in ["linux", "android"]
1890-
)
1885+
_support_readlink_with_fd = (
1886+
hasattr(os, 'readlink') \
1887+
and os.readlink in os.supports_fd
18911888
)
18921889

18931890
def _open_symlink_as_fd(self, path):
18941891
open_flags = os.O_RDONLY
1895-
if hasattr(os, "O_SYMLINK"): # macOS
1892+
if hasattr(os, "O_SYMLINK"): # macOS/iOS
18961893
open_flags |= os.O_SYMLINK
1897-
elif hasattr(os, "O_NOFOLLOW") and hasattr(os, "O_PATH"): # Linux
1894+
elif hasattr(os, "O_NOFOLLOW") and hasattr(os, "O_PATH"): # Linux/Android
18981895
open_flags |= os.O_NOFOLLOW | os.O_PATH
18991896
else:
19001897
self.fail("lacking open flags for this test")
@@ -1947,9 +1944,10 @@ def test_readlink_with_fd_throws_not_implemented_error(self):
19471944
with self.assertRaises(NotImplementedError):
19481945
os.readlink(fd)
19491946

1950-
@unittest.skipUnless(hasattr(os, "readlink"), "needs os.readlink")
1951-
def test_readlink_is_in_supports_fd_on_supported_platforms(self):
1952-
self.assertEqual(os.readlink in os.supports_fd, self._support_readlink_with_fd)
1947+
@unittest.skipUnless(sys.platform in ["linux", "android", "darwin", "ios"],
1948+
"feature not supported on this platform")
1949+
def test_readlink_is_marked_as_supports_fd(self):
1950+
self.assertIn(os.readlink, os.supports_fd)
19531951

19541952
@unittest.skipUnless(os.rename in os.supports_dir_fd, "test needs dir_fd support in os.rename()")
19551953
def test_rename_dir_fd(self):
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
:func:`os.readlink` now accepts a file descriptor referring to a
2-
symlink on Linux, Android and macOS.
2+
symlink on Linux, Android, macOS and iOS.

‎Modules/clinic/posixmodule.c.h‎

Lines changed: 3 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Modules/posixmodule.c‎

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ static const unsigned int _Py_STATX_KNOWN = (STATX_BASIC_STATS | STATX_BTIME
505505
# define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
506506
# define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
507507
# define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
508-
# define HAVE_FREADLINK_RUNTIME __builtin_available(macOS 13.0, *)
508+
# define HAVE_FREADLINK_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, *)
509509
# define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
510510
# define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
511511
# define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
@@ -11009,22 +11009,13 @@ that directory.
1100911009
dir_fd may not be implemented on your platform. If it is unavailable,
1101011010
using it will raise a NotImplementedError.
1101111011

11012-
On Linux, Android and macOS, path may be a file descriptor referring to
11013-
a symlink. If it is, dir_fd must be None, and the return value will be a
11014-
string object. (File descriptors for symlinks can be obtained with
11015-
11016-
os.open(..., os.O_RDONLY | os.O_PATH | os.O_NOFOLLOW)
11017-
11018-
on Linux and Android, and:
11019-
11020-
os.open(..., os.O_RDONLY | os.O_SYMLINK)
11021-
11022-
on macOS.)
11012+
On Linux, Android, macOS and iOS, path may be a file descriptor
11013+
referring to a symlink. If it is, dir_fd must be None.
1102311014
[clinic start generated code]*/
1102411015

1102511016
static PyObject *
1102611017
os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
11027-
/*[clinic end generated code: output=d21b732a2e814030 input=14546747b3db62f6]*/
11018+
/*[clinic end generated code: output=d21b732a2e814030 input=d90bddfeee86f673]*/
1102811019
{
1102911020
#if defined(HAVE_READLINK)
1103011021
char buffer[MAXPATHLEN+1];
@@ -11079,10 +11070,12 @@ os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
1107911070
}
1108011071
buffer[length] = '\0';
1108111072

11082-
if (path->is_fd || PyUnicode_Check(path->object))
11073+
if (path->is_fd || PyUnicode_Check(path->object)) {
1108311074
return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
11084-
else
11075+
}
11076+
else {
1108511077
return PyBytes_FromStringAndSize(buffer, length);
11078+
}
1108611079
#elif defined(MS_WINDOWS)
1108711080
DWORD n_bytes_returned;
1108811081
DWORD io_result = 0;

‎configure‎

Lines changed: 42 additions & 42 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎configure.ac‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5578,6 +5578,7 @@ AC_CHECK_FUNCS([ \
55785578
wait wait3 wait4 waitid waitpid wcscoll wcsftime wcsxfrm wmemcmp writev \
55795579
])
55805580

5581+
PY_CHECK_FUNC_PRIVATE([freadlink], [@%:@include <unistd.h>])
55815582
PY_CHECK_FUNC_PRIVATE([strerror_r], [@%:@include <string.h>])
55825583

55835584

@@ -5600,7 +5601,6 @@ fi
56005601
# raise an error if used at runtime. Force these symbols off.
56015602
if test "$ac_sys_system" != "iOS" ; then
56025603
AC_CHECK_FUNCS([dup3 getentropy getgroups pipe2 system])
5603-
PY_CHECK_FUNC_PRIVATE([freadlink], [@%:@include <unistd.h>])
56045604
fi
56055605

56065606
AC_CHECK_DECL([dirfd],

0 commit comments

Comments
 (0)