tests/krb5/kdc_base_test.py: Remove 'credentials' class attribute
[Samba.git] / lib / util / sys_rw.c
blobd74395fc409143fbc5a2cc3e2d0bb4e6a1100d3f
1 /*
2 * Unix SMB/CIFS implementation.
3 * Samba system utilities
4 * Copyright (C) Andrew Tridgell 1992-1998
5 * Copyright (C) Jeremy Allison 1998-2005
6 * Copyright (C) Timur Bakeyev 2005
7 * Copyright (C) Bjoern Jacke 2006-2007
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "replace.h"
24 #include "system/filesys.h"
25 #include "lib/util/sys_rw.h"
27 bool sys_valid_io_range(off_t offset, size_t length)
29 uint64_t last_byte_ofs;
31 if (offset < 0) {
32 return false;
35 if (offset > INT64_MAX) {
36 return false;
39 if (length > UINT32_MAX) {
40 return false;
43 last_byte_ofs = (uint64_t)offset + (uint64_t)length;
44 if (last_byte_ofs > INT64_MAX) {
45 return false;
48 return true;
51 /*******************************************************************
52 A read wrapper that will deal with EINTR/EWOULDBLOCK
53 ********************************************************************/
55 ssize_t sys_read(int fd, void *buf, size_t count)
57 ssize_t ret;
59 do {
60 ret = read(fd, buf, count);
61 } while (ret == -1 && (errno == EINTR || errno == EAGAIN ||
62 errno == EWOULDBLOCK));
64 return ret;
67 /**
68 * read wrapper, void variant:
69 * This is intended to be used as a void variant of
70 * read in situations where the caller wants to ignore
71 * the result. Hence not checking for EAGAIN|EWOULDBLOCK.
73 void sys_read_v(int fd, void *buf, size_t count)
75 ssize_t ret;
77 do {
78 ret = read(fd, buf, count);
79 } while (ret == -1 && errno == EINTR);
83 /*******************************************************************
84 A write wrapper that will deal with EINTR/EWOULDBLOCK.
85 ********************************************************************/
87 ssize_t sys_write(int fd, const void *buf, size_t count)
89 ssize_t ret;
91 do {
92 ret = write(fd, buf, count);
93 } while (ret == -1 && (errno == EINTR || errno == EAGAIN ||
94 errno == EWOULDBLOCK));
96 return ret;
99 /**
100 * write wrapper to deal with EINTR and friends.
101 * void-variant that ignores the number of bytes written.
102 * This is intended to be used as a void variant of
103 * write in situations where the caller wants to ignore
104 * the result. Hence not checking for EAGAIN|EWOULDBLOCK.
106 void sys_write_v(int fd, const void *buf, size_t count)
108 ssize_t ret;
110 do {
111 ret = write(fd, buf, count);
112 } while (ret == -1 && errno == EINTR);
116 /*******************************************************************
117 A writev wrapper that will deal with EINTR.
118 ********************************************************************/
120 ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt)
122 ssize_t ret;
124 do {
125 ret = writev(fd, iov, iovcnt);
126 } while (ret == -1 && (errno == EINTR || errno == EAGAIN ||
127 errno == EWOULDBLOCK));
129 return ret;
132 /*******************************************************************
133 A pread wrapper that will deal with EINTR
134 ********************************************************************/
136 ssize_t sys_pread(int fd, void *buf, size_t count, off_t off)
138 ssize_t ret;
140 do {
141 ret = pread(fd, buf, count, off);
142 } while (ret == -1 && errno == EINTR);
143 return ret;
146 /*******************************************************************
147 A pread wrapper that will deal with EINTR and never return a short
148 read unless pread returns zero meaning EOF.
149 ********************************************************************/
151 ssize_t sys_pread_full(int fd, void *buf, size_t count, off_t off)
153 ssize_t total_read = 0;
154 uint8_t *curr_buf = (uint8_t *)buf;
155 size_t curr_count = count;
156 off_t curr_off = off;
157 bool ok;
159 ok = sys_valid_io_range(off, count);
160 if (!ok) {
161 errno = EINVAL;
162 return -1;
165 while (curr_count != 0) {
166 ssize_t ret = sys_pread(fd,
167 curr_buf,
168 curr_count,
169 curr_off);
171 if (ret == -1) {
172 return -1;
174 if (ret == 0) {
175 /* EOF */
176 break;
179 if (ret > curr_count) {
180 errno = EIO;
181 return -1;
184 curr_buf += ret;
185 curr_count -= ret;
186 curr_off += ret;
188 total_read += ret;
191 return total_read;
194 /*******************************************************************
195 A write wrapper that will deal with EINTR
196 ********************************************************************/
198 ssize_t sys_pwrite(int fd, const void *buf, size_t count, off_t off)
200 ssize_t ret;
202 do {
203 ret = pwrite(fd, buf, count, off);
204 } while (ret == -1 && errno == EINTR);
205 return ret;
208 /*******************************************************************
209 A pwrite wrapper that will deal with EINTR and never allow a short
210 write unless the file system returns an error.
211 ********************************************************************/
213 ssize_t sys_pwrite_full(int fd, const void *buf, size_t count, off_t off)
215 ssize_t total_written = 0;
216 const uint8_t *curr_buf = (const uint8_t *)buf;
217 size_t curr_count = count;
218 off_t curr_off = off;
219 bool ok;
221 ok = sys_valid_io_range(off, count);
222 if (!ok) {
223 errno = EINVAL;
224 return -1;
227 while (curr_count != 0) {
228 ssize_t ret = sys_pwrite(fd,
229 curr_buf,
230 curr_count,
231 curr_off);
233 if (ret == -1) {
234 return -1;
236 if (ret == 0) {
237 /* Ensure we can never spin. */
238 errno = ENOSPC;
239 return -1;
242 if (ret > curr_count) {
243 errno = EIO;
244 return -1;
247 curr_buf += ret;
248 curr_count -= ret;
249 curr_off += ret;
251 total_written += ret;
254 return total_written;