X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fmisc.c;h=734dc4eded7adcac4f7a29d84111a0d49306cfb4;hb=2a61a3701f1fa04e83a2a39013ab56530a44b777;hp=adc9298689caaef63a4777787e41b8049f44e544;hpb=50a57a014748f196dede7e677b509f6a7ec4f486;p=chaz%2Ftar diff --git a/src/misc.c b/src/misc.c index adc9298..734dc4e 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; } @@ -106,7 +105,7 @@ quote_copy_string (const char *string) completes the unquoting anyway. This is used for reading the saved directory file in incremental - dumps. It is used for decoding old `N' records (demangling names). + dumps. It is used for decoding old 'N' records (demangling names). But also, it is used for decoding file arguments, would they come from the shell or a -T file, and for decoding the --exclude argument. */ @@ -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 @@ -663,7 +713,7 @@ static int wdcache[CHDIR_CACHE_SIZE]; static size_t wdcache_count; int -chdir_count () +chdir_count (void) { if (wd_count == 0) return wd_count; @@ -764,11 +814,11 @@ chdir_do (int i) int prev = wdcache[0]; for (ci = 1; prev != i; ci++) { - int curr = wdcache[ci]; + int cur = wdcache[ci]; wdcache[ci] = prev; - if (curr == i) + if (cur == i) break; - prev = curr; + prev = cur; } wdcache[0] = i; } @@ -912,7 +962,7 @@ page_aligned_alloc (void **ptr, size_t size) struct namebuf { - char *buffer; /* directory, `/', and directory member */ + char *buffer; /* directory, '/', and directory member */ size_t buffer_size; /* allocated size of name_buffer */ size_t dir_length; /* length of directory part in buffer */ };