// Copyright 2021 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 <string.h>
#include <sys/stat.h>

#include "src/storage/f2fs/f2fs.h"

#ifndef __Fuchsia__
#include "lib/stdcompat/string_view.h"
#endif  // __Fuchsia__

namespace f2fs {

zx_status_t Dir::NewInode(uint32_t mode, fbl::RefPtr<VnodeF2fs> *out) {
  SuperblockInfo &superblock_info = Vfs()->GetSuperblockInfo();
  nid_t ino;
  fbl::RefPtr<VnodeF2fs> vnode_refptr;
  VnodeF2fs *vnode = nullptr;

  do {
    fs::SharedLock rlock(superblock_info.GetFsLock(LockType::kFileOp));
    if (!Vfs()->GetNodeManager().AllocNid(ino)) {
      return ZX_ERR_NO_SPACE;
    }
  } while (false);

  VnodeF2fs::Allocate(Vfs(), ino, mode, &vnode_refptr);

  vnode = vnode_refptr.get();

  vnode->SetUid(getuid());

  if (HasGid()) {
    vnode->SetGid(GetGid());
    if (S_ISDIR(mode))
      mode |= S_ISGID;
  } else {
    vnode->SetGid(getgid());
  }

  vnode->SetMode(static_cast<umode_t>(mode));
  vnode->InitSize();
  vnode->InitNlink();
  vnode->InitBlocks();

  timespec cur_time;
  clock_gettime(CLOCK_REALTIME, &cur_time);
  vnode->SetATime(cur_time);
  vnode->SetCTime(cur_time);
  vnode->SetMTime(cur_time);
  vnode->SetGeneration(superblock_info.GetNextGeneration());
  superblock_info.IncNextGeneration();

  if (superblock_info.TestOpt(kMountInlineData) && !vnode->IsDir()) {
    vnode->SetFlag(InodeInfoFlag::kInlineData);
  }

  if (superblock_info.TestOpt(kMountInlineDentry) && vnode->IsDir()) {
    vnode->SetFlag(InodeInfoFlag::kInlineDentry);
  }

  vnode->SetFlag(InodeInfoFlag::kNewInode);
  Vfs()->InsertVnode(vnode);
  vnode->MarkInodeDirty();

  *out = std::move(vnode_refptr);
  return ZX_OK;
}

bool Dir::IsMultimediaFile(VnodeF2fs &vnode, std::string_view sub) {
  // compare lower case
  if (cpp20::ends_with(vnode.GetNameView(), sub))
    return true;

  // compare upper case
  std::string upper_sub(sub);
  std::transform(upper_sub.cbegin(), upper_sub.cend(), upper_sub.begin(), ::toupper);
  return cpp20::ends_with(vnode.GetNameView(), upper_sub.c_str());
}

/**
 * Set multimedia files as cold files for hot/cold data separation
 */
void Dir::SetColdFile(VnodeF2fs &vnode) {
  const std::vector<std::string> &extension_list = Vfs()->GetSuperblockInfo().GetExtensionList();

  for (const auto &extension : extension_list) {
    if (IsMultimediaFile(vnode, extension)) {
      vnode.SetAdvise(FAdvise::kCold);
      break;
    }
  }
}

zx_status_t Dir::DoCreate(std::string_view name, uint32_t mode, fbl::RefPtr<fs::Vnode> *out) {
  SuperblockInfo &superblock_info = Vfs()->GetSuperblockInfo();
  fbl::RefPtr<VnodeF2fs> vnode_refptr;
  VnodeF2fs *vnode = nullptr;

  if (zx_status_t err = NewInode(S_IFREG | mode, &vnode_refptr); err != ZX_OK)
    return err;
  vnode = vnode_refptr.get();

  vnode->SetName(name);

  if (!superblock_info.TestOpt(kMountDisableExtIdentify))
    SetColdFile(*vnode);

  {
    fs::SharedLock rlock(superblock_info.GetFsLock(LockType::kFileOp));
    if (zx_status_t err = AddLink(name, vnode); err != ZX_OK) {
      vnode->ClearNlink();
      vnode->UnlockNewInode();
      Vfs()->GetVCache().RemoveDirty(vnode);
      Vfs()->GetNodeManager().AllocNidFailed(vnode->Ino());
      return err;
    }
  }

  Vfs()->GetNodeManager().AllocNidDone(vnode->Ino());

#if 0  // porting needed
  // if (!superblock_info.IsOnRecovery())
  //   d_instantiate(dentry, inode);
#endif
  vnode->UnlockNewInode();

  Vfs()->GetSegmentManager().BalanceFs();

  *out = std::move(vnode_refptr);
  return ZX_OK;
}

zx_status_t Dir::Link(std::string_view name, fbl::RefPtr<fs::Vnode> new_child) {
  if (Vfs()->GetSuperblockInfo().TestCpFlags(CpFlag::kCpErrorFlag)) {
    return ZX_ERR_BAD_STATE;
  }

  if (!fs::IsValidName(name)) {
    return ZX_ERR_INVALID_ARGS;
  }

  fbl::RefPtr<VnodeF2fs> target = fbl::RefPtr<VnodeF2fs>::Downcast(std::move(new_child));
  if (target->IsDir())
    return ZX_ERR_NOT_FILE;

  if (auto old_entry = FindEntry(name); !old_entry.is_error()) {
    return ZX_ERR_ALREADY_EXISTS;
  }

  timespec cur_time;
  clock_gettime(CLOCK_REALTIME, &cur_time);
  target->SetCTime(cur_time);

  {
    fs::SharedLock rlock(Vfs()->GetSuperblockInfo().GetFsLock(LockType::kFileOp));
    target->SetFlag(InodeInfoFlag::kIncLink);
    if (zx_status_t err = AddLink(name, target.get()); err != ZX_OK) {
      target->ClearFlag(InodeInfoFlag::kIncLink);
      return err;
    }
  }

#if 0  // porting needed
  // d_instantiate(dentry, inode);
#endif

  Vfs()->GetSegmentManager().BalanceFs();

  return ZX_OK;
}

#if 0  // porting needed
// dentry *Dir::F2fsGetParent(dentry *child) {
//   return nullptr;
//   // qstr dotdot = QSTR_INIT("..", 2);
//   // uint64_t ino = Inode_by_name(child->d_inode, &dotdot);
//   // if (!ino)
//   //   return ErrPtr(-ENOENT);
//   // return d_obtain_alias(f2fs_iget(child->d_inode->i_sb, ino));
// }
#endif

zx_status_t Dir::DoLookup(std::string_view name, fbl::RefPtr<fs::Vnode> *out) {
  fbl::RefPtr<VnodeF2fs> vn;

  if (!fs::IsValidName(name)) {
    return ZX_ERR_INVALID_ARGS;
  }

  if (auto dir_entry = FindEntry(name); !dir_entry.is_error()) {
    nid_t ino = LeToCpu((*dir_entry).ino);
#if 0  // porting needed
    // if (!f2fs_has_inline_dentry(dir))
    //   kunmap(page);
#endif

    if (zx_status_t ret = VnodeF2fs::Vget(Vfs(), ino, &vn); ret != ZX_OK)
      return ret;

    *out = std::move(vn);

    return ZX_OK;
  }

  return ZX_ERR_NOT_FOUND;
}

zx_status_t Dir::Lookup(std::string_view name, fbl::RefPtr<fs::Vnode> *out) {
  return DoLookup(name, out);
}

zx_status_t Dir::DoUnlink(VnodeF2fs *vnode, std::string_view name) {
  DirEntry *de;
  {
    fbl::RefPtr<Page> page;

    de = FindEntry(name, &page);
    if (de == nullptr) {
      return ZX_ERR_NOT_FOUND;
    }

    {
      fs::SharedLock rlock(Vfs()->GetSuperblockInfo().GetFsLock(LockType::kFileOp));
      if (zx_status_t err = Vfs()->CheckOrphanSpace(); err != ZX_OK) {
#if 0  // porting needed
      // if (!f2fs_has_inline_dentry(dir))
      //   kunmap(page);
#endif
        return err;
      }

      DeleteEntry(de, page, vnode);
    }
  }
  Vfs()->GetSegmentManager().BalanceFs();
  return ZX_OK;
}

#if 0  // porting needed
// int Dir::F2fsSymlink(dentry *dentry, const char *symname) {
//   return 0;
//   //   fbl::RefPtr<VnodeF2fs> vnode_refptr;
//   //   VnodeF2fs *vnode = nullptr;
//   //   unsigned symlen = strlen(symname) + 1;
//   //   int err;

//   //   err = NewInode(S_IFLNK | S_IRWXUGO, &vnode_refptr);
//   //   if (err)
//   //     return err;
//   //   vnode = vnode_refptr.get();

//   //   // inode->i_mapping->a_ops = &f2fs_dblock_aops;

//   //   // err = AddLink(dentry, vnode);
//   //   if (err)
//   //     goto out;

//   //   err = page_symlink(vnode, symname, symlen);
//   //   Vfs()->GetNodeManager().AllocNidDone(vnode->Ino());

//   //   // d_instantiate(dentry, vnode);
//   //   UnlockNewInode(vnode);

//   //   Vfs()->GetSegmentManager().BalanceFs();

//   //   return err;
//   // out:
//   //   vnode->ClearNlink();
//   //   UnlockNewInode(vnode);
//   //   Vfs()->GetNodeManager().AllocNidFailed(vnode->Ino());
//   //   return err;
// }
#endif

zx_status_t Dir::Mkdir(std::string_view name, uint32_t mode, fbl::RefPtr<fs::Vnode> *out) {
  fbl::RefPtr<VnodeF2fs> vnode_refptr;
  VnodeF2fs *vnode = nullptr;

  if (zx_status_t err = NewInode(S_IFDIR | mode, &vnode_refptr); err != ZX_OK)
    return err;
  vnode = vnode_refptr.get();
  vnode->SetName(name);
  vnode->SetFlag(InodeInfoFlag::kIncLink);
  {
    SuperblockInfo &superblock_info = Vfs()->GetSuperblockInfo();
    fs::SharedLock rlock(superblock_info.GetFsLock(LockType::kFileOp));
    if (zx_status_t err = AddLink(name, vnode); err != ZX_OK) {
      vnode->ClearFlag(InodeInfoFlag::kIncLink);
      vnode->ClearNlink();
      vnode->UnlockNewInode();
      Vfs()->GetVCache().RemoveDirty(vnode);
      Vfs()->GetNodeManager().AllocNidFailed(vnode->Ino());
      return err;
    }
  }
  Vfs()->GetNodeManager().AllocNidDone(vnode->Ino());

#if 0  // porting needed
  // d_instantiate(dentry, inode);
#endif
  vnode->UnlockNewInode();

  Vfs()->GetSegmentManager().BalanceFs();

  *out = std::move(vnode_refptr);
  return ZX_OK;
}

zx_status_t Dir::Rmdir(Dir *vnode, std::string_view name) {
  if (vnode->IsEmptyDir())
    return DoUnlink(vnode, name);
  return ZX_ERR_NOT_EMPTY;
}

#if 0  // porting needed
// int Dir::F2fsMknod(dentry *dentry, umode_t mode, dev_t rdev) {
//   fbl::RefPtr<VnodeF2fs> vnode_refptr;
//   VnodeF2fs *vnode = nullptr;
//   int err = 0;

//   // if (!new_valid_dev(rdev))
//   //   return -EINVAL;

//   err = NewInode(mode, &vnode_refptr);
//   if (err)
//     return err;
//   vnode = vnode_refptr.get();

//   // init_special_inode(inode, inode->i_mode, rdev);
//   // inode->i_op = &f2fs_special_inode_operations;

//   // err = AddLink(dentry, vnode);
//   if (err)
//     goto out;

//   Vfs()->GetNodeManager().AllocNidDone(vnode->Ino());
//   // d_instantiate(dentry, inode);
//   UnlockNewInode(vnode);

//   Vfs()->GetSegmentManager().BalanceFs();

//   return 0;
// out:
//   vnode->ClearNlink();
//   UnlockNewInode(vnode);
//   Vfs()->GetNodeManager().AllocNidFailed(vnode->Ino());
//   return err;
// }
#endif

zx::status<bool> Dir::IsSubdir(Dir *possible_dir) {
  Dir *vn = possible_dir;
  fbl::RefPtr<VnodeF2fs> parent = nullptr;

  while (vn->Ino() != Vfs()->GetSuperblockInfo().GetRootIno()) {
    if (vn->Ino() == Ino()) {
      return zx::ok(true);
    }

    if (zx_status_t status = VnodeF2fs::Vget(Vfs(), vn->GetParentNid(), &parent); status != ZX_OK) {
      return zx::error(status);
    }

    vn = static_cast<Dir *>(parent.get());
  }
  return zx::ok(false);
}

zx_status_t Dir::Rename(fbl::RefPtr<fs::Vnode> _newdir, std::string_view oldname,
                        std::string_view newname, bool src_must_be_dir, bool dst_must_be_dir) {
  if (Vfs()->GetSuperblockInfo().TestCpFlags(CpFlag::kCpErrorFlag)) {
    return ZX_ERR_BAD_STATE;
  }

  fbl::RefPtr<VnodeF2fs> old_vn_ref;
  fbl::RefPtr<VnodeF2fs> new_vn_ref;
  Dir *old_dir = this;
  Dir *new_dir = static_cast<Dir *>(_newdir.get());
  VnodeF2fs *old_vnode = nullptr;
  nid_t old_ino;
  VnodeF2fs *new_vnode = nullptr;
  nid_t new_ino;
  DirEntry *old_dir_entry = nullptr;
  DirEntry *old_entry;
  DirEntry *new_entry;
  timespec cur_time;

  {
    fbl::RefPtr<Page> old_page;
    fbl::RefPtr<Page> new_page;
    fbl::RefPtr<Page> old_dir_page;

    if (!fs::IsValidName(oldname) || !fs::IsValidName(newname)) {
      return ZX_ERR_INVALID_ARGS;
    }

    clock_gettime(CLOCK_REALTIME, &cur_time);

    if (new_dir->GetNlink() == 0)
      return ZX_ERR_NOT_FOUND;

    old_entry = FindEntry(oldname, &old_page);
    if (!old_entry) {
      return ZX_ERR_NOT_FOUND;
    }

    old_ino = LeToCpu(old_entry->ino);
    if (zx_status_t err = VnodeF2fs::Vget(Vfs(), old_ino, &old_vn_ref); err != ZX_OK) {
      return err;
    }

    old_vnode = old_vn_ref.get();
    ZX_ASSERT(old_vnode->IsSameName(oldname));

    if (!old_vnode->IsDir() && (src_must_be_dir || dst_must_be_dir)) {
      return ZX_ERR_NOT_DIR;
    }

    ZX_ASSERT(!src_must_be_dir || old_vnode->IsDir());

    if (old_vnode->IsDir()) {
      old_dir_entry = (static_cast<Dir *>(old_vnode))->ParentDir(&old_dir_page);
      if (!old_dir_entry) {
#if 0  // porting needed
       // if (!f2fs_has_inline_dentry(old_dir))
       //   kunmap(old_page);
#endif
        return ZX_ERR_IO;
      }

      auto is_subdir = (static_cast<Dir *>(old_vnode))->IsSubdir(new_dir);
      if (is_subdir.is_error()) {
        return is_subdir.error_value();
      }
      if (*is_subdir) {
        return ZX_ERR_INVALID_ARGS;
      }
    }

    do {
      fs::SharedLock rlock(Vfs()->GetSuperblockInfo().GetFsLock(LockType::kFileOp));

      new_entry = new_dir->FindEntry(newname, &new_page);
      if (new_entry) {
        new_ino = LeToCpu(new_entry->ino);
        if (zx_status_t err = VnodeF2fs::Vget(Vfs(), new_ino, &new_vn_ref); err != ZX_OK) {
          if (old_dir_entry) {
#if 0  // porting needed
       // if (!f2fs_has_inline_dentry(old_inode))
       //   kunmap(old_dir_page);
#endif
          }

#if 0  // porting needed
       // if (!f2fs_has_inline_dentry(old_dir))
       //   kunmap(old_page);
#endif
          return err;
        }

        new_vnode = new_vn_ref.get();
        ZX_ASSERT(new_vnode->IsSameName(newname));

        if (!new_vnode->IsDir() && (src_must_be_dir || dst_must_be_dir)) {
          return ZX_ERR_NOT_DIR;
        }

        if (old_vnode->IsDir() && !new_vnode->IsDir()) {
          return ZX_ERR_NOT_DIR;
        }

        if (!old_vnode->IsDir() && new_vnode->IsDir()) {
          return ZX_ERR_NOT_FILE;
        }

        if (old_dir == new_dir && oldname == newname) {
          return ZX_OK;
        }

        if (old_dir_entry &&
            (!new_vnode->IsDir() || !(static_cast<Dir *>(new_vnode))->IsEmptyDir())) {
#if 0  // porting needed
       // if (!f2fs_has_inline_dentry(old_inode))
       //   kunmap(old_dir_page);
       // if (!f2fs_has_inline_dentry(old_dir))
       //   kunmap(old_page);
#endif
          return ZX_ERR_NOT_EMPTY;
        }

        old_vnode->SetName(newname);
        new_dir->SetLink(new_entry, new_page, old_vnode);

        new_vnode->SetCTime(cur_time);
        if (old_dir_entry)
          new_vnode->DropNlink();
        new_vnode->DropNlink();
        if (!new_vnode->GetNlink())
          Vfs()->AddOrphanInode(new_vnode);
        new_vnode->WriteInode(false);
      } else {
        if (old_dir == new_dir && oldname == newname) {
          return ZX_OK;
        }

        old_vnode->SetName(newname);
        if (zx_status_t err = new_dir->AddLink(newname, old_vnode); err != ZX_OK) {
          if (old_dir_entry) {
#if 0  // porting needed
       // if (!f2fs_has_inline_dentry(old_inode))
       //   kunmap(old_dir_page);
#endif
          }

#if 0  // porting needed
       // if (!f2fs_has_inline_dentry(old_dir))
       //   kunmap(old_page);
#endif
          return err;
        }

        if (old_dir_entry) {
          new_dir->IncNlink();
          new_dir->WriteInode(false);
        }
      }

      old_vnode->SetParentNid(new_dir->Ino());
      old_vnode->SetCTime(cur_time);
      old_vnode->SetFlag(InodeInfoFlag::kNeedCp);
      old_vnode->MarkInodeDirty();

      DeleteEntry(old_entry, old_page, nullptr);

      if (old_dir_entry) {
        if (old_dir != new_dir) {
          (static_cast<Dir *>(old_vnode))->SetLink(old_dir_entry, old_dir_page, new_dir);
        } else {
#if 0  // porting needed
       // if (!f2fs_has_inline_dentry(old_inode))
       //   kunmap(old_dir_page);
#endif
          old_dir_page.reset();
        }
        old_dir->DropNlink();
        old_dir->WriteInode(false);
      }
    } while (false);
  }

  Vfs()->GetSegmentManager().BalanceFs();
  return ZX_OK;
}

zx_status_t Dir::Create(std::string_view name, uint32_t mode, fbl::RefPtr<fs::Vnode> *out) {
  if (Vfs()->GetSuperblockInfo().TestCpFlags(CpFlag::kCpErrorFlag)) {
    return ZX_ERR_BAD_STATE;
  }

  if (!fs::IsValidName(name)) {
    return ZX_ERR_INVALID_ARGS;
  }

  if (GetNlink() == 0)
    return ZX_ERR_NOT_FOUND;

  if (auto ret = FindEntry(name); !ret.is_error()) {
    return ZX_ERR_ALREADY_EXISTS;
  }

  zx_status_t status = ZX_OK;
  if (S_ISDIR(mode)) {
    status = Mkdir(name, mode, out);
  } else {
    status = DoCreate(name, mode, out);
  }
  if (status == ZX_OK) {
    status = (*out)->OpenValidating(fs::VnodeConnectionOptions(), nullptr);
  }
  return status;
}

zx_status_t Dir::Unlink(std::string_view name, bool must_be_dir) {
  if (Vfs()->GetSuperblockInfo().TestCpFlags(CpFlag::kCpErrorFlag)) {
    return ZX_ERR_BAD_STATE;
  }

  fbl::RefPtr<fs::Vnode> vn;
  if (zx_status_t status = DoLookup(name, &vn); status != ZX_OK) {
    return status;
  }

  VnodeF2fs *vnode = (VnodeF2fs *)vn.get();
  if (vnode->IsDir())
    return Rmdir(static_cast<Dir *>(vnode), name);

  if (must_be_dir)
    return ZX_ERR_NOT_DIR;

  return DoUnlink(vnode, name);
}

}  // namespace f2fs
