]>
git.proxmox.com Git - ceph.git/blob - ceph/src/common/safe_io.c
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2011 New Dream Network
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
15 #include "common/safe_io.h"
16 #include "include/compat.h"
24 #include <sys/socket.h>
26 ssize_t
safe_read(int fd
, void *buf
, size_t count
)
31 ssize_t r
= read(fd
, buf
, count
- cnt
);
42 buf
= (char *)buf
+ r
;
48 // "read" doesn't work with Windows sockets.
49 ssize_t
safe_recv(int fd
, void *buf
, size_t count
)
54 ssize_t r
= recv(fd
, (SOCKOPT_VAL_TYPE
)buf
, count
- cnt
, 0);
60 int err
= ceph_sock_errno();
61 if (err
== EAGAIN
|| err
== EINTR
) {
67 buf
= (char *)buf
+ r
;
72 ssize_t
safe_recv(int fd
, void *buf
, size_t count
)
74 // We'll use "safe_read" so that this can work with any type of
76 return safe_read(fd
, buf
, count
);
80 ssize_t
safe_read_exact(int fd
, void *buf
, size_t count
)
82 ssize_t ret
= safe_read(fd
, buf
, count
);
85 if ((size_t)ret
!= count
)
90 ssize_t
safe_recv_exact(int fd
, void *buf
, size_t count
)
92 ssize_t ret
= safe_recv(fd
, buf
, count
);
95 if ((size_t)ret
!= count
)
100 ssize_t
safe_write(int fd
, const void *buf
, size_t count
)
103 ssize_t r
= write(fd
, buf
, count
);
110 buf
= (char *)buf
+ r
;
116 ssize_t
safe_send(int fd
, const void *buf
, size_t count
)
119 ssize_t r
= send(fd
, (SOCKOPT_VAL_TYPE
)buf
, count
, 0);
121 int err
= ceph_sock_errno();
122 if (err
== EINTR
|| err
== EAGAIN
) {
128 buf
= (char *)buf
+ r
;
133 ssize_t
safe_send(int fd
, const void *buf
, size_t count
)
135 return safe_write(fd
, buf
, count
);
139 ssize_t
safe_pread(int fd
, void *buf
, size_t count
, off_t offset
)
142 char *b
= (char*)buf
;
144 while (cnt
< count
) {
145 ssize_t r
= pread(fd
, b
+ cnt
, count
- cnt
, offset
+ cnt
);
161 ssize_t
safe_pread_exact(int fd
, void *buf
, size_t count
, off_t offset
)
163 ssize_t ret
= safe_pread(fd
, buf
, count
, offset
);
166 if ((size_t)ret
!= count
)
171 ssize_t
safe_pwrite(int fd
, const void *buf
, size_t count
, off_t offset
)
174 ssize_t r
= pwrite(fd
, buf
, count
, offset
);
181 buf
= (char *)buf
+ r
;
187 #ifdef CEPH_HAVE_SPLICE
188 ssize_t
safe_splice(int fd_in
, off_t
*off_in
, int fd_out
, off_t
*off_out
,
189 size_t len
, unsigned int flags
)
194 ssize_t r
= splice(fd_in
, off_in
, fd_out
, off_out
, len
- cnt
, flags
);
211 ssize_t
safe_splice_exact(int fd_in
, off_t
*off_in
, int fd_out
,
212 off_t
*off_out
, size_t len
, unsigned int flags
)
214 ssize_t ret
= safe_splice(fd_in
, off_in
, fd_out
, off_out
, len
, flags
);
217 if ((size_t)ret
!= len
)
223 int safe_write_file(const char *base
, const char *file
,
224 const char *val
, size_t vallen
,
232 // does the file already have correct content?
234 ret
= safe_read_file(base
, file
, oldval
, sizeof(oldval
));
235 if (ret
== (int)vallen
&& memcmp(oldval
, val
, vallen
) == 0)
238 snprintf(fn
, sizeof(fn
), "%s/%s", base
, file
);
239 snprintf(tmp
, sizeof(tmp
), "%s/%s.tmp", base
, file
);
240 fd
= open(tmp
, O_WRONLY
|O_CREAT
|O_TRUNC
|O_BINARY
, mode
);
245 ret
= safe_write(fd
, val
, vallen
);
247 VOID_TEMP_FAILURE_RETRY(close(fd
));
252 if (ret
< 0) ret
= -errno
;
253 VOID_TEMP_FAILURE_RETRY(close(fd
));
258 ret
= rename(tmp
, fn
);
265 fd
= open(base
, O_RDONLY
|O_BINARY
);
271 if (ret
< 0) ret
= -errno
;
272 VOID_TEMP_FAILURE_RETRY(close(fd
));
277 int safe_read_file(const char *base
, const char *file
,
278 char *val
, size_t vallen
)
283 snprintf(fn
, sizeof(fn
), "%s/%s", base
, file
);
284 fd
= open(fn
, O_RDONLY
|O_BINARY
);
288 len
= safe_read(fd
, val
, vallen
);
290 VOID_TEMP_FAILURE_RETRY(close(fd
));
293 // close sometimes returns errors, but only after write()
294 VOID_TEMP_FAILURE_RETRY(close(fd
));