for systems with a broken select use u_sleep() to ensure the write
[rsync/rsync.git] / util.c
CommitLineData
c627d613
AT
1/*
2 Copyright (C) Andrew Tridgell 1996
3 Copyright (C) Paul Mackerras 1996
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18*/
19
20/*
21 Utilities used in rsync
22
23 tridge, June 1996
24 */
25#include "rsync.h"
26
720b47f2 27int num_waiting(int fd)
94481d91
AT
28{
29 int len=0;
94481d91 30 ioctl(fd,FIONREAD,&len);
94481d91
AT
31 return(len);
32}
33
d9bea2dd 34
c6e7fcb4 35struct map_struct *map_file(int fd,off_t len)
c627d613 36{
c6e7fcb4
AT
37 struct map_struct *ret;
38 ret = (struct map_struct *)malloc(sizeof(*ret));
39 if (!ret) out_of_memory("map_file");
40
41 ret->map = NULL;
42 ret->fd = fd;
43 ret->size = len;
44 ret->p = NULL;
45 ret->p_size = 0;
46 ret->p_offset = 0;
47 ret->p_len = 0;
48
d9bea2dd
AT
49#ifdef HAVE_MMAP
50 if (len < MAX_MAP_SIZE)
c6e7fcb4 51 ret->map = (char *)mmap(NULL,len,PROT_READ,MAP_SHARED,fd,0);
d9bea2dd 52#endif
c627d613
AT
53 return ret;
54}
55
c6e7fcb4 56char *map_ptr(struct map_struct *map,off_t offset,int len)
d9bea2dd 57{
0cfcfa29
AT
58 int nread = -2;
59
c6e7fcb4
AT
60 if (map->map)
61 return map->map+offset;
d9bea2dd
AT
62
63 if (len == 0)
64 return NULL;
65
c6e7fcb4 66 len = MIN(len,map->size-offset);
d9bea2dd 67
c6e7fcb4
AT
68 if (offset >= map->p_offset &&
69 offset+len <= map->p_offset+map->p_len) {
70 return (map->p + (offset - map->p_offset));
d9bea2dd
AT
71 }
72
34ccb63e 73 len = MAX(len,CHUNK_SIZE);
c6e7fcb4 74 len = MIN(len,map->size - offset);
d9bea2dd 75
c6e7fcb4
AT
76 if (len > map->p_size) {
77 if (map->p) free(map->p);
78 map->p = (char *)malloc(len);
79 if (!map->p) out_of_memory("map_ptr");
80 map->p_size = len;
d9bea2dd
AT
81 }
82
c6e7fcb4 83 if (lseek(map->fd,offset,SEEK_SET) != offset ||
0cfcfa29 84 (nread=read(map->fd,map->p,len)) != len) {
feaa89c4
AT
85 fprintf(FERROR,"EOF in map_ptr! (offset=%d len=%d nread=%d errno=%d)\n",
86 (int)offset, len, nread, errno);
87 exit_cleanup(1);
d9bea2dd
AT
88 }
89
c6e7fcb4
AT
90 map->p_offset = offset;
91 map->p_len = len;
d9bea2dd 92
c6e7fcb4 93 return map->p;
d9bea2dd
AT
94}
95
96
c6e7fcb4 97void unmap_file(struct map_struct *map)
c627d613 98{
7bec6a5c 99#ifdef HAVE_MMAP
c6e7fcb4
AT
100 if (map->map)
101 munmap(map->map,map->size);
7bec6a5c 102#endif
c6e7fcb4
AT
103 if (map->p) free(map->p);
104 free(map);
c627d613
AT
105}
106
107
c627d613
AT
108/* this is taken from CVS */
109int piped_child(char **command,int *f_in,int *f_out)
110{
111 int pid;
112 int to_child_pipe[2];
113 int from_child_pipe[2];
114
115 if (pipe(to_child_pipe) < 0 ||
116 pipe(from_child_pipe) < 0) {
dc5ddbcc 117 fprintf(FERROR,"pipe: %s\n",strerror(errno));
34ccb63e 118 exit_cleanup(1);
c627d613
AT
119 }
120
121
122 pid = fork();
123 if (pid < 0) {
dc5ddbcc 124 fprintf(FERROR,"fork: %s\n",strerror(errno));
34ccb63e 125 exit_cleanup(1);
c627d613
AT
126 }
127
128 if (pid == 0)
129 {
6574b4f7 130 extern int orig_umask;
c627d613
AT
131 if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
132 close(to_child_pipe[1]) < 0 ||
133 close(from_child_pipe[0]) < 0 ||
134 dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
dc5ddbcc 135 fprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
34ccb63e 136 exit_cleanup(1);
c627d613 137 }
773f2bd4
AT
138 if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
139 if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
6574b4f7 140 umask(orig_umask);
c627d613 141 execvp(command[0], command);
dc5ddbcc 142 fprintf(FERROR,"Failed to exec %s : %s\n",
c627d613 143 command[0],strerror(errno));
34ccb63e 144 exit_cleanup(1);
c627d613
AT
145 }
146
147 if (close(from_child_pipe[1]) < 0 ||
148 close(to_child_pipe[0]) < 0) {
dc5ddbcc 149 fprintf(FERROR,"Failed to close : %s\n",strerror(errno));
34ccb63e 150 exit_cleanup(1);
c627d613
AT
151 }
152
153 *f_in = from_child_pipe[0];
154 *f_out = to_child_pipe[1];
155
156 return pid;
157}
158
159
160void out_of_memory(char *str)
161{
dc5ddbcc 162 fprintf(FERROR,"out of memory in %s\n",str);
34ccb63e 163 exit_cleanup(1);
c627d613
AT
164}
165
166
c627d613
AT
167
168int set_modtime(char *fname,time_t modtime)
169{
1e9f155a 170#ifdef HAVE_UTIMBUF
c627d613
AT
171 struct utimbuf tbuf;
172 tbuf.actime = time(NULL);
173 tbuf.modtime = modtime;
174 return utime(fname,&tbuf);
175#elif defined(HAVE_UTIME)
176 time_t t[2];
177 t[0] = time(NULL);
178 t[1] = modtime;
179 return utime(fname,t);
180#else
181 struct timeval t[2];
182 t[0].tv_sec = time(NULL);
183 t[0].tv_usec = 0;
184 t[1].tv_sec = modtime;
185 t[1].tv_usec = 0;
186 return utimes(fname,t);
187#endif
188}
94481d91 189
720b47f2
AT
190
191
192/****************************************************************************
193Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
194else
195if SYSV use O_NDELAY
196if BSD use FNDELAY
197****************************************************************************/
198int set_blocking(int fd, int set)
199{
200 int val;
201#ifdef O_NONBLOCK
202#define FLAG_TO_SET O_NONBLOCK
203#else
204#ifdef SYSV
205#define FLAG_TO_SET O_NDELAY
206#else /* BSD */
207#define FLAG_TO_SET FNDELAY
208#endif
209#endif
210
211 if((val = fcntl(fd, F_GETFL, 0)) == -1)
212 return -1;
213 if(set) /* Turn blocking on - ie. clear nonblock flag */
214 val &= ~FLAG_TO_SET;
215 else
216 val |= FLAG_TO_SET;
217 return fcntl( fd, F_SETFL, val);
218#undef FLAG_TO_SET
219}
6574b4f7
AT
220
221/****************************************************************************
222create any necessary directories in fname. Unfortunately we don't know
223what perms to give the directory when this is called so we need to rely
224on the umask
225****************************************************************************/
226int create_directory_path(char *fname)
227{
228 extern int orig_umask;
229 char *p;
230
231 while (*fname == '/') fname++;
232 while (strncmp(fname,"./",2)==0) fname += 2;
233
234 p = fname;
235 while ((p=strchr(p,'/'))) {
236 *p = 0;
237 mkdir(fname,0777 & ~orig_umask);
238 *p = '/';
239 p++;
240 }
241 return 0;
242}
950ab32d
AT
243
244
245/* Write LEN bytes at PTR to descriptor DESC, retrying if interrupted.
246 Return LEN upon success, write's (negative) error code otherwise.
247
248 derived from GNU C's cccp.c.
249*/
250int full_write(int desc, char *ptr, int len)
251{
252 int total_written;
253
254 total_written = 0;
255 while (len > 0) {
256 int written = write (desc, ptr, len);
257 if (written < 0) {
258#ifdef EINTR
259 if (errno == EINTR)
260 continue;
261#endif
262 return written;
263 }
264 total_written += written;
265 ptr += written;
266 len -= written;
267 }
268 return total_written;
269}
270
271/* Read LEN bytes at PTR from descriptor DESC, retrying if interrupted.
272 Return the actual number of bytes read, zero for EOF, or negative
273 for an error.
274
275 derived from GNU C's cccp.c. */
276int safe_read(int desc, char *ptr, int len)
277{
278 int n_chars;
279
280 if (len <= 0)
281 return len;
282
283#ifdef EINTR
284 do {
285 n_chars = read(desc, ptr, len);
286 } while (n_chars < 0 && errno == EINTR);
287#else
288 n_chars = read(desc, ptr, len);
289#endif
290
291 return n_chars;
292}
293
294
295/* copy a file - this is used in conjunction with the --temp-dir option */
296int copy_file(char *source, char *dest, mode_t mode)
297{
298 int ifd;
299 int ofd;
300 char buf[1024 * 8];
301 int len; /* Number of bytes read into `buf'. */
302
303 ifd = open(source, O_RDONLY);
304 if (ifd == -1) {
305 fprintf(FERROR,"open %s: %s\n",
306 source,strerror(errno));
307 return -1;
308 }
309
310 if (unlink(dest) && errno != ENOENT) {
311 fprintf(FERROR,"unlink %s: %s\n",
312 dest,strerror(errno));
313 return -1;
314 }
315
316 ofd = open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode);
317 if (ofd < 0) {
318 fprintf(FERROR,"open %s: %s\n",
319 dest,strerror(errno));
320 close(ifd);
321 return -1;
322 }
323
324 while ((len = safe_read(ifd, buf, sizeof(buf))) > 0) {
325 if (full_write(ofd, buf, len) < 0) {
326 fprintf(FERROR,"write %s: %s\n",
327 dest,strerror(errno));
328 close(ifd);
329 close(ofd);
330 return -1;
331 }
332 }
333
334 close(ifd);
335 close(ofd);
336
337 if (len < 0) {
338 fprintf(FERROR,"read %s: %s\n",
339 source,strerror(errno));
340 return -1;
341 }
342
343 return 0;
344}
feaa89c4
AT
345
346/* sleep for a while via select */
347void u_sleep(int usec)
348{
349 struct timeval tv;
350
351 tv.tv_sec = 0;
352 tv.tv_usec = usec;
353 select(0, NULL, NULL, NULL, &tv);
354}