diff options
Diffstat (limited to 'libbb/xfuncs.c')
-rw-r--r-- | libbb/xfuncs.c | 85 |
1 files changed, 69 insertions, 16 deletions
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index d843414f9..8562a4fcb 100644 --- a/libbb/xfuncs.c +++ b/libbb/xfuncs.c @@ -120,40 +120,55 @@ int bb_xopen3(const char *pathname, int flags, int mode) #endif #ifdef L_xread -ssize_t bb_xread(int fd, void *buf, size_t count) + +// Die with an error message if we can't read the entire buffer. + +void xread(int fd, void *buf, size_t count) { - ssize_t size; + while (count) { + ssize_t size; - size = read(fd, buf, count); - if (size < 0) { - bb_perror_msg_and_die(bb_msg_read_error); + if ((size = safe_read(fd, buf, count)) < 1) + bb_error_msg_and_die("Short read"); + count -= size; + buf = ((char *) buf) + size; } - return(size); } #endif -#ifdef L_xread_all -void bb_xread_all(int fd, void *buf, size_t count) -{ - ssize_t size; +#ifdef L_xwrite +// Die with an error message if we can't write the entire buffer. + +void xwrite(int fd, void *buf, size_t count) +{ while (count) { - if ((size = bb_xread(fd, buf, count)) == 0) { /* EOF */ - bb_error_msg_and_die("Short read"); - } + ssize_t size; + + if ((size = safe_write(fd, buf, count)) < 1) + bb_error_msg_and_die("Short write"); count -= size; buf = ((char *) buf) + size; } - return; +} +#endif + +#ifdef L_xlseek + +// Die if we can't lseek to the right spot. + +void xlseek(int fd, off_t offset, int whence) +{ + if (whence != lseek(fd, offset, whence)) bb_error_msg_and_die("lseek"); } #endif #ifdef L_xread_char -unsigned char bb_xread_char(int fd) +unsigned char xread_char(int fd) { char tmp; - bb_xread_all(fd, &tmp, 1); + xread(fd, &tmp, 1); return(tmp); } @@ -294,3 +309,41 @@ void xsetuid(uid_t uid) if (setuid(uid)) bb_error_msg_and_die("setuid"); } #endif + +#ifdef L_fdlength +off_t fdlength(int fd) +{ + off_t bottom = 0, top = 0, pos; + long size; + + // If the ioctl works for this, return it. + + if (ioctl(fd, BLKGETSIZE, &size) >= 0) return size*512; + + // If not, do a binary search for the last location we can read. + + do { + char temp; + + pos = bottom + (top - bottom) / 2;; + + // If we can read from the current location, it's bigger. + + if (lseek(fd, pos, 0)>=0 && safe_read(fd, &temp, 1)==1) { + if (bottom == top) bottom = top = (top+1) * 2; + else bottom = pos; + + // If we can't, it's smaller. + + } else { + if (bottom == top) { + if (!top) return 0; + bottom = top/2; + } + else top = pos; + } + } while (bottom + 1 != top); + + return pos + 1; +} +#endif |