X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=src%2Fmisc.c;h=3add37188903ff2d0f194b81ec8c8ce8c3ceed8c;hb=03858cf583ce299b836d8a848967ce290a6bf303;hp=cb12947ac5aa4c3276b2a59af03c52a8d9062644;hpb=983113b140dbb540923a3112fa27e9f508ff70c5;p=chaz%2Ftar diff --git a/src/misc.c b/src/misc.c index cb12947..3add371 100644 --- a/src/misc.c +++ b/src/misc.c @@ -37,8 +37,7 @@ void assign_string (char **string, const char *value) { - if (*string) - free (*string); + free (*string); *string = value ? xstrdup (value) : 0; } @@ -617,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 @@ -856,21 +906,6 @@ file_removed_diag (const char *name, bool top_level, diagfn (name); } -void -dir_removed_diag (const char *name, bool top_level, - void (*diagfn) (char const *name)) -{ - if (!top_level && errno == ENOENT) - { - WARNOPT (WARN_FILE_REMOVED, - (0, 0, _("%s: Directory removed before we read it"), - quotearg_colon (name))); - set_exit_status (TAREXIT_DIFFERS); - } - else - diagfn (name); -} - void write_fatal_details (char const *name, ssize_t status, size_t size) {