|  | /* 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; | 
|  | } |