| 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)
|