// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 <fcntl.h>
#include <unistd.h>

#include <sys/sendfile.h>
#include <sys/syscall.h>

#include <stout/stringify.hpp>

#include <stout/os/close.hpp>
#include <stout/os/open.hpp>
#include <stout/os/stat.hpp>

using std::string;

#if !defined(MFD_CLOEXEC)
#define MFD_CLOEXEC 0x0001U
#endif

#if !defined(MFD_ALLOW_SEALING)
#define MFD_ALLOW_SEALING 0x0002U
#endif

#if !defined(F_ADD_SEALS)
#define F_ADD_SEALS 1033
#endif

#if !defined(F_GET_SEALS)
#define F_GET_SEALS 1034
#endif

#if !defined(F_SEAL_SEAL)
#define F_SEAL_SEAL   0x0001
#endif

#if !defined(F_SEAL_SHRINK)
#define F_SEAL_SHRINK 0x0002
#endif

#if !defined(F_SEAL_GROW)
#define F_SEAL_GROW   0x0004
#endif

#if !defined(F_SEAL_WRITE)
#define F_SEAL_WRITE  0x0008
#endif

namespace mesos {
namespace internal {
namespace memfd {

static Try<int_fd> create(const string& name, unsigned int flags)
{
#ifdef __NR_memfd_create
  int_fd fd = ::syscall(__NR_memfd_create, name.c_str(), flags);
  if (fd == -1) {
    return ErrnoError("Failed to create memfd");
  }

  return fd;
#else
#error "The memfd syscall is not available."
#endif
}


Try<int_fd> cloneSealedFile(const std::string& filePath)
{
  if (!os::stat::isfile(filePath)) {
    return Error("The original file '" + filePath + "' is not a regular file");
  }

  Try<Bytes> size = os::stat::size(filePath);
  if (size.isError()) {
    return Error("Failed to get the size of the source file: " + size.error());
  }

  Try<int_fd> fileFd = os::open(filePath, O_CLOEXEC | O_RDONLY);
  if (fileFd.isError()) {
    return Error("Failed to open source file: " + fileFd.error());
  }

  Try<int_fd> memFd = create(filePath, MFD_CLOEXEC | MFD_ALLOW_SEALING);
  if (memFd.isError()) {
    os::close(fileFd.get());
    return Error("Failed to open memfd file: " + memFd.error());
  }

  size_t remaining = size->bytes();
  while (remaining > 0) {
    ssize_t written = sendfile(memFd.get(), fileFd.get(), nullptr, remaining);
    if (written == -1) {
      ErrnoError error("Failed to copy file");
      os::close(fileFd.get());
      os::close(memFd.get());
      return error;
    } else if (static_cast<size_t>(written) > remaining) {
      os::close(fileFd.get());
      os::close(memFd.get());
      return Error("More bytes written than requested");
    } else {
      remaining -= written;
    }
  }

  os::close(fileFd.get());

  int ret = fchmod(memFd.get(), S_IRWXU | S_IRWXG | S_IRWXO);
  if (ret == -1) {
    ErrnoError error("Failed to chmod");
    os::close(memFd.get());
    return error;
  }

  // Seal the memfd file.
  ret = fcntl(
      memFd.get(),
      F_ADD_SEALS,
      F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);

  if (ret == -1) {
    ErrnoError error("Failed to seal the memfd");
    os::close(memFd.get());
    return error;
  }

  return memFd.get();
}

} // namespace memfd {
} // namespace internal {
} // namespace mesos {
