Example #1
0
def get_terminal_size():
    """Returns a tuple (x, y) representing the width(x) and the height(x)
    in characters of the terminal window."""
    def ioctl_GWINSZ(fd):
        try:
            import fcntl
            import termios
            import struct
            cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,
                                                 '1234'))
        except:
            return None
        if cr == (0, 0):
            return None
        return cr

    cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
    if not cr:
        try:
            fd = testos.open(testos.ctermid(), testos.O_RDONLY)
            cr = ioctl_GWINSZ(fd)
            testos.close(fd)
        except:
            pass
    if not cr:
        cr = (testos.environ.get('LINES',
                                 25), testos.environ.get('COLUMNS', 80))
    return int(cr[1]), int(cr[0])
Example #2
0
def get_path_uid(path):
    """
    Return path's uid.

    Does not follow symlinks:
        https://github.com/pypa/pip/pull/935#discussion_r5307003

    Placed this function in compat due to differences on AIX and
    Jython, that should eventually go away.

    :raises OSError: When path is a symlink or can't be read.
    """
    if hasattr(testos, 'O_NOFOLLOW'):
        fd = testos.open(path, testos.O_RDONLY | testos.O_NOFOLLOW)
        file_uid = testos.fstat(fd).st_uid
        testos.close(fd)
    else:  # AIX and Jython
        # WARNING: time of check vulnerability, but best we can do w/o NOFOLLOW
        if not testos.path.islink(path):
            # older versions of Jython don't have `os.fstat`
            file_uid = testos.stat(path).st_uid
        else:
            # raise OSError for parity with os.O_NOFOLLOW above
            raise OSError(
                "%s is a symlink; Will not return uid for symlinks" % path
            )
    return file_uid
Example #3
0
def _mkstemp_inner(dir, pre, suf, flags, output_type):
    """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile."""

    names = _get_candidate_names()
    if output_type is bytes:
        names = map(_os.fsencode, names)

    for seq in range(TMP_MAX):
        name = next(names)
        file = _os.path.join(dir, pre + name + suf)
        try:
            fd = _os.open(file, flags, 0o600)
        except FileExistsError:
            continue  # try again
        except PermissionError:
            # This exception is thrown when a directory with the chosen name
            # already exists on windows.
            if (_os.name == 'nt' and _os.path.isdir(dir)
                    and _os.access(dir, _os.W_OK)):
                continue
            else:
                raise
        return (fd, _os.path.abspath(file))

    raise FileExistsError(_errno.EEXIST, "No usable temporary file name found")
Example #4
0
def rmtree(path, ignore_errors=False, onerror=None):
    """Recursively delete a directory tree.

    If ignore_errors is set, errors are ignored; otherwise, if onerror
    is set, it is called to handle the error with arguments (func,
    path, exc_info) where func is platform and implementation dependent;
    path is the argument to that function that caused it to fail; and
    exc_info is a tuple returned by sys.exc_info().  If ignore_errors
    is false and onerror is None, an exception is raised.

    """
    if ignore_errors:

        def onerror(*args):
            pass
    elif onerror is None:

        def onerror(*args):
            raise

    if _use_fd_functions:
        # While the unsafe rmtree works fine on bytes, the fd based does not.
        if isinstance(path, bytes):
            path = testos.fsdecode(path)
        # Note: To guard against symlink races, we use the standard
        # lstat()/open()/fstat() trick.
        try:
            orig_st = testos.lstat(path)
        except Exception:
            onerror(testos.lstat, path, sys.exc_info())
            return
        try:
            fd = testos.open(path, testos.O_RDONLY)
        except Exception:
            onerror(testos.lstat, path, sys.exc_info())
            return
        try:
            if testos.path.samestat(orig_st, testos.fstat(fd)):
                _rmtree_safe_fd(fd, path, onerror)
                try:
                    testos.rmdir(path)
                except OSError:
                    onerror(testos.rmdir, path, sys.exc_info())
            else:
                try:
                    # symlinks to directories are forbidden, see bug #1669
                    raise OSError("Cannot call rmtree on a symbolic link")
                except OSError:
                    onerror(testos.path.islink, path, sys.exc_info())
        finally:
            testos.close(fd)
    else:
        return _rmtree_unsafe(path, onerror)
Example #5
0
def _rmtree_safe_fd(topfd, path, onerror):
    names = []
    try:
        names = testos.listdir(topfd)
    except OSError as err:
        err.filename = path
        onerror(testos.listdir, path, sys.exc_info())
    for name in names:
        fullname = testos.path.join(path, name)
        try:
            orig_st = testos.stat(name, dir_fd=topfd, follow_symlinks=False)
            mode = orig_st.st_mode
        except OSError:
            mode = 0
        if stat.S_ISDIR(mode):
            try:
                dirfd = testos.open(name, testos.O_RDONLY, dir_fd=topfd)
            except OSError:
                onerror(testos.open, fullname, sys.exc_info())
            else:
                try:
                    if testos.path.samestat(orig_st, testos.fstat(dirfd)):
                        _rmtree_safe_fd(dirfd, fullname, onerror)
                        try:
                            testos.rmdir(name, dir_fd=topfd)
                        except OSError:
                            onerror(testos.rmdir, fullname, sys.exc_info())
                    else:
                        try:
                            # This can only happen if someone replaces
                            # a directory with a symlink after the call to
                            # stat.S_ISDIR above.
                            raise OSError("Cannot call rmtree on a symbolic "
                                          "link")
                        except OSError:
                            onerror(testos.path.islink, fullname,
                                    sys.exc_info())
                finally:
                    testos.close(dirfd)
        else:
            try:
                testos.unlink(name, dir_fd=topfd)
            except OSError:
                onerror(testos.unlink, fullname, sys.exc_info())
Example #6
0
def _get_default_tempdir():
    """Calculate the default directory to use for temporary files.
    This routine should be called exactly once.

    We determine whether or not a candidate temp dir is usable by
    trying to create and write to a file in that directory.  If this
    is successful, the test file is deleted.  To prevent denial of
    service, the name of the test file must be randomized."""

    namer = _RandomNameSequence()
    dirlist = _candidate_tempdir_list()

    for dir in dirlist:
        if dir != _os.curdir:
            dir = _os.path.abspath(dir)
        # Try only a few names per directory.
        for seq in range(100):
            name = next(namer)
            filename = _os.path.join(dir, name)
            try:
                fd = _os.open(filename, _bin_openflags, 0o600)
                try:
                    try:
                        with _io.open(fd, 'wb', closefd=False) as fp:
                            fp.write(b'blat')
                    finally:
                        _os.close(fd)
                finally:
                    _os.unlink(filename)
                return dir
            except FileExistsError:
                pass
            except PermissionError:
                # This exception is thrown when a directory with the chosen name
                # already exists on windows.
                if (_os.name == 'nt' and _os.path.isdir(dir)
                        and _os.access(dir, _os.W_OK)):
                    continue
                break  # no point trying more names in this directory
            except OSError:
                break  # no point trying more names in this directory
    raise FileNotFoundError(
        _errno.ENOENT, "No usable temporary directory found in %s" % dirlist)
Example #7
0
def write_pid_to_pidfile(pidfile_path):
    """ Write the PID in the named PID file.

        Get the numeric process ID (“PID”) of the current process
        and write it to the named file as a line of text.

        """
    open_flags = (testos.O_CREAT | testos.O_EXCL | testos.O_WRONLY)
    open_mode = 0o644
    pidfile_fd = testos.open(pidfile_path, open_flags, open_mode)
    pidfile = testos.fdopen(pidfile_fd, 'w')

    # According to the FHS 2.3 section on PID files in /var/run:
    #
    #   The file must consist of the process identifier in
    #   ASCII-encoded decimal, followed by a newline character. For
    #   example, if crond was process number 25, /var/run/crond.pid
    #   would contain three characters: two, five, and newline.

    pid = testos.getpid()
    pidfile.write("%s\n" % pid)
    pidfile.close()
Example #8
0
def _secure_open_write(filename, fmode):
    # We only want to write to this file, so open it in write only mode
    flags = testos.O_WRONLY

    # os.O_CREAT | os.O_EXCL will fail if the file already exists, so we only
    #  will open *new* files.
    # We specify this because we want to ensure that the mode we pass is the
    # mode of the file.
    flags |= testos.O_CREAT | testos.O_EXCL

    # Do not follow symlinks to prevent someone from making a symlink that
    # we follow and insecurely open a cache file.
    if hasattr(testos, "O_NOFOLLOW"):
        flags |= testos.O_NOFOLLOW

    # On Windows we'll mark this file as binary
    if hasattr(testos, "O_BINARY"):
        flags |= testos.O_BINARY

    # Before we open our file, we want to delete any existing file that is
    # there
    try:
        testos.remove(filename)
    except (IOError, OSError):
        # The file must not exist already, so we can just skip ahead to opening
        pass

    # Open our file, the use of os.O_CREAT | os.O_EXCL will ensure that if a
    # race condition happens between the os.remove and this line, that an
    # error will be raised. Because we utilize a lockfile this should only
    # happen if someone is attempting to attack us.
    fd = testos.open(filename, flags, fmode)
    try:
        return testos.fdopen(fd, "wb")
    except:
        # An error occurred wrapping our FD in a file object
        testos.close(fd)
        raise
Example #9
0
 def _stat(fn):
     fd = _os.open(fn, _os.O_RDONLY)
     _os.close(fd)
Example #10
0
    def TemporaryFile(mode='w+b',
                      buffering=-1,
                      encoding=None,
                      newline=None,
                      suffix=None,
                      prefix=None,
                      dir=None):
        """Create and return a temporary file.
        Arguments:
        'prefix', 'suffix', 'dir' -- as for mkstemp.
        'mode' -- the mode argument to io.open (default "w+b").
        'buffering' -- the buffer size argument to io.open (default -1).
        'encoding' -- the encoding argument to io.open (default None)
        'newline' -- the newline argument to io.open (default None)
        The file is created as mkstemp() would do it.

        Returns an object with a file-like interface.  The file has no
        name, and will cease to exist when it is closed.
        """
        global _O_TMPFILE_WORKS

        prefix, suffix, dir, output_type = _sanitize_params(
            prefix, suffix, dir)

        flags = _bin_openflags
        if _O_TMPFILE_WORKS:
            try:
                flags2 = (flags | _os.O_TMPFILE) & ~_os.O_CREAT
                fd = _os.open(dir, flags2, 0o600)
            except IsADirectoryError:
                # Linux kernel older than 3.11 ignores the O_TMPFILE flag:
                # O_TMPFILE is read as O_DIRECTORY. Trying to open a directory
                # with O_RDWR|O_DIRECTORY fails with IsADirectoryError, a
                # directory cannot be open to write. Set flag to False to not
                # try again.
                _O_TMPFILE_WORKS = False
            except OSError:
                # The filesystem of the directory does not support O_TMPFILE.
                # For example, OSError(95, 'Operation not supported').
                #
                # On Linux kernel older than 3.11, trying to open a regular
                # file (or a symbolic link to a regular file) with O_TMPFILE
                # fails with NotADirectoryError, because O_TMPFILE is read as
                # O_DIRECTORY.
                pass
            else:
                try:
                    return _io.open(fd,
                                    mode,
                                    buffering=buffering,
                                    newline=newline,
                                    encoding=encoding)
                except:
                    _os.close(fd)
                    raise
            # Fallback to _mkstemp_inner().

        (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags, output_type)
        try:
            _os.unlink(name)
            return _io.open(fd,
                            mode,
                            buffering=buffering,
                            newline=newline,
                            encoding=encoding)
        except:
            _os.close(fd)
            raise