void hf3fs_setattr()

in src/fuse/FuseOps.cc [808:907]


void hf3fs_setattr(fuse_req_t req, fuse_ino_t fino, struct stat *attr, int to_set, struct fuse_file_info *fi) {
  (void)fi;

  auto userInfo = UserInfo(flat::Uid(fuse_req_ctx(req)->uid), flat::Gid(fuse_req_ctx(req)->gid), d.fuseToken);
  if (d.userConfig.getConfig(userInfo).readonly()) {
    fuse_reply_err(req, EROFS);
    return;
  }

  auto ino = real_ino(fino);
  struct fuse_file_info fi2 {};
  if (!fi) {
    fi = &fi2;
  }
  auto pi = inodeOf(*fi, ino);

  XLOGF(OP_LOG_LEVEL, "hf3fs_setattr(ino={}, to_set={}, pid={})", ino, to_set, fuse_req_ctx(req)->pid);
  record("setattr", fuse_req_ctx(req)->uid);

  if (checkVirtDir(ino)) {
    fuse_reply_err(req, EPERM);
    return;
  }

  std::optional<Result<Inode>> res;
  if (to_set & (FUSE_SET_ATTR_MODE | FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID)) {
    std::optional<Permission> perm = std::nullopt;
    std::optional<Uid> uid = std::nullopt;
    std::optional<Gid> gid = std::nullopt;
    if (to_set & FUSE_SET_ATTR_UID) {
      uid = Uid(attr->st_uid);
    }
    if (to_set & FUSE_SET_ATTR_GID) {
      gid = Gid(attr->st_gid);
    }
    if (to_set & FUSE_SET_ATTR_MODE) {
      perm = Permission(attr->st_mode & ALLPERMS);
    }
    res = withRequestInfo(req, d.metaClient->setPermission(userInfo, ino, std::nullopt, false, uid, gid, perm));
    if (res->hasError()) {
      handle_error(req, res.value());
      return;
    }
  }
  if (to_set & FUSE_SET_ATTR_SIZE) {
    {
      std::lock_guard lock(pi->wbMtx);
      auto wb = pi->writeBuf;
      if (wb) {
        if (wb->len) {
          XLOGF(DBG, "flushing for truncate");
          if (flushBuf(req, pi, wb->off, *wb->memh, wb->len, true) < 0) {
            wb->len = 0;
            return;
          }
          wb->len = 0;
        }
      }
    }
    res = withRequestInfo(req, truncate(userInfo, *pi, attr->st_size));
    if (res->hasError()) {
      handle_error(req, res.value());
      return;
    }
  }
  if (to_set & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {
    std::optional<UtcTime> atime, mtime;
    if (to_set & FUSE_SET_ATTR_ATIME) {
      pi->dynamicAttr.wlock()->atime.reset();
      if (to_set & FUSE_SET_ATTR_ATIME_NOW) {
        atime = SETATTR_TIME_NOW;
      } else {
        atime = UtcTime::from(std::chrono::duration_cast<std::chrono::milliseconds>(
            std::chrono::seconds{attr->st_atim.tv_sec} + std::chrono::nanoseconds{attr->st_atim.tv_nsec}));
      }
    }
    if (to_set & FUSE_SET_ATTR_MTIME) {
      pi->dynamicAttr.wlock()->mtime.reset();
      if (to_set & FUSE_SET_ATTR_MTIME_NOW) {
        mtime = SETATTR_TIME_NOW;
      } else {
        mtime = UtcTime::from(std::chrono::duration_cast<std::chrono::milliseconds>(
            std::chrono::seconds{attr->st_mtim.tv_sec} + std::chrono::nanoseconds{attr->st_mtim.tv_nsec}));
      }
    }
    res = withRequestInfo(req, d.metaClient->utimes(userInfo, ino, std::nullopt, false, atime, mtime));
    if (res->hasError()) {
      handle_error(req, res.value());
      return;
    }
  }

  if (res) {
    struct ::stat buf;
    fillLinuxStat(buf, res->value());
    fuse_reply_attr(req, &buf, d.userConfig.getConfig(userInfo).attr_timeout());
  } else {
    hf3fs_getattr(req, linux_ino(ino), fi);
  }
}