def UpdateSparseImageIfNeeded(self, fd, length, offset): missing_chunks = self.GetMissingChunks(fd, length, offset) if not missing_chunks: return client_id = rdf_client.GetClientURNFromPath(fd.urn.Path()) flow_utils.StartFlowAndWait( client_id, token=self.token, flow_name=filesystem.UpdateSparseImageChunks.__name__, file_urn=fd.urn, chunks_to_fetch=missing_chunks)
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)