uv: Upgrade to v0.11.17
[platform/upstream/nodejs.git] / deps / uv / src / unix / fs.c
1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2  *
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:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
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
19  * IN THE SOFTWARE.
20  */
21
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.)
27  */
28
29 #include "uv.h"
30 #include "internal.h"
31
32 #include <errno.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <sys/time.h>
40 #include <pthread.h>
41 #include <dirent.h>
42 #include <unistd.h>
43 #include <fcntl.h>
44 #include <utime.h>
45 #include <poll.h>
46
47 #if defined(__linux__) || defined(__sun)
48 # include <sys/sendfile.h>
49 #elif defined(__APPLE__) || defined(__FreeBSD__)
50 # include <sys/socket.h>
51 # include <sys/uio.h>
52 #endif
53
54 #define INIT(type)                                                            \
55   do {                                                                        \
56     uv__req_init((loop), (req), UV_FS);                                       \
57     (req)->fs_type = UV_FS_ ## type;                                          \
58     (req)->result = 0;                                                        \
59     (req)->ptr = NULL;                                                        \
60     (req)->loop = loop;                                                       \
61     (req)->path = NULL;                                                       \
62     (req)->new_path = NULL;                                                   \
63     (req)->cb = (cb);                                                         \
64   }                                                                           \
65   while (0)
66
67 #define PATH                                                                  \
68   do {                                                                        \
69     (req)->path = strdup(path);                                               \
70     if ((req)->path == NULL)                                                  \
71       return -ENOMEM;                                                         \
72   }                                                                           \
73   while (0)
74
75 #define PATH2                                                                 \
76   do {                                                                        \
77     size_t path_len;                                                          \
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)                                                  \
83       return -ENOMEM;                                                         \
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);                \
87   }                                                                           \
88   while (0)
89
90 #define POST                                                                  \
91   do {                                                                        \
92     if ((cb) != NULL) {                                                       \
93       uv__work_submit((loop), &(req)->work_req, uv__fs_work, uv__fs_done);    \
94       return 0;                                                               \
95     }                                                                         \
96     else {                                                                    \
97       uv__fs_work(&(req)->work_req);                                          \
98       uv__fs_done(&(req)->work_req, 0);                                       \
99       return (req)->result;                                                   \
100     }                                                                         \
101   }                                                                           \
102   while (0)
103
104
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);
110 #else
111   return fsync(req->file);
112 #endif
113 }
114
115
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.
120    */
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)];
125   int r;
126
127   if (no_utimesat)
128     goto skip;
129
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;
134
135   r = uv__utimesat(req->file, NULL, ts, 0);
136   if (r == 0)
137     return r;
138
139   if (errno != ENOSYS)
140     return r;
141
142   no_utimesat = 1;
143
144 skip:
145
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);
151
152   r = utimes(path, tv);
153   if (r == 0)
154     return r;
155
156   switch (errno) {
157   case ENOENT:
158     if (fcntl(req->file, F_GETFL) == -1 && errno == EBADF)
159       break;
160     /* Fall through. */
161
162   case EACCES:
163   case ENOTDIR:
164     errno = ENOSYS;
165     break;
166   }
167
168   return r;
169
170 #elif defined(__APPLE__)                                                      \
171     || defined(__DragonFly__)                                                 \
172     || defined(__FreeBSD__)                                                   \
173     || defined(__NetBSD__)                                                    \
174     || defined(__OpenBSD__)                                                   \
175     || defined(__sun)
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;
181 # if defined(__sun)
182   return futimesat(req->file, NULL, tv);
183 # else
184   return futimes(req->file, tv);
185 # endif
186 #else
187   errno = ENOSYS;
188   return -1;
189 #endif
190 }
191
192
193 static ssize_t uv__fs_read(uv_fs_t* req) {
194   if (req->off < 0)
195     return read(req->file, req->buf, req->len);
196   else
197     return pread(req->file, req->buf, req->len, req->off);
198 }
199
200
201 static int uv__fs_readdir_filter(const struct dirent* dent) {
202   return strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0;
203 }
204
205
206 /* This should have been called uv__fs_scandir(). */
207 static ssize_t uv__fs_readdir(uv_fs_t* req) {
208   struct dirent **dents;
209   int saved_errno;
210   size_t off;
211   size_t len;
212   char *buf;
213   int i;
214   int n;
215
216   dents = NULL;
217   n = scandir(req->path, &dents, uv__fs_readdir_filter, alphasort);
218
219   if (n == 0)
220     goto out; /* osx still needs to deallocate some memory */
221   else if (n == -1)
222     return n;
223
224   len = 0;
225
226   for (i = 0; i < n; i++)
227     len += strlen(dents[i]->d_name) + 1;
228
229   buf = malloc(len);
230
231   if (buf == NULL) {
232     errno = ENOMEM;
233     n = -1;
234     goto out;
235   }
236
237   off = 0;
238
239   for (i = 0; i < n; i++) {
240     len = strlen(dents[i]->d_name) + 1;
241     memcpy(buf + off, dents[i]->d_name, len);
242     off += len;
243   }
244
245   req->ptr = buf;
246
247 out:
248   saved_errno = errno;
249   if (dents != NULL) {
250     for (i = 0; i < n; i++)
251       free(dents[i]);
252     free(dents);
253   }
254   errno = saved_errno;
255
256   return n;
257 }
258
259
260 static ssize_t uv__fs_readlink(uv_fs_t* req) {
261   ssize_t len;
262   char* buf;
263
264   len = pathconf(req->path, _PC_PATH_MAX);
265
266   if (len == -1) {
267 #if defined(PATH_MAX)
268     len = PATH_MAX;
269 #else
270     len = 4096;
271 #endif
272   }
273
274   buf = malloc(len + 1);
275
276   if (buf == NULL) {
277     errno = ENOMEM;
278     return -1;
279   }
280
281   len = readlink(req->path, buf, len);
282
283   if (len == -1) {
284     free(buf);
285     return -1;
286   }
287
288   buf[len] = '\0';
289   req->ptr = buf;
290
291   return 0;
292 }
293
294
295 static ssize_t uv__fs_sendfile_emul(uv_fs_t* req) {
296   struct pollfd pfd;
297   int use_pread;
298   off_t offset;
299   ssize_t nsent;
300   ssize_t nread;
301   ssize_t nwritten;
302   size_t buflen;
303   size_t len;
304   ssize_t n;
305   int in_fd;
306   int out_fd;
307   char buf[8192];
308
309   len = req->len;
310   in_fd = req->flags;
311   out_fd = req->file;
312   offset = req->off;
313   use_pread = 1;
314
315   /* Here are the rules regarding errors:
316    *
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.
320    *
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.
323    *
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.
326    *
327    * If we get EAGAIN when writing to the target fd, we poll() on it until
328    * it becomes writable again.
329    *
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
334    *        successive reads.
335    *
336    * FIXME: There is no way now to signal that we managed to send *some* data
337    *        before a write error.
338    */
339   for (nsent = 0; (size_t) nsent < len; ) {
340     buflen = len - nsent;
341
342     if (buflen > sizeof(buf))
343       buflen = sizeof(buf);
344
345     do
346       if (use_pread)
347         nread = pread(in_fd, buf, buflen, offset);
348       else
349         nread = read(in_fd, buf, buflen);
350     while (nread == -1 && errno == EINTR);
351
352     if (nread == 0)
353       goto out;
354
355     if (nread == -1) {
356       if (use_pread && nsent == 0 && (errno == EIO || errno == ESPIPE)) {
357         use_pread = 0;
358         continue;
359       }
360
361       if (nsent == 0)
362         nsent = -1;
363
364       goto out;
365     }
366
367     for (nwritten = 0; nwritten < nread; ) {
368       do
369         n = write(out_fd, buf + nwritten, nread - nwritten);
370       while (n == -1 && errno == EINTR);
371
372       if (n != -1) {
373         nwritten += n;
374         continue;
375       }
376
377       if (errno != EAGAIN && errno != EWOULDBLOCK) {
378         nsent = -1;
379         goto out;
380       }
381
382       pfd.fd = out_fd;
383       pfd.events = POLLOUT;
384       pfd.revents = 0;
385
386       do
387         n = poll(&pfd, 1, -1);
388       while (n == -1 && errno == EINTR);
389
390       if (n == -1 || (pfd.revents & ~POLLOUT) != 0) {
391         errno = EIO;
392         nsent = -1;
393         goto out;
394       }
395     }
396
397     offset += nread;
398     nsent += nread;
399   }
400
401 out:
402   if (nsent != -1)
403     req->off = offset;
404
405   return nsent;
406 }
407
408
409 static ssize_t uv__fs_sendfile(uv_fs_t* req) {
410   int in_fd;
411   int out_fd;
412
413   in_fd = req->flags;
414   out_fd = req->file;
415
416 #if defined(__linux__) || defined(__sun)
417   {
418     off_t off;
419     ssize_t r;
420
421     off = req->off;
422     r = sendfile(out_fd, in_fd, &off, req->len);
423
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.
427      */
428     if (r != -1 || off > req->off) {
429       r = off - req->off;
430       req->off = off;
431       return r;
432     }
433
434     if (errno == EINVAL ||
435         errno == EIO ||
436         errno == ENOTSOCK ||
437         errno == EXDEV) {
438       errno = 0;
439       return uv__fs_sendfile_emul(req);
440     }
441
442     return -1;
443   }
444 #elif defined(__FreeBSD__) || defined(__APPLE__)
445   {
446     off_t len;
447     ssize_t r;
448
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.
452      */
453
454 #if defined(__FreeBSD__)
455     len = 0;
456     r = sendfile(in_fd, out_fd, req->off, req->len, NULL, &len, 0);
457 #else
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. */
460     len = req->len;
461     r = sendfile(in_fd, out_fd, req->off, &len, NULL, 0);
462 #endif
463
464     if (r != -1 || len != 0) {
465       req->off += len;
466       return (ssize_t) len;
467     }
468
469     if (errno == EINVAL ||
470         errno == EIO ||
471         errno == ENOTSOCK ||
472         errno == EXDEV) {
473       errno = 0;
474       return uv__fs_sendfile_emul(req);
475     }
476
477     return -1;
478   }
479 #else
480   /* Squelch compiler warnings. */
481   (void) &in_fd;
482   (void) &out_fd;
483
484   return uv__fs_sendfile_emul(req);
485 #endif
486 }
487
488
489 static ssize_t uv__fs_utime(uv_fs_t* req) {
490   struct utimbuf buf;
491   buf.actime = req->atime;
492   buf.modtime = req->mtime;
493   return utime(req->path, &buf); /* TODO use utimes() where available */
494 }
495
496
497 static ssize_t uv__fs_write(uv_fs_t* req) {
498   ssize_t r;
499
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
502    * a dup().
503    */
504 #if defined(__APPLE__)
505   static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
506   pthread_mutex_lock(&lock);
507 #endif
508
509   if (req->off < 0)
510     r = write(req->file, req->buf, req->len);
511   else
512     r = pwrite(req->file, req->buf, req->len, req->off);
513
514 #if defined(__APPLE__)
515   pthread_mutex_unlock(&lock);
516 #endif
517
518   return r;
519 }
520
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;
532
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__)    || \
554      defined(__NetBSD__)
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;
559 # else
560   dst->st_birthtim.tv_sec = src->st_ctim.tv_sec;
561   dst->st_birthtim.tv_nsec = src->st_ctim.tv_nsec;
562   dst->st_flags = 0;
563   dst->st_gen = 0;
564 # endif
565 #else
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;
574   dst->st_flags = 0;
575   dst->st_gen = 0;
576 #endif
577 }
578
579
580 static int uv__fs_stat(const char *path, uv_stat_t *buf) {
581   struct stat pbuf;
582   int ret;
583   ret = stat(path, &pbuf);
584   uv__to_stat(&pbuf, buf);
585   return ret;
586 }
587
588
589 static int uv__fs_lstat(const char *path, uv_stat_t *buf) {
590   struct stat pbuf;
591   int ret;
592   ret = lstat(path, &pbuf);
593   uv__to_stat(&pbuf, buf);
594   return ret;
595 }
596
597
598 static int uv__fs_fstat(int fd, uv_stat_t *buf) {
599   struct stat pbuf;
600   int ret;
601   ret = fstat(fd, &pbuf);
602   uv__to_stat(&pbuf, buf);
603   return ret;
604 }
605
606
607 static void uv__fs_work(struct uv__work* w) {
608   int retry_on_eintr;
609   uv_fs_t* req;
610   ssize_t r;
611
612   req = container_of(w, uv_fs_t, work_req);
613   retry_on_eintr = !(req->fs_type == UV_FS_CLOSE);
614
615   do {
616     errno = 0;
617
618 #define X(type, action)                                                       \
619   case UV_FS_ ## type:                                                        \
620     r = action;                                                               \
621     break;
622
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));
649     default: abort();
650     }
651
652 #undef X
653   }
654   while (r == -1 && errno == EINTR && retry_on_eintr);
655
656   if (r == -1)
657     req->result = -errno;
658   else
659     req->result = r;
660
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;
665   }
666 }
667
668
669 static void uv__fs_done(struct uv__work* w, int status) {
670   uv_fs_t* req;
671
672   req = container_of(w, uv_fs_t, work_req);
673   uv__req_unregister(req->loop, req);
674
675   if (status == -ECANCELED) {
676     assert(req->result == 0);
677     req->result = -ECANCELED;
678   }
679
680   if (req->cb != NULL)
681     req->cb(req);
682 }
683
684
685 int uv_fs_chmod(uv_loop_t* loop,
686                 uv_fs_t* req,
687                 const char* path,
688                 int mode,
689                 uv_fs_cb cb) {
690   INIT(CHMOD);
691   PATH;
692   req->mode = mode;
693   POST;
694 }
695
696
697 int uv_fs_chown(uv_loop_t* loop,
698                 uv_fs_t* req,
699                 const char* path,
700                 uv_uid_t uid,
701                 uv_gid_t gid,
702                 uv_fs_cb cb) {
703   INIT(CHOWN);
704   PATH;
705   req->uid = uid;
706   req->gid = gid;
707   POST;
708 }
709
710
711 int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
712   INIT(CLOSE);
713   req->file = file;
714   POST;
715 }
716
717
718 int uv_fs_fchmod(uv_loop_t* loop,
719                  uv_fs_t* req,
720                  uv_file file,
721                  int mode,
722                  uv_fs_cb cb) {
723   INIT(FCHMOD);
724   req->file = file;
725   req->mode = mode;
726   POST;
727 }
728
729
730 int uv_fs_fchown(uv_loop_t* loop,
731                  uv_fs_t* req,
732                  uv_file file,
733                  uv_uid_t uid,
734                  uv_gid_t gid,
735                  uv_fs_cb cb) {
736   INIT(FCHOWN);
737   req->file = file;
738   req->uid = uid;
739   req->gid = gid;
740   POST;
741 }
742
743
744 int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
745   INIT(FDATASYNC);
746   req->file = file;
747   POST;
748 }
749
750
751 int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
752   INIT(FSTAT);
753   req->file = file;
754   POST;
755 }
756
757
758 int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
759   INIT(FSYNC);
760   req->file = file;
761   POST;
762 }
763
764
765 int uv_fs_ftruncate(uv_loop_t* loop,
766                     uv_fs_t* req,
767                     uv_file file,
768                     int64_t off,
769                     uv_fs_cb cb) {
770   INIT(FTRUNCATE);
771   req->file = file;
772   req->off = off;
773   POST;
774 }
775
776
777 int uv_fs_futime(uv_loop_t* loop,
778                  uv_fs_t* req,
779                  uv_file file,
780                  double atime,
781                  double mtime,
782                  uv_fs_cb cb) {
783   INIT(FUTIME);
784   req->file = file;
785   req->atime = atime;
786   req->mtime = mtime;
787   POST;
788 }
789
790
791 int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
792   INIT(LSTAT);
793   PATH;
794   POST;
795 }
796
797
798 int uv_fs_link(uv_loop_t* loop,
799                uv_fs_t* req,
800                const char* path,
801                const char* new_path,
802                uv_fs_cb cb) {
803   INIT(LINK);
804   PATH2;
805   POST;
806 }
807
808
809 int uv_fs_mkdir(uv_loop_t* loop,
810                 uv_fs_t* req,
811                 const char* path,
812                 int mode,
813                 uv_fs_cb cb) {
814   INIT(MKDIR);
815   PATH;
816   req->mode = mode;
817   POST;
818 }
819
820
821 int uv_fs_open(uv_loop_t* loop,
822                uv_fs_t* req,
823                const char* path,
824                int flags,
825                int mode,
826                uv_fs_cb cb) {
827   INIT(OPEN);
828   PATH;
829   req->flags = flags;
830   req->mode = mode;
831   POST;
832 }
833
834
835 int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
836                uv_file file,
837                void* buf,
838                size_t len,
839                int64_t off,
840                uv_fs_cb cb) {
841   INIT(READ);
842   req->file = file;
843   req->buf = buf;
844   req->len = len;
845   req->off = off;
846   POST;
847 }
848
849
850 int uv_fs_readdir(uv_loop_t* loop,
851                   uv_fs_t* req,
852                   const char* path,
853                   int flags,
854                   uv_fs_cb cb) {
855   INIT(READDIR);
856   PATH;
857   req->flags = flags;
858   POST;
859 }
860
861
862 int uv_fs_readlink(uv_loop_t* loop,
863                    uv_fs_t* req,
864                    const char* path,
865                    uv_fs_cb cb) {
866   INIT(READLINK);
867   PATH;
868   POST;
869 }
870
871
872 int uv_fs_rename(uv_loop_t* loop,
873                  uv_fs_t* req,
874                  const char* path,
875                  const char* new_path,
876                  uv_fs_cb cb) {
877   INIT(RENAME);
878   PATH2;
879   POST;
880 }
881
882
883 int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
884   INIT(RMDIR);
885   PATH;
886   POST;
887 }
888
889
890 int uv_fs_sendfile(uv_loop_t* loop,
891                    uv_fs_t* req,
892                    uv_file out_fd,
893                    uv_file in_fd,
894                    int64_t off,
895                    size_t len,
896                    uv_fs_cb cb) {
897   INIT(SENDFILE);
898   req->flags = in_fd; /* hack */
899   req->file = out_fd;
900   req->off = off;
901   req->len = len;
902   POST;
903 }
904
905
906 int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
907   INIT(STAT);
908   PATH;
909   POST;
910 }
911
912
913 int uv_fs_symlink(uv_loop_t* loop,
914                   uv_fs_t* req,
915                   const char* path,
916                   const char* new_path,
917                   int flags,
918                   uv_fs_cb cb) {
919   INIT(SYMLINK);
920   PATH2;
921   req->flags = flags;
922   POST;
923 }
924
925
926 int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
927   INIT(UNLINK);
928   PATH;
929   POST;
930 }
931
932
933 int uv_fs_utime(uv_loop_t* loop,
934                 uv_fs_t* req,
935                 const char* path,
936                 double atime,
937                 double mtime,
938                 uv_fs_cb cb) {
939   INIT(UTIME);
940   PATH;
941   req->atime = atime;
942   req->mtime = mtime;
943   POST;
944 }
945
946
947 int uv_fs_write(uv_loop_t* loop,
948                 uv_fs_t* req,
949                 uv_file file,
950                 const void* buf,
951                 size_t len,
952                 int64_t off,
953                 uv_fs_cb cb) {
954   INIT(WRITE);
955   req->file = file;
956   req->buf = (void*) buf;
957   req->len = len;
958   req->off = off;
959   POST;
960 }
961
962
963 void uv_fs_req_cleanup(uv_fs_t* req) {
964   free((void*) req->path);
965   req->path = NULL;
966   req->new_path = NULL;
967
968   if (req->ptr != &req->statbuf)
969     free(req->ptr);
970   req->ptr = NULL;
971 }