// Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "update_engine/payload_generator/filesystem_iterator.h"

#include <dirent.h>
#include <errno.h>
#include <sys/types.h>

#include <set>
#include <string>
#include <vector>

#include <base/logging.h>

#include "update_engine/utils.h"

using std::set;
using std::string;
using std::vector;

namespace chromeos_update_engine {

// We use a macro here for two reasons:
// 1. We want to be able to return from the caller's function.
// 2. We can use the #macro_arg ism to get a string of the calling statement,
//    which we can log.

#define RETURN_ERROR_IF_FALSE(_statement)                               \
  do {                                                                  \
    bool _result = (_statement);                                        \
    if (!_result) {                                                     \
      string _message = utils::ErrnoNumberAsString(errno);              \
      LOG(INFO) << #_statement << " failed: " << _message << ". Aborting"; \
      is_end_ = true;                                                   \
      is_err_ = true;                                                   \
      return;                                                           \
    }                                                                   \
  } while (0)

FilesystemIterator::FilesystemIterator(
    const std::string& path,
    const std::set<std::string>& excl_prefixes)
    : excl_prefixes_(excl_prefixes),
      is_end_(false),
      is_err_(false) {
  root_path_ = utils::NormalizePath(path, true);
  RETURN_ERROR_IF_FALSE(lstat(root_path_.c_str(), &stbuf_) == 0);
  root_dev_ = stbuf_.st_dev;
}

FilesystemIterator::~FilesystemIterator() {
  for (vector<DIR*>::iterator it = dirs_.begin(); it != dirs_.end(); ++it) {
    LOG_IF(ERROR, closedir(*it) != 0) << "closedir failed";
  }
}

// Returns the size of the current file
off_t FilesystemIterator::GetFileSize() const {
  return utils::FileSize(GetFullPath());
}

// Returns full path for current file
std::string FilesystemIterator::GetFullPath() const {
  return root_path_ + GetPartialPath();
}

std::string FilesystemIterator::GetPartialPath() const {
  std::string ret;
  for (vector<string>::const_iterator it = names_.begin();
       it != names_.end(); ++it) {
    ret += "/";
    ret += *it;
  }
  return ret;
}

// Increments to the next file
void FilesystemIterator::Increment() {
  // If we're currently on a dir, descend into children, but only if
  // we're on the same device as the root device

  bool entering_dir = false;  // true if we're entering into a new dir
  if (S_ISDIR(stbuf_.st_mode) && (stbuf_.st_dev == root_dev_)) {
    DIR* dir = opendir(GetFullPath().c_str());
    if ((!dir) && ((errno == ENOTDIR) || (errno == ENOENT))) {
      // opendir failed b/c either it's not a dir or it doesn't exist.
      // that's fine. let's just skip over this.
      LOG(ERROR) << "Can't descend into " << GetFullPath();
    } else {
      RETURN_ERROR_IF_FALSE(dir);
      entering_dir = true;
      dirs_.push_back(dir);
    }
  }

  if (!entering_dir && names_.empty()) {
    // root disappeared while we tried to descend into it
    is_end_ = true;
    return;
  }

  if (!entering_dir)
    names_.pop_back();

  IncrementInternal();
  for (set<string>::const_iterator it = excl_prefixes_.begin();
       it != excl_prefixes_.end(); ++it) {
    if (utils::StringHasPrefix(GetPartialPath(), *it)) {
      Increment();
      break;
    }
  }
  return;
}

// Assumes that we need to find the next child of dirs_.back(), or if
// there are none more, go up the chain
void FilesystemIterator::IncrementInternal() {
  CHECK_EQ(dirs_.size(), names_.size() + 1);
  for (;;) {
    struct dirent dir_entry;
    struct dirent* dir_entry_pointer;
    int r;
    RETURN_ERROR_IF_FALSE(
        (r = readdir_r(dirs_.back(), &dir_entry, &dir_entry_pointer)) == 0);
    if (dir_entry_pointer) {
      // Found an entry
      names_.push_back(dir_entry_pointer->d_name);
      // Validate
      RETURN_ERROR_IF_FALSE(lstat(GetFullPath().c_str(), &stbuf_) == 0);
      if (strcmp(dir_entry_pointer->d_name, ".") &&
          strcmp(dir_entry_pointer->d_name, "..")) {
        // Done
        return;
      }
      // Child didn't work out. Try again
      names_.pop_back();
    } else {
      // No more children in this dir. Pop it and try again
      RETURN_ERROR_IF_FALSE(closedir(dirs_.back()) == 0);
      dirs_.pop_back();
      if (dirs_.empty()) {
        CHECK(names_.empty());
        // Done with the entire iteration
        is_end_ = true;
        return;
      }
      CHECK(!names_.empty());
      names_.pop_back();
    }
  }
}

}  //   namespace chromeos_update_engine
