aboutsummaryrefslogtreecommitdiff
blob: 6600a7190ba1f07c4bc8ee06c08ee01a0410d455 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
"""Wrapper for readdir which grabs file type from d_type."""


import errno
import os
from stat import (
    S_IFBLK,
    S_IFCHR,
    S_IFDIR,
    S_IFIFO,
    S_IFLNK,
    S_IFMT,
    S_IFREG,
    S_IFSOCK,
    S_ISDIR,
    S_ISREG,
)

from ..mappings import ProtectedDict

# we can still use the cpy pjoin here, just need to do something about the
# import cycle.
pjoin = os.path.join


def stat_swallow_enoent(path, check, default=False, stat=os.stat):
    try:
        return check(stat(path).st_mode)
    except OSError as oe:
        if oe.errno == errno.ENOENT:
            return default
        raise


def listdir_dirs(path, followSymlinks=True):
    """
    Return a list of all subdirectories within a directory

    :param path: directory to scan
    :param followSymlinks: this controls if symlinks are resolved.
        If True and the symlink resolves to a directory, it is returned,
        else if False it isn't returned.
    :return: list of directories within `path`
    """
    scheck = S_ISDIR
    pjf = pjoin
    lstat = os.lstat
    if followSymlinks:
        return [
            x for x in os.listdir(path) if stat_swallow_enoent(pjf(path, x), scheck)
        ]
    lstat = os.lstat
    return [x for x in os.listdir(path) if scheck(lstat(pjf(path, x)).st_mode)]


def listdir_files(path, followSymlinks=True):
    """
    Return a list of all files within a directory

    :param path: directory to scan
    :param followSymlinks: this controls if symlinks are resolved.
        If True and the symlink resolves to a file, it is returned,
        else if False it isn't returned.
    :return: list of files within `path`
    """

    scheck = S_ISREG
    pjf = pjoin
    if followSymlinks:
        return [
            x for x in os.listdir(path) if stat_swallow_enoent(pjf(path, x), scheck)
        ]
    lstat = os.lstat
    return [x for x in os.listdir(path) if scheck(lstat(pjf(path, x)).st_mode)]


# we store this outside the function to ensure that
# the strings used are reused, thus avoiding unneeded
# allocations
d_type_mapping = ProtectedDict(
    {
        S_IFREG: "file",
        S_IFDIR: "directory",
        S_IFLNK: "symlink",
        S_IFCHR: "chardev",
        S_IFBLK: "block",
        S_IFSOCK: "socket",
        S_IFIFO: "fifo",
    }
)


def readdir(path):
    """
    Given a directory, return a list of (filename, filetype)

    see :py:data:`d_type_mappings` for the translation used

    :param path: path of a directory to scan
    :return: list of (filename, filetype)
    """
    return [
        (name, d_type_mapping[S_IFMT(os.lstat(pjoin(path, name)).st_mode)])
        for name in os.listdir(path)
    ]