Esempio n. 1
0
    def _Stat(self, path, ext_attrs=False):
        """Returns stat information of a specific path.

    Args:
      path: A unicode string containing the path.
      ext_attrs: Whether the call should also collect extended attributes.

    Returns:
      a StatResponse proto

    Raises:
      IOError when call to os.stat() fails
    """
        # Note that the encoding of local path is system specific
        local_path = client_utils.CanonicalPathToLocalPath(path)
        result = client_utils.StatEntryFromPath(local_path,
                                                self.pathspec,
                                                ext_attrs=ext_attrs)

        # Is this a symlink? If so we need to note the real location of the file.
        try:
            result.symlink = os.readlink(local_path)
            # Note: unlike Python 2 (raising OSError), Python 3 raises a ValueError
            # if the path in question doesn't point to a link.
        except (OSError, AttributeError, ValueError):
            pass

        return result
Esempio n. 2
0
    def Stat(self, path=None, ext_attrs=False):
        """Returns stat information of a specific path.

    Args:
      path: a Unicode string containing the path or None.
            If path is None the value in self.path is used.
      ext_attrs: Whether the call should also collect extended attributes.

    Returns:
      a StatResponse proto

    Raises:
      IOError when call to os.stat() fails
    """
        # Note that the encoding of local path is system specific
        local_path = client_utils.CanonicalPathToLocalPath(path or self.path)
        result = client_utils.StatEntryFromPath(local_path,
                                                self.pathspec,
                                                ext_attrs=ext_attrs)

        # Is this a symlink? If so we need to note the real location of the file.
        try:
            result.symlink = utils.SmartUnicode(os.readlink(local_path))
        except (OSError, AttributeError):
            pass

        return result
Esempio n. 3
0
    def RecursiveListNames(self, depth=0, cross_devs=False):
        path = client_utils.CanonicalPathToLocalPath(self.path)
        path_depth = self._GetDepth(self.path)

        if not cross_devs:
            path_dev = self._GetDevice(path)

        for root, dirs, files in os.walk(self.path):
            dirs.sort()
            files.sort()

            root_depth = self._GetDepth(root)

            # The recursion of the `os.walk` procedure is guided by the `dirs`
            # variable [1]. By clearing `dirs` below we force the generator to omit
            # certain rdf_paths.
            #
            # [1]: https://docs.python.org/2/library/os.html#os.walk

            if not cross_devs and self._GetDevice(root) != path_dev:
                dirs[:] = []  # We don't need to go deeper (clear the list)
            elif root_depth - path_depth >= depth:
                yield (root, dirs[:], files)  # Shallow copy
                dirs[:] = []
            else:
                yield (root, dirs, files)
Esempio n. 4
0
    def Stat(self, path=None):
        """Returns stat information of a specific path.

    Args:
      path: a Unicode string containing the path or None.
            If path is None the value in self.path is used.

    Returns:
      a StatResponse proto

    Raises:
      IOError when call to os.stat() fails
    """
        # Note that the encoding of local path is system specific
        local_path = client_utils.CanonicalPathToLocalPath(path or self.path)
        stat = self._GetStat(local_path)
        result = MakeStatResponse(stat, self.pathspec)

        # Is this a symlink? If so we need to note the real location of the file.
        try:
            result.symlink = utils.SmartUnicode(os.readlink(local_path))
        except (OSError, AttributeError):
            pass

        return result
Esempio n. 5
0
    def GetMountPoint(self, path=None):
        """Walk back from the path to find the mount point.

    Args:
      path: a Unicode string containing the path or None. If path is None the
        value in self.path is used.

    Returns:
      path string of the mount point
    """
        path = os.path.abspath(
            client_utils.CanonicalPathToLocalPath(path or self.path))

        while not os.path.ismount(path):
            path = os.path.dirname(path)

        return path
Esempio n. 6
0
    def StatFS(self, path=None):
        """Call os.statvfs for a given list of rdf_paths. OS X and Linux only.

    Note that a statvfs call for a network filesystem (e.g. NFS) that is
    unavailable, e.g. due to no network, will result in the call blocking.

    Args:
      path: a Unicode string containing the path or None.
            If path is None the value in self.path is used.
    Returns:
      posix.statvfs_result object
    Raises:
      RuntimeError: if called on windows
    """
        if platform.system() == "Windows":
            raise RuntimeError("os.statvfs not available on Windows")

        local_path = client_utils.CanonicalPathToLocalPath(path or self.path)

        return os.statvfs(local_path)
Esempio n. 7
0
    def RecursiveListNames(self, depth=0, cross_devs=False):
        path = client_utils.CanonicalPathToLocalPath(self.path)
        path_depth = self._GetDepth(self.path)

        if not cross_devs:
            path_dev = self._GetDevice(path)

        for root, dirs, files in os.walk(self.path):
            dirs.sort()
            files.sort()

            root_depth = self._GetDepth(root)

            if not cross_devs and self._GetDevice(root) != path_dev:
                dirs[:] = []  # We don't need to go deeper (clear the list)
            elif root_depth - path_depth >= depth:
                yield (root, dirs[:], files)  # Shallow copy
                dirs[:] = []
            else:
                yield (root, dirs, files)
Esempio n. 8
0
    def __init__(self,
                 base_fd,
                 handlers,
                 pathspec=None,
                 progress_callback=None):
        super(File, self).__init__(base_fd,
                                   handlers=handlers,
                                   pathspec=pathspec,
                                   progress_callback=progress_callback)
        if base_fd is None:
            self.pathspec.Append(pathspec)

        # We can stack on another directory, which means we concatenate their
        # directory with ours.
        elif base_fd.IsDirectory():
            self.pathspec.last.path = utils.JoinPath(self.pathspec.last.path,
                                                     pathspec.path)

        else:
            raise IOError(
                "File handler can not be stacked on another handler.")

        self.path = self.pathspec.last.path

        # We can optionally apply a global offset to the file.
        if self.pathspec[0].HasField("offset"):
            self.file_offset = self.pathspec[0].offset

        self.pathspec.last.path_options = rdf_paths.PathSpec.Options.CASE_LITERAL

        self.FileHacks()
        self.filename = client_utils.CanonicalPathToLocalPath(self.path)

        error = None
        # Pythonic way - duck typing. Is the handle a directory?
        try:
            if not self.files:
                # Note that the encoding of local path is system specific
                local_path = client_utils.CanonicalPathToLocalPath(self.path +
                                                                   "/")
                self.files = [
                    utils.SmartUnicode(entry)
                    for entry in os.listdir(local_path)
                ]
        # Some filesystems do not support unicode properly
        except UnicodeEncodeError as e:
            raise IOError(str(e))
        except (IOError, OSError) as e:
            self.files = []
            error = e

        # Ok, it's not. Is it a file then?
        try:
            with FileHandleManager(self.filename) as fd:

                if pathspec.last.HasField("file_size_override"):
                    self.size = pathspec.last.file_size_override - self.file_offset
                else:
                    # Work out how large the file is.
                    if self.size is None:
                        fd.Seek(0, 2)
                        end = fd.Tell()
                        if end == 0:
                            # This file is not seekable, we just use the default.
                            end = pathspec.last.file_size_override

                        self.size = end - self.file_offset

            error = None
        # Some filesystems do not support unicode properly
        except UnicodeEncodeError as e:
            raise IOError(str(e))

        except IOError as e:
            if error:
                error = e

        if error is not None:
            raise error  # pylint: disable=raising-bad-type
Esempio n. 9
0
  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))
Esempio n. 10
0
  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.
      path = utils.NormalizePath(args.path)
      if platform.system() == "Windows":
        # TODO: On non-Windows systems `CanonicalPathToLocalPath`
        # is equivalent to `SmartStr`, so it does nothing except for breaking
        # the types. However, a lot of code actually depends on this behaviour
        # so we cannot easily change it. As a workaround for now we simply do
        # not call it on Linux and macOS but ideally we should get rid of this
        # `SmartStr` call and not branch here.
        path = client_utils.CanonicalPathToLocalPath(path)

      paths = [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))