summaryrefslogtreecommitdiffstats
path: root/Modules/posixmodule.c
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2023-12-24 10:57:11 (GMT)
committerGitHub <noreply@github.com>2023-12-24 10:57:11 (GMT)
commit1f06baeabd7ef64b7be6af7cb6fc03ec410b1aa2 (patch)
treee444e19cb3748885d3f7ad31329ea050e8a5eb14 /Modules/posixmodule.c
parent53330f167792a2947ab8b0faafb11019d7fb09b6 (diff)
downloadcpython-1f06baeabd7ef64b7be6af7cb6fc03ec410b1aa2.zip
cpython-1f06baeabd7ef64b7be6af7cb6fc03ec410b1aa2.tar.gz
cpython-1f06baeabd7ef64b7be6af7cb6fc03ec410b1aa2.tar.bz2
gh-113191: Add support of os.fchmod() on Windows (GH-113192)
Also support a file descriptor in os.chmod().
Diffstat (limited to 'Modules/posixmodule.c')
-rw-r--r--Modules/posixmodule.c80
1 files changed, 56 insertions, 24 deletions
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index c7ee591..c635fd4 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -2855,6 +2855,8 @@ FTRUNCATE
#ifdef MS_WINDOWS
#undef PATH_HAVE_FTRUNCATE
#define PATH_HAVE_FTRUNCATE 1
+ #undef PATH_HAVE_FCHMOD
+ #define PATH_HAVE_FCHMOD 1
#endif
/*[python input]
@@ -3332,7 +3334,38 @@ win32_lchmod(LPCWSTR path, int mode)
}
return SetFileAttributesW(path, attr);
}
-#endif
+
+static int
+win32_hchmod(HANDLE hfile, int mode)
+{
+ FILE_BASIC_INFO info;
+ if (!GetFileInformationByHandleEx(hfile, FileBasicInfo,
+ &info, sizeof(info)))
+ {
+ return 0;
+ }
+ if (mode & _S_IWRITE) {
+ info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
+ }
+ else {
+ info.FileAttributes |= FILE_ATTRIBUTE_READONLY;
+ }
+ return SetFileInformationByHandle(hfile, FileBasicInfo,
+ &info, sizeof(info));
+}
+
+static int
+win32_fchmod(int fd, int mode)
+{
+ HANDLE hfile = _Py_get_osfhandle_noraise(fd);
+ if (hfile == INVALID_HANDLE_VALUE) {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return 0;
+ }
+ return win32_hchmod(hfile, mode);
+}
+
+#endif /* MS_WINDOWS */
/*[clinic input]
os.chmod
@@ -3395,27 +3428,16 @@ os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
#ifdef MS_WINDOWS
result = 0;
Py_BEGIN_ALLOW_THREADS
- if (follow_symlinks) {
- HANDLE hfile;
- FILE_BASIC_INFO info;
-
- hfile = CreateFileW(path->wide,
- FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
- 0, NULL,
- OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ if (path->fd != -1) {
+ result = win32_fchmod(path->fd, mode);
+ }
+ else if (follow_symlinks) {
+ HANDLE hfile = CreateFileW(path->wide,
+ FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
+ 0, NULL,
+ OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (hfile != INVALID_HANDLE_VALUE) {
- if (GetFileInformationByHandleEx(hfile, FileBasicInfo,
- &info, sizeof(info)))
- {
- if (mode & _S_IWRITE) {
- info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
- }
- else {
- info.FileAttributes |= FILE_ATTRIBUTE_READONLY;
- }
- result = SetFileInformationByHandle(hfile, FileBasicInfo,
- &info, sizeof(info));
- }
+ result = win32_hchmod(hfile, mode);
(void)CloseHandle(hfile);
}
}
@@ -3511,7 +3533,7 @@ os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
}
-#ifdef HAVE_FCHMOD
+#if defined(HAVE_FCHMOD) || defined(MS_WINDOWS)
/*[clinic input]
os.fchmod
@@ -3533,12 +3555,21 @@ os_fchmod_impl(PyObject *module, int fd, int mode)
/*[clinic end generated code: output=afd9bc05b4e426b3 input=b5594618bbbc22df]*/
{
int res;
- int async_err = 0;
if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
return NULL;
}
+#ifdef MS_WINDOWS
+ res = 0;
+ Py_BEGIN_ALLOW_THREADS
+ res = win32_fchmod(fd, mode);
+ Py_END_ALLOW_THREADS
+ if (!res) {
+ return PyErr_SetFromWindowsErr(0);
+ }
+#else /* MS_WINDOWS */
+ int async_err = 0;
do {
Py_BEGIN_ALLOW_THREADS
res = fchmod(fd, mode);
@@ -3546,10 +3577,11 @@ os_fchmod_impl(PyObject *module, int fd, int mode)
} while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
if (res != 0)
return (!async_err) ? posix_error() : NULL;
+#endif /* MS_WINDOWS */
Py_RETURN_NONE;
}
-#endif /* HAVE_FCHMOD */
+#endif /* HAVE_FCHMOD || MS_WINDOWS */
#if defined(HAVE_LCHMOD) || defined(MS_WINDOWS)