1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to
5 * deal in the Software without restriction, including without limitation the
6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 * sell copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 /* Caveat emptor: this file deviates from the libuv convention of returning
23 * negated errno codes. Most uv_fs_*() functions map directly to the system
24 * call of the same name. For more complex wrappers, it's easier to just
25 * return -1 with errno set. The dispatcher in uv__fs_work() takes care of
26 * getting the errno to the right place (req->result or as the return value.)
37 #include <sys/types.h>
47 #if defined(__linux__) || defined(__sun)
48 # include <sys/sendfile.h>
49 #elif defined(__APPLE__) || defined(__FreeBSD__)
50 # include <sys/socket.h>
56 uv__req_init((loop), (req), UV_FS); \
57 (req)->fs_type = UV_FS_ ## type; \
62 (req)->new_path = NULL; \
69 (req)->path = strdup(path); \
70 if ((req)->path == NULL) \
78 size_t new_path_len; \
79 path_len = strlen((path)) + 1; \
80 new_path_len = strlen((new_path)) + 1; \
81 (req)->path = malloc(path_len + new_path_len); \
82 if ((req)->path == NULL) \
84 (req)->new_path = (req)->path + path_len; \
85 memcpy((void*) (req)->path, (path), path_len); \
86 memcpy((void*) (req)->new_path, (new_path), new_path_len); \
93 uv__work_submit((loop), &(req)->work_req, uv__fs_work, uv__fs_done); \
97 uv__fs_work(&(req)->work_req); \
98 uv__fs_done(&(req)->work_req, 0); \
99 return (req)->result; \
105 static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
106 #if defined(__linux__) || defined(__sun) || defined(__NetBSD__)
107 return fdatasync(req->file);
108 #elif defined(__APPLE__) && defined(F_FULLFSYNC)
109 return fcntl(req->file, F_FULLFSYNC);
111 return fsync(req->file);
116 static ssize_t uv__fs_futime(uv_fs_t* req) {
117 #if defined(__linux__)
118 /* utimesat() has nanosecond resolution but we stick to microseconds
119 * for the sake of consistency with other platforms.
121 static int no_utimesat;
122 struct timespec ts[2];
123 struct timeval tv[2];
124 char path[sizeof("/proc/self/fd/") + 3 * sizeof(int)];
130 ts[0].tv_sec = req->atime;
131 ts[0].tv_nsec = (unsigned long)(req->atime * 1000000) % 1000000 * 1000;
132 ts[1].tv_sec = req->mtime;
133 ts[1].tv_nsec = (unsigned long)(req->mtime * 1000000) % 1000000 * 1000;
135 r = uv__utimesat(req->file, NULL, ts, 0);
146 tv[0].tv_sec = req->atime;
147 tv[0].tv_usec = (unsigned long)(req->atime * 1000000) % 1000000;
148 tv[1].tv_sec = req->mtime;
149 tv[1].tv_usec = (unsigned long)(req->mtime * 1000000) % 1000000;
150 snprintf(path, sizeof(path), "/proc/self/fd/%d", (int) req->file);
152 r = utimes(path, tv);
158 if (fcntl(req->file, F_GETFL) == -1 && errno == EBADF)
170 #elif defined(__APPLE__) \
171 || defined(__DragonFly__) \
172 || defined(__FreeBSD__) \
173 || defined(__NetBSD__) \
174 || defined(__OpenBSD__) \
176 struct timeval tv[2];
177 tv[0].tv_sec = req->atime;
178 tv[0].tv_usec = (unsigned long)(req->atime * 1000000) % 1000000;
179 tv[1].tv_sec = req->mtime;
180 tv[1].tv_usec = (unsigned long)(req->mtime * 1000000) % 1000000;
182 return futimesat(req->file, NULL, tv);
184 return futimes(req->file, tv);
193 static ssize_t uv__fs_read(uv_fs_t* req) {
195 return read(req->file, req->buf, req->len);
197 return pread(req->file, req->buf, req->len, req->off);
201 static int uv__fs_readdir_filter(const struct dirent* dent) {
202 return strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0;
206 /* This should have been called uv__fs_scandir(). */
207 static ssize_t uv__fs_readdir(uv_fs_t* req) {
208 struct dirent **dents;
217 n = scandir(req->path, &dents, uv__fs_readdir_filter, alphasort);
220 goto out; /* osx still needs to deallocate some memory */
226 for (i = 0; i < n; i++)
227 len += strlen(dents[i]->d_name) + 1;
239 for (i = 0; i < n; i++) {
240 len = strlen(dents[i]->d_name) + 1;
241 memcpy(buf + off, dents[i]->d_name, len);
250 for (i = 0; i < n; i++)
260 static ssize_t uv__fs_readlink(uv_fs_t* req) {
264 len = pathconf(req->path, _PC_PATH_MAX);
267 #if defined(PATH_MAX)
274 buf = malloc(len + 1);
281 len = readlink(req->path, buf, len);
295 static ssize_t uv__fs_sendfile_emul(uv_fs_t* req) {
315 /* Here are the rules regarding errors:
317 * 1. Read errors are reported only if nsent==0, otherwise we return nsent.
318 * The user needs to know that some data has already been sent, to stop
319 * them from sending it twice.
321 * 2. Write errors are always reported. Write errors are bad because they
322 * mean data loss: we've read data but now we can't write it out.
324 * We try to use pread() and fall back to regular read() if the source fd
325 * doesn't support positional reads, for example when it's a pipe fd.
327 * If we get EAGAIN when writing to the target fd, we poll() on it until
328 * it becomes writable again.
330 * FIXME: If we get a write error when use_pread==1, it should be safe to
331 * return the number of sent bytes instead of an error because pread()
332 * is, in theory, idempotent. However, special files in /dev or /proc
333 * may support pread() but not necessarily return the same data on
336 * FIXME: There is no way now to signal that we managed to send *some* data
337 * before a write error.
339 for (nsent = 0; (size_t) nsent < len; ) {
340 buflen = len - nsent;
342 if (buflen > sizeof(buf))
343 buflen = sizeof(buf);
347 nread = pread(in_fd, buf, buflen, offset);
349 nread = read(in_fd, buf, buflen);
350 while (nread == -1 && errno == EINTR);
356 if (use_pread && nsent == 0 && (errno == EIO || errno == ESPIPE)) {
367 for (nwritten = 0; nwritten < nread; ) {
369 n = write(out_fd, buf + nwritten, nread - nwritten);
370 while (n == -1 && errno == EINTR);
377 if (errno != EAGAIN && errno != EWOULDBLOCK) {
383 pfd.events = POLLOUT;
387 n = poll(&pfd, 1, -1);
388 while (n == -1 && errno == EINTR);
390 if (n == -1 || (pfd.revents & ~POLLOUT) != 0) {
409 static ssize_t uv__fs_sendfile(uv_fs_t* req) {
416 #if defined(__linux__) || defined(__sun)
422 r = sendfile(out_fd, in_fd, &off, req->len);
424 /* sendfile() on SunOS returns EINVAL if the target fd is not a socket but
425 * it still writes out data. Fortunately, we can detect it by checking if
426 * the offset has been updated.
428 if (r != -1 || off > req->off) {
434 if (errno == EINVAL ||
439 return uv__fs_sendfile_emul(req);
444 #elif defined(__FreeBSD__) || defined(__APPLE__)
449 /* sendfile() on FreeBSD and Darwin returns EAGAIN if the target fd is in
450 * non-blocking mode and not all data could be written. If a non-zero
451 * number of bytes have been sent, we don't consider it an error.
454 #if defined(__FreeBSD__)
456 r = sendfile(in_fd, out_fd, req->off, req->len, NULL, &len, 0);
458 /* The darwin sendfile takes len as an input for the length to send,
459 * so make sure to initialize it with the caller's value. */
461 r = sendfile(in_fd, out_fd, req->off, &len, NULL, 0);
464 if (r != -1 || len != 0) {
466 return (ssize_t) len;
469 if (errno == EINVAL ||
474 return uv__fs_sendfile_emul(req);
480 /* Squelch compiler warnings. */
484 return uv__fs_sendfile_emul(req);
489 static ssize_t uv__fs_utime(uv_fs_t* req) {
491 buf.actime = req->atime;
492 buf.modtime = req->mtime;
493 return utime(req->path, &buf); /* TODO use utimes() where available */
497 static ssize_t uv__fs_write(uv_fs_t* req) {
500 /* Serialize writes on OS X, concurrent write() and pwrite() calls result in
501 * data loss. We can't use a per-file descriptor lock, the descriptor may be
504 #if defined(__APPLE__)
505 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
506 pthread_mutex_lock(&lock);
510 r = write(req->file, req->buf, req->len);
512 r = pwrite(req->file, req->buf, req->len, req->off);
514 #if defined(__APPLE__)
515 pthread_mutex_unlock(&lock);
521 static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
522 dst->st_dev = src->st_dev;
523 dst->st_mode = src->st_mode;
524 dst->st_nlink = src->st_nlink;
525 dst->st_uid = src->st_uid;
526 dst->st_gid = src->st_gid;
527 dst->st_rdev = src->st_rdev;
528 dst->st_ino = src->st_ino;
529 dst->st_size = src->st_size;
530 dst->st_blksize = src->st_blksize;
531 dst->st_blocks = src->st_blocks;
533 #if defined(__APPLE__)
534 dst->st_atim.tv_sec = src->st_atimespec.tv_sec;
535 dst->st_atim.tv_nsec = src->st_atimespec.tv_nsec;
536 dst->st_mtim.tv_sec = src->st_mtimespec.tv_sec;
537 dst->st_mtim.tv_nsec = src->st_mtimespec.tv_nsec;
538 dst->st_ctim.tv_sec = src->st_ctimespec.tv_sec;
539 dst->st_ctim.tv_nsec = src->st_ctimespec.tv_nsec;
540 dst->st_birthtim.tv_sec = src->st_birthtimespec.tv_sec;
541 dst->st_birthtim.tv_nsec = src->st_birthtimespec.tv_nsec;
542 dst->st_flags = src->st_flags;
543 dst->st_gen = src->st_gen;
544 #elif defined(_BSD_SOURCE) || defined(_SVID_SOURCE) || defined(_XOPEN_SOURCE)
545 dst->st_atim.tv_sec = src->st_atim.tv_sec;
546 dst->st_atim.tv_nsec = src->st_atim.tv_nsec;
547 dst->st_mtim.tv_sec = src->st_mtim.tv_sec;
548 dst->st_mtim.tv_nsec = src->st_mtim.tv_nsec;
549 dst->st_ctim.tv_sec = src->st_ctim.tv_sec;
550 dst->st_ctim.tv_nsec = src->st_ctim.tv_nsec;
551 # if defined(__DragonFly__) || \
552 defined(__FreeBSD__) || \
553 defined(__OpenBSD__) || \
555 dst->st_birthtim.tv_sec = src->st_birthtim.tv_sec;
556 dst->st_birthtim.tv_nsec = src->st_birthtim.tv_nsec;
557 dst->st_flags = src->st_flags;
558 dst->st_gen = src->st_gen;
560 dst->st_birthtim.tv_sec = src->st_ctim.tv_sec;
561 dst->st_birthtim.tv_nsec = src->st_ctim.tv_nsec;
566 dst->st_atim.tv_sec = src->st_atime;
567 dst->st_atim.tv_nsec = 0;
568 dst->st_mtim.tv_sec = src->st_mtime;
569 dst->st_mtim.tv_nsec = 0;
570 dst->st_ctim.tv_sec = src->st_ctime;
571 dst->st_ctim.tv_nsec = 0;
572 dst->st_birthtim.tv_sec = src->st_ctime;
573 dst->st_birthtim.tv_nsec = 0;
580 static int uv__fs_stat(const char *path, uv_stat_t *buf) {
583 ret = stat(path, &pbuf);
584 uv__to_stat(&pbuf, buf);
589 static int uv__fs_lstat(const char *path, uv_stat_t *buf) {
592 ret = lstat(path, &pbuf);
593 uv__to_stat(&pbuf, buf);
598 static int uv__fs_fstat(int fd, uv_stat_t *buf) {
601 ret = fstat(fd, &pbuf);
602 uv__to_stat(&pbuf, buf);
607 static void uv__fs_work(struct uv__work* w) {
612 req = container_of(w, uv_fs_t, work_req);
613 retry_on_eintr = !(req->fs_type == UV_FS_CLOSE);
618 #define X(type, action) \
619 case UV_FS_ ## type: \
623 switch (req->fs_type) {
624 X(CHMOD, chmod(req->path, req->mode));
625 X(CHOWN, chown(req->path, req->uid, req->gid));
626 X(CLOSE, close(req->file));
627 X(FCHMOD, fchmod(req->file, req->mode));
628 X(FCHOWN, fchown(req->file, req->uid, req->gid));
629 X(FDATASYNC, uv__fs_fdatasync(req));
630 X(FSTAT, uv__fs_fstat(req->file, &req->statbuf));
631 X(FSYNC, fsync(req->file));
632 X(FTRUNCATE, ftruncate(req->file, req->off));
633 X(FUTIME, uv__fs_futime(req));
634 X(LSTAT, uv__fs_lstat(req->path, &req->statbuf));
635 X(LINK, link(req->path, req->new_path));
636 X(MKDIR, mkdir(req->path, req->mode));
637 X(OPEN, open(req->path, req->flags, req->mode));
638 X(READ, uv__fs_read(req));
639 X(READDIR, uv__fs_readdir(req));
640 X(READLINK, uv__fs_readlink(req));
641 X(RENAME, rename(req->path, req->new_path));
642 X(RMDIR, rmdir(req->path));
643 X(SENDFILE, uv__fs_sendfile(req));
644 X(STAT, uv__fs_stat(req->path, &req->statbuf));
645 X(SYMLINK, symlink(req->path, req->new_path));
646 X(UNLINK, unlink(req->path));
647 X(UTIME, uv__fs_utime(req));
648 X(WRITE, uv__fs_write(req));
654 while (r == -1 && errno == EINTR && retry_on_eintr);
657 req->result = -errno;
661 if (r == 0 && (req->fs_type == UV_FS_STAT ||
662 req->fs_type == UV_FS_FSTAT ||
663 req->fs_type == UV_FS_LSTAT)) {
664 req->ptr = &req->statbuf;
669 static void uv__fs_done(struct uv__work* w, int status) {
672 req = container_of(w, uv_fs_t, work_req);
673 uv__req_unregister(req->loop, req);
675 if (status == -ECANCELED) {
676 assert(req->result == 0);
677 req->result = -ECANCELED;
685 int uv_fs_chmod(uv_loop_t* loop,
697 int uv_fs_chown(uv_loop_t* loop,
711 int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
718 int uv_fs_fchmod(uv_loop_t* loop,
730 int uv_fs_fchown(uv_loop_t* loop,
744 int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
751 int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
758 int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
765 int uv_fs_ftruncate(uv_loop_t* loop,
777 int uv_fs_futime(uv_loop_t* loop,
791 int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
798 int uv_fs_link(uv_loop_t* loop,
801 const char* new_path,
809 int uv_fs_mkdir(uv_loop_t* loop,
821 int uv_fs_open(uv_loop_t* loop,
835 int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
850 int uv_fs_readdir(uv_loop_t* loop,
862 int uv_fs_readlink(uv_loop_t* loop,
872 int uv_fs_rename(uv_loop_t* loop,
875 const char* new_path,
883 int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
890 int uv_fs_sendfile(uv_loop_t* loop,
898 req->flags = in_fd; /* hack */
906 int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
913 int uv_fs_symlink(uv_loop_t* loop,
916 const char* new_path,
926 int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
933 int uv_fs_utime(uv_loop_t* loop,
947 int uv_fs_write(uv_loop_t* loop,
956 req->buf = (void*) buf;
963 void uv_fs_req_cleanup(uv_fs_t* req) {
964 free((void*) req->path);
966 req->new_path = NULL;
968 if (req->ptr != &req->statbuf)