Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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);
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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;
}
Esempio n. 7
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;
}
Esempio n. 8
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;
}
Esempio n. 9
0
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
}
Esempio n. 10
0
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
}
Esempio n. 11
0
/* 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;
}
Esempio n. 12
0
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 */
}
Esempio n. 13
0
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 */
}