// Copyright (c) 2012 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 "nacl_io/kernel_handle.h"

#include <errno.h>
#include <pthread.h>

#include "nacl_io/filesystem.h"
#include "nacl_io/node.h"
#include "nacl_io/osunistd.h"
#include "nacl_io/socket/socket_node.h"

#include "sdk_util/auto_lock.h"

namespace nacl_io {

// It is only legal to construct a handle while the kernel lock is held.
KernelHandle::KernelHandle() : filesystem_(NULL), node_(NULL) {
}

KernelHandle::KernelHandle(const ScopedFilesystem& fs, const ScopedNode& node)
    : filesystem_(fs), node_(node) {
}

KernelHandle::~KernelHandle() {
  // Force release order for cases where filesystem_ is not ref'd by mounting.
  node_.reset(NULL);
  filesystem_.reset(NULL);
}

// Returns the SocketNode* if this node is a socket.
SocketNode* KernelHandle::socket_node() {
  if (node_.get() && node_->IsaSock())
    return reinterpret_cast<SocketNode*>(node_.get());
  return NULL;
}

Error KernelHandle::Init(int open_flags) {
  handle_attr_.flags = open_flags;

  if ((open_flags & O_CREAT) == 0 && !node_->CanOpen(open_flags)) {
    return EACCES;
  }

  // Directories can only be opened read-only.
  if ((open_flags & 3) != O_RDONLY && node_->IsaDir()) {
    return EISDIR;
  }

  if (open_flags & O_APPEND) {
    Error error = node_->GetSize(&handle_attr_.offs);
    if (error)
      return error;
  }

  return 0;
}

Error KernelHandle::Seek(off_t offset, int whence, off_t* out_offset) {
  // By default, don't move the offset.
  *out_offset = offset;
  off_t base;
  off_t node_size;

  AUTO_LOCK(handle_lock_);
  if (!node_->IsSeekable())
    return ESPIPE;

  Error error = node_->GetSize(&node_size);
  if (error)
    return error;

  switch (whence) {
    case SEEK_SET:
      base = 0;
      break;
    case SEEK_CUR:
      base = handle_attr_.offs;
      break;
    case SEEK_END:
      base = node_size;
      break;
    default:
      return -1;
  }

  if (base + offset < 0)
    return EINVAL;

  off_t new_offset = base + offset;

  // Seeking past the end of the file will zero out the space between the old
  // end and the new end.
  if (new_offset > node_size) {
    error = node_->FTruncate(new_offset);
    if (error)
      return EINVAL;
  }

  *out_offset = handle_attr_.offs = new_offset;
  return 0;
}

Error KernelHandle::Read(void* buf, size_t nbytes, int* cnt) {
  sdk_util::AutoLock read_lock(handle_lock_);
  if (OpenMode() == O_WRONLY)
    return EACCES;
  if (!node_->IsSeekable()){
    read_lock.Unlock();
    AUTO_LOCK(input_lock_);
    return node_->Read(handle_attr_, buf, nbytes, cnt);
  }
  Error error = node_->Read(handle_attr_, buf, nbytes, cnt);
  if (0 == error)
    handle_attr_.offs += *cnt;
  return error;
}

Error KernelHandle::Write(const void* buf, size_t nbytes, int* cnt) {
  sdk_util::AutoLock write_lock(handle_lock_);
  if (OpenMode() == O_RDONLY)
    return EACCES;
  if (!node_->IsSeekable()){
    write_lock.Unlock();
    AUTO_LOCK(output_lock_);
    return node_->Write(handle_attr_, buf, nbytes, cnt);
  }
  Error error = node_->Write(handle_attr_, buf, nbytes, cnt);
  if (0 == error)
    handle_attr_.offs += *cnt;
  return error;
}

Error KernelHandle::GetDents(struct dirent* pdir, size_t nbytes, int* cnt) {
  AUTO_LOCK(handle_lock_);
  Error error = node_->GetDents(handle_attr_.offs, pdir, nbytes, cnt);
  if (0 == error)
    handle_attr_.offs += *cnt;
  return error;
}

Error KernelHandle::Fcntl(int request, int* result, ...) {
  va_list ap;
  va_start(ap, result);
  Error rtn = VFcntl(request, result, ap);
  va_end(ap);
  return rtn;
}

Error KernelHandle::VFcntl(int request, int* result, va_list args) {
  switch (request) {
    case F_GETFL: {
      // Should not block, but could if blocked on Connect or Accept. This is
      // acceptable.
      AUTO_LOCK(handle_lock_);
      *result = handle_attr_.flags;
      return 0;
    }
    case F_SETFL: {
      AUTO_LOCK(handle_lock_);
      int flags = va_arg(args, int);
      if (!(flags & O_APPEND) && (handle_attr_.flags & O_APPEND)) {
        // Attempt to clear O_APPEND.
        return EPERM;
      }
      // Only certain flags are mutable
      const int mutable_flags = O_ASYNC | O_NONBLOCK;
      flags &= mutable_flags;
      handle_attr_.flags &= ~mutable_flags;
      handle_attr_.flags |= flags;
      return 0;
    }
    default:
      LOG_ERROR("Unsupported fcntl: %#x", request);
      break;
  }
  return ENOSYS;
}

Error KernelHandle::Accept(PP_Resource* new_sock,
                           struct sockaddr* addr,
                           socklen_t* len) {
  SocketNode* sock = socket_node();
  if (!sock)
    return ENOTSOCK;

  AUTO_LOCK(handle_lock_);
  return sock->Accept(handle_attr_, new_sock, addr, len);
}

Error KernelHandle::Connect(const struct sockaddr* addr, socklen_t len) {
  SocketNode* sock = socket_node();
  if (!sock)
    return ENOTSOCK;

  AUTO_LOCK(handle_lock_);
  return sock->Connect(handle_attr_, addr, len);
}

Error KernelHandle::Recv(void* buf, size_t len, int flags, int* out_len) {
  SocketNode* sock = socket_node();
  if (!sock)
    return ENOTSOCK;
  if (OpenMode() == O_WRONLY)
    return EACCES;

  AUTO_LOCK(input_lock_);
  return sock->Recv(handle_attr_, buf, len, flags, out_len);
}

Error KernelHandle::RecvFrom(void* buf,
                             size_t len,
                             int flags,
                             struct sockaddr* src_addr,
                             socklen_t* addrlen,
                             int* out_len) {
  SocketNode* sock = socket_node();
  if (!sock)
    return ENOTSOCK;
  if (OpenMode() == O_WRONLY)
    return EACCES;

  AUTO_LOCK(input_lock_);
  return sock->RecvFrom(handle_attr_, buf, len, flags, src_addr, addrlen,
                        out_len);
}

Error KernelHandle::Send(const void* buf, size_t len, int flags, int* out_len) {
  SocketNode* sock = socket_node();
  if (!sock)
    return ENOTSOCK;
  if (OpenMode() == O_RDONLY)
    return EACCES;

  AUTO_LOCK(output_lock_);
  return sock->Send(handle_attr_, buf, len, flags, out_len);
}

Error KernelHandle::SendTo(const void* buf,
                           size_t len,
                           int flags,
                           const struct sockaddr* dest_addr,
                           socklen_t addrlen,
                           int* out_len) {
  SocketNode* sock = socket_node();
  if (!sock)
    return ENOTSOCK;
  if (OpenMode() == O_RDONLY)
    return EACCES;

  AUTO_LOCK(output_lock_);
  return sock->SendTo(handle_attr_, buf, len, flags, dest_addr, addrlen,
                      out_len);
}

}  // namespace nacl_io
