// Copyright 2017 The Fuchsia 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 <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

#ifdef __Fuchsia__
#include <zircon/device/vfs.h>
#include <zircon/syscalls.h>
#include <fbl/auto_lock.h>
#endif

#include <fbl/alloc_checker.h>
#include <fs/vfs.h>
#include <fs/vnode.h>
#include <fs/watcher.h>
#include <lib/zx/channel.h>

#include <utility>

namespace fs {

WatcherContainer::WatcherContainer() = default;
WatcherContainer::~WatcherContainer() = default;

WatcherContainer::VnodeWatcher::VnodeWatcher(zx::channel h, uint32_t mask)
    : h(std::move(h)),
      mask(mask & ~(fuchsia_io_WATCH_MASK_EXISTING | fuchsia_io_WATCH_MASK_IDLE)) {}

WatcherContainer::VnodeWatcher::~VnodeWatcher() {}

// Transmission buffer for sending directory watcher notifications to clients.
// Allows enqueueing multiple messages in a buffer before sending an IPC message
// to a client.
class WatchBuffer {
 public:
  DISALLOW_COPY_ASSIGN_AND_MOVE(WatchBuffer);
  WatchBuffer() = default;

  zx_status_t AddMsg(const zx::channel& c, unsigned event, fbl::StringPiece name);
  zx_status_t Send(const zx::channel& c);

 private:
  size_t watch_buf_size_ = 0;
  char watch_buf_[fuchsia_io_MAX_BUF]{};
};

zx_status_t WatchBuffer::AddMsg(const zx::channel& c, unsigned event, fbl::StringPiece name) {
  size_t slen = name.length();
  size_t mlen = sizeof(vfs_watch_msg_t) + slen;
  if (mlen + watch_buf_size_ > sizeof(watch_buf_)) {
    // This message won't fit in the watch_buf; transmit first.
    zx_status_t status = Send(c);
    if (status != ZX_OK) {
      return status;
    }
  }
  vfs_watch_msg_t* vmsg =
      reinterpret_cast<vfs_watch_msg_t*>((uintptr_t)watch_buf_ + watch_buf_size_);
  vmsg->event = static_cast<uint8_t>(event);
  vmsg->len = static_cast<uint8_t>(slen);
  memcpy(vmsg->name, name.data(), slen);
  watch_buf_size_ += mlen;
  return ZX_OK;
}

zx_status_t WatchBuffer::Send(const zx::channel& c) {
  if (watch_buf_size_ > 0) {
    // Only write if we have something to write
    zx_status_t status = c.write(0, watch_buf_, static_cast<uint32_t>(watch_buf_size_), nullptr, 0);
    watch_buf_size_ = 0;
    if (status != ZX_OK) {
      return status;
    }
  }
  return ZX_OK;
}

zx_status_t WatcherContainer::WatchDir(Vfs* vfs, Vnode* vn, uint32_t mask, uint32_t options,
                                       zx::channel channel) {
  if ((mask & fuchsia_io_WATCH_MASK_ALL) == 0) {
    // No events to watch
    return ZX_ERR_INVALID_ARGS;
  }

  fbl::AllocChecker ac;
  fbl::unique_ptr<VnodeWatcher> watcher(new (&ac) VnodeWatcher(std::move(channel), mask));
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }

  if (mask & fuchsia_io_WATCH_MASK_EXISTING) {
    vdircookie_t dircookie;
    memset(&dircookie, 0, sizeof(dircookie));
    char readdir_buf[FDIO_CHUNK_SIZE];
    WatchBuffer wb;
    {
      // Send "fuchsia_io_WATCH_EVENT_EXISTING" for all entries in readdir
      while (true) {
        size_t actual;
        zx_status_t status =
            vfs->Readdir(vn, &dircookie, readdir_buf, sizeof(readdir_buf), &actual);
        if (status != ZX_OK || actual == 0) {
          break;
        }
        void* ptr = readdir_buf;
        while (actual >= sizeof(vdirent_t)) {
          auto dirent = reinterpret_cast<vdirent_t*>(ptr);
          if (dirent->name[0]) {
            wb.AddMsg(watcher->h, fuchsia_io_WATCH_EVENT_EXISTING,
                      fbl::StringPiece(dirent->name, dirent->size));
          }
          size_t entry_len = dirent->size + sizeof(vdirent_t);
          ZX_ASSERT(entry_len <= actual);  // Prevent underflow
          actual -= entry_len;
          ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(entry_len) +
                                        reinterpret_cast<uintptr_t>(ptr));
        }
      }
    }

    // Send fuchsia_io_WATCH_EVENT_IDLE to signify that readdir has completed
    if (mask & fuchsia_io_WATCH_MASK_IDLE) {
      wb.AddMsg(watcher->h, fuchsia_io_WATCH_EVENT_IDLE, "");
    }

    wb.Send(watcher->h);
  }

  fbl::AutoLock lock(&lock_);
  watch_list_.push_back(std::move(watcher));
  return ZX_OK;
}

void WatcherContainer::Notify(fbl::StringPiece name, unsigned event) {
  if (name.length() > fuchsia_io_MAX_FILENAME) {
    return;
  }

  fbl::AutoLock lock(&lock_);

  if (watch_list_.is_empty()) {
    return;
  }

  uint8_t msg[sizeof(vfs_watch_msg_t) + name.length()];
  vfs_watch_msg_t* vmsg = reinterpret_cast<vfs_watch_msg_t*>(msg);
  vmsg->event = static_cast<uint8_t>(event);
  vmsg->len = static_cast<uint8_t>(name.length());
  memcpy(vmsg->name, name.data(), name.length());

  for (auto it = watch_list_.begin(); it != watch_list_.end();) {
    if (!(it->mask & (1 << event))) {
      ++it;
      continue;
    }

    zx_status_t status = it->h.write(0, msg, static_cast<uint32_t>(sizeof(msg)), nullptr, 0);
    if (status < 0) {
      // Lazily remove watchers when their handles cannot accept incoming
      // watch messages.
      auto to_remove = it;
      ++it;
      watch_list_.erase(to_remove);
    } else {
      ++it;
    }
  }
}

}  // namespace fs
