2 * file_io.c - Helper functions for reading and writing to file descriptors.
6 * Copyright (C) 2013 Eric Biggers
8 * This file is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU Lesser General Public License as published by the Free
10 * Software Foundation; either version 3 of the License, or (at your option) any
13 * This file is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this file; if not, see http://www.gnu.org/licenses/.
26 #include "wimlib/error.h"
27 #include "wimlib/file_io.h"
28 #include "wimlib/util.h"
30 # include "wimlib/win32.h" /* For pread(), pwrite() replacements */
37 /* Wrapper around read() that checks for errors keeps retrying until all
38 * requested bytes have been read or until end-of file has occurred.
41 * WIMLIB_ERR_SUCCESS (0)
42 * WIMLIB_ERR_READ (errno set)
43 * WIMLIB_ERR_UNEXPECTED_END_OF_FILE (errno set to 0)
46 full_read(struct filedes *fd, void *buf, size_t count)
49 size_t bytes_remaining;
51 for (bytes_remaining = count;
53 bytes_remaining -= bytes_read, buf += bytes_read)
55 bytes_read = read(fd->fd, buf, bytes_remaining);
56 if (unlikely(bytes_read <= 0)) {
57 if (bytes_read == 0) {
59 return WIMLIB_ERR_UNEXPECTED_END_OF_FILE;
60 } else if (errno == EINTR) {
63 return WIMLIB_ERR_READ;
67 count -= bytes_remaining;
73 pipe_read(struct filedes *fd, void *buf, size_t count, off_t offset)
77 /* Verify the offset. */
78 if (offset < fd->offset) {
79 ERROR("Can't seek backwards in pipe "
80 "(offset %"PRIu64" => %"PRIu64").\n"
81 " Make sure the WIM was captured as "
82 "pipable.", fd->offset, offset);
84 return WIMLIB_ERR_RESOURCE_ORDER;
87 /* Manually seek to the requested position. */
88 while (fd->offset != offset) {
89 size_t bytes_to_read = min(offset - fd->offset, BUFFER_SIZE);
90 u8 dummy[bytes_to_read];
92 ret = full_read(fd, dummy, bytes_to_read);
97 /* Do the actual read. */
98 return full_read(fd, buf, count);
101 /* Wrapper around pread() that checks for errors and keeps retrying until all
102 * requested bytes have been read or until end-of file has occurred. This also
103 * transparently handle reading from pipe files, but the caller needs to be sure
104 * the requested offset is greater than or equal to the current offset, or else
105 * WIMLIB_ERR_RESOURCE_ORDER will be returned.
108 * WIMLIB_ERR_SUCCESS (0)
109 * WIMLIB_ERR_READ (errno set)
110 * WIMLIB_ERR_UNEXPECTED_END_OF_FILE (errno set to 0)
111 * WIMLIB_ERR_RESOURCE_ORDER (errno set to ESPIPE)
114 full_pread(struct filedes *fd, void *buf, size_t count, off_t offset)
117 size_t bytes_remaining;
122 for (bytes_remaining = count;
123 bytes_remaining != 0;
124 bytes_remaining -= bytes_read, buf += bytes_read,
125 offset += bytes_read)
127 bytes_read = pread(fd->fd, buf, bytes_remaining, offset);
128 if (unlikely(bytes_read <= 0)) {
129 if (bytes_read == 0) {
131 return WIMLIB_ERR_UNEXPECTED_END_OF_FILE;
132 } else if (errno == EINTR) {
134 } else if (errno == ESPIPE) {
138 return WIMLIB_ERR_READ;
145 return pipe_read(fd, buf, count, offset);
148 /* Wrapper around write() that checks for errors and keeps retrying until all
149 * requested bytes have been written.
152 * WIMLIB_ERR_SUCCESS (0)
153 * WIMLIB_ERR_WRITE (errno set)
156 full_write(struct filedes *fd, const void *buf, size_t count)
158 ssize_t bytes_written;
159 size_t bytes_remaining;
161 for (bytes_remaining = count;
162 bytes_remaining != 0;
163 bytes_remaining -= bytes_written, buf += bytes_written)
165 bytes_written = write(fd->fd, buf, bytes_remaining);
166 if (unlikely(bytes_written < 0)) {
169 return WIMLIB_ERR_WRITE;
177 /* Wrapper around pwrite() that checks for errors and keeps retrying until all
178 * requested bytes have been written.
181 * WIMLIB_ERR_SUCCESS (0)
182 * WIMLIB_ERR_WRITE (errno set)
185 full_pwrite(struct filedes *fd, const void *buf, size_t count, off_t offset)
187 ssize_t bytes_written;
188 size_t bytes_remaining;
190 for (bytes_remaining = count;
191 bytes_remaining != 0;
192 bytes_remaining -= bytes_written, buf += bytes_written,
193 offset += bytes_written)
195 bytes_written = pwrite(fd->fd, buf, bytes_remaining, offset);
196 if (unlikely(bytes_written < 0)) {
199 return WIMLIB_ERR_WRITE;
206 raw_pread(struct filedes *fd, void *buf, size_t count, off_t offset)
208 return pread(fd->fd, buf, count, offset);
212 raw_pwrite(struct filedes *fd, const void *buf, size_t count, off_t offset)
214 return pwrite(fd->fd, buf, count, offset);
217 off_t filedes_seek(struct filedes *fd, off_t offset)
223 if (fd->offset != offset) {
224 if (lseek(fd->fd, offset, SEEK_SET) == -1)
231 bool filedes_is_seekable(struct filedes *fd)
233 return !fd->is_pipe && lseek(fd->fd, 0, SEEK_CUR) != -1;