• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#
2# Copyright 2017 - The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16import logging
17from vts.runners.host import asserts
18from vts.runners.host import const
19
20_PERMISSION_GROUPS = 3  # 3 permission groups: owner, group, all users
21_READ_PERMISSION = 4
22_WRITE_PERMISSION = 2
23_EXECUTE_PERMISSION = 1
24
25
26def Exists(filepath, shell):
27    """Determines if a file exists.
28
29    Args:
30        filepath: string, path to file
31        shell: an instance of the VTS shell
32
33    Returns:
34        True if the file exists, False otherwise
35    """
36    cmd = "ls %s" % filepath
37    results = shell.Execute(cmd)
38    if results[const.EXIT_CODE][0] != 0:
39        return False
40
41    out_str = str(results[const.STDOUT][0]).strip()
42    return out_str.find(filepath) == 0
43
44
45def FindFiles(shell, path, name_pattern):
46    """Searches a path for files on device.
47
48    Args:
49        shell: the ShellMirrorObject.
50        path: string, the path to search on device.
51        name_pattern: string, the file name pattern.
52
53    Returns:
54        list of strings, the paths to the found files.
55
56    Raises:
57        IOError if the pattern contains quotes, or the path does not exist.
58    """
59    if '"' in name_pattern or "'" in name_pattern:
60        raise IOError("File name pattern contains quotes")
61    cmd = "find %s -name \"%s\"" % (path, name_pattern)
62    results = shell.Execute(cmd)
63    logging.info("%s: Shell command '%s' results: %s", path, cmd, results)
64
65    if results[const.EXIT_CODE][0] != 0:
66        raise IOError(results[const.STDERR][0])
67
68    stdout = str(results[const.STDOUT][0])
69    return stdout.strip().split("\n")
70
71
72def ReadFileContent(filepath, shell):
73    """Read the content of a file and perform assertions.
74
75    Args:
76        filepath: string, path to file
77        shell: an instance of the VTS shell
78
79    Returns:
80        string, content of file
81
82    Raises:
83        IOError if the file does not exist.
84    """
85    cmd = "cat %s" % filepath
86    results = shell.Execute(cmd)
87    logging.info("%s: Shell command '%s' results: %s", filepath, cmd, results)
88
89    # checks the exit code
90    if results[const.EXIT_CODE][0] != 0:
91        raise IOError(results[const.STDERR][0])
92
93    return results[const.STDOUT][0]
94
95
96def GetPermission(path, shell):
97    """Read the file permission bits of a path.
98
99    Args:
100        filepath: string, path to a file or directory
101        shell: an instance of the VTS shell
102
103    Returns:
104        String, octal permission bits for the path
105
106    Raises:
107        IOError if the path does not exist or has invalid permission bits.
108    """
109    cmd = "stat -c %%a %s" % path
110    results = shell.Execute(cmd)
111    logging.info("%s: Shell command '%s' results: %s", path, cmd, results)
112
113    # checks the exit code
114    if results[const.EXIT_CODE][0] != 0:
115        raise IOError(results[const.STDERR][0])
116
117    accessBits = results[const.STDOUT][0].strip()
118    if len(accessBits) != 3:
119        raise IOError("%s: Wrong number of access bits (%s)" % (path,
120                                                                accessBits))
121    return accessBits
122
123
124def _HasPermission(permission_bits, groupIndex, permission):
125    """Determines if the permission bits grant a permission to a group.
126
127    Args:
128        permission_bits: string, the octal permissions string (e.g. 741)
129        groupIndex: int, the index of the group into the permissions string.
130                    (e.g. 0 is owner group). If set to -1, then all groups are
131                    checked.
132        permission: the value of the permission.
133
134    Returns:
135        True if the group(s) has read permission.
136
137    Raises:
138        ValueError if the group or permission bits are invalid
139    """
140    if groupIndex >= _PERMISSION_GROUPS:
141        raise ValueError("Invalid group: %s" % str(groupIndex))
142
143    if len(permission_bits) != _PERMISSION_GROUPS:
144        raise ValueError("Invalid permission bits: %s" % str(permission_bits))
145
146    # Define the start/end group index
147    start = groupIndex
148    end = groupIndex + 1
149    if groupIndex < 0:
150        start = 0
151        end = _PERMISSION_GROUPS
152
153    for i in range(start, end):
154        perm = int(permission_bits[i])  # throws ValueError if not an integer
155        if perm > 7:
156            raise ValueError("Invalid permission bit: %s" % str(perm))
157        if perm & permission == 0:
158            # Return false if any group lacks the permission
159            return False
160    # Return true if no group lacks the permission
161    return True
162
163
164def IsReadable(permission_bits):
165    """Determines if the permission bits grant read permission to any group.
166
167    Args:
168        permission_bits: string, the octal permissions string (e.g. 741)
169
170    Returns:
171        True if any group has read permission.
172
173    Raises:
174        ValueError if the group or permission bits are invalid
175    """
176    return any([
177        _HasPermission(permission_bits, i, _READ_PERMISSION)
178        for i in range(_PERMISSION_GROUPS)
179    ])
180
181
182def IsWritable(permission_bits):
183    """Determines if the permission bits grant write permission to any group.
184
185    Args:
186        permission_bits: string, the octal permissions string (e.g. 741)
187
188    Returns:
189        True if any group has write permission.
190
191    Raises:
192        ValueError if the group or permission bits are invalid
193    """
194    return any([
195        _HasPermission(permission_bits, i, _WRITE_PERMISSION)
196        for i in range(_PERMISSION_GROUPS)
197    ])
198
199
200def IsExecutable(permission_bits):
201    """Determines if the permission bits grant execute permission to any group.
202
203    Args:
204        permission_bits: string, the octal permissions string (e.g. 741)
205
206    Returns:
207        True if any group has execute permission.
208
209    Raises:
210        ValueError if the group or permission bits are invalid
211    """
212    return any([
213        _HasPermission(permission_bits, i, _EXECUTE_PERMISSION)
214        for i in range(_PERMISSION_GROUPS)
215    ])
216
217
218def IsReadOnly(permission_bits):
219    """Determines if the permission bits grant read-only permission.
220
221    Read-only permission is granted if some group has read access but no group
222    has write access.
223
224    Args:
225        permission_bits: string, the octal permissions string (e.g. 741)
226
227    Returns:
228        True if any group has read permission, none have write.
229
230    Raises:
231        ValueError if the group or permission bits are invalid
232    """
233    return IsReadable(permission_bits) and not IsWritable(permission_bits)
234
235
236def IsWriteOnly(permission_bits):
237    """Determines if the permission bits grant write-only permission.
238
239    Write-only permission is granted if some group has write access but no group
240    has read access.
241
242    Args:
243        permission_bits: string, the octal permissions string (e.g. 741)
244
245    Returns:
246        True if any group has write permission, none have read.
247
248    Raises:
249        ValueError if the group or permission bits are invalid
250    """
251    return IsWritable(permission_bits) and not IsReadable(permission_bits)
252
253
254def IsReadWrite(permission_bits):
255    """Determines if the permission bits grant read/write permissions.
256
257    Read-write permission is granted if some group has read access and some has
258    write access. The groups may be different.
259
260    Args:
261        permission_bits: string, the octal permissions string (e.g. 741)
262
263    Returns:
264        True if read and write permissions are granted to any group(s).
265
266    Raises:
267        ValueError if the group or permission bits are invalid
268    """
269    return IsReadable(permission_bits) and IsWritable(permission_bits)
270
271
272def assertPermissionsAndExistence(shell, path, check_permission):
273    """Asserts that the specified path exists and has the correct permission.
274
275    Args:
276        path: string, path to validate existence and permissions
277        check_permission: function which takes unix permissions in octal
278                          format and returns True if the permissions are
279                          correct, False otherwise.
280    """
281    asserts.assertTrue(Exists(path, shell), "%s: File does not exist." % path)
282    try:
283        permission = GetPermission(path, shell)
284        asserts.assertTrue(
285            check_permission(permission),
286            "%s: File has invalid permissions (%s)" % (path, permission))
287    except (ValueError, IOError) as e:
288        asserts.fail("Failed to assert permissions: %s" % str(e))
289