// 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::F2fsNewInode(uint32_t mode, fbl::RefPtr<VnodeF2fs> *out) {
  f2fs_sb_info &sbi = Vfs()->SbInfo();
  nid_t ino;
  fbl::RefPtr<VnodeF2fs> vnode_refptr;
  VnodeF2fs *vnode = nullptr;
  auto cur_time = time(nullptr);

  do {
    fbl::AutoLock lock(&sbi.fs_lock[NODE_NEW]);
    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->i_uid = getuid();

  if (i_mode & S_ISGID) {
    vnode->i_gid = i_gid;
    if (S_ISDIR(mode))
      mode |= S_ISGID;
  } else {
    vnode->i_gid = getgid();
  }

  vnode->i_mode = mode;
  vnode->i_blocks = 0;

  cur_time = time(nullptr);
  vnode->i_mtime.tv_sec = cur_time;
  vnode->i_mtime.tv_nsec = 0;
  vnode->i_atime.tv_sec = cur_time;
  vnode->i_atime.tv_nsec = 0;
  vnode->i_ctime.tv_sec = cur_time;
  vnode->i_ctime.tv_nsec = 0;

  vnode->i_generation = sbi.s_next_generation++;

  Vfs()->InsertVnode(vnode);

  MarkInodeDirty(vnode);
  *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) {
  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]))) {
      fi.i_advise |= FADVISE_COLD_BIT;
      break;
    }
  }
}

zx_status_t Dir::F2fsCreate(fbl::StringPiece name, uint32_t mode, fbl::RefPtr<fs::Vnode> *out) {
  f2fs_sb_info &sbi = Vfs()->SbInfo();
  fbl::RefPtr<VnodeF2fs> vnode_refptr;
  VnodeF2fs *vnode = nullptr;

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

  vnode->i_name_sp = name;

  if (!test_opt(&sbi, DISABLE_EXT_IDENTIFY))
    SetColdFile(name.data());

  SetInodeFlag(&vnode->fi, FI_INC_LINK);
  if (zx_status_t err = F2fsAddLink(name, vnode); err != ZX_OK) {
    vnode->ClearNlink();
    UnlockNewInode(vnode);
    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
  UnlockNewInode(vnode);

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

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

zx_status_t Dir::Link(fbl::StringPiece name, fbl::RefPtr<fs::Vnode> _target) {
  VnodeF2fs *target = static_cast<VnodeF2fs *>(_target.get());
  auto cur_time = time(nullptr);

  fbl::AutoLock lock(&i_mutex);
  fbl::AutoLock tlock(&target->i_mutex);

  target->i_ctime.tv_sec = cur_time;
  target->i_ctime.tv_nsec = 0;

#if 0  // porting needed
  // AtomicInc(&inode->i_count);
#endif

  SetInodeFlag(&target->fi, FI_INC_LINK);
  if (zx_status_t err = F2fsAddLink(name, target); err != ZX_OK) {
    ClearInodeFlag(&target->fi, FI_INC_LINK);
    Iput(target);
    return err;
  }

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

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

  return ZX_OK;
}

#if 0  // porting needed
// dentry *Dir::F2fsGetParent(dentry *child) {
//   return nullptr;
//   // qstr dotdot = QSTR_INIT("..", 2);
//   // uint64_t ino = f2fs_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::F2fsLookup(fbl::StringPiece name, fbl::RefPtr<fs::Vnode> *out) {
  fbl::RefPtr<VnodeF2fs> vn;
  f2fs_dir_entry *de;
  Page *page;

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

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

    if (zx_status_t ret = VnodeF2fs::F2fsVget(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(fbl::StringPiece name, fbl::RefPtr<fs::Vnode> *out) {
  fbl::AutoLock lock(&i_mutex);
  return F2fsLookup(name, out);
}

zx_status_t Dir::F2fsUnlink(VnodeF2fs *vnode, fbl::StringPiece name) {
  f2fs_dir_entry *de;
  Page *page;

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

  if (zx_status_t err = Vfs()->CheckOrphanSpace(); err != ZX_OK) {
#if 0  // porting needed
    // kunmap(page);
#endif
    F2fsPutPage(page, 0);
    return err;
  }

  F2fsDeleteEntry(de, page, vnode);

  /* In order to evict this inode,  we set it dirty */
  MarkInodeDirty(vnode);
  Vfs()->Segmgr().F2fsBalanceFs();

  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 = F2fsNewInode(S_IFLNK | S_IRWXUGO, &vnode_refptr);
//   //   if (err)
//   //     return err;
//   //   vnode = vnode_refptr.get();

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

//   //   // err = F2fsAddLink(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().F2fsBalanceFs();

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

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

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

  vnode->i_name_sp = name;

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

  SetInodeFlag(&vnode->fi, FI_INC_LINK);
  if (zx_status_t err = F2fsAddLink(name, vnode); err != ZX_OK) {
    ClearInodeFlag(&vnode->fi, FI_INC_LINK);
    vnode->ClearNlink();
    UnlockNewInode(vnode);
    Iput(vnode);
    Vfs()->Nodemgr().AllocNidFailed(vnode->Ino());
    return err;
  }

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

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

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

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

zx_status_t Dir::F2fsRmdir(Dir *vnode, fbl::StringPiece name) {
  if (vnode->F2fsEmptyDir())
    return F2fsUnlink(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 = F2fsNewInode(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 = F2fsAddLink(dentry, vnode);
//   if (err)
//     goto out;

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

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

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

zx_status_t Dir::Rename(fbl::RefPtr<fs::Vnode> _newdir, fbl::StringPiece oldname,
                        fbl::StringPiece newname, bool src_must_be_dir, bool dst_must_be_dir) {
  f2fs_sb_info &sbi = Vfs()->SbInfo();
  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;
  f2fs_dir_entry *old_dir_entry = nullptr;
  f2fs_dir_entry *old_entry;
  f2fs_dir_entry *new_entry;
  auto cur_time = time(nullptr);

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

  fbl::AutoLock lock(&i_mutex);

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

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

  old_vnode = old_vn_ref.get();
  old_vnode->i_name_sp = oldname;

  ZX_ASSERT(!src_must_be_dir || S_ISDIR(old_vnode->i_mode));

  if (S_ISDIR(old_vnode->i_mode)) {
    old_dir_entry = (static_cast<Dir *>(old_vnode))->F2fsParentDir(&old_dir_page);
    if (!old_dir_entry) {
#if 0  // porting needed
      // kunmap(old_page);
#endif
      F2fsPutPage(old_page, 0);

      return ZX_ERR_IO;
    }
  }

  do {
    fbl::AutoLock rlock(&sbi.fs_lock[RENAME]);

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

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

        return err;
      }

      new_vnode = new_vn_ref.get();
      new_vnode->i_name_sp = newname;

      if (old_dir_entry && (!S_ISDIR(new_vnode->i_mode) || !(static_cast<Dir *>(new_vnode))->F2fsEmptyDir())) {
#if 0  // porting needed
        // kunmap(old_dir_page);
#endif
        F2fsPutPage(old_dir_page, 0);

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

        return ZX_ERR_NOT_EMPTY;
      }

      new_dir->F2fsSetLink(new_entry, new_page, old_vnode);

      cur_time = time(nullptr);
      new_vnode->i_ctime.tv_sec = cur_time;
      new_vnode->i_ctime.tv_nsec = 0;
      if (old_dir_entry)
        new_vnode->DropNlink();
      new_vnode->DropNlink();
      if (!new_vnode->i_nlink)
        Vfs()->AddOrphanInode(new_vnode->Ino());
      new_vnode->F2fsWriteInode(NULL);
    } else {
      old_vnode->i_name_sp = newname;
      if (zx_status_t err = new_dir->F2fsAddLink(newname, old_vnode); err != ZX_OK) {
        if (old_dir_entry) {
#if 0  // porting needed
          // kunmap(old_dir_page);
#endif
          F2fsPutPage(old_dir_page, 0);
        }

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

        return err;
      }

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

    old_vnode->i_ctime.tv_sec = cur_time;
    old_vnode->i_ctime.tv_nsec = 0;
    SetInodeFlag(&old_vnode->fi, FI_NEED_CP);
    MarkInodeDirty(old_vnode);

    // 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 = F2fsFindEntry(oldname, &old_page);

    F2fsDeleteEntry(old_entry, old_page, NULL);

    if (old_dir_entry) {
      if (old_dir != new_dir) {
        (static_cast<Dir *>(old_vnode))->F2fsSetLink(old_dir_entry, old_dir_page, new_dir);
      } else {
#if 0  // porting needed
        // kunmap(old_dir_page);
#endif
        F2fsPutPage(old_dir_page, 0);
      }
      old_dir->DropNlink();
      old_dir->F2fsWriteInode(NULL);
    }
  } while (false);

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

zx_status_t Dir::Create(fbl::StringPiece name, uint32_t mode, fbl::RefPtr<fs::Vnode> *out) {
  Page *page;
  fbl::AutoLock lock(&i_mutex);

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

  if (S_ISDIR(mode))
    return F2fsMkdir(name, mode, out);
  
  return F2fsCreate(name, mode, out);
}

zx_status_t Dir::Unlink(fbl::StringPiece name, bool must_be_dir) {
  fbl::RefPtr<fs::Vnode> vn;
  fbl::AutoLock lock(&i_mutex);

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

  VnodeF2fs *vnode = (VnodeF2fs *)vn.get();

  if (S_ISDIR(vnode->i_mode))
    return F2fsRmdir(static_cast<Dir *>(vnode), name);

  return F2fsUnlink(vnode, name);
}

}  // namespace f2fs
