diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index c3849a93c0c..2c46d4bf172 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -3186,6 +3186,50 @@ os_wait(PyObject *module, PyObject *Py_UNUSED(ignored)) #endif /* defined(HAVE_WAIT) */ +#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)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; + static const char * const _keywords[] = {"path", "dir_fd", NULL}; + static _PyArg_Parser _parser = {"O&|$O&:readlink", _keywords, 0}; + path_t path = PATH_T_INITIALIZE("readlink", "path", 0, 0); + int dir_fd = DEFAULT_DIR_FD; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + path_converter, &path, READLINKAT_DIR_FD_CONVERTER, &dir_fd)) { + goto exit; + } + 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__, @@ -5873,6 +5917,80 @@ exit: #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; + + if (!PyArg_Parse(arg, "i:get_blocking", &fd)) { + 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)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_ParseStack(args, nargs, "ii:set_blocking", + &fd, &blocking)) { + 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" @@ -6425,6 +6543,10 @@ exit: #define OS_WAIT_METHODDEF #endif /* !defined(OS_WAIT_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) */ @@ -6645,7 +6767,15 @@ exit: #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) */ -/*[clinic end generated code: output=758ee0434fb03d90 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0f23518dd4482e66 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 0ac0042f124..53d2ce22439 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -7524,67 +7524,61 @@ os_wait_impl(PyObject *module) #if defined(HAVE_READLINK) || defined(MS_WINDOWS) -PyDoc_STRVAR(readlink__doc__, -"readlink(path, *, dir_fd=None) -> path\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\ -dir_fd may not be implemented on your platform.\n\ - If it is unavailable, using it will raise a NotImplementedError."); +/*[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 * -posix_readlink(PyObject *self, PyObject *args, PyObject *kwargs) +os_readlink_impl(PyObject *module, path_t *path, int dir_fd) +/*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/ { - path_t path; - int dir_fd = DEFAULT_DIR_FD; #if defined(HAVE_READLINK) char buffer[MAXPATHLEN+1]; ssize_t length; + + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_READLINKAT + if (dir_fd != DEFAULT_DIR_FD) + length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN); + else +#endif + length = readlink(path->narrow, buffer, MAXPATHLEN); + Py_END_ALLOW_THREADS + + 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; HANDLE reparse_point_handle; - char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer; const wchar_t *print_name; -#endif - PyObject *return_value = NULL; - static char *keywords[] = {"path", "dir_fd", NULL}; + PyObject *result; - memset(&path, 0, sizeof(path)); - path.function_name = "readlink"; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:readlink", keywords, - path_converter, &path, - READLINKAT_DIR_FD_CONVERTER, &dir_fd)) - return NULL; - -#if defined(HAVE_READLINK) - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_READLINKAT - if (dir_fd != DEFAULT_DIR_FD) - length = readlinkat(dir_fd, path.narrow, buffer, MAXPATHLEN); - else -#endif - length = readlink(path.narrow, buffer, MAXPATHLEN); - Py_END_ALLOW_THREADS - - if (length < 0) { - return_value = path_error(&path); - goto exit; - } - buffer[length] = '\0'; - - if (PyUnicode_Check(path.object)) - return_value = PyUnicode_DecodeFSDefaultAndSize(buffer, length); - else - return_value = PyBytes_FromStringAndSize(buffer, length); -#elif defined(MS_WINDOWS) /* First get a handle to the reparse point */ Py_BEGIN_ALLOW_THREADS reparse_point_handle = CreateFileW( - path.wide, + path->wide, 0, 0, 0, @@ -7594,8 +7588,7 @@ posix_readlink(PyObject *self, PyObject *args, PyObject *kwargs) Py_END_ALLOW_THREADS if (reparse_point_handle == INVALID_HANDLE_VALUE) { - return_value = path_error(&path); - goto exit; + return path_error(path); } Py_BEGIN_ALLOW_THREADS @@ -7612,28 +7605,25 @@ posix_readlink(PyObject *self, PyObject *args, PyObject *kwargs) Py_END_ALLOW_THREADS if (io_result == 0) { - return_value = path_error(&path); - goto exit; + return path_error(path); } if (rdb->ReparseTag != IO_REPARSE_TAG_SYMLINK) { PyErr_SetString(PyExc_ValueError, "not a symbolic link"); - goto exit; + return NULL; } print_name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer + rdb->SymbolicLinkReparseBuffer.PrintNameOffset); - return_value = PyUnicode_FromWideChar(print_name, - rdb->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(wchar_t)); - if (path.narrow) { - Py_SETREF(return_value, PyUnicode_EncodeFSDefault(return_value)); + result = PyUnicode_FromWideChar(print_name, + rdb->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(wchar_t)); + if (path->narrow) { + Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); } + return result; #endif -exit: - path_cleanup(&path); - return return_value; } #endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */ @@ -11918,43 +11908,45 @@ os_set_handle_inheritable_impl(PyObject *module, intptr_t handle, #endif /* MS_WINDOWS */ #ifndef MS_WINDOWS -PyDoc_STRVAR(get_blocking__doc__, - "get_blocking(fd) -> bool\n" \ - "\n" \ - "Get the blocking mode of the file descriptor:\n" \ - "False if the O_NONBLOCK flag is set, True if the flag is cleared."); +/*[clinic input] +os.get_blocking -> bool + fd: int + / -static PyObject* -posix_get_blocking(PyObject *self, PyObject *args) +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 fd; int blocking; - if (!PyArg_ParseTuple(args, "i:get_blocking", &fd)) - return NULL; - _Py_BEGIN_SUPPRESS_IPH blocking = _Py_get_blocking(fd); _Py_END_SUPPRESS_IPH - if (blocking < 0) - return NULL; - return PyBool_FromLong(blocking); + return blocking; } -PyDoc_STRVAR(set_blocking__doc__, - "set_blocking(fd, blocking)\n" \ - "\n" \ - "Set the blocking mode of the specified file descriptor.\n" \ - "Set the O_NONBLOCK flag if blocking is False,\n" \ - "clear the O_NONBLOCK flag otherwise."); +/*[clinic input] +os.set_blocking + fd: int + blocking: bool(accept={int}) + / -static PyObject* -posix_set_blocking(PyObject *self, PyObject *args) +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 fd, blocking, result; - - if (!PyArg_ParseTuple(args, "ii:set_blocking", &fd, &blocking)) - return NULL; + int result; _Py_BEGIN_SUPPRESS_IPH result = _Py_set_blocking(fd, blocking); @@ -13048,11 +13040,7 @@ static PyMethodDef posix_methods[] = { OS_GETPRIORITY_METHODDEF OS_SETPRIORITY_METHODDEF OS_POSIX_SPAWN_METHODDEF -#if defined(HAVE_READLINK) || defined(MS_WINDOWS) - {"readlink", (PyCFunction)posix_readlink, - METH_VARARGS | METH_KEYWORDS, - readlink__doc__}, -#endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */ + OS_READLINK_METHODDEF OS_RENAME_METHODDEF OS_REPLACE_METHODDEF OS_RMDIR_METHODDEF @@ -13206,8 +13194,8 @@ static PyMethodDef posix_methods[] = { OS_GET_HANDLE_INHERITABLE_METHODDEF OS_SET_HANDLE_INHERITABLE_METHODDEF #ifndef MS_WINDOWS - {"get_blocking", posix_get_blocking, METH_VARARGS, get_blocking__doc__}, - {"set_blocking", posix_set_blocking, METH_VARARGS, set_blocking__doc__}, + OS_GET_BLOCKING_METHODDEF + OS_SET_BLOCKING_METHODDEF #endif OS_SCANDIR_METHODDEF OS_FSPATH_METHODDEF