// 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 "f2fs.h"

namespace f2fs {

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

  do {
    fs::SharedLock rlock(sbi.fs_lock[static_cast<int>(LockType::kFileOp)]);
    if (!Vfs()->Nodemgr().AllocNid(&ino)) {
      Iput(vnode);
      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(mode);
  vnode->InitSize();
  vnode->ClearNlink();
  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(sbi.s_next_generation++);

  if (TestOpt(&sbi, kMountInlineDentry) && vnode->IsDir())
    vnode->SetFlag(InodeInfoFlag::kInlineDentry);

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

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

int Dir::IsMultimediaFile(const char *s, const char *sub) {
  int slen = strlen(s);
  int sublen = strlen(sub);
  int ret;

  if (sublen > slen)
    return 1;

  if (ret = memcmp(s + slen - sublen, sub, sublen); ret != 0) { /* compare upper case */
    int i;
    char upper_sub[8];
    for (i = 0; i < sublen && i < static_cast<int>(sizeof(upper_sub)); i++)
      upper_sub[i] = toupper(sub[i]);
    return memcmp(s + slen - sublen, upper_sub, sublen);
  }

  return ret;
}

/**
 * Set multimedia files as cold files for hot/cold data separation
 */
inline void Dir::SetColdFile(const char *name, VnodeF2fs *vnode) {
  int i;
  uint8_t(*extlist)[8] = Vfs()->RawSb().extension_list;

  int count = LeToCpu(Vfs()->RawSb().extension_count);
  for (i = 0; i < count; i++) {
    if (!IsMultimediaFile(name, reinterpret_cast<const char *>(extlist[i]))) {
      vnode->SetAdvise(FAdvise::kCold);
      break;
    }
  }
}

zx_status_t Dir::DoCreate(std::string_view name, uint32_t mode, fbl::RefPtr<fs::Vnode> *out) {
  SbInfo &sbi = Vfs()->GetSbInfo();
  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 (!TestOpt(&sbi, kMountDisableExtIdentify))
    SetColdFile(name.data(), vnode);

  vnode->SetFlag(InodeInfoFlag::kIncLink);
  {
    fs::SharedLock rlock(sbi.fs_lock[static_cast<int>(LockType::kFileOp)]);
    if (zx_status_t err = AddLink(name, vnode); err != ZX_OK) {
      vnode->ClearNlink();
      vnode->UnlockNewInode();
      Iput(vnode);
      Vfs()->Nodemgr().AllocNidFailed(vnode->Ino());
      return err;
    }
  }

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

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

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

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

zx_status_t Dir::Link(std::string_view name, fbl::RefPtr<fs::Vnode> _target) {
  VnodeF2fs *target = static_cast<VnodeF2fs *>(_target.get());

  if (target->IsDir())
    return ZX_ERR_NOT_FILE;

  Page *old_entry_page;
  DirEntry *old_entry = FindEntry(name, &old_entry_page);
  if (old_entry != nullptr) {
    nid_t old_ino = LeToCpu(old_entry->ino);
    if (old_ino == target->Ino())
      return ZX_ERR_ALREADY_EXISTS;
  }

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

#if 0  // porting needed
  // AtomicInc(&inode->i_count);
#endif
  {
    SbInfo &sbi = Vfs()->GetSbInfo();
    fs::SharedLock rlock(sbi.fs_lock[static_cast<int>(LockType::kFileOp)]);
    target->SetFlag(InodeInfoFlag::kIncLink);
    if (zx_status_t err = AddLink(name, target); err != ZX_OK) {
      target->ClearFlag(InodeInfoFlag::kIncLink);
      Iput(target);
      return err;
    }
  }

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

  Vfs()->Segmgr().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;
  DirEntry *de;
  Page *page;

  if (name.length() > kMaxNameLen)
    return ZX_ERR_OUT_OF_RANGE;

  de = FindEntry(name, &page);
  if (de) {
    nid_t ino = LeToCpu(de->ino);
#if 0  // porting needed
    // if (!f2fs_has_inline_dentry(dir))
    //   kunmap(page);
#endif
    F2fsPutPage(page, 0);

    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;
  Page *page;

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

  {
    SbInfo &sbi = Vfs()->GetSbInfo();
    fs::SharedLock rlock(sbi.fs_lock[static_cast<int>(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
      F2fsPutPage(page, 0);
      return err;
    }

    DeleteEntry(de, page, vnode);
  }

  Vfs()->Segmgr().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()->Nodemgr().AllocNidDone(vnode->Ino());

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

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

//   //   return err;
//   // out:
//   //   vnode->ClearNlink();
//   //   UnlockNewInode(vnode);
//   //   // Iput(inode);
//   //   Vfs()->Nodemgr().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);

#if 0  // porting needed
  // mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS | __GFP_ZERO);
#endif

  vnode->SetFlag(InodeInfoFlag::kIncLink);
  {
    SbInfo &sbi = Vfs()->GetSbInfo();
    fs::SharedLock rlock(sbi.fs_lock[static_cast<int>(LockType::kFileOp)]);
    if (zx_status_t err = AddLink(name, vnode); err != ZX_OK) {
      vnode->ClearFlag(InodeInfoFlag::kIncLink);
      vnode->ClearNlink();
      vnode->UnlockNewInode();
      Iput(vnode);
      Vfs()->Nodemgr().AllocNidFailed(vnode->Ino());
      return err;
    }
  }
  Vfs()->Nodemgr().AllocNidDone(vnode->Ino());

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

  Vfs()->Segmgr().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()->Nodemgr().AllocNidDone(vnode->Ino());
//   // d_instantiate(dentry, inode);
//   UnlockNewInode(vnode);

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

//   return 0;
// out:
//   vnode->ClearNlink();
//   UnlockNewInode(vnode);
//   Iput(vnode);
//   Vfs()->Nodemgr().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() != RootIno(&Vfs()->GetSbInfo())) {
    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) {
  SbInfo &sbi = Vfs()->GetSbInfo();
  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;
  nid_t old_ino;
  VnodeF2fs *new_vnode;
  nid_t new_ino;
  Page *old_dir_page;
  Page *old_page;
  Page *new_page;
  DirEntry *old_dir_entry = nullptr;
  DirEntry *old_entry;
  DirEntry *new_entry;
  timespec cur_time;

  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
      F2fsPutPage(old_page, 0);

      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(sbi.fs_lock[static_cast<int>(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
          F2fsPutPage(old_dir_page, 0);
        }

#if 0  // porting needed
      // if (!f2fs_has_inline_dentry(old_dir))
      //   kunmap(old_page);
#endif
        F2fsPutPage(old_page, 0);

        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);
#endif
        F2fsPutPage(old_dir_page, 0);

#if 0  // porting needed
      // if (!f2fs_has_inline_dentry(old_dir))
      //   kunmap(old_page);
#endif
        F2fsPutPage(old_page, 0);

        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(NULL);
    } 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
          F2fsPutPage(old_dir_page, 0);
        }

#if 0  // porting needed
      // if (!f2fs_has_inline_dentry(old_dir))
      //   kunmap(old_page);
#endif
        F2fsPutPage(old_page, 0);

        return err;
      }

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

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

    // TODO(djkim): remove this after pager is available
    // If old_dir == new_dir, old_page is not up-to-date after add new entry with newname
    // Therefore, old_page should be read again, unless pager is implemented
    if (old_dir == new_dir)
      old_entry = FindEntry(oldname, &old_page);

    DeleteEntry(old_entry, old_page, NULL);

    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
        F2fsPutPage(old_dir_page, 0);
      }
      old_dir->DropNlink();
      old_dir->WriteInode(NULL);
    }
  } while (false);

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

zx_status_t Dir::Create(std::string_view name, uint32_t mode, fbl::RefPtr<fs::Vnode> *out) {
  Page *page;
  zx_status_t status = ZX_OK;

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

  if (FindEntry(name, &page) != nullptr) {
    return ZX_ERR_ALREADY_EXISTS;
  }

  if (S_ISDIR(mode)) {
    status = Mkdir(name, mode, out);
  } else {
    status = DoCreate(name, mode, out);
  }

  if (status != ZX_OK)
    return status;

  status = (*out)->OpenValidating(fs::VnodeConnectionOptions(), nullptr);
  return status;
}

zx_status_t Dir::Unlink(std::string_view name, bool must_be_dir) {
  fbl::RefPtr<fs::Vnode> vn;

  if (DoLookup(name, &vn) != ZX_OK) {
    return ZX_ERR_NOT_FOUND;
  }

  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
