View difference between Paste ID: aCUwTumB and dGaX3mx8
SHOW: | | - or go back to the newest paste.
1
#!/usr/bin/python
2
3
import contextlib
4
import ctypes
5
6
cf = ctypes.cdll.LoadLibrary('/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation')
7
8
cf.CFShow.argtypes = [ctypes.c_void_p]
9
cf.CFShow.restype = None
10
11
cf.CFRelease.argtypes = [ctypes.c_void_p]
12
cf.CFRelease.restype = None
13
14
cf.CFStringCreateWithBytes.argtypes = [ctypes.c_void_p, 
15
                                       ctypes.c_char_p, ctypes.c_long, 
16
                                       ctypes.c_int, ctypes.c_int]
17
cf.CFStringCreateWithBytes.restype = ctypes.c_void_p
18
19
cf.CFStringGetMaximumSizeOfFileSystemRepresentation.argtypes = [ctypes.c_void_p]
20
cf.CFStringGetMaximumSizeOfFileSystemRepresentation.restype = ctypes.c_int
21
22
cf.CFStringGetFileSystemRepresentation.argtypes = [ctypes.c_void_p,
23
                                                   ctypes.c_char_p,
24
                                                   ctypes.c_long]
25
cf.CFStringGetFileSystemRepresentation.restype = ctypes.c_int
26
27
cf.CFURLCreateFromFileSystemRepresentation.argtypes = [ctypes.c_void_p,
28
                                                       ctypes.c_char_p,
29
                                                       ctypes.c_long,
30
                                                       ctypes.c_int]
31
cf.CFURLCreateFromFileSystemRepresentation.restype = ctypes.c_void_p
32
33
cf.CFURLCopyResourcePropertyForKey.argtypes = [ctypes.c_void_p,
34
                                               ctypes.c_void_p,
35
                                               ctypes.c_void_p,
36
                                               ctypes.c_void_p]
37
cf.CFURLCopyResourcePropertyForKey.restype = ctypes.c_int
38
39
cf.CFBooleanGetValue.argtypes = [ctypes.c_void_p]
40
cf.CFBooleanGetValue.restype = ctypes.c_int
41
42
cf.CFURLEnumeratorCreateForDirectoryURL.argtypes = [ctypes.c_void_p,
43
                                                    ctypes.c_void_p,
44
                                                    ctypes.c_int,
45
                                                    ctypes.c_void_p]
46
cf.CFURLEnumeratorCreateForDirectoryURL.restype = ctypes.c_void_p
47
48
49
cf.CFURLEnumeratorGetNextURL.argtypes = [ctypes.c_void_p,
50
                                         ctypes.c_void_p,
51
                                         ctypes.c_void_p]
52
cf.CFURLEnumeratorGetNextURL.restype = ctypes.c_int
53
54
cf.CFURLCopyFileSystemPath.argtypes = [ctypes.c_void_p, ctypes.c_int]
55
cf.CFURLCopyFileSystemPath.restype = ctypes.c_void_p
56
57
# From CFString.h
58
# http://www.opensource.apple.com/source/CF/CF-744/CFString.h
59
# The value has been the same from at least 10.2-10.8.
60
kCFStringEncodingUTF8 = 0x08000100
61
62
# Documented here:
63
# https://developer.apple.com/library/mac/#documentation/CoreFoundation/Reference/CFURLEnumeratorRef/Reference/reference.html
64
kCFURLEnumeratorSkipInvisibles = 1 << 1
65
66
kCFURLEnumeratorSuccess = 1
67
kCFURLEnumeratorEnd = 2
68
kCFURLEnumeratorError = 3
69
kCFURLEnumeratorDirectoryPostOrderSuccess = 4
70
71
# Documented here:
72
# http://developer.apple.com/library/ios/#documentation/CoreFoundation/Reference/CFURLRef/Reference/reference.html
73
kCFURLPOSIXPathStyle = 0
74
75
# This one is a static CFStringRef.
76
kCFURLIsHiddenKey = ctypes.c_void_p.in_dll(cf, 'kCFURLIsHiddenKey')
77
78-
path = b'/Users/abarnert/.bash_history'
78+
79
def cfreleasing(stuff):
80
    try:
81
        yield
82
    finally:
83
        for thing in stuff:
84
            cf.CFRelease(thing)
85
86
def cfstr_to_unicode(cfstr):
87
    count = cf.CFStringGetMaximumSizeOfFileSystemRepresentation(cfstr)
88
    buf = (ctypes.c_char * count)()
89
    if cf.CFStringGetFileSystemRepresentation(cfstr, buf, count):
90
        return buf.value.decode('UTF-8')
91
    raise OSError('CFStringGetFileSystemRepresentation failed')
92
93
def is_hidden(path):
94
    if not isinstance(path, bytes):
95
        path = path.encode('UTF-8')
96
    stuff = []
97
    with cfreleasing(stuff):
98
        url = cf.CFURLCreateFromFileSystemRepresentation(None, path, len(path), False)
99
        stuff.append(url)
100
        val = ctypes.c_void_p(0)
101
        ret = cf.CFURLCopyResourcePropertyForKey(url, kCFURLIsHiddenKey,
102
                                                 ctypes.addressof(val), None)
103
        if ret:
104
            result = cf.CFBooleanGetValue(val)
105
            stuff.append(val)
106
            return True if result else False
107
        # TODO: You could pass a CFErrorRef instead of None, and do all the
108
        # work to wrap that in a Python exception, etc.
109
        raise OSError('CFURLCopyResourcePropertyForKey failed')
110
111
def listdir_skipping_hidden(path):
112
    if not isinstance(path, bytes):
113
        path = path.encode('UTF-8')
114
    stuff = []
115
    with cfreleasing(stuff):
116
        url = cf.CFURLCreateFromFileSystemRepresentation(None, 
117
                                                         path, len(path), 
118
                                                         True)
119
        stuff.append(url)
120
        enum = cf.CFURLEnumeratorCreateForDirectoryURL(None, url,
121
                                                       kCFURLEnumeratorSkipInvisibles,
122
                                                       None)
123
        stuff.append(enum)
124
        paths = []
125
        while True:
126
            url = ctypes.c_void_p(0)
127
            ret = cf.CFURLEnumeratorGetNextURL(enum, ctypes.addressof(url), None)
128
            if ret != kCFURLEnumeratorSuccess:
129
                break
130
            path = cf.CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle)
131
            stuff.append(path)
132
            paths.append(cfstr_to_unicode(path))
133
        return paths
134
135
if __name__ == '__main__':
136
    import sys
137
    for arg in sys.argv[1:]:
138
        print('{}: {}'.format(arg, is_hidden(arg)))
139
        if arg[-1] == '/':
140
            for path in listdir_skipping_hidden(arg):
141
                print('  {}'.format(path))