'musl fpathconf ignores the file descriptor and returns a constant',
)
def test_pathconf_negative_fd_uses_fd_semantics(self):
+ if os.pathconf not in os.supports_fd:
+ self.skipTest('needs fpathconf()')
+
with self.assertRaises(OSError) as ctx:
os.pathconf(-1, 1)
self.assertEqual(ctx.exception.errno, errno.EBADF)
+ @support.subTests("fd", [-1, -5])
+ def test_negative_fd_ebadf(self, fd):
+ tests = [(os.stat, fd)]
+ if hasattr(os, "statx"):
+ tests.append((os.statx, fd, 0))
+ if os.chdir in os.supports_fd:
+ tests.append((os.chdir, fd))
+ if os.chmod in os.supports_fd:
+ tests.append((os.chmod, fd, 0o777))
+ if hasattr(os, "chown") and os.chown in os.supports_fd:
+ tests.append((os.chown, fd, 0, 0))
+ if os.listdir in os.supports_fd:
+ tests.append((os.listdir, fd))
+ if os.utime in os.supports_fd:
+ tests.append((os.utime, fd, (0, 0)))
+ if hasattr(os, "truncate") and os.truncate in os.supports_fd:
+ tests.append((os.truncate, fd, 0))
+ if hasattr(os, 'statvfs') and os.statvfs in os.supports_fd:
+ tests.append((os.statvfs, fd))
+ if hasattr(os, "setxattr"):
+ tests.append((os.getxattr, fd, b"user.test"))
+ tests.append((os.setxattr, fd, b"user.test", b"1"))
+ tests.append((os.removexattr, fd, b"user.test"))
+ tests.append((os.listxattr, fd))
+ if os.scandir in os.supports_fd:
+ tests.append((os.scandir, fd))
+
+ for func, *args in tests:
+ with self.subTest(func=func, args=args):
+ with self.assertRaises(OSError) as ctx:
+ func(*args)
+ self.assertEqual(ctx.exception.errno, errno.EBADF)
+
+ if hasattr(os, "execve") and os.execve in os.supports_fd:
+ # glibc fails with EINVAL, musl fails with EBADF
+ with self.assertRaises(OSError) as ctx:
+ os.execve(fd, [sys.executable, "-c", "pass"], os.environ)
+ self.assertIn(ctx.exception.errno, (errno.EBADF, errno.EINVAL))
+
+ if support.MS_WINDOWS:
+ import nt
+ self.assertFalse(nt._path_exists(fd))
+ self.assertFalse(nt._path_lexists(fd))
+ self.assertFalse(nt._path_isdir(fd))
+ self.assertFalse(nt._path_isfile(fd))
+ self.assertFalse(nt._path_islink(fd))
+ self.assertFalse(nt._path_isjunction(fd))
+
@unittest.skipUnless(hasattr(os, 'ftruncate'), 'test needs os.ftruncate()')
def test_ftruncate(self):
self.check(os.truncate, 0)
}
static int
-fd_and_follow_symlinks_invalid(const char *function_name, int fd,
+fd_and_follow_symlinks_invalid(const char *function_name, int is_fd,
int follow_symlinks)
{
- if ((fd >= 0) && (!follow_symlinks)) {
+ if (is_fd && (!follow_symlinks)) {
PyErr_Format(PyExc_ValueError,
"%s: cannot use fd and follow_symlinks together",
function_name);
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))
+ fd_and_follow_symlinks_invalid("stat", path->is_fd, follow_symlinks))
return NULL;
Py_BEGIN_ALLOW_THREADS
- if (path->fd != -1)
+ if (path->is_fd) {
result = FSTAT(path->fd, &st);
+ }
#ifdef MS_WINDOWS
else if (follow_symlinks)
result = win32_stat(path->wide, &st);
{
if (path_and_dir_fd_invalid("statx", path, dir_fd) ||
dir_fd_and_fd_invalid("statx", dir_fd, path->fd) ||
- fd_and_follow_symlinks_invalid("statx", path->fd, follow_symlinks)) {
+ fd_and_follow_symlinks_invalid("statx", path->is_fd, follow_symlinks)) {
return NULL;
}
int result;
Py_BEGIN_ALLOW_THREADS
- if (path->fd != -1) {
+ if (path->is_fd) {
result = statx(path->fd, "", flags | AT_EMPTY_PATH, mask, &v->stx);
}
else {
result = !win32_wchdir(path->wide);
#else
#ifdef HAVE_FCHDIR
- if (path->fd != -1)
+ if (path->is_fd)
result = fchdir(path->fd);
else
#endif
#ifdef MS_WINDOWS
result = 0;
Py_BEGIN_ALLOW_THREADS
- if (path->fd != -1) {
+ if (path->is_fd) {
result = win32_fchmod(path->fd, mode);
}
else if (follow_symlinks) {
#else /* MS_WINDOWS */
Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_FCHMOD
- if (path->fd != -1)
+ if (path->is_fd) {
result = fchmod(path->fd, mode);
+ }
else
#endif /* HAVE_CHMOD */
#ifdef HAVE_LCHMOD
return NULL;
#endif
if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
- fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
+ fd_and_follow_symlinks_invalid("chown", path->is_fd, follow_symlinks))
return NULL;
if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_FCHOWN
- if (path->fd != -1)
+ if (path->is_fd)
result = fchown(path->fd, uid, gid);
else
#endif
errno = 0;
#ifdef HAVE_FDOPENDIR
- if (path->fd != -1) {
+ if (path->is_fd) {
if (HAVE_FDOPENDIR_RUNTIME) {
/* closedir() closes the FD, so we duplicate it */
fd = _Py_dup(path->fd);
}
Py_BEGIN_ALLOW_THREADS
- if (path->fd != -1) {
+ if (path->is_fd) {
HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
if (hfile != INVALID_HANDLE_VALUE) {
if (GetFileType(hfile) != FILE_TYPE_UNKNOWN || !GetLastError()) {
}
Py_BEGIN_ALLOW_THREADS
- if (path->fd != -1) {
+ if (path->is_fd) {
HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
if (hfile != INVALID_HANDLE_VALUE) {
result = _testFileTypeByHandle(hfile, testedType, TRUE);
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))
+ fd_and_follow_symlinks_invalid("utime", path->is_fd, follow_symlinks))
return NULL;
#if !defined(HAVE_UTIMENSAT)
#endif
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
- if (path->fd != -1)
+ if (path->is_fd)
result = utime_fd(&utime, path->fd);
else
#endif
_Py_BEGIN_SUPPRESS_IPH
#ifdef HAVE_FEXECVE
- if (path->fd > -1)
+ if (path->is_fd)
fexecve(path->fd, argvlist, envlist);
else
#endif
int fd;
#endif
- if (path->fd != -1)
+ if (path->is_fd)
return os_ftruncate_impl(module, path->fd, length);
if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
struct statfs st;
Py_BEGIN_ALLOW_THREADS
- if (path->fd != -1) {
+ if (path->is_fd) {
result = fstatfs(path->fd, &st);
}
else
Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_FSTATVFS
- if (path->fd != -1) {
+ if (path->is_fd) {
result = fstatvfs(path->fd, &st);
}
else
int follow_symlinks)
/*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
{
- if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
+ if (fd_and_follow_symlinks_invalid("getxattr", path->is_fd, follow_symlinks))
return NULL;
if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
void *ptr = PyBytesWriter_GetData(writer);
Py_BEGIN_ALLOW_THREADS;
- if (path->fd >= 0)
+ if (path->is_fd)
result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
else if (follow_symlinks)
result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
{
ssize_t result;
- if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
+ if (fd_and_follow_symlinks_invalid("setxattr", path->is_fd, follow_symlinks))
return NULL;
if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
}
Py_BEGIN_ALLOW_THREADS;
- if (path->fd > -1)
+ if (path->is_fd)
result = fsetxattr(path->fd, attribute->narrow,
value->buf, value->len, flags);
else if (follow_symlinks)
{
ssize_t result;
- if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
+ if (fd_and_follow_symlinks_invalid("removexattr", path->is_fd, follow_symlinks))
return NULL;
if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
}
Py_BEGIN_ALLOW_THREADS;
- if (path->fd > -1)
+ if (path->is_fd)
result = fremovexattr(path->fd, attribute->narrow);
else if (follow_symlinks)
result = removexattr(path->narrow, attribute->narrow);
const char *name;
char *buffer = NULL;
- if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
+ if (fd_and_follow_symlinks_invalid("listxattr", path->is_fd, follow_symlinks))
goto exit;
if (PySys_Audit("os.listxattr", "(O)",
}
Py_BEGIN_ALLOW_THREADS;
- if (path->fd > -1)
+ if (path->is_fd)
length = flistxattr(path->fd, buffer, buffer_size);
else if (follow_symlinks)
length = listxattr(name, buffer, buffer_size);
entry->stat = NULL;
entry->lstat = NULL;
- if (path->fd != -1) {
+ if (path->is_fd) {
entry->dir_fd = path->fd;
joined_path = NULL;
}
if (!entry->name)
goto error;
- if (path->fd != -1) {
+ if (path->is_fd) {
entry->path = Py_NewRef(entry->name);
}
else if (!entry->path)
iterator->dirp = NULL;
Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_FDOPENDIR
- if (iterator->path.fd != -1)
+ if (iterator->path.is_fd) {
rewinddir(dirp);
+ }
#endif
closedir(dirp);
Py_END_ALLOW_THREADS
#else /* POSIX */
errno = 0;
#ifdef HAVE_FDOPENDIR
- if (iterator->path.fd != -1) {
+ if (iterator->path.is_fd) {
if (HAVE_FDOPENDIR_RUNTIME) {
/* closedir() closes the FD, so we duplicate it */
fd = _Py_dup(iterator->path.fd);