From: Victor Stinner Date: Fri, 24 Apr 2015 22:21:52 +0000 (+0200) Subject: (Merge 3.4) Issue #9246: On POSIX, os.getcwd() now supports paths longer than X-Git-Tag: v3.5.0b1~294 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cc0bbbc781254cc43628649815435ababafa35e2;p=python (Merge 3.4) Issue #9246: On POSIX, os.getcwd() now supports paths longer than 1025 bytes. Patch written by William Orr. --- cc0bbbc781254cc43628649815435ababafa35e2 diff --cc Misc/NEWS index 4f702d05c2,2616bf7d93..c559ea528a --- a/Misc/NEWS +++ b/Misc/NEWS @@@ -12,61 -12,6 +12,64 @@@ Core and Builtin - Issue #24022: Fix tokenizer crash when processing undecodable source code. +Library +------- + ++- Issue #9246: On POSIX, os.getcwd() now supports paths longer than 1025 bytes. ++ Patch written by William Orr. ++ +- Issue #17445: add difflib.diff_bytes() to support comparison of + byte strings (fixes a regression from Python 2). + +- Issue #23917: Fall back to sequential compilation when ProcessPoolExecutor + doesn't exist. Patch by Claudiu Popa. + +- Issue #23008: Fixed resolving attributes with boolean value is False in pydoc. + +- Fix asyncio issue 235: LifoQueue and PriorityQueue's put didn't + increment unfinished tasks (this bug was introduced when + JoinableQueue was merged with Queue). + +- Issue #23908: os functions now reject paths with embedded null character + on Windows instead of silently truncate them. + +- Issue #23728: binascii.crc_hqx() could return an integer outside of the range + 0-0xffff for empty data. + - - Issue #23887: urllib.error.HTTPError now has a proper repr() representation. ++- Issue #23887: urllib.error.HTTPError now has a proper repr() representation. + Patch by Berker Peksag. + +Documentation +------------- + +- Issue #24029: Document the name binding behavior for submodule imports. + +Tools/Demos +----------- + +- Issue #24031: make patchcheck now supports git checkouts, too. + +What's New in Python 3.5.0 alpha 4? +=================================== + +Release date: 2015-04-19 + +Core and Builtins +----------------- + +- Issue #22980: Under Linux, GNU/KFreeBSD and the Hurd, C extensions now include + the architecture triplet in the extension name, to make it easy to test builds + for different ABIs in the same working tree. Under OS X, the extension name + now includes PEP 3149-style information. + +- Issue #22631: Added Linux-specific socket constant CAN_RAW_FD_FRAMES. + Patch courtesy of Joe Jevnik. + +- Issue #23731: Implement PEP 488: removal of .pyo files. + +- Issue #23726: Don't enable GC for user subclasses of non-GC types that + don't add any new fields. Patch by Eugene Toder. + - Issue #23309: Avoid a deadlock at shutdown if a daemon thread is aborted while it is holding a lock to a buffered I/O object, and the main thread tries to use the same I/O object (typically stdout or stderr). A fatal diff --cc Modules/posixmodule.c index ce34b3b0b8,04f0d3639c..3bed9583a9 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@@ -3306,26 -3460,39 +3309,43 @@@ posix_getcwd(int use_bytes return NULL; #endif + buf = cwd = NULL; Py_BEGIN_ALLOW_THREADS - res = getcwd(buf, sizeof buf); + do { + buflen += chunk; + tmpbuf = PyMem_RawRealloc(buf, buflen); + if (tmpbuf == NULL) + break; + + buf = tmpbuf; + cwd = getcwd(buf, buflen); + } while (cwd == NULL && errno == ERANGE); Py_END_ALLOW_THREADS - if (res == NULL) + + if (cwd == NULL) { + PyMem_RawFree(buf); return posix_error(); + } + if (use_bytes) - return PyBytes_FromStringAndSize(buf, strlen(buf)); - return PyUnicode_DecodeFSDefault(buf); + obj = PyBytes_FromStringAndSize(buf, strlen(buf)); + else + obj = PyUnicode_DecodeFSDefault(buf); + PyMem_RawFree(buf); + + return obj; } -PyDoc_STRVAR(posix_getcwd__doc__, -"getcwd() -> path\n\n\ -Return a unicode string representing the current working directory."); + +/*[clinic input] +os.getcwd + +Return a unicode string representing the current working directory. +[clinic start generated code]*/ static PyObject * -posix_getcwd_unicode(PyObject *self) +os_getcwd_impl(PyModuleDef *module) +/*[clinic end generated code: output=efe3a8c0121525ea input=f069211bb70e3d39]*/ { return posix_getcwd(0); } @@@ -8559,344 -8530,310 +8579,344 @@@ os_pipe2_impl(PyModuleDef *module, int } #endif /* HAVE_PIPE2 */ + #ifdef HAVE_WRITEV -PyDoc_STRVAR(posix_writev__doc__, -"writev(fd, buffers) -> byteswritten\n\n\ -Write the contents of *buffers* to file descriptor *fd*. *buffers*\n\ -must be a sequence of bytes-like objects.\n\n\ -writev writes the contents of each object to the file descriptor\n\ -and returns the total number of bytes written."); +/*[clinic input] +os.writev -> Py_ssize_t + fd: int + buffers: object + / -static PyObject * -posix_writev(PyObject *self, PyObject *args) +Iterate over buffers, and write the contents of each to a file descriptor. + +Returns the total number of bytes written. +buffers must be a sequence of bytes-like objects. +[clinic start generated code]*/ + +static Py_ssize_t +os_writev_impl(PyModuleDef *module, int fd, PyObject *buffers) +/*[clinic end generated code: output=a48925dbf2d5c238 input=5b8d17fe4189d2fe]*/ { - int fd, cnt; - Py_ssize_t res; - PyObject *seq; + int cnt; + Py_ssize_t result; + int async_err = 0; struct iovec *iov; Py_buffer *buf; - if (!PyArg_ParseTuple(args, "iO:writev", &fd, &seq)) - return NULL; - if (!PySequence_Check(seq)) { + + if (!PySequence_Check(buffers)) { PyErr_SetString(PyExc_TypeError, "writev() arg 2 must be a sequence"); - return NULL; + return -1; } - cnt = PySequence_Size(seq); + cnt = PySequence_Size(buffers); - if (iov_setup(&iov, &buf, seq, cnt, PyBUF_SIMPLE) < 0) { - return NULL; + if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { + return -1; } - Py_BEGIN_ALLOW_THREADS - res = writev(fd, iov, cnt); - Py_END_ALLOW_THREADS + do { + Py_BEGIN_ALLOW_THREADS + result = writev(fd, iov, cnt); + Py_END_ALLOW_THREADS + } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); iov_cleanup(iov, buf, cnt); - if (res < 0) - return posix_error(); + if (result < 0 && !async_err) + posix_error(); - return PyLong_FromSsize_t(res); + return result; } -#endif +#endif /* HAVE_WRITEV */ + #ifdef HAVE_PWRITE -PyDoc_STRVAR(posix_pwrite__doc__, -"pwrite(fd, string, offset) -> byteswritten\n\n\ -Write string to a file descriptor, fd, from offset, leaving the file\n\ -offset unchanged."); +/*[clinic input] +os.pwrite -> Py_ssize_t -static PyObject * -posix_pwrite(PyObject *self, PyObject *args) + fd: int + buffer: Py_buffer + offset: Py_off_t + / + +Write bytes to a file descriptor starting at a particular offset. + +Write buffer to fd, starting at offset bytes from the beginning of +the file. Returns the number of bytes writte. Does not change the +current file offset. +[clinic start generated code]*/ + +static Py_ssize_t +os_pwrite_impl(PyModuleDef *module, int fd, Py_buffer *buffer, + Py_off_t offset) +/*[clinic end generated code: output=93aabdb40e17d325 input=19903f1b3dd26377]*/ { - Py_buffer pbuf; - int fd; - off_t offset; Py_ssize_t size; - - if (!PyArg_ParseTuple(args, "iy*O&:pwrite", &fd, &pbuf, _parse_off_t, &offset)) - return NULL; + int async_err = 0; if (!_PyVerify_fd(fd)) { - PyBuffer_Release(&pbuf); - return posix_error(); + posix_error(); + return -1; } - Py_BEGIN_ALLOW_THREADS - size = pwrite(fd, pbuf.buf, (size_t)pbuf.len, offset); - Py_END_ALLOW_THREADS - PyBuffer_Release(&pbuf); - if (size < 0) - return posix_error(); - return PyLong_FromSsize_t(size); + + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + + if (size < 0 && !async_err) + posix_error(); + return size; } -#endif +#endif /* HAVE_PWRITE */ + #ifdef HAVE_MKFIFO -PyDoc_STRVAR(posix_mkfifo__doc__, -"mkfifo(path, mode=0o666, *, dir_fd=None)\n\n\ -Create a FIFO (a POSIX named pipe).\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.mkfifo + + path: path_t + mode: int=0o666 + * + dir_fd: dir_fd(requires='mkfifoat')=None + +Create a "fifo" (a POSIX named pipe). + +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_mkfifo(PyObject *self, PyObject *args, PyObject *kwargs) +os_mkfifo_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd) +/*[clinic end generated code: output=8f5f5e72c630049a input=73032e98a36e0e19]*/ { - path_t path; - int mode = 0666; - int dir_fd = DEFAULT_DIR_FD; int result; - PyObject *return_value = NULL; - static char *keywords[] = {"path", "mode", "dir_fd", NULL}; + int async_err = 0; - memset(&path, 0, sizeof(path)); - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|i$O&:mkfifo", keywords, - path_converter, &path, - &mode, + do { + Py_BEGIN_ALLOW_THREADS #ifdef HAVE_MKFIFOAT - dir_fd_converter, &dir_fd -#else - dir_fd_unavailable, &dir_fd + if (dir_fd != DEFAULT_DIR_FD) + result = mkfifoat(dir_fd, path->narrow, mode); + else #endif - )) - return NULL; + result = mkfifo(path->narrow, mode); + Py_END_ALLOW_THREADS + } while (result != 0 && errno == EINTR && + !(async_err = PyErr_CheckSignals())); + if (result != 0) + return (!async_err) ? posix_error() : NULL; - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_MKFIFOAT - if (dir_fd != DEFAULT_DIR_FD) - result = mkfifoat(dir_fd, path.narrow, mode); - else -#endif - result = mkfifo(path.narrow, mode); - Py_END_ALLOW_THREADS + Py_RETURN_NONE; +} +#endif /* HAVE_MKFIFO */ - if (result < 0) { - return_value = posix_error(); - goto exit; - } - return_value = Py_None; - Py_INCREF(Py_None); +#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) +/*[clinic input] +os.mknod -exit: - path_cleanup(&path); - return return_value; -} -#endif + path: path_t + mode: int=0o600 + device: dev_t=0 + * + dir_fd: dir_fd(requires='mknodat')=None -#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) -PyDoc_STRVAR(posix_mknod__doc__, -"mknod(filename, mode=0o600, device=0, *, dir_fd=None)\n\n\ -Create a filesystem node (file, device special file or named pipe)\n\ -named filename. mode specifies both the permissions to use and the\n\ -type of node to be created, being combined (bitwise OR) with one of\n\ -S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. For S_IFCHR and S_IFBLK,\n\ -device defines the newly created device special file (probably using\n\ -os.makedev()), otherwise it is ignored.\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."); +Create a node in the file system. + +Create a node in the file system (file, device special file or named pipe) +at path. mode specifies both the permissions to use and the +type of node to be created, being combined (bitwise OR) with one of +S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode, +device defines the newly created device special file (probably using +os.makedev()). Otherwise device is ignored. +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_mknod(PyObject *self, PyObject *args, PyObject *kwargs) +os_mknod_impl(PyModuleDef *module, path_t *path, int mode, dev_t device, + int dir_fd) +/*[clinic end generated code: output=5151a8a9f754d272 input=ee44531551a4d83b]*/ { - path_t path; - int mode = 0666; - dev_t device = 0; - int dir_fd = DEFAULT_DIR_FD; int result; - PyObject *return_value = NULL; - static char *keywords[] = {"path", "mode", "device", "dir_fd", NULL}; + int async_err = 0; - memset(&path, 0, sizeof(path)); - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|iO&$O&:mknod", keywords, - path_converter, &path, - &mode, _Py_Dev_Converter, &device, + do { + Py_BEGIN_ALLOW_THREADS #ifdef HAVE_MKNODAT - dir_fd_converter, &dir_fd -#else - dir_fd_unavailable, &dir_fd + if (dir_fd != DEFAULT_DIR_FD) + result = mknodat(dir_fd, path->narrow, mode, device); + else #endif - )) - return NULL; + result = mknod(path->narrow, mode, device); + Py_END_ALLOW_THREADS + } while (result != 0 && errno == EINTR && + !(async_err = PyErr_CheckSignals())); + if (result != 0) + return (!async_err) ? posix_error() : NULL; - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_MKNODAT - if (dir_fd != DEFAULT_DIR_FD) - result = mknodat(dir_fd, path.narrow, mode, device); - else -#endif - result = mknod(path.narrow, mode, device); - Py_END_ALLOW_THREADS + Py_RETURN_NONE; +} +#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */ - if (result < 0) { - return_value = posix_error(); - goto exit; - } - return_value = Py_None; - Py_INCREF(Py_None); +#ifdef HAVE_DEVICE_MACROS +/*[clinic input] +os.major -> unsigned_int -exit: - path_cleanup(&path); - return return_value; -} -#endif + device: dev_t + / -#ifdef HAVE_DEVICE_MACROS -PyDoc_STRVAR(posix_major__doc__, -"major(device) -> major number\n\ -Extracts a device major number from a raw device number."); +Extracts a device major number from a raw device number. +[clinic start generated code]*/ -static PyObject * -posix_major(PyObject *self, PyObject *args) +static unsigned int +os_major_impl(PyModuleDef *module, dev_t device) +/*[clinic end generated code: output=ba55693ab49bac34 input=1e16a4d30c4d4462]*/ { - dev_t device; - if (!PyArg_ParseTuple(args, "O&:major", _Py_Dev_Converter, &device)) - return NULL; - return PyLong_FromLong((long)major(device)); + return major(device); } -PyDoc_STRVAR(posix_minor__doc__, -"minor(device) -> minor number\n\ -Extracts a device minor number from a raw device number."); -static PyObject * -posix_minor(PyObject *self, PyObject *args) +/*[clinic input] +os.minor -> unsigned_int + + device: dev_t + / + +Extracts a device minor number from a raw device number. +[clinic start generated code]*/ + +static unsigned int +os_minor_impl(PyModuleDef *module, dev_t device) +/*[clinic end generated code: output=2867219ebf274e27 input=0842c6d23f24c65e]*/ { - dev_t device; - if (!PyArg_ParseTuple(args, "O&:minor", _Py_Dev_Converter, &device)) - return NULL; - return PyLong_FromLong((long)minor(device)); + return minor(device); } -PyDoc_STRVAR(posix_makedev__doc__, -"makedev(major, minor) -> device number\n\ -Composes a raw device number from the major and minor device numbers."); -static PyObject * -posix_makedev(PyObject *self, PyObject *args) +/*[clinic input] +os.makedev -> dev_t + + major: int + minor: int + / + +Composes a raw device number from the major and minor device numbers. +[clinic start generated code]*/ + +static dev_t +os_makedev_impl(PyModuleDef *module, int major, int minor) +/*[clinic end generated code: output=7cb6264352437660 input=4b9fd8fc73cbe48f]*/ { - int major, minor; - if (!PyArg_ParseTuple(args, "ii:makedev", &major, &minor)) - return NULL; - return _PyLong_FromDev(makedev(major, minor)); + return makedev(major, minor); } -#endif /* device macros */ +#endif /* HAVE_DEVICE_MACROS */ -#ifdef HAVE_FTRUNCATE -PyDoc_STRVAR(posix_ftruncate__doc__, -"ftruncate(fd, length)\n\n\ -Truncate a file to a specified length."); +#if defined HAVE_FTRUNCATE || defined MS_WINDOWS +/*[clinic input] +os.ftruncate + + fd: int + length: Py_off_t + / + +Truncate a file, specified by file descriptor, to a specific length. +[clinic start generated code]*/ static PyObject * -posix_ftruncate(PyObject *self, PyObject *args) +os_ftruncate_impl(PyModuleDef *module, int fd, Py_off_t length) +/*[clinic end generated code: output=3666f401d76bf834 input=63b43641e52818f2]*/ { - int fd; - off_t length; - int res; - - if (!PyArg_ParseTuple(args, "iO&:ftruncate", &fd, _parse_off_t, &length)) - return NULL; + int result; + int async_err = 0; - Py_BEGIN_ALLOW_THREADS - res = ftruncate(fd, length); - Py_END_ALLOW_THREADS - if (res < 0) + if (!_PyVerify_fd(fd)) return posix_error(); - Py_INCREF(Py_None); - return Py_None; -} + + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH +#ifdef MS_WINDOWS + result = _chsize_s(fd, length); +#else + result = ftruncate(fd, length); #endif + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (result != 0 && errno == EINTR && + !(async_err = PyErr_CheckSignals())); + if (result != 0) + return (!async_err) ? posix_error() : NULL; + Py_RETURN_NONE; +} +#endif /* HAVE_FTRUNCATE || MS_WINDOWS */ + + +#if defined HAVE_TRUNCATE || defined MS_WINDOWS +/*[clinic input] +os.truncate + path: path_t(allow_fd='PATH_HAVE_FTRUNCATE') + length: Py_off_t + +Truncate a file, specified by path, to a specific length. -#ifdef HAVE_TRUNCATE -PyDoc_STRVAR(posix_truncate__doc__, -"truncate(path, length)\n\n\ -Truncate the file given by path to length bytes.\n\ -On some platforms, path may also be specified as an open file descriptor.\n\ - If this functionality is unavailable, using it raises an exception."); +On some platforms, path may also be specified as an open file descriptor. + If this functionality is unavailable, using it raises an exception. +[clinic start generated code]*/ static PyObject * -posix_truncate(PyObject *self, PyObject *args, PyObject *kwargs) +os_truncate_impl(PyModuleDef *module, path_t *path, Py_off_t length) +/*[clinic end generated code: output=f60a9e08370e9e2e input=77229cf0b50a9b77]*/ { - path_t path; - off_t length; - int res; - PyObject *result = NULL; - static char *keywords[] = {"path", "length", NULL}; - - memset(&path, 0, sizeof(path)); - path.function_name = "truncate"; -#ifdef HAVE_FTRUNCATE - path.allow_fd = 1; + int result; +#ifdef MS_WINDOWS + int fd; #endif - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&:truncate", keywords, - path_converter, &path, - _parse_off_t, &length)) - return NULL; + + if (path->fd != -1) + return os_ftruncate_impl(module, path->fd, length); Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_FTRUNCATE - if (path.fd != -1) - res = ftruncate(path.fd, length); + _Py_BEGIN_SUPPRESS_IPH +#ifdef MS_WINDOWS + if (path->wide) + fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT); else -#endif - res = truncate(path.narrow, length); - Py_END_ALLOW_THREADS - if (res < 0) - result = path_error(&path); + fd = _open(path->narrow, _O_WRONLY | _O_BINARY | _O_NOINHERIT); - if (fd < 0) ++ if (fd < 0) + result = -1; else { - Py_INCREF(Py_None); - result = Py_None; + result = _chsize_s(fd, length); + close(fd); + if (result < 0) + errno = result; } - path_cleanup(&path); - return result; -} +#else + result = truncate(path->narrow, length); #endif + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + if (result < 0) + return path_error(path); -/* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise() - and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is - defined, which is the case in Python on AIX. AIX bug report: + Py_RETURN_NONE; +} +#endif /* HAVE_TRUNCATE || MS_WINDOWS */ + + +/* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise() + and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is + defined, which is the case in Python on AIX. AIX bug report: http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */ #if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__) # define POSIX_FADVISE_AIX_BUG