XS-libuv

 view release on metacpan or  search on metacpan

libuv-1.49.2/src/unix/fs.c  view on Meta::CPAN

     destination are not the same file. If they are the same, bail out early. */
  if ((req->flags & UV_FS_COPYFILE_EXCL) == 0) {
    /* Get the destination file's mode. */
    if (uv__fstat(dstfd, &dst_statsbuf)) {
      err = UV__ERR(errno);
      goto out;
    }

    /* Check if srcfd and dstfd refer to the same file */
    if (src_statsbuf.st_dev == dst_statsbuf.st_dev &&
        src_statsbuf.st_ino == dst_statsbuf.st_ino) {
      goto out;
    }

    /* Truncate the file in case the destination already existed. */
    if (ftruncate(dstfd, 0) != 0) {
      err = UV__ERR(errno);

      /* ftruncate() on ceph-fuse fails with EACCES when the file is created
       * with read only permissions. Since ftruncate() on a newly created
       * file is a meaningless operation anyway, detect that condition
       * and squelch the error.
       */
      if (err != UV_EACCES)
        goto out;

      if (dst_statsbuf.st_size > 0)
        goto out;

      err = 0;
    }
  }

  /**
   * Change the timestamps of the destination file to match the source file.
   */
#if defined(__APPLE__)
  times[0] = src_statsbuf.st_atimespec;
  times[1] = src_statsbuf.st_mtimespec;
#elif defined(_AIX)
  times[0].tv_sec = src_statsbuf.st_atime;
  times[0].tv_nsec = src_statsbuf.st_atime_n;
  times[1].tv_sec = src_statsbuf.st_mtime;
  times[1].tv_nsec = src_statsbuf.st_mtime_n;
#else
  times[0] = src_statsbuf.st_atim;
  times[1] = src_statsbuf.st_mtim;
#endif

  if (futimens(dstfd, times) == -1) {
    err = UV__ERR(errno);
    goto out;
  }

  /*
   * Change the ownership and permissions of the destination file to match the
   * source file.
   * `cp -p` does not care about errors here, so we don't either. Reuse the
   * `result` variable to silence a -Wunused-result warning.
   */
  result = fchown(dstfd, src_statsbuf.st_uid, src_statsbuf.st_gid);

  if (fchmod(dstfd, src_statsbuf.st_mode) == -1) {
    err = UV__ERR(errno);
#ifdef __linux__
    /* fchmod() on CIFS shares always fails with EPERM unless the share is
     * mounted with "noperm". As fchmod() is a meaningless operation on such
     * shares anyway, detect that condition and squelch the error.
     */
    if (err != UV_EPERM)
      goto out;

    if (!uv__is_cifs_or_smb(dstfd))
      goto out;

    err = 0;
#else  /* !__linux__ */
    goto out;
#endif  /* !__linux__ */
  }

#ifdef FICLONE
  if (req->flags & UV_FS_COPYFILE_FICLONE ||
      req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
    if (ioctl(dstfd, FICLONE, srcfd) == 0) {
      /* ioctl() with FICLONE succeeded. */
      goto out;
    }
    /* If an error occurred and force was set, return the error to the caller;
     * fall back to sendfile() when force was not set. */
    if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
      err = UV__ERR(errno);
      goto out;
    }
  }
#else
  if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
    err = UV_ENOSYS;
    goto out;
  }
#endif

  bytes_to_send = src_statsbuf.st_size;
  in_offset = 0;
  while (bytes_to_send != 0) {
    bytes_chunk = SSIZE_MAX;
    if (bytes_to_send < (off_t) bytes_chunk)
      bytes_chunk = bytes_to_send;
    uv_fs_sendfile(NULL, &fs_req, dstfd, srcfd, in_offset, bytes_chunk, NULL);
    bytes_written = fs_req.result;
    uv_fs_req_cleanup(&fs_req);

    if (bytes_written < 0) {
      err = bytes_written;
      break;
    }

    bytes_to_send -= bytes_written;
    in_offset += bytes_written;
  }

libuv-1.49.2/src/unix/fs.c  view on Meta::CPAN


  iovmax = uv__getiovmax();
  nbufs = req->nbufs;
  bufs = req->bufs;
  total = 0;

  while (nbufs > 0) {
    req->nbufs = nbufs;
    if (req->nbufs > iovmax)
      req->nbufs = iovmax;

    do
      result = uv__fs_write(req);
    while (result < 0 && errno == EINTR);

    if (result <= 0) {
      if (total == 0)
        total = result;
      break;
    }

    if (req->off >= 0)
      req->off += result;

    req->nbufs = uv__fs_buf_offset(req->bufs, result);
    req->bufs += req->nbufs;
    nbufs -= req->nbufs;
    total += result;
  }

  if (bufs != req->bufsml)
    uv__free(bufs);

  req->bufs = NULL;
  req->nbufs = 0;

  return total;
}


static void uv__fs_work(struct uv__work* w) {
  int retry_on_eintr;
  uv_fs_t* req;
  ssize_t r;

  req = container_of(w, uv_fs_t, work_req);
  retry_on_eintr = !(req->fs_type == UV_FS_CLOSE ||
                     req->fs_type == UV_FS_READ);

  do {
    errno = 0;

#define X(type, action)                                                       \
  case UV_FS_ ## type:                                                        \
    r = action;                                                               \
    break;

    switch (req->fs_type) {
    X(ACCESS, access(req->path, req->flags));
    X(CHMOD, chmod(req->path, req->mode));
    X(CHOWN, chown(req->path, req->uid, req->gid));
    X(CLOSE, uv__fs_close(req->file));
    X(COPYFILE, uv__fs_copyfile(req));
    X(FCHMOD, fchmod(req->file, req->mode));
    X(FCHOWN, fchown(req->file, req->uid, req->gid));
    X(LCHOWN, lchown(req->path, req->uid, req->gid));
    X(FDATASYNC, uv__fs_fdatasync(req));
    X(FSTAT, uv__fs_fstat(req->file, &req->statbuf));
    X(FSYNC, uv__fs_fsync(req));
    X(FTRUNCATE, ftruncate(req->file, req->off));
    X(FUTIME, uv__fs_futime(req));
    X(LUTIME, uv__fs_lutime(req));
    X(LSTAT, uv__fs_lstat(req->path, &req->statbuf));
    X(LINK, link(req->path, req->new_path));
    X(MKDIR, mkdir(req->path, req->mode));
    X(MKDTEMP, uv__fs_mkdtemp(req));
    X(MKSTEMP, uv__fs_mkstemp(req));
    X(OPEN, uv__fs_open(req));
    X(READ, uv__fs_read(req));
    X(SCANDIR, uv__fs_scandir(req));
    X(OPENDIR, uv__fs_opendir(req));
    X(READDIR, uv__fs_readdir(req));
    X(CLOSEDIR, uv__fs_closedir(req));
    X(READLINK, uv__fs_readlink(req));
    X(REALPATH, uv__fs_realpath(req));
    X(RENAME, rename(req->path, req->new_path));
    X(RMDIR, rmdir(req->path));
    X(SENDFILE, uv__fs_sendfile(req));
    X(STAT, uv__fs_stat(req->path, &req->statbuf));
    X(STATFS, uv__fs_statfs(req));
    X(SYMLINK, symlink(req->path, req->new_path));
    X(UNLINK, unlink(req->path));
    X(UTIME, uv__fs_utime(req));
    X(WRITE, uv__fs_write_all(req));
    default: abort();
    }
#undef X
  } while (r == -1 && errno == EINTR && retry_on_eintr);

  if (r == -1)
    req->result = UV__ERR(errno);
  else
    req->result = r;

  if (r == 0 && (req->fs_type == UV_FS_STAT ||
                 req->fs_type == UV_FS_FSTAT ||
                 req->fs_type == UV_FS_LSTAT)) {
    req->ptr = &req->statbuf;
  }
}


static void uv__fs_done(struct uv__work* w, int status) {
  uv_fs_t* req;

  req = container_of(w, uv_fs_t, work_req);
  uv__req_unregister(req->loop);

  if (status == UV_ECANCELED) {
    assert(req->result == 0);
    req->result = UV_ECANCELED;
  }

  req->cb(req);
}


void uv__fs_post(uv_loop_t* loop, uv_fs_t* req) {
  uv__req_register(loop);
  uv__work_submit(loop,
                  &req->work_req,
                  UV__WORK_FAST_IO,
                  uv__fs_work,
                  uv__fs_done);
}


int uv_fs_access(uv_loop_t* loop,
                 uv_fs_t* req,
                 const char* path,
                 int flags,
                 uv_fs_cb cb) {
  INIT(ACCESS);
  PATH;
  req->flags = flags;
  POST;
}


int uv_fs_chmod(uv_loop_t* loop,
                uv_fs_t* req,
                const char* path,
                int mode,
                uv_fs_cb cb) {
  INIT(CHMOD);
  PATH;
  req->mode = mode;
  POST;
}


int uv_fs_chown(uv_loop_t* loop,
                uv_fs_t* req,
                const char* path,
                uv_uid_t uid,
                uv_gid_t gid,
                uv_fs_cb cb) {
  INIT(CHOWN);
  PATH;
  req->uid = uid;
  req->gid = gid;
  POST;
}


int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
  INIT(CLOSE);
  req->file = file;
  if (cb != NULL)
    if (uv__iou_fs_close(loop, req))
      return 0;
  POST;
}


int uv_fs_fchmod(uv_loop_t* loop,
                 uv_fs_t* req,
                 uv_file file,
                 int mode,
                 uv_fs_cb cb) {
  INIT(FCHMOD);
  req->file = file;
  req->mode = mode;
  POST;
}


int uv_fs_fchown(uv_loop_t* loop,
                 uv_fs_t* req,
                 uv_file file,
                 uv_uid_t uid,
                 uv_gid_t gid,
                 uv_fs_cb cb) {
  INIT(FCHOWN);
  req->file = file;
  req->uid = uid;
  req->gid = gid;
  POST;
}


int uv_fs_lchown(uv_loop_t* loop,
                 uv_fs_t* req,
                 const char* path,
                 uv_uid_t uid,
                 uv_gid_t gid,
                 uv_fs_cb cb) {
  INIT(LCHOWN);
  PATH;
  req->uid = uid;
  req->gid = gid;
  POST;
}


int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
  INIT(FDATASYNC);
  req->file = file;
  if (cb != NULL)
    if (uv__iou_fs_fsync_or_fdatasync(loop, req, /* IORING_FSYNC_DATASYNC */ 1))
      return 0;
  POST;
}


int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
  INIT(FSTAT);
  req->file = file;
  if (cb != NULL)
    if (uv__iou_fs_statx(loop, req, /* is_fstat */ 1, /* is_lstat */ 0))
      return 0;
  POST;
}


int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
  INIT(FSYNC);
  req->file = file;
  if (cb != NULL)
    if (uv__iou_fs_fsync_or_fdatasync(loop, req, /* no flags */ 0))
      return 0;
  POST;
}


int uv_fs_ftruncate(uv_loop_t* loop,
                    uv_fs_t* req,
                    uv_file file,
                    int64_t off,
                    uv_fs_cb cb) {
  INIT(FTRUNCATE);
  req->file = file;
  req->off = off;
  if (cb != NULL)
    if (uv__iou_fs_ftruncate(loop, req))
      return 0;
  POST;
}


int uv_fs_futime(uv_loop_t* loop,
                 uv_fs_t* req,



( run in 0.573 second using v1.01-cache-2.11-cpan-5511b514fd6 )