1 | #!/usr/bin/env python2
|
2 | """Bool_stat.py.
|
3 |
|
4 | Not translating this file directly.
|
5 | """
|
6 | from __future__ import print_function
|
7 |
|
8 | import stat
|
9 | import posix_ as posix
|
10 | from posix_ import X_OK, R_OK, W_OK # refers directly to C macro
|
11 | from _devbuild.gen.id_kind_asdl import Id, Id_t
|
12 | from _devbuild.gen.syntax_asdl import word_t, loc
|
13 | from core.error import e_die
|
14 | from core import ui
|
15 |
|
16 |
|
17 | def isatty(fd_str, blame_word):
|
18 | # type: (str, word_t) -> bool
|
19 | try:
|
20 | fd = int(fd_str)
|
21 | except ValueError:
|
22 | e_die('Invalid file descriptor %r' % fd_str, loc.Word(blame_word))
|
23 |
|
24 | try:
|
25 | return posix.isatty(fd)
|
26 | # fd is user input, and causes this exception in the binding.
|
27 | except OverflowError:
|
28 | e_die('File descriptor %r is too big' % fd_str, loc.Word(blame_word))
|
29 |
|
30 |
|
31 | def DoUnaryOp(op_id, s):
|
32 | # type: (Id_t, str) -> bool
|
33 |
|
34 | # Only use lstat if we're testing for a symlink.
|
35 | if op_id in (Id.BoolUnary_h, Id.BoolUnary_L):
|
36 | try:
|
37 | mode = posix.lstat(s).st_mode
|
38 | except OSError:
|
39 | # TODO: simple_test_builtin should this as status=2.
|
40 | #e_die("lstat() error: %s", e, word=node.child)
|
41 | return False
|
42 |
|
43 | return stat.S_ISLNK(mode)
|
44 |
|
45 | try:
|
46 | st = posix.stat(s)
|
47 | except OSError as e:
|
48 | # TODO: simple_test_builtin should this as status=2.
|
49 | # Problem: we really need errno, because test -f / is bad argument,
|
50 | # while test -f /nonexistent is a good argument but failed. Gah.
|
51 | # ENOENT vs. ENAMETOOLONG.
|
52 | #e_die("stat() error: %s", e, word=node.child)
|
53 | return False
|
54 | mode = st.st_mode
|
55 |
|
56 | if op_id in (Id.BoolUnary_e, Id.BoolUnary_a): # -a is alias for -e
|
57 | return True
|
58 |
|
59 | if op_id == Id.BoolUnary_b:
|
60 | return stat.S_ISBLK(mode)
|
61 |
|
62 | if op_id == Id.BoolUnary_c:
|
63 | return stat.S_ISCHR(mode)
|
64 |
|
65 | if op_id == Id.BoolUnary_d:
|
66 | return stat.S_ISDIR(mode)
|
67 |
|
68 | if op_id == Id.BoolUnary_f:
|
69 | return stat.S_ISREG(mode)
|
70 |
|
71 | if op_id == Id.BoolUnary_g:
|
72 | return bool(stat.S_IMODE(mode) & stat.S_ISGID)
|
73 |
|
74 | if op_id == Id.BoolUnary_k:
|
75 | # need 'bool' for MyPy
|
76 | return bool(stat.S_IMODE(mode) & stat.S_ISVTX)
|
77 |
|
78 | if op_id == Id.BoolUnary_p:
|
79 | return stat.S_ISFIFO(mode)
|
80 |
|
81 | if op_id == Id.BoolUnary_r:
|
82 | return posix.access(s, R_OK)
|
83 |
|
84 | if op_id == Id.BoolUnary_s:
|
85 | return st.st_size != 0
|
86 |
|
87 | if op_id == Id.BoolUnary_u:
|
88 | return bool(stat.S_IMODE(mode) & stat.S_ISUID)
|
89 |
|
90 | if op_id == Id.BoolUnary_w:
|
91 | return posix.access(s, W_OK)
|
92 |
|
93 | if op_id == Id.BoolUnary_x:
|
94 | return posix.access(s, X_OK)
|
95 |
|
96 | if op_id == Id.BoolUnary_G:
|
97 | return st.st_gid == posix.getegid()
|
98 |
|
99 | if op_id == Id.BoolUnary_O:
|
100 | return st.st_uid == posix.geteuid()
|
101 |
|
102 | if op_id == Id.BoolUnary_S:
|
103 | return stat.S_ISSOCK(mode)
|
104 |
|
105 | e_die("%s isn't implemented" % ui.PrettyId(op_id), loc.Missing)
|
106 |
|
107 |
|
108 | def DoBinaryOp(op_id, s1, s2):
|
109 | # type: (Id_t, str, str) -> bool
|
110 | try:
|
111 | st1 = posix.stat(s1)
|
112 | except OSError:
|
113 | st1 = None
|
114 | try:
|
115 | st2 = posix.stat(s2)
|
116 | except OSError:
|
117 | st2 = None
|
118 |
|
119 | if op_id in (Id.BoolBinary_nt, Id.BoolBinary_ot):
|
120 | # pretend it's a very old file
|
121 | m1 = 0 if st1 is None else st1.st_mtime
|
122 | m2 = 0 if st2 is None else st2.st_mtime
|
123 | if op_id == Id.BoolBinary_nt:
|
124 | return m1 > m2
|
125 | else:
|
126 | return m1 < m2
|
127 |
|
128 | if op_id == Id.BoolBinary_ef:
|
129 | if st1 is None:
|
130 | return False
|
131 | if st2 is None:
|
132 | return False
|
133 | return st1.st_dev == st2.st_dev and st1.st_ino == st2.st_ino
|
134 |
|
135 | raise AssertionError(op_id)
|