Skip to content

Commit a7130e4

Browse files
committed
fcntl add the F_KINFO constant for FreeBSD 13.1 and onwards.
1 parent 0651936 commit a7130e4

File tree

5 files changed

+42
-2
lines changed

5 files changed

+42
-2
lines changed

Doc/library/fcntl.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ descriptor.
5757
``FICLONERANGE`` constants, which allow to share some data of one file with
5858
another file by reflinking on some filesystems (e.g., btrfs, OCFS2, and
5959
XFS). This behavior is commonly referred to as "copy-on-write".
60+
On FreeBSD >= 13.1, the :mod:`fcntl` module exposes the ``F_KINFO``
61+
constant which allow to get the path of the file descriptor.
6062

6163
The module defines the following functions:
6264

Lib/test/test_fcntl.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,13 @@ def test_fcntl_f_getpath(self):
193193
res = fcntl.fcntl(self.f.fileno(), fcntl.F_GETPATH, bytes(len(expected)))
194194
self.assertEqual(expected, res)
195195

196+
@unittest.skipUnless(sys.platform.startswith("freebsd") and hasattr(fcntl, "F_KINFO"), "F_KINFO is only available on freebsd")
197+
def test_fcntl_f_kinfo(self):
198+
self.f = open(TESTFN, 'wb')
199+
expected = os.path.abspath(TESTFN).encode('utf-8')
200+
res = fcntl.fcntl(self.f.fileno(), fcntl.F_KINFO)
201+
self.assertEqual(expected, res)
202+
196203
@unittest.skipUnless(
197204
hasattr(fcntl, "F_SETPIPE_SZ") and hasattr(fcntl, "F_GETPIPE_SZ"),
198205
"F_SETPIPE_SZ and F_GETPIPE_SZ are not available on all platforms.")

Modules/fcntlmodule.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
#include <stropts.h>
2020
#endif
2121

22+
#ifdef HAVE_SYS_USER_H
23+
#include <sys/user.h>
24+
#endif
25+
2226
/*[clinic input]
2327
module fcntl
2428
[clinic start generated code]*/
@@ -64,6 +68,12 @@ fcntl_fcntl_impl(PyObject *module, int fd, int code, PyObject *arg)
6468

6569
if (arg != NULL) {
6670
int parse_result;
71+
#ifdef F_KINFO
72+
if (code == F_KINFO) {
73+
PyErr_SetString(PyExc_ValueError,
74+
"fcntl arg not permitted with F_KINFO");
75+
}
76+
#endif
6777

6878
if (PyArg_Parse(arg, "s#", &str, &len)) {
6979
if ((size_t)len > sizeof buf) {
@@ -93,6 +103,21 @@ fcntl_fcntl_impl(PyObject *module, int fd, int code, PyObject *arg)
93103
}
94104
}
95105

106+
#ifdef F_KINFO
107+
if (code == F_KINFO) {
108+
struct kinfo_file f = {.kf_structsize = KINFO_FILE_SIZE};
109+
do {
110+
Py_BEGIN_ALLOW_THREADS
111+
ret = fcntl(fd, code, &f);
112+
Py_END_ALLOW_THREADS
113+
} while (ret == -1 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
114+
if (ret < 0) {
115+
return !async_err ? PyErr_SetFromErrno(PyExc_OSError) : NULL;
116+
}
117+
return PyBytes_FromString(f.kf_path);
118+
}
119+
#endif
120+
96121
do {
97122
Py_BEGIN_ALLOW_THREADS
98123
ret = fcntl(fd, code, (int)int_arg);
@@ -485,6 +510,9 @@ all_ins(PyObject* m)
485510
#ifdef F_DUPFD_CLOEXEC
486511
if (PyModule_AddIntMacro(m, F_DUPFD_CLOEXEC)) return -1;
487512
#endif
513+
#ifdef F_KINFO
514+
if (PyModule_AddIntMacro(m, F_KINFO)) return -1;
515+
#endif
488516
#ifdef F_GETFD
489517
if (PyModule_AddIntMacro(m, F_GETFD)) return -1;
490518
#endif

configure.ac

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2701,8 +2701,8 @@ AC_CHECK_HEADERS([ \
27012701
sys/endian.h sys/epoll.h sys/event.h sys/eventfd.h sys/file.h sys/ioctl.h sys/kern_control.h \
27022702
sys/loadavg.h sys/lock.h sys/memfd.h sys/mkdev.h sys/mman.h sys/modem.h sys/param.h sys/poll.h \
27032703
sys/random.h sys/resource.h sys/select.h sys/sendfile.h sys/socket.h sys/soundcard.h sys/stat.h \
2704-
sys/statvfs.h sys/sys_domain.h sys/syscall.h sys/sysmacros.h sys/termio.h sys/time.h sys/times.h sys/timerfd.h \
2705-
sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h sys/xattr.h sysexits.h syslog.h \
2704+
sys/statvfs.h sys/sys_domain.h sys/syscall.h sys/sysmacros.h sys/termio.h sys/time.h sys/times.h \
2705+
sys/types.h sys/uio.h sys/un.h sys/user.h sys/utsname.h sys/wait.h sys/xattr.h sysexits.h syslog.h \
27062706
termios.h util.h utime.h utmp.h \
27072707
])
27082708
AC_HEADER_DIRENT

pyconfig.h.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,6 +1391,9 @@
13911391
/* Define to 1 if you have the <sys/un.h> header file. */
13921392
#undef HAVE_SYS_UN_H
13931393

1394+
/* Define to 1 if you have the <sys/user.h> header file. */
1395+
#undef HAVE_SYS_USER_H
1396+
13941397
/* Define to 1 if you have the <sys/utsname.h> header file. */
13951398
#undef HAVE_SYS_UTSNAME_H
13961399

0 commit comments

Comments
 (0)