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