]> wimlib.net Git - wimlib/blob - src/file_io.c
imagex_update(): Error if no image specified with multi-image WIM
[wimlib] / src / file_io.c
1 /*
2  * file_io.c - Helper functions for reading and writing to file descriptors.
3  */
4
5 /*
6  * Copyright (C) 2013 Eric Biggers
7  *
8  * This file is part of wimlib, a library for working with WIM files.
9  *
10  * wimlib is free software; you can redistribute it and/or modify it under the
11  * terms of the GNU General Public License as published by the Free
12  * Software Foundation; either version 3 of the License, or (at your option)
13  * any later version.
14  *
15  * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY
16  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
17  * A PARTICULAR PURPOSE. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with wimlib; if not, see http://www.gnu.org/licenses/.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #  include "config.h"
26 #endif
27
28 #include "wimlib/file_io.h"
29 #ifdef __WIN32__
30 #  include "wimlib/win32.h" /* For pread(), pwrite() replacements */
31 #else
32 #  include <sys/uio.h> /* for writev() and `struct iovec' */
33 #endif
34
35 #include <errno.h>
36 #include <unistd.h>
37
38
39 /* Like read(), but keep trying until everything has been written or we know for
40  * sure that there was an error (or end-of-file). */
41 size_t
42 full_read(int fd, void *buf, size_t count)
43 {
44         ssize_t bytes_read;
45         size_t bytes_remaining;
46
47         for (bytes_remaining = count;
48              bytes_remaining != 0;
49              bytes_remaining -= bytes_read, buf += bytes_read)
50         {
51                 bytes_read = read(fd, buf, bytes_remaining);
52                 if (bytes_read <= 0) {
53                         if (bytes_read == 0)
54                                 errno = EIO;
55                         else if (errno == EINTR)
56                                 continue;
57                         break;
58                 }
59         }
60         return count - bytes_remaining;
61 }
62
63 /* Like write(), but keep trying until everything has been written or we know
64  * for sure that there was an error. */
65 size_t
66 full_write(int fd, const void *buf, size_t count)
67 {
68         ssize_t bytes_written;
69         size_t bytes_remaining;
70
71         for (bytes_remaining = count;
72              bytes_remaining != 0;
73              bytes_remaining -= bytes_written, buf += bytes_written)
74         {
75                 bytes_written = write(fd, buf, bytes_remaining);
76                 if (bytes_written < 0) {
77                         if (errno == EINTR)
78                                 continue;
79                         break;
80                 }
81         }
82         return count - bytes_remaining;
83 }
84
85 /* Like pread(), but keep trying until everything has been read or we know for
86  * sure that there was an error (or end-of-file) */
87 size_t
88 full_pread(int fd, void *buf, size_t count, off_t offset)
89 {
90         ssize_t bytes_read;
91         size_t bytes_remaining;
92
93         for (bytes_remaining = count;
94              bytes_remaining != 0;
95              bytes_remaining -= bytes_read, buf += bytes_read,
96                 offset += bytes_read)
97         {
98                 bytes_read = pread(fd, buf, bytes_remaining, offset);
99                 if (bytes_read <= 0) {
100                         if (bytes_read == 0)
101                                 errno = EIO;
102                         else if (errno == EINTR)
103                                 continue;
104                         break;
105                 }
106         }
107         return count - bytes_remaining;
108 }
109
110 /* Like pwrite(), but keep trying until everything has been written or we know
111  * for sure that there was an error. */
112 size_t
113 full_pwrite(int fd, const void *buf, size_t count, off_t offset)
114 {
115         ssize_t bytes_written;
116         size_t bytes_remaining;
117
118         for (bytes_remaining = count;
119              bytes_remaining != 0;
120              bytes_remaining -= bytes_written, buf += bytes_written,
121                 offset += bytes_written)
122         {
123                 bytes_written = pwrite(fd, buf, bytes_remaining, offset);
124                 if (bytes_written < 0) {
125                         if (errno == EINTR)
126                                 continue;
127                         break;
128                 }
129         }
130         return count - bytes_remaining;
131 }
132
133 /* Like writev(), but keep trying until everything has been written or we know
134  * for sure that there was an error. */
135 size_t
136 full_writev(int fd, struct iovec *iov, int iovcnt)
137 {
138         size_t total_bytes_written = 0;
139         while (iovcnt > 0) {
140                 ssize_t bytes_written;
141
142                 bytes_written = writev(fd, iov, iovcnt);
143                 if (bytes_written < 0) {
144                         if (errno == EINTR)
145                                 continue;
146                         break;
147                 }
148                 total_bytes_written += bytes_written;
149                 while (bytes_written) {
150                         if (bytes_written >= iov[0].iov_len) {
151                                 bytes_written -= iov[0].iov_len;
152                                 iov++;
153                                 iovcnt--;
154                         } else {
155                                 iov[0].iov_base += bytes_written;
156                                 iov[0].iov_len -= bytes_written;
157                                 bytes_written = 0;
158                         }
159                 }
160         }
161         return total_bytes_written;
162 }
163
164 off_t
165 filedes_offset(int fd)
166 {
167         return lseek(fd, 0, SEEK_CUR);
168 }