Esempio n. 1
0
Status readFile(const fs::path& path,
                std::string& content,
                size_t size,
                bool dry_run) {
  auto handle = OpenReadableFile(path);
  if (handle.fd < 0) {
    return Status(1, "Cannot open file for reading: " + path.string());
  }

  struct stat file;
  if (fstat(handle.fd, &file) < 0) {
    return Status(1, "Cannot access path: " + path.string());
  }

  off_t file_size = file.st_size;
  if (file_size == 0 && size > 0) {
    file_size = static_cast<off_t>(size);
  }

  // Erase/clear provided string buffer.
  content.erase();
  // Apply the max byte-read based on file/link target ownership.
  off_t read_max = (file.st_uid == 0)
                       ? FLAGS_read_max
                       : std::min(FLAGS_read_max, FLAGS_read_user_max);
  if (file_size > read_max) {
    VLOG(1) << "Cannot read " << path << " size exceeds limit: " << file_size
            << " > " << read_max;
    return Status(1, "File exceeds read limits");
  }

  if (dry_run) {
    // The caller is only interested in performing file read checks.
    boost::system::error_code ec;
    return Status(0, fs::canonical(path, ec).string());
  }

  if (file_size == 0) {
    off_t total_bytes = 0;
    ssize_t part_bytes = 0;
    do {
      auto part = std::string(4096, '\0');
      part_bytes = read(handle.fd, &part[0], 4096);
      if (part_bytes > 0) {
        total_bytes += part_bytes;
        if (total_bytes >= read_max) {
          return Status(1, "File exceeds read limits");
        }
        content += part.substr(0, part_bytes);
      }
    } while (part_bytes > 0);
  } else {
    content = std::string(file_size, '\0');
    read(handle.fd, &content[0], file_size);
  }
  return Status(0, "OK");
}
Esempio n. 2
0
Status readFile(
    const fs::path& path,
    size_t size,
    size_t block_size,
    bool dry_run,
    bool preserve_time,
    std::function<void(std::string& buffer, size_t size)> predicate) {
  auto handle = OpenReadableFile(path);
  if (handle.fd < 0) {
    return Status(1, "Cannot open file for reading: " + path.string());
  }

  struct stat file;
  if (fstat(handle.fd, &file) < 0) {
    return Status(1, "Cannot access path: " + path.string());
  }

  off_t file_size = file.st_size;
  if (file_size == 0 && size > 0) {
    file_size = static_cast<off_t>(size);
  }

  // Apply the max byte-read based on file/link target ownership.
  off_t read_max = (file.st_uid == 0)
                       ? FLAGS_read_max
                       : std::min(FLAGS_read_max, FLAGS_read_user_max);
  if (file_size > read_max) {
    VLOG(1) << "Cannot read " << path << " size exceeds limit: " << file_size
            << " > " << read_max;
    return Status(1, "File exceeds read limits");
  }

  if (dry_run) {
    // The caller is only interested in performing file read checks.
    boost::system::error_code ec;
    return Status(0, fs::canonical(path, ec).string());
  }

  struct timeval times[2];
#if defined(__linux__)
  TIMESPEC_TO_TIMEVAL(&times[0], &file.st_atim);
  TIMESPEC_TO_TIMEVAL(&times[1], &file.st_mtim);
#else
  TIMESPEC_TO_TIMEVAL(&times[0], &file.st_atimespec);
  TIMESPEC_TO_TIMEVAL(&times[1], &file.st_mtimespec);
#endif

  if (file_size == 0) {
    off_t total_bytes = 0;
    ssize_t part_bytes = 0;
    do {
      auto part = std::string(4096, '\0');
      part_bytes = read(handle.fd, &part[0], block_size);
      if (part_bytes > 0) {
        total_bytes += part_bytes;
        if (total_bytes >= read_max) {
          return Status(1, "File exceeds read limits");
        }
        //        content += part.substr(0, part_bytes);
        predicate(part, part_bytes);
      }
    } while (part_bytes > 0);
  } else {
    auto content = std::string(file_size, '\0');
    read(handle.fd, &content[0], file_size);
    predicate(content, file_size);
  }

  // Attempt to restore the atime and mtime before the file read.
  if (preserve_time && !FLAGS_disable_forensic) {
    futimes(handle.fd, times);
  }
  return Status(0, "OK");
}