| /* 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 <stdio.h> |
| #include <stdlib.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <fcntl.h> |
| #include <errno.h> |
| #include <unistd.h> |
| |
| #define FAST_FUNC |
| |
| 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) |
| { |
| #ifdef ZXIC_WIN |
| int fd = open(filename, O_RDONLY | O_BINARY); |
| #else |
| int fd = open(filename, O_RDONLY); |
| #endif |
| if (fd < 0) |
| return fd; |
| return read_close(fd, buf, size); |
| } |
| |
| ssize_t FAST_FUNC safe_write(int fd, const void *buf, size_t count) |
| { |
| ssize_t n; |
| |
| for (;;) { |
| n = write(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 write(), |
| * the "error" was transient. |
| */ |
| errno = 0; |
| /* repeat the write() */ |
| } |
| |
| return n; |
| } |
| |
| ssize_t FAST_FUNC full_write(int fd, const void *buf, size_t len) |
| { |
| ssize_t cc; |
| ssize_t total; |
| |
| total = 0; |
| |
| while (len) { |
| cc = safe_write(fd, buf, len); |
| |
| if (cc < 0) { |
| if (total) { |
| /* we already wrote some! */ |
| /* user can do another write to know the error code */ |
| return total; |
| } |
| return cc; /* write() returns -1 on failure. */ |
| } |
| |
| total += cc; |
| buf = ((const char *)buf) + cc; |
| len -= cc; |
| } |
| |
| return total; |
| } |
| |
| ssize_t FAST_FUNC open_write_close(const char *filename, void *buf, size_t size) |
| { |
| ssize_t ret; |
| #ifdef ZXIC_WIN |
| int fd_to = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0640); |
| #else |
| int fd_to = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_SYNC, 0640); |
| #endif |
| |
| if(fd_to < 0) |
| return -1; |
| |
| ret = full_write(fd_to, buf, size); |
| fsync(fd_to); |
| close(fd_to); |
| |
| return ret; |
| } |