| /* vi: set sw=4 ts=4: */ |
| /* |
| * Utility routines. |
| * |
| * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> |
| * |
| * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
| */ |
| #include "libbb.h" |
| |
| ssize_t FAST_FUNC safe_read(int fd, void *buf, size_t count) |
| { |
| ssize_t n; |
| |
| for (;;) { |
| n = read(fd, buf, count); |
| if (n >= 0 || errno != EINTR) |
| break; |
| /* Some callers set errno=0, are upset when they see EINTR. |
| * Returning EINTR is wrong since we retry read(), |
| * the "error" was transient. |
| */ |
| errno = 0; |
| /* repeat the read() */ |
| } |
| |
| return n; |
| } |
| |
| /* |
| * Read all of the supplied buffer from a file. |
| * This does multiple reads as necessary. |
| * Returns the amount read, or -1 on an error. |
| * A short read is returned on an end of file. |
| */ |
| ssize_t FAST_FUNC full_read(int fd, void *buf, size_t len) |
| { |
| ssize_t cc; |
| ssize_t total; |
| |
| total = 0; |
| |
| while (len) { |
| cc = safe_read(fd, buf, len); |
| |
| if (cc < 0) { |
| if (total) { |
| /* we already have some! */ |
| /* user can do another read to know the error code */ |
| return total; |
| } |
| return cc; /* read() returns -1 on failure. */ |
| } |
| if (cc == 0) |
| break; |
| buf = ((char *)buf) + cc; |
| total += cc; |
| len -= cc; |
| } |
| |
| return total; |
| } |
| |
| ssize_t FAST_FUNC read_close(int fd, void *buf, size_t size) |
| { |
| /*int e;*/ |
| size = full_read(fd, buf, size); |
| /*e = errno;*/ |
| close(fd); |
| /*errno = e;*/ |
| return size; |
| } |
| |
| ssize_t FAST_FUNC open_read_close(const char *filename, void *buf, size_t size) |
| { |
| int fd = open(filename, O_RDONLY); |
| if (fd < 0) |
| return fd; |
| return read_close(fd, buf, size); |
| } |