static int faulthandler_get_fileno(PyObject **file_ptr) { PyObject *result; long fd_long; long fd; PyObject *file = *file_ptr; if (file == NULL || file == Py_None) { file = PySys_GetObject("stderr"); if (file == NULL) { PyErr_SetString(PyExc_RuntimeError, "unable to get sys.stderr"); return -1; } if (file == Py_None) { PyErr_SetString(PyExc_RuntimeError, "sys.stderr is None"); return -1; } } else if (PYINT_CHECK(file)) { fd = PYINT_ASLONG(file); if (fd == -1 && PyErr_Occurred()) return -1; if (fd < 0 || fd > INT_MAX || !_PyVerify_fd(fd)) { PyErr_SetString(PyExc_ValueError, "file is not a valid file descripter"); return -1; } *file_ptr = NULL; return (int)fd; } result = PyObject_CallMethod(file, "fileno", ""); if (result == NULL) return -1; fd = -1; if (PYINT_CHECK(result)) { fd_long = PYINT_ASLONG(result); if (0 < fd_long && fd_long < INT_MAX) fd = (int)fd_long; } Py_DECREF(result); if (fd == -1) { PyErr_SetString(PyExc_RuntimeError, "file.fileno() is not a valid file descriptor"); return -1; } result = PyObject_CallMethod(file, "flush", ""); if (result != NULL) Py_DECREF(result); else { /* ignore flush() error */ PyErr_Clear(); } *file_ptr = file; return fd; }
PyObject * _Py_device_encoding(int fd) { #if defined(MS_WINDOWS) UINT cp; #endif if (!_PyVerify_fd(fd) || !isatty(fd)) { Py_RETURN_NONE; } #if defined(MS_WINDOWS) if (fd == 0) cp = GetConsoleCP(); else if (fd == 1 || fd == 2) cp = GetConsoleOutputCP(); else cp = 0; /* GetConsoleCP() and GetConsoleOutputCP() return 0 if the application has no console */ if (cp != 0) return PyUnicode_FromFormat("cp%u", (unsigned int)cp); #elif defined(CODESET) { char *codeset = nl_langinfo(CODESET); if (codeset != NULL && codeset[0] != 0) return PyUnicode_FromString(codeset); } #endif Py_RETURN_NONE; }
static int faulthandler_get_fileno(PyObject **file_ptr) { PyObject *result; long fd_long; int fd; PyObject *file = *file_ptr; if (file == NULL || file == Py_None) { file = _PySys_GetObjectId(&PyId_stderr); if (file == NULL) { PyErr_SetString(PyExc_RuntimeError, "unable to get sys.stderr"); return -1; } if (file == Py_None) { PyErr_SetString(PyExc_RuntimeError, "sys.stderr is None"); return -1; } } else if (PyLong_Check(file)) { fd = _PyLong_AsInt(file); if (fd == -1 && PyErr_Occurred()) return -1; if (fd < 0 || !_PyVerify_fd(fd)) { PyErr_SetString(PyExc_ValueError, "file is not a valid file descripter"); return -1; } *file_ptr = NULL; return fd; } result = _PyObject_CallMethodId(file, &PyId_fileno, ""); if (result == NULL) return -1; fd = -1; if (PyLong_Check(result)) { fd_long = PyLong_AsLong(result); if (0 <= fd_long && fd_long < INT_MAX) fd = (int)fd_long; } Py_DECREF(result); if (fd == -1) { PyErr_SetString(PyExc_RuntimeError, "file.fileno() is not a valid file descriptor"); return -1; } result = _PyObject_CallMethodId(file, &PyId_flush, ""); if (result != NULL) Py_DECREF(result); else { /* ignore flush() error */ PyErr_Clear(); } *file_ptr = file; return fd; }
FILE * libxml_PyFileGet(PyObject *f) { int fd, flags; FILE *res; const char *mode; fd = PyObject_AsFileDescriptor(f); if (!_PyVerify_fd(fd)) return(NULL); /* * Get the flags on the fd to understand how it was opened */ flags = fcntl(fd, F_GETFL, 0); switch (flags & O_ACCMODE) { case O_RDWR: if (flags & O_APPEND) mode = "a+"; else mode = "rw"; break; case O_RDONLY: if (flags & O_APPEND) mode = "r+"; else mode = "r"; break; case O_WRONLY: if (flags & O_APPEND) mode = "a"; else mode = "w"; break; default: return(NULL); } /* * the FILE struct gets a new fd, so that it can be closed * independently of the file descriptor given. The risk though is * lack of sync. So at the python level sync must be implemented * before and after a conversion took place. No way around it * in the Python3 infrastructure ! * The duplicated fd and FILE * will be released in the subsequent * call to libxml_PyFileRelease() which must be genrated accodingly */ fd = dup(fd); if (fd == -1) return(NULL); res = fdopen(fd, mode); if (res == NULL) { close(fd); return(NULL); } return(res); }
static int is_valid_fd(int fd) { int dummy_fd; if (fd < 0 || !_PyVerify_fd(fd)) return 0; dummy_fd = dup(fd); if (dummy_fd < 0) return 0; close(dummy_fd); return 1; }
static int is_valid_fd(int fd) { int dummy_fd; if (fd < 0 || !_PyVerify_fd(fd)) return 0; _Py_BEGIN_SUPPRESS_IPH dummy_fd = dup(fd); if (dummy_fd >= 0) close(dummy_fd); _Py_END_SUPPRESS_IPH return dummy_fd >= 0; }
/* Check if a file descriptor is valid or not. Return 0 if the file descriptor is invalid, return non-zero otherwise. */ static int is_valid_fd(int fd) { int fd2; if (fd < 0 || !_PyVerify_fd(fd)) return 0; _Py_BEGIN_SUPPRESS_IPH /* Prefer dup() over fstat(). fstat() can require input/output whereas dup() doesn't, there is a low risk of EMFILE/ENFILE at Python startup. */ fd2 = dup(fd); if (fd2 >= 0) close(fd2); _Py_END_SUPPRESS_IPH return fd2 >= 0; }
static Py_intptr_t msvcrt_get_osfhandle_impl(PyModuleDef *module, int fd) /*[clinic end generated code: output=376bff52586b55a6 input=c7d18d02c8017ec1]*/ { Py_intptr_t handle = -1; if (!_PyVerify_fd(fd)) { PyErr_SetFromErrno(PyExc_IOError); } else { _Py_BEGIN_SUPPRESS_IPH handle = _get_osfhandle(fd); _Py_END_SUPPRESS_IPH if (handle == -1) PyErr_SetFromErrno(PyExc_IOError); } return handle; }
static int get_inheritable(int fd, int raise) { #ifdef MS_WINDOWS HANDLE handle; DWORD flags; if (!_PyVerify_fd(fd)) { if (raise) PyErr_SetFromErrno(PyExc_OSError); return -1; } handle = (HANDLE)_get_osfhandle(fd); if (handle == INVALID_HANDLE_VALUE) { if (raise) PyErr_SetFromWindowsErr(0); return -1; } if (!GetHandleInformation(handle, &flags)) { if (raise) PyErr_SetFromWindowsErr(0); return -1; } return (flags & HANDLE_FLAG_INHERIT); #else int flags; flags = fcntl(fd, F_GETFD, 0); if (flags == -1) { if (raise) PyErr_SetFromErrno(PyExc_OSError); return -1; } return !(flags & FD_CLOEXEC); #endif }
static int set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works) { #ifdef MS_WINDOWS HANDLE handle; DWORD flags; #else #if defined(HAVE_SYS_IOCTL_H) && defined(FIOCLEX) && defined(FIONCLEX) static int ioctl_works = -1; int request; int err; #endif int flags; int res; #endif /* atomic_flag_works can only be used to make the file descriptor non-inheritable */ assert(!(atomic_flag_works != NULL && inheritable)); if (atomic_flag_works != NULL && !inheritable) { if (*atomic_flag_works == -1) { int inheritable = get_inheritable(fd, raise); if (inheritable == -1) return -1; *atomic_flag_works = !inheritable; } if (*atomic_flag_works) return 0; } #ifdef MS_WINDOWS if (!_PyVerify_fd(fd)) { if (raise) PyErr_SetFromErrno(PyExc_OSError); return -1; } handle = (HANDLE)_get_osfhandle(fd); if (handle == INVALID_HANDLE_VALUE) { if (raise) PyErr_SetFromWindowsErr(0); return -1; } if (inheritable) flags = HANDLE_FLAG_INHERIT; else flags = 0; if (!SetHandleInformation(handle, HANDLE_FLAG_INHERIT, flags)) { if (raise) PyErr_SetFromWindowsErr(0); return -1; } return 0; #else #if defined(HAVE_SYS_IOCTL_H) && defined(FIOCLEX) && defined(FIONCLEX) if (ioctl_works != 0) { /* fast-path: ioctl() only requires one syscall */ if (inheritable) request = FIONCLEX; else request = FIOCLEX; err = ioctl(fd, request, NULL); if (!err) { ioctl_works = 1; return 0; } if (errno != ENOTTY) { if (raise) PyErr_SetFromErrno(PyExc_OSError); return -1; } else { /* Issue #22258: Here, ENOTTY means "Inappropriate ioctl for device". The ioctl is declared but not supported by the kernel. Remember that ioctl() doesn't work. It is the case on Illumos-based OS for example. */ ioctl_works = 0; } /* fallback to fcntl() if ioctl() does not work */ } #endif /* slow-path: fcntl() requires two syscalls */ flags = fcntl(fd, F_GETFD); if (flags < 0) { if (raise) PyErr_SetFromErrno(PyExc_OSError); return -1; } if (inheritable) flags &= ~FD_CLOEXEC; else flags |= FD_CLOEXEC; res = fcntl(fd, F_SETFD, flags); if (res < 0) { if (raise) PyErr_SetFromErrno(PyExc_OSError); return -1; } return 0; #endif }
/* Duplicate a file descriptor. The new file descriptor is created as non-inheritable. Return a new file descriptor on success, raise an OSError exception and return -1 on error. The GIL is released to call dup(). The caller must hold the GIL. */ int _Py_dup(int fd) { #ifdef MS_WINDOWS HANDLE handle; DWORD ftype; #endif if (!_PyVerify_fd(fd)) { PyErr_SetFromErrno(PyExc_OSError); return -1; } #ifdef MS_WINDOWS handle = (HANDLE)_get_osfhandle(fd); if (handle == INVALID_HANDLE_VALUE) { PyErr_SetFromWindowsErr(0); return -1; } /* get the file type, ignore the error if it failed */ ftype = GetFileType(handle); Py_BEGIN_ALLOW_THREADS fd = dup(fd); Py_END_ALLOW_THREADS if (fd < 0) { PyErr_SetFromErrno(PyExc_OSError); return -1; } /* Character files like console cannot be make non-inheritable */ if (ftype != FILE_TYPE_CHAR) { if (_Py_set_inheritable(fd, 0, NULL) < 0) { close(fd); return -1; } } #elif defined(HAVE_FCNTL_H) && defined(F_DUPFD_CLOEXEC) Py_BEGIN_ALLOW_THREADS fd = fcntl(fd, F_DUPFD_CLOEXEC, 0); Py_END_ALLOW_THREADS if (fd < 0) { PyErr_SetFromErrno(PyExc_OSError); return -1; } #else Py_BEGIN_ALLOW_THREADS fd = dup(fd); Py_END_ALLOW_THREADS if (fd < 0) { PyErr_SetFromErrno(PyExc_OSError); return -1; } if (_Py_set_inheritable(fd, 0, NULL) < 0) { close(fd); return -1; } #endif return fd; }
static int my_fgets(char *buf, int len, FILE *fp) { char *p; int err; while (1) { if (PyOS_InputHook != NULL) (void)(PyOS_InputHook)(); errno = 0; clearerr(fp); if (_PyVerify_fd(fileno(fp))) p = fgets(buf, len, fp); else p = NULL; if (p != NULL) return 0; /* No error */ err = errno; #ifdef MS_WINDOWS /* In the case of a Ctrl+C or some other external event interrupting the operation: Win2k/NT: ERROR_OPERATION_ABORTED is the most recent Win32 error code (and feof() returns TRUE). Win9x: Ctrl+C seems to have no effect on fgets() returning early - the signal handler is called, but the fgets() only returns "normally" (ie, when Enter hit or feof()) */ if (GetLastError()==ERROR_OPERATION_ABORTED) { /* Signals come asynchronously, so we sleep a brief moment before checking if the handler has been triggered (we cant just return 1 before the signal handler has been called, as the later signal may be treated as a separate interrupt). */ Sleep(1); if (PyOS_InterruptOccurred()) { return 1; /* Interrupt */ } /* Either the sleep wasn't long enough (need a short loop retrying?) or not interrupted at all (in which case we should revisit the whole thing!) Logging some warning would be nice. assert is not viable as under the debugger, the various dialogs mean the condition is not true. */ } #endif /* MS_WINDOWS */ if (feof(fp)) { clearerr(fp); return -1; /* EOF */ } #ifdef EINTR if (err == EINTR) { int s; #ifdef WITH_THREAD PyEval_RestoreThread(_PyOS_ReadlineTState); #endif s = PyErr_CheckSignals(); #ifdef WITH_THREAD PyEval_SaveThread(); #endif if (s < 0) return 1; /* try again */ continue; } #endif if (PyOS_InterruptOccurred()) { return 1; /* Interrupt */ } return -2; /* Error */ } /* NOTREACHED */ }
static int my_fgets(char *buf, int len, FILE *fp) { #ifdef MS_WINDOWS HANDLE hInterruptEvent; #endif char *p; int err; while (1) { if (PyOS_InputHook != NULL) (void)(PyOS_InputHook)(); errno = 0; clearerr(fp); if (_PyVerify_fd(fileno(fp))) p = fgets(buf, len, fp); else p = NULL; if (p != NULL) return 0; /* No error */ err = errno; #ifdef MS_WINDOWS /* Ctrl-C anywhere on the line or Ctrl-Z if the only character on a line will set ERROR_OPERATION_ABORTED. Under normal circumstances Ctrl-C will also have caused the SIGINT handler to fire which will have set the event object returned by _PyOS_SigintEvent. This signal fires in another thread and is not guaranteed to have occurred before this point in the code. Therefore: check whether the event is set with a small timeout. If it is, assume this is a Ctrl-C and reset the event. If it isn't set assume that this is a Ctrl-Z on its own and drop through to check for EOF. */ if (GetLastError()==ERROR_OPERATION_ABORTED) { hInterruptEvent = _PyOS_SigintEvent(); switch (WaitForSingleObject(hInterruptEvent, 10)) { case WAIT_OBJECT_0: ResetEvent(hInterruptEvent); return 1; /* Interrupt */ case WAIT_FAILED: return -2; /* Error */ } } #endif /* MS_WINDOWS */ if (feof(fp)) { clearerr(fp); return -1; /* EOF */ } #ifdef EINTR if (err == EINTR) { int s; #ifdef WITH_THREAD PyEval_RestoreThread(_PyOS_ReadlineTState); #endif s = PyErr_CheckSignals(); #ifdef WITH_THREAD PyEval_SaveThread(); #endif if (s < 0) return 1; /* try again */ continue; } #endif if (PyOS_InterruptOccurred()) { return 1; /* Interrupt */ } return -2; /* Error */ } /* NOTREACHED */ }