docs: def ListDirectory(self, pathspec, depth=0):
      """A recursive generator of files."""
      # Limit recursion depth
      if depth >= self.request.max_depth:
        return
  
      try:
        fd = vfs.VFSOpen(pathspec, progress_callback=self.Progress)
        files = fd.ListFiles(ext_attrs=self.request.collect_ext_attrs)
      except (IOError, OSError) as e:
        if depth == 0:
          # We failed to open the directory the server asked for because dir
          # doesn't exist or some other reason. So we set status and return
          # back to the caller ending the Iterator.
          self.SetStatus(rdf_flows.GrrStatus.ReturnedStatus.IOERROR, e)
        else:
          # Can't open the directory we're searching, ignore the directory.
          logging.info("Find failed to ListDirectory for %s. Err: %s", pathspec,
                       e)
        return
  
      # If we are not supposed to cross devices, and don't know yet
      # which device we are on, we need to find out.
      if not self.request.cross_devs and self.filesystem_id is None:
        dir_stat = fd.Stat()
        self.filesystem_id = dir_stat.st_dev
  
      for file_stat in files:
  
        if stat.S_ISDIR(int(file_stat.st_mode)):
          # Do not traverse directories in a different filesystem.
          is_same_fs = self.filesystem_id == file_stat.st_dev
          if is_same_fs or self.request.cross_devs:
            for child_stat in self.ListDirectory(file_stat.pathspec, depth + 1):
              yield child_stat
  
        yield file_stat