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