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 _Test(shell, *args): 27 """Executes test command on device. 28 29 Args: 30 shell: an instance of the VTS shell. 31 *args: strings, the command line arguments. 32 33 Returns: 34 boolean, whether the condition is true. 35 """ 36 cmd = "test %s" % " ".join(args) 37 results = shell.Execute(cmd) 38 return results[const.EXIT_CODE][0] == 0 39 40 41def Exists(filepath, shell): 42 """Determines if a file or directory exists. 43 44 Args: 45 filepath: string, the path to a file or a directory. 46 shell: an instance of the VTS shell. 47 48 Returns: 49 True if exists, False otherwise. 50 """ 51 return _Test(shell, "-e", filepath) 52 53 54def IsDirectory(path, shell): 55 """Determines if a path is a directory. 56 57 Args: 58 path: string, a path on device. 59 shell: an instance of the VTS shell. 60 61 Returns: 62 True if the path is a directory, False otherwise. 63 """ 64 return _Test(shell, "-d", path) 65 66 67def FindFiles(shell, path, name_pattern, options=None): 68 """Searches a path for files on device. 69 70 Args: 71 shell: the ShellMirrorObject. 72 path: string, the path to search on device. 73 name_pattern: string, the file name pattern. 74 options: string, other options passed to find command. 75 76 Returns: 77 list of strings, the paths to the found files. 78 79 Raises: 80 IOError if the pattern contains quotes, or the path does not exist. 81 """ 82 if '"' in name_pattern or "'" in name_pattern: 83 raise IOError("File name pattern contains quotes") 84 cmd = "find %s -name \"%s\"" % (path, name_pattern) 85 if options is not None: 86 cmd += " " + options 87 results = shell.Execute(cmd) 88 logging.debug("%s: Shell command '%s' results: %s", path, cmd, results) 89 90 if results[const.EXIT_CODE][0] != 0: 91 raise IOError(results[const.STDERR][0]) 92 93 stdout = str(results[const.STDOUT][0]) 94 # Filter out empty strings before return. 95 return filter(None, stdout.strip().split("\n")) 96 97 98def ReadFileContent(filepath, shell): 99 """Read the content of a file and perform assertions. 100 101 Args: 102 filepath: string, path to file 103 shell: an instance of the VTS shell 104 105 Returns: 106 string, content of file 107 108 Raises: 109 IOError if the file does not exist. 110 """ 111 cmd = "cat %s" % filepath 112 results = shell.Execute(cmd) 113 logging.debug("%s: Shell command '%s' results: %s", filepath, cmd, results) 114 115 # checks the exit code 116 if results[const.EXIT_CODE][0] != 0: 117 raise IOError(results[const.STDERR][0]) 118 119 return results[const.STDOUT][0] 120 121 122def GetPermission(path, shell): 123 """Read the file permission bits of a path. 124 125 Args: 126 filepath: string, path to a file or directory 127 shell: an instance of the VTS shell 128 129 Returns: 130 String, octal permission bits for the path 131 132 Raises: 133 IOError if the path does not exist or has invalid permission bits. 134 """ 135 cmd = "stat -c %%a %s" % path 136 results = shell.Execute(cmd) 137 logging.debug("%s: Shell command '%s' results: %s", path, cmd, results) 138 139 # checks the exit code 140 if results[const.EXIT_CODE][0] != 0: 141 raise IOError(results[const.STDERR][0]) 142 143 accessBits = results[const.STDOUT][0].strip() 144 if len(accessBits) != 3: 145 raise IOError("%s: Wrong number of access bits (%s)" % (path, 146 accessBits)) 147 return accessBits 148 149 150def _HasPermission(permission_bits, groupIndex, permission): 151 """Determines if the permission bits grant a permission to a group. 152 153 Args: 154 permission_bits: string, the octal permissions string (e.g. 741) 155 groupIndex: int, the index of the group into the permissions string. 156 (e.g. 0 is owner group). If set to -1, then all groups are 157 checked. 158 permission: the value of the permission. 159 160 Returns: 161 True if the group(s) has read permission. 162 163 Raises: 164 ValueError if the group or permission bits are invalid 165 """ 166 if groupIndex >= _PERMISSION_GROUPS: 167 raise ValueError("Invalid group: %s" % str(groupIndex)) 168 169 if len(permission_bits) != _PERMISSION_GROUPS: 170 raise ValueError("Invalid permission bits: %s" % str(permission_bits)) 171 172 # Define the start/end group index 173 start = groupIndex 174 end = groupIndex + 1 175 if groupIndex < 0: 176 start = 0 177 end = _PERMISSION_GROUPS 178 179 for i in range(start, end): 180 perm = int(permission_bits[i]) # throws ValueError if not an integer 181 if perm > 7: 182 raise ValueError("Invalid permission bit: %s" % str(perm)) 183 if perm & permission == 0: 184 # Return false if any group lacks the permission 185 return False 186 # Return true if no group lacks the permission 187 return True 188 189 190def IsReadable(permission_bits): 191 """Determines if the permission bits grant read permission to any group. 192 193 Args: 194 permission_bits: string, the octal permissions string (e.g. 741) 195 196 Returns: 197 True if any group has read permission. 198 199 Raises: 200 ValueError if the group or permission bits are invalid 201 """ 202 return any([ 203 _HasPermission(permission_bits, i, _READ_PERMISSION) 204 for i in range(_PERMISSION_GROUPS) 205 ]) 206 207 208def IsWritable(permission_bits): 209 """Determines if the permission bits grant write permission to any group. 210 211 Args: 212 permission_bits: string, the octal permissions string (e.g. 741) 213 214 Returns: 215 True if any group has write permission. 216 217 Raises: 218 ValueError if the group or permission bits are invalid 219 """ 220 return any([ 221 _HasPermission(permission_bits, i, _WRITE_PERMISSION) 222 for i in range(_PERMISSION_GROUPS) 223 ]) 224 225 226def IsExecutable(permission_bits): 227 """Determines if the permission bits grant execute permission to any group. 228 229 Args: 230 permission_bits: string, the octal permissions string (e.g. 741) 231 232 Returns: 233 True if any group has execute permission. 234 235 Raises: 236 ValueError if the group or permission bits are invalid 237 """ 238 return any([ 239 _HasPermission(permission_bits, i, _EXECUTE_PERMISSION) 240 for i in range(_PERMISSION_GROUPS) 241 ]) 242 243 244def IsReadOnly(permission_bits): 245 """Determines if the permission bits grant read-only permission. 246 247 Read-only permission is granted if some group has read access but no group 248 has write access. 249 250 Args: 251 permission_bits: string, the octal permissions string (e.g. 741) 252 253 Returns: 254 True if any group has read permission, none have write. 255 256 Raises: 257 ValueError if the group or permission bits are invalid 258 """ 259 return IsReadable(permission_bits) and not IsWritable(permission_bits) 260 261 262def IsWriteOnly(permission_bits): 263 """Determines if the permission bits grant write-only permission. 264 265 Write-only permission is granted if some group has write access but no group 266 has read access. 267 268 Args: 269 permission_bits: string, the octal permissions string (e.g. 741) 270 271 Returns: 272 True if any group has write permission, none have read. 273 274 Raises: 275 ValueError if the group or permission bits are invalid 276 """ 277 return IsWritable(permission_bits) and not IsReadable(permission_bits) 278 279 280def IsReadWrite(permission_bits): 281 """Determines if the permission bits grant read/write permissions. 282 283 Read-write permission is granted if some group has read access and some has 284 write access. The groups may be different. 285 286 Args: 287 permission_bits: string, the octal permissions string (e.g. 741) 288 289 Returns: 290 True if read and write permissions are granted to any group(s). 291 292 Raises: 293 ValueError if the group or permission bits are invalid 294 """ 295 return IsReadable(permission_bits) and IsWritable(permission_bits) 296 297 298def assertPermissionsAndExistence(shell, path, check_permission): 299 """Asserts that the specified path exists and has the correct permission. 300 301 Args: 302 path: string, path to validate existence and permissions 303 check_permission: function which takes unix permissions in octal 304 format and returns True if the permissions are 305 correct, False otherwise. 306 """ 307 asserts.assertTrue(Exists(path, shell), "%s: File does not exist." % path) 308 try: 309 permission = GetPermission(path, shell) 310 asserts.assertTrue( 311 check_permission(permission), 312 "%s: File has invalid permissions (%s)" % (path, permission)) 313 except (ValueError, IOError) as e: 314 asserts.fail("Failed to assert permissions: %s" % str(e)) 315