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