X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fmisc.c;h=3add37188903ff2d0f194b81ec8c8ce8c3ceed8c;hb=03858cf583ce299b836d8a848967ce290a6bf303;hp=b75f2ab4e419e4f9a928e75b25342630f2ad17ec;hpb=7a5a3708cb8b33494cd6ac64bfe163f631a33edf;p=chaz%2Ftar diff --git a/src/misc.c b/src/misc.c index b75f2ab..3add371 100644 --- a/src/misc.c +++ b/src/misc.c @@ -616,6 +616,57 @@ deref_stat (char const *name, struct stat *buf) return fstatat (chdir_fd, name, buf, fstatat_flags); } +/* Read from FD into the buffer BUF with COUNT bytes. Attempt to fill + BUF. Wait until input is available; this matters because files are + opened O_NONBLOCK for security reasons, and on some file systems + this can cause read to fail with errno == EAGAIN. Return the + actual number of bytes read, zero for EOF, or + SAFE_READ_ERROR upon error. */ +size_t +blocking_read (int fd, void *buf, size_t count) +{ + size_t bytes = safe_read (fd, buf, count); + +#if defined F_SETFL && O_NONBLOCK + if (bytes == SAFE_READ_ERROR && errno == EAGAIN) + { + int flags = fcntl (fd, F_GETFL); + if (0 <= flags && flags & O_NONBLOCK + && fcntl (fd, F_SETFL, flags & ~O_NONBLOCK) != -1) + bytes = safe_read (fd, buf, count); + } +#endif + + return bytes; +} + +/* Write to FD from the buffer BUF with COUNT bytes. Do a full write. + Wait until an output buffer is available; this matters because + files are opened O_NONBLOCK for security reasons, and on some file + systems this can cause write to fail with errno == EAGAIN. Return + the actual number of bytes written, setting errno if that is less + than COUNT. */ +size_t +blocking_write (int fd, void const *buf, size_t count) +{ + size_t bytes = full_write (fd, buf, count); + +#if defined F_SETFL && O_NONBLOCK + if (bytes < count && errno == EAGAIN) + { + int flags = fcntl (fd, F_GETFL); + if (0 <= flags && flags & O_NONBLOCK + && fcntl (fd, F_SETFL, flags & ~O_NONBLOCK) != -1) + { + char const *buffer = buf; + bytes += full_write (fd, buffer + bytes, count - bytes); + } + } +#endif + + return bytes; +} + /* Set FD's (i.e., assuming the working directory is PARENTFD, FILE's) access time to ATIME. */ int