def GetRawDevice(path): """Resolve the raw device that contains the path.""" device_map = GetMountpoints() path = utils.SmartUnicode(path) mount_point = path = utils.NormalizePath(path, "/") result = rdf_paths.PathSpec(pathtype=rdf_paths.PathSpec.PathType.OS) # Assign the most specific mount point to the result while mount_point: try: result.path, fs_type = device_map[mount_point] if fs_type in [ "ext2", "ext3", "ext4", "vfat", "ntfs", "Apple_HFS", "hfs", "msdos" ]: # These are read filesystems result.pathtype = rdf_paths.PathSpec.PathType.OS else: result.pathtype = rdf_paths.PathSpec.PathType.UNSET # Drop the mount point path = utils.NormalizePath(path[len(mount_point):]) return result, path except KeyError: mount_point = os.path.dirname(mount_point)
def GetRawDevice(path): """Resolve the raw device that contains the path.""" device_map = GetMountpoints() path = utils.SmartUnicode(path) mount_point = path = utils.NormalizePath(path, "/") result = rdf_paths.PathSpec(pathtype=rdf_paths.PathSpec.PathType.OS) # Assign the most specific mount point to the result while mount_point: try: result.path, fs_type = device_map[mount_point] if fs_type in SUPPORTED_FILESYSTEMS: # These are read filesystems result.pathtype = rdf_paths.PathSpec.PathType.OS else: logging.error( "Filesystem %s is not supported. Supported filesystems " "are %s", fs_type, SUPPORTED_FILESYSTEMS) result.pathtype = rdf_paths.PathSpec.PathType.UNSET # Drop the mount point path = utils.NormalizePath(path[len(mount_point):]) result.mount_point = mount_point return result, path except KeyError: mount_point = os.path.dirname(mount_point)
def PopulateCache(self): """Parse the paths from the fixture.""" if self.paths: return # The cache is attached to the class so it can be shared by all instance. self.paths = self.__class__.cache[self.prefix] = {} for path, (vfs_type, attributes) in client_fixture.VFS: if not path.startswith(self.prefix): continue path = utils.NormalizePath(path[len(self.prefix):]) if path == "/": continue stat = rdf_client.StatEntry() args = {"client_id": "C.1234"} attrs = attributes.get("aff4:stat") if attrs: attrs %= args # Remove any %% and interpolate client_id. stat = rdf_client.StatEntry.FromTextFormat( utils.SmartStr(attrs)) stat.pathspec = rdf_paths.PathSpec( pathtype=self.supported_pathtype, path=path) # TODO(user): Once we add tests around not crossing device boundaries, # we need to be smarter here, especially for the root entry. stat.st_dev = 1 path = self._NormalizeCaseForPath(path, vfs_type) self.paths[path] = (vfs_type, stat) self.BuildIntermediateDirectories()
def GenerateDirectory(self, input_dir=None, output_dir=None, replacements=None): input_dir = utils.NormalizePath(input_dir) output_dir = utils.NormalizePath(output_dir) replacements = replacements or [] for (root, _, files) in os.walk(input_dir): for filename in files: in_file = utils.JoinPath(root, filename) out_file = in_file.replace(input_dir, output_dir) for (s, replacement) in replacements: out_file = out_file.replace(s, replacement) utils.EnsureDirExists(os.path.dirname(out_file)) self.GenerateFile(in_file, out_file)
def ParseFromString(self, initializer): """Create RDFRUN from string. Args: initializer: url string """ # Strip off the aff4: prefix if necessary. if initializer.startswith("aff4:/"): initializer = initializer[5:] self._string_urn = utils.NormalizePath(initializer)
def Interpolate(self, client=None): kb = client.Get(client.Schema.KNOWLEDGE_BASE) patterns = artifact_utils.InterpolateKbAttributes(self._value, kb) for pattern in patterns: # Normalize the component path (this allows us to resolve ../ # sequences). pattern = utils.NormalizePath(pattern.replace("\\", "/")) for pattern in self.InterpolateGrouping(pattern): yield pattern
def testNormpath(self): """Test our Normpath.""" data = [ ("foo/../../../../", "/"), ("/foo/../../../../bar", "/bar"), ("/foo/bar/../3sdfdfsa/.", "/foo/3sdfdfsa"), ("../foo/bar", "/foo/bar"), ("./foo/bar", "/foo/bar"), ("/", "/"), ] for test, expected in data: self.assertEqual(expected, utils.NormalizePath(test))
def GetRawDevice(path): """Resolves the raw device that contains the path. Args: path: A path to examine. Returns: A pathspec to read the raw device as well as the modified path to read within the raw device. This is usually the path without the mount point. Raises: IOError: if the path does not exist or some unexpected behaviour occurs. """ path = CanonicalPathToLocalPath(path) # Try to expand the shortened paths try: path = win32file.GetLongPathName(path) except pywintypes.error: pass try: mount_point = win32file.GetVolumePathName(path) except pywintypes.error as details: logging.info("path not found. %s", details) raise IOError("No mountpoint for path: %s" % path) if not path.startswith(mount_point): stripped_mp = mount_point.rstrip("\\") if not path.startswith(stripped_mp): raise IOError("path %s is not mounted under %s" % (path, mount_point)) corrected_path = LocalPathToCanonicalPath(path[len(mount_point):]) corrected_path = utils.NormalizePath(corrected_path) volume = win32file.GetVolumeNameForVolumeMountPoint(mount_point).rstrip( "\\") volume = LocalPathToCanonicalPath(volume) # The pathspec for the raw volume result = rdf_paths.PathSpec(path=volume, pathtype=rdf_paths.PathSpec.PathType.OS, mount_point=mount_point.rstrip("\\")) return result, corrected_path
def CanonicalPathToLocalPath(path): """Linux uses a normal path. We always want to encode as UTF-8 here. If the environment for the client is broken, Python might assume an ASCII based filesystem (those should be rare nowadays) and things will go wrong if we let Python decide what to do. If the filesystem actually is ASCII, encoding and decoding will not change anything so things will still work as expected. Args: path: the canonical path as an Unicode string Returns: a unicode string or an encoded (narrow) string dependent on system settings """ return utils.SmartStr(utils.NormalizePath(path))
def testTSKFileInode(self): """Test opening a file through an indirect pathspec.""" pathspec = rdf_paths.PathSpec(path=os.path.join( self.base_path, "test_img.dd"), pathtype=rdf_paths.PathSpec.PathType.OS) pathspec.Append(pathtype=rdf_paths.PathSpec.PathType.TSK, inode=12, path="/Test Directory") pathspec.Append(pathtype=rdf_paths.PathSpec.PathType.TSK, path="numbers.txt") fd = vfs.VFSOpen(pathspec) # Check that the new pathspec is correctly reduced to two components. self.assertEqual( fd.pathspec.first.path, utils.NormalizePath(os.path.join(self.base_path, "test_img.dd"))) self.assertEqual(fd.pathspec[1].path, "/Test Directory/numbers.txt") # And the correct inode is placed in the final branch. self.assertEqual(fd.Stat().pathspec.nested_path.inode, 15) self.TestFileHandling(fd)
def testTSKFileCasing(self): """Test our ability to read the correct casing from image.""" path = os.path.join(self.base_path, "test_img.dd") path2 = os.path.join("test directory", "NuMbErS.TxT") ps2 = rdf_paths.PathSpec(path=path2, pathtype=rdf_paths.PathSpec.PathType.TSK) ps = rdf_paths.PathSpec(path=path, pathtype=rdf_paths.PathSpec.PathType.OS) ps.Append(ps2) fd = vfs.VFSOpen(ps) # This fixes Windows paths. path = path.replace("\\", "/") # The pathspec should have 2 components. self.assertEqual(fd.pathspec.first.path, utils.NormalizePath(path)) self.assertEqual(fd.pathspec.first.pathtype, rdf_paths.PathSpec.PathType.OS) nested = fd.pathspec.last self.assertEqual(nested.path, u"/Test Directory/numbers.txt") self.assertEqual(nested.pathtype, rdf_paths.PathSpec.PathType.TSK)
def LocalPathToCanonicalPath(path): """Linux uses a normal path.""" return utils.NormalizePath(path)
def Run(self, args): """Delete all the GRR temp files in path. If path is a directory, look in the top level for filenames beginning with Client.tempfile_prefix, and delete them. If path is a regular file and starts with Client.tempfile_prefix delete it. Args: args: pathspec pointing to directory containing temp files to be deleted, or a single file to be deleted. Returns: deleted: array of filename strings that were deleted Raises: ErrorBadPath: if path doesn't exist or is not a regular file or directory """ allowed_temp_dirs = [ GetTempDirForRoot(root) for root in config.CONFIG["Client.tempdir_roots"] ] if args.path: # Normalize the path, so DeleteGRRTempFile can correctly check if # it is within Client.tempdir. paths = [ client_utils.CanonicalPathToLocalPath( utils.NormalizePath(args.path)) ] else: paths = allowed_temp_dirs deleted = [] errors = [] for path in paths: if os.path.isdir(path): for filename in os.listdir(path): abs_filename = os.path.join(path, filename) try: DeleteGRRTempFile(abs_filename) deleted.append(abs_filename) except Exception as e: # pylint: disable=broad-except # The error we are most likely to get is ErrorNotTempFile but # especially on Windows there might be locking issues that raise # various WindowsErrors so we just catch them all and continue # deleting all other temp files in this directory. errors.append(e) elif os.path.isfile(path): DeleteGRRTempFile(path) deleted = [path] elif path not in allowed_temp_dirs: if not os.path.exists(path): raise ErrorBadPath("File %s does not exist" % path) else: raise ErrorBadPath("Not a regular file or directory: %s" % path) reply = "" if deleted: reply = "Deleted: %s." % deleted else: reply = "Nothing deleted." if errors: reply += "\n%s" % errors self.SendReply(rdf_client.LogMessage(data=reply))