(root)/
util-linux-2.39/
include/
all-io.h
       1  /*
       2   * No copyright is claimed.  This code is in the public domain; do with
       3   * it what you wish.
       4   *
       5   * Written by Karel Zak <kzak@redhat.com>
       6   *            Petr Uzel <petr.uzel@suse.cz>
       7   */
       8  
       9  #ifndef UTIL_LINUX_ALL_IO_H
      10  #define UTIL_LINUX_ALL_IO_H
      11  
      12  #include <string.h>
      13  #include <unistd.h>
      14  #include <errno.h>
      15  #include <sys/types.h>
      16  #ifdef HAVE_SYS_SENDFILE_H
      17  # include <sys/sendfile.h>
      18  #endif
      19  
      20  #include "c.h"
      21  
      22  static inline int write_all(int fd, const void *buf, size_t count)
      23  {
      24  	while (count) {
      25  		ssize_t tmp;
      26  
      27  		errno = 0;
      28  		tmp = write(fd, buf, count);
      29  		if (tmp > 0) {
      30  			count -= tmp;
      31  			if (count)
      32  				buf = (const void *) ((const char *) buf + tmp);
      33  		} else if (errno != EINTR && errno != EAGAIN)
      34  			return -1;
      35  		if (errno == EAGAIN)	/* Try later, *sigh* */
      36  			xusleep(250000);
      37  	}
      38  	return 0;
      39  }
      40  
      41  static inline int fwrite_all(const void *ptr, size_t size,
      42  			     size_t nmemb, FILE *stream)
      43  {
      44  	while (nmemb) {
      45  		size_t tmp;
      46  
      47  		errno = 0;
      48  		tmp = fwrite(ptr, size, nmemb, stream);
      49  		if (tmp > 0) {
      50  			nmemb -= tmp;
      51  			if (nmemb)
      52  				ptr = (const void *) ((const char *) ptr + (tmp * size));
      53  		} else if (errno != EINTR && errno != EAGAIN)
      54  			return -1;
      55  		if (errno == EAGAIN)	/* Try later, *sigh* */
      56  			xusleep(250000);
      57  	}
      58  	return 0;
      59  }
      60  
      61  static inline ssize_t read_all(int fd, char *buf, size_t count)
      62  {
      63  	ssize_t ret;
      64  	ssize_t c = 0;
      65  	int tries = 0;
      66  
      67  	memset(buf, 0, count);
      68  	while (count > 0) {
      69  		ret = read(fd, buf, count);
      70  		if (ret < 0) {
      71  			if ((errno == EAGAIN || errno == EINTR) && (tries++ < 5)) {
      72  				xusleep(250000);
      73  				continue;
      74  			}
      75  			return c ? c : -1;
      76  		}
      77  		if (ret == 0)
      78  			return c;
      79  		tries = 0;
      80  		count -= ret;
      81  		buf += ret;
      82  		c += ret;
      83  	}
      84  	return c;
      85  }
      86  
      87  static inline ssize_t read_all_alloc(int fd, char **buf)
      88  {
      89  	size_t size = 1024, c = 0;
      90  	ssize_t ret;
      91  
      92  	*buf = malloc(size);
      93  	if (!*buf)
      94  		return -1;
      95  
      96  	while (1) {
      97  		ret = read_all(fd, *buf + c, size - c);
      98  		if (ret < 0) {
      99  			free(*buf);
     100  			*buf = NULL;
     101  			return -1;
     102  		}
     103  
     104  		if (ret == 0)
     105  			return c;
     106  
     107  		c += ret;
     108  		if (c == size) {
     109  			size *= 2;
     110  			*buf = realloc(*buf, size);
     111  			if (!*buf)
     112  				return -1;
     113  		}
     114  	}
     115  }
     116  
     117  static inline ssize_t sendfile_all(int out, int in, off_t *off, size_t count)
     118  {
     119  #if defined(HAVE_SENDFILE) && defined(__linux__)
     120  	ssize_t ret;
     121  	ssize_t c = 0;
     122  	int tries = 0;
     123  	while (count) {
     124  		ret = sendfile(out, in, off, count);
     125  		if (ret < 0) {
     126  			if ((errno == EAGAIN || errno == EINTR) && (tries++ < 5)) {
     127  				xusleep(250000);
     128  				continue;
     129  			}
     130  			return c ? c : -1;
     131  		}
     132  		if (ret == 0)
     133  			return c;
     134  		tries = 0;
     135  		count -= ret;
     136  		c += ret;
     137  	}
     138  	return c;
     139  #else
     140  	errno = ENOSYS;
     141  	return -1;
     142  #endif
     143  }
     144  #endif /* UTIL_LINUX_ALL_IO_H */