// Copyright 2015 The Chromium 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 "services/files/directory_impl.h"

#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/posix/eintr_wrapper.h"
#include "build/build_config.h"
#include "services/files/file_impl.h"
#include "services/files/shared_impl.h"
#include "services/files/util.h"

namespace mojo {
namespace files {

namespace {

// Calls |closedir()| on a |DIR*|.
struct DIRDeleter {
  void operator()(DIR* dir) const { PCHECK(closedir(dir) == 0); }
};
using ScopedDIR = scoped_ptr<DIR, DIRDeleter>;

Error ValidateOpenFlags(uint32_t open_flags, bool is_directory) {
  // Treat unknown flags as "unimplemented".
  if ((open_flags &
       ~(kOpenFlagRead | kOpenFlagWrite | kOpenFlagCreate | kOpenFlagExclusive |
         kOpenFlagAppend | kOpenFlagTruncate)))
    return Error::UNIMPLEMENTED;

  // At least one of |kOpenFlagRead| or |kOpenFlagWrite| must be set.
  if (!(open_flags & (kOpenFlagRead | kOpenFlagWrite)))
    return Error::INVALID_ARGUMENT;

  // |kOpenFlagCreate| requires |kOpenFlagWrite|.
  if ((open_flags & kOpenFlagCreate) && !(open_flags & kOpenFlagWrite))
    return Error::INVALID_ARGUMENT;

  // |kOpenFlagExclusive| requires |kOpenFlagCreate|.
  if ((open_flags & kOpenFlagExclusive) && !(open_flags & kOpenFlagCreate))
    return Error::INVALID_ARGUMENT;

  if (is_directory) {
    // Check that file-only flags aren't set.
    if ((open_flags & (kOpenFlagAppend | kOpenFlagTruncate)))
      return Error::INVALID_ARGUMENT;
    return Error::OK;
  }

  // File-only flags:

  // |kOpenFlagAppend| requires |kOpenFlagWrite|.
  if ((open_flags & kOpenFlagAppend) && !(open_flags & kOpenFlagWrite))
    return Error::INVALID_ARGUMENT;

  // |kOpenFlagTruncate| requires |kOpenFlagWrite|.
  if ((open_flags & kOpenFlagTruncate) && !(open_flags & kOpenFlagWrite))
    return Error::INVALID_ARGUMENT;

  return Error::OK;
}

Error ValidateDeleteFlags(uint32_t delete_flags) {
  // Treat unknown flags as "unimplemented".
  if ((delete_flags &
       ~(kDeleteFlagFileOnly | kDeleteFlagDirectoryOnly |
         kDeleteFlagRecursive)))
    return Error::UNIMPLEMENTED;

  // Only one of the three currently-defined flags may be set.
  if ((delete_flags & kDeleteFlagFileOnly) &&
      (delete_flags & (kDeleteFlagDirectoryOnly | kDeleteFlagRecursive)))
    return Error::INVALID_ARGUMENT;
  if ((delete_flags & kDeleteFlagDirectoryOnly) &&
      (delete_flags & (kDeleteFlagFileOnly | kDeleteFlagRecursive)))
    return Error::INVALID_ARGUMENT;
  if ((delete_flags & kDeleteFlagRecursive) &&
      (delete_flags & (kDeleteFlagFileOnly | kDeleteFlagDirectoryOnly)))
    return Error::INVALID_ARGUMENT;

  return Error::OK;
}

}  // namespace

DirectoryImpl::DirectoryImpl(InterfaceRequest<Directory> request,
                             base::ScopedFD dir_fd,
                             scoped_ptr<base::ScopedTempDir> temp_dir)
    : binding_(this, request.Pass()),
      dir_fd_(dir_fd.Pass()),
      temp_dir_(temp_dir.Pass()) {
  DCHECK(dir_fd_.is_valid());
}

DirectoryImpl::~DirectoryImpl() {
}

void DirectoryImpl::Read(const ReadCallback& callback) {
  static const size_t kMaxReadCount = 1000;

  DCHECK(dir_fd_.is_valid());

  // |fdopendir()| takes ownership of the FD (giving it to the |DIR| --
  // |closedir()| will close the FD)), so we need to |dup()| ours.
  base::ScopedFD fd(dup(dir_fd_.get()));
  if (!fd.is_valid()) {
    callback.Run(ErrnoToError(errno), nullptr);
    return;
  }

  ScopedDIR dir(fdopendir(fd.release()));
  if (!dir) {
    callback.Run(ErrnoToError(errno), nullptr);
    return;
  }

  auto result = Array<DirectoryEntryPtr>::New(0);

// Warning: This is not portable (per POSIX.1 -- |buffer| may not be large
// enough), but it's fine for Linux.
#if !defined(OS_ANDROID) && !defined(OS_LINUX)
#error "Use of struct dirent for readdir_r() buffer not portable; please check."
#endif
  struct dirent buffer;
  for (size_t n = 0;;) {
    struct dirent* entry = nullptr;
    if (int error = readdir_r(dir.get(), &buffer, &entry)) {
      // |error| is effectively an errno (for |readdir_r()|), AFAICT.
      callback.Run(ErrnoToError(error), nullptr);
      return;
    }

    if (!entry)
      break;

    n++;
    if (n > kMaxReadCount) {
      LOG(WARNING) << "Directory contents truncated";
      callback.Run(Error::OUT_OF_RANGE, result.Pass());
      return;
    }

    DirectoryEntryPtr e = DirectoryEntry::New();
    switch (entry->d_type) {
      case DT_DIR:
        e->type = FileType::DIRECTORY;
        break;
      case DT_REG:
        e->type = FileType::REGULAR_FILE;
        break;
      default:
        e->type = FileType::UNKNOWN;
        break;
    }
    e->name = String(entry->d_name);
    result.push_back(e.Pass());
  }

  callback.Run(Error::OK, result.Pass());
}

void DirectoryImpl::Stat(const StatCallback& callback) {
  DCHECK(dir_fd_.is_valid());
  StatFD(dir_fd_.get(), FileType::DIRECTORY, callback);
}

void DirectoryImpl::Touch(TimespecOrNowPtr atime,
                          TimespecOrNowPtr mtime,
                          const TouchCallback& callback) {
  DCHECK(dir_fd_.is_valid());
  TouchFD(dir_fd_.get(), atime.Pass(), mtime.Pass(), callback);
}

// TODO(vtl): Move the implementation to a thread pool.
void DirectoryImpl::OpenFile(const String& path,
                             InterfaceRequest<File> file,
                             uint32_t open_flags,
                             const OpenFileCallback& callback) {
  DCHECK(!path.is_null());
  DCHECK(dir_fd_.is_valid());

  Error error = IsPathValid(path);
  if (error != Error::OK) {
    callback.Run(error);
    return;
  }
  // TODO(vtl): Make sure the path doesn't exit this directory (if appropriate).
  // TODO(vtl): Maybe allow absolute paths?

  error = ValidateOpenFlags(open_flags, false);
  if (error != Error::OK) {
    callback.Run(error);
    return;
  }

  int flags = 0;
  if ((open_flags & kOpenFlagRead))
    flags |= (open_flags & kOpenFlagWrite) ? O_RDWR : O_RDONLY;
  else
    flags |= O_WRONLY;
  if ((open_flags & kOpenFlagCreate))
    flags |= O_CREAT;
  if ((open_flags & kOpenFlagExclusive))
    flags |= O_EXCL;
  if ((open_flags & kOpenFlagAppend))
    flags |= O_APPEND;
  if ((open_flags & kOpenFlagTruncate))
    flags |= O_TRUNC;

  base::ScopedFD file_fd(
      HANDLE_EINTR(openat(dir_fd_.get(), path.get().c_str(), flags, 0600)));
  if (!file_fd.is_valid()) {
    callback.Run(ErrnoToError(errno));
    return;
  }

  if (file.is_pending())
    new FileImpl(file.Pass(), file_fd.Pass());
  callback.Run(Error::OK);
}

void DirectoryImpl::OpenDirectory(const String& path,
                                  InterfaceRequest<Directory> directory,
                                  uint32_t open_flags,
                                  const OpenDirectoryCallback& callback) {
  DCHECK(!path.is_null());
  DCHECK(dir_fd_.is_valid());

  Error error = IsPathValid(path);
  if (error != Error::OK) {
    callback.Run(error);
    return;
  }
  // TODO(vtl): Make sure the path doesn't exit this directory (if appropriate).
  // TODO(vtl): Maybe allow absolute paths?

  error = ValidateOpenFlags(open_flags, false);
  if (error != Error::OK) {
    callback.Run(error);
    return;
  }

  // TODO(vtl): Implement read-only (whatever that means).
  if (!(open_flags & kOpenFlagWrite)) {
    callback.Run(Error::UNIMPLEMENTED);
    return;
  }

  if ((open_flags & kOpenFlagCreate)) {
    if (mkdirat(dir_fd_.get(), path.get().c_str(), 0700) != 0) {
      // Allow |EEXIST| if |kOpenFlagExclusive| is not set. Note, however, that
      // it does not guarantee that |path| is a directory.
      // TODO(vtl): Hrm, ponder if we should check that |path| is a directory.
      if ((errno != EEXIST) || (open_flags & kOpenFlagExclusive)) {
        callback.Run(ErrnoToError(errno));
        return;
      }
    }
  }

  base::ScopedFD new_dir_fd(
      HANDLE_EINTR(openat(dir_fd_.get(), path.get().c_str(), O_DIRECTORY, 0)));
  if (!new_dir_fd.is_valid()) {
    callback.Run(ErrnoToError(errno));
    return;
  }

  if (directory.is_pending())
    new DirectoryImpl(directory.Pass(), new_dir_fd.Pass(), nullptr);
  callback.Run(Error::OK);
}

void DirectoryImpl::Rename(const String& path,
                           const String& new_path,
                           const RenameCallback& callback) {
  DCHECK(!path.is_null());
  DCHECK(!new_path.is_null());
  DCHECK(dir_fd_.is_valid());

  Error error = IsPathValid(path);
  if (error != Error::OK) {
    callback.Run(error);
    return;
  }

  error = IsPathValid(new_path);
  if (error != Error::OK) {
    callback.Run(error);
    return;
  }
  // TODO(vtl): See TODOs about |path| in OpenFile().

  if (renameat(dir_fd_.get(), path.get().c_str(), dir_fd_.get(),
               new_path.get().c_str())) {
    callback.Run(ErrnoToError(errno));
    return;
  }

  callback.Run(Error::OK);
}

void DirectoryImpl::Delete(const String& path,
                           uint32_t delete_flags,
                           const DeleteCallback& callback) {
  DCHECK(!path.is_null());
  DCHECK(dir_fd_.is_valid());

  Error error = IsPathValid(path);
  if (error != Error::OK) {
    callback.Run(error);
    return;
  }
  // TODO(vtl): See TODOs about |path| in OpenFile().

  error = ValidateDeleteFlags(delete_flags);
  if (error != Error::OK) {
    callback.Run(error);
    return;
  }

  // TODO(vtl): Recursive not yet supported.
  if ((delete_flags & kDeleteFlagRecursive)) {
    callback.Run(Error::UNIMPLEMENTED);
    return;
  }

  // First try deleting it as a file, unless we're told to do directory-only.
  if (!(delete_flags & kDeleteFlagDirectoryOnly)) {
    if (unlinkat(dir_fd_.get(), path.get().c_str(), 0) == 0) {
      callback.Run(Error::OK);
      return;
    }

    // If file-only, don't continue.
    if ((delete_flags & kDeleteFlagFileOnly)) {
      callback.Run(ErrnoToError(errno));
      return;
    }
  }

  // Try deleting it as a directory.
  if (unlinkat(dir_fd_.get(), path.get().c_str(), AT_REMOVEDIR) == 0) {
    callback.Run(Error::OK);
    return;
  }

  callback.Run(ErrnoToError(errno));
}

}  // namespace files
}  // namespace mojo
