def _RunAndWaitForVFSFileUpdate(self, path): """Runs a flow on the client, and waits for it to finish.""" client_id = rdf_client.GetClientURNFromPath(path) # If we're not actually in a directory on a client, no need to run a flow. if client_id is None: return flow_utils.UpdateVFSFileAndWait(client_id, token=self.token, vfs_file_urn=self.root.Add(path), timeout=self.timeout)
def Read(self, path, length=None, offset=0, fh=None): fd = aff4.FACTORY.Open(self.root.Add(path), token=self.token) last = fd.Get(fd.Schema.CONTENT_LAST) client_id = rdf_client.GetClientURNFromPath(path) if not self.DataRefreshRequired(last=last, path=path): return super(GRRFuse, self).Read(path, length, offset, fh) if isinstance(fd, standard.AFF4SparseImage): # If we have a sparse image, update just a part of it. self.UpdateSparseImageIfNeeded(fd, length, offset) # Read the file from the datastore as usual. return super(GRRFuse, self).Read(path, length, offset, fh) # If it's the first time we've seen this path (or we're asking # explicitly), try and make it an AFF4SparseImage. if last is None or self.force_sparse_image: pathspec = fd.Get(fd.Schema.PATHSPEC) # Either makes a new AFF4SparseImage or gets the file fully, # depending on size. flow_utils.StartFlowAndWait( client_id, token=self.token, flow_name=filesystem.MakeNewAFF4SparseImage.__name__, pathspec=pathspec, size_threshold=self.size_threshold) # Reopen the fd in case it's changed to be an AFF4SparseImage fd = aff4.FACTORY.Open(self.root.Add(path), token=self.token) # If we are now a sparse image, just download the part we requested # from the client. if isinstance(fd, standard.AFF4SparseImage): flow_utils.StartFlowAndWait( client_id, token=self.token, flow_name=filesystem.FetchBufferForSparseImage.__name__, file_urn=self.root.Add(path), length=length, offset=offset) else: # This was a file we'd seen before that wasn't a sparse image, so update # it the usual way. self._RunAndWaitForVFSFileUpdate(path) # Read the file from the datastore as usual. return super(GRRFuse, self).Read(path, length, offset, fh)
def Run(self, args): """Downloads files/directories with the given path.""" # If we're exporting a path inside a client, check to see if we have access # to that client and get the appropriate token. This means we can avoid # having to specify --reason. client_id = client.GetClientURNFromPath(args.path) if client_id is not None: token = security.Approval.GetApprovalForObject( client_id, token=data_store.default_token, username=data_store.default_token.username) data_store.default_token = token try: directory = aff4.FACTORY.Open(args.path, "AFF4Volume", token=data_store.default_token) except aff4.InstantiationError: directory = None if directory and not isinstance(directory, aff4.VFSDirectory): # If directory is not a VFSDirectory, check that it's in its' parent # children list. This way we check that the path actually exists. directory_parent = aff4.FACTORY.Open( directory.urn.Dirname(), token=data_store.default_token) if directory.urn not in directory_parent.ListChildren(): raise RuntimeError("Specified path %s doesn't exist!" % directory.urn) if directory: export_utils.RecursiveDownload(directory, args.output, overwrite=args.overwrite, max_depth=args.depth, max_threads=args.threads) else: export_utils.CopyAFF4ToLocal(args.path, args.output, overwrite=args.overwrite, token=data_store.default_token)
def main(unused_argv): config_lib.CONFIG.AddContext( "Commandline Context", "Context applied for all command line tools") startup.Init() if fuse is None: logging.critical("""Could not start! fusepy must be installed to run fuse_mount.py! Try: sudo pip install fusepy""") sys.exit(1) if not flags.FLAGS.mountpoint: Usage() sys.exit(1) # We multiple inherit from GRRFuse and fuse.Operations. In the # case that fuse is present, we run the actual FUSE layer, since we have # fuse.Operations. In the case that fuse is not present, we have already # exited by now if we were run from the command line, and if we were not run # from the command line, we've been imported, and we run the tests using a # mock fuse. class FuseOperation(GRRFuse, fuse.Operations): pass root = flags.FLAGS.aff4path username = flags.FLAGS.username or getpass.getuser() token = access_control.ACLToken(username=username, reason=flags.FLAGS.reason or "fusemount") # If we're exporting a path inside a client, check to see if we have access to # that client and get the appropriate token. client_id = client.GetClientURNFromPath(root) if client_id is not None: token = security.Approval.GetApprovalForObject( client_id, token=token, username=username) data_store.default_token = token logging.info("fuse_mount.py is mounting %s at %s....", root, flags.FLAGS.mountpoint) refresh_policy = flags.FLAGS.refresh_policy if refresh_policy == "always": max_age_before_refresh = datetime.timedelta(0) elif refresh_policy == "never": # Set the max age to be the maximum possible time difference. max_age_before_refresh = datetime.timedelta.max elif refresh_policy == "if_older_than_max_age": max_age_before_refresh = datetime.timedelta( seconds=flags.FLAGS.max_age_before_refresh) else: # Otherwise, a flag outside the enum was given and the flag validator threw # an execption. pass fuse_operation = FuseOperation( root=root, token=token, max_age_before_refresh=max_age_before_refresh, ignore_cache=flags.FLAGS.ignore_cache, force_sparse_image=flags.FLAGS.force_sparse_image, sparse_image_threshold=flags.FLAGS.sparse_image_threshold, timeout=flags.FLAGS.timeout) fuse.FUSE(fuse_operation, flags.FLAGS.mountpoint, foreground=not flags.FLAGS.background)