/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "scoped_flock.h"

#include <sys/file.h>
#include <sys/stat.h>

#include <android-base/logging.h>
#include <android-base/stringprintf.h>

#include "file_utils.h"
#include "unix_file/fd_file.h"

namespace art {

using android::base::StringPrintf;  // NOLINT - StringPrintf is actually used

/* static */ ScopedFlock LockedFile::Open(const char* filename, std::string* error_msg) {
  return Open(filename, O_CREAT | O_RDWR, true, error_msg);
}

/* static */ ScopedFlock LockedFile::Open(const char* filename, int flags, bool block,
                                          std::string* error_msg) {
#ifdef _WIN32
  // TODO: implement file locking for Windows.
  UNUSED(filename);
  UNUSED(flags);
  UNUSED(block);
  *error_msg = "flock is unsupported on Windows";
  return nullptr;
#else
  while (true) {
    // NOTE: We don't check usage here because the ScopedFlock should *never* be
    // responsible for flushing its underlying FD. Its only purpose should be
    // to acquire a lock, and the unlock / close in the corresponding
    // destructor. Callers should explicitly flush files they're writing to if
    // that is the desired behaviour.
    std::unique_ptr<File> file(OS::OpenFileWithFlags(filename, flags, /* auto_flush= */ false));
    if (file.get() == nullptr) {
      *error_msg = StringPrintf("Failed to open file '%s': %s", filename, strerror(errno));
      return nullptr;
    }

    int operation = block ? LOCK_EX : (LOCK_EX | LOCK_NB);
    int flock_result = TEMP_FAILURE_RETRY(flock(file->Fd(), operation));
    if (flock_result == EWOULDBLOCK) {
      // File is locked by someone else and we are required not to block;
      return nullptr;
    }
    if (flock_result != 0) {
      *error_msg = StringPrintf("Failed to lock file '%s': %s", filename, strerror(errno));
      return nullptr;
    }
    struct stat fstat_stat;
    int fstat_result = TEMP_FAILURE_RETRY(fstat(file->Fd(), &fstat_stat));
    if (fstat_result != 0) {
      *error_msg = StringPrintf("Failed to fstat file '%s': %s", filename, strerror(errno));
      return nullptr;
    }
    struct stat stat_stat;
    int stat_result = TEMP_FAILURE_RETRY(stat(filename, &stat_stat));
    if (stat_result != 0) {
      PLOG(WARNING) << "Failed to stat, will retry: " << filename;
      // ENOENT can happen if someone racing with us unlinks the file we created so just retry.
      if (block) {
        continue;
      } else {
        // Note that in theory we could race with someone here for a long time and end up retrying
        // over and over again. This potential behavior does not fit well in the non-blocking
        // semantics. Thus, if we are not require to block return failure when racing.
        return nullptr;
      }
    }
    if (fstat_stat.st_dev != stat_stat.st_dev || fstat_stat.st_ino != stat_stat.st_ino) {
      LOG(WARNING) << "File changed while locking, will retry: " << filename;
      if (block) {
        continue;
      } else {
        // See comment above.
        return nullptr;
      }
    }

    return ScopedFlock(new LockedFile(std::move((*file.get()))));
  }
#endif
}

ScopedFlock LockedFile::DupOf(const int fd, const std::string& path,
                              const bool read_only_mode, std::string* error_msg) {
#ifdef _WIN32
  // TODO: implement file locking for Windows.
  UNUSED(fd);
  UNUSED(path);
  UNUSED(read_only_mode);
  *error_msg = "flock is unsupported on Windows.";
  return nullptr;
#else
  // NOTE: We don't check usage here because the ScopedFlock should *never* be
  // responsible for flushing its underlying FD. Its only purpose should be
  // to acquire a lock, and the unlock / close in the corresponding
  // destructor. Callers should explicitly flush files they're writing to if
  // that is the desired behaviour.
  ScopedFlock locked_file(
      new LockedFile(DupCloexec(fd), path, /* check_usage= */ false, read_only_mode));
  if (locked_file->Fd() == -1) {
    *error_msg = StringPrintf("Failed to duplicate open file '%s': %s",
                              locked_file->GetPath().c_str(), strerror(errno));
    return nullptr;
  }
  if (0 != TEMP_FAILURE_RETRY(flock(locked_file->Fd(), LOCK_EX))) {
    *error_msg = StringPrintf(
        "Failed to lock file '%s': %s", locked_file->GetPath().c_str(), strerror(errno));
    return nullptr;
  }

  return locked_file;
#endif
}

void LockedFile::ReleaseLock() {
#ifndef _WIN32
  if (this->Fd() != -1) {
    int flock_result = TEMP_FAILURE_RETRY(flock(this->Fd(), LOCK_UN));
    if (flock_result != 0) {
      // Only printing a warning is okay since this is only used with either:
      // 1) a non-blocking Init call, or
      // 2) as a part of a seperate binary (eg dex2oat) which has it's own timeout logic to prevent
      //    deadlocks.
      // This means we can be sure that the warning won't cause a deadlock.
      PLOG(WARNING) << "Unable to unlock file " << this->GetPath();
    }
  }
#endif
}

}  // namespace art
