save another couple of round trip latencies. This set of changes is
[rsync/rsync.git] / util.c
... / ...
CommitLineData
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
27int num_waiting(int fd)
28{
29 int len=0;
30 ioctl(fd,FIONREAD,&len);
31 return(len);
32}
33
34
35struct map_struct *map_file(int fd,OFF_T len)
36{
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
49#ifdef HAVE_MMAP
50 if (len < MAX_MAP_SIZE) {
51 ret->map = (char *)mmap(NULL,len,PROT_READ,MAP_SHARED,fd,0);
52 if (ret->map == (char *)-1) {
53 ret->map = NULL;
54 }
55 }
56#endif
57 return ret;
58}
59
60
61char *map_ptr(struct map_struct *map,OFF_T offset,int len)
62{
63 int nread = -2;
64
65 if (map->map)
66 return map->map+offset;
67
68 if (len == 0)
69 return NULL;
70
71 if (len > (map->size-offset))
72 len = map->size-offset;
73
74 if (offset >= map->p_offset &&
75 offset+len <= map->p_offset+map->p_len) {
76 return (map->p + (offset - map->p_offset));
77 }
78
79 len = MAX(len,CHUNK_SIZE);
80 if (len > (map->size-offset))
81 len = map->size-offset;
82
83 if (len > map->p_size) {
84 if (map->p) free(map->p);
85 map->p = (char *)malloc(len);
86 if (!map->p) out_of_memory("map_ptr");
87 map->p_size = len;
88 }
89
90 if (do_lseek(map->fd,offset,SEEK_SET) != offset ||
91 (nread=read(map->fd,map->p,len)) != len) {
92 rprintf(FERROR,"EOF in map_ptr! (offset=%d len=%d nread=%d errno=%d)\n",
93 (int)offset, len, nread, errno);
94 exit_cleanup(1);
95 }
96
97 map->p_offset = offset;
98 map->p_len = len;
99
100 return map->p;
101}
102
103
104void unmap_file(struct map_struct *map)
105{
106#ifdef HAVE_MMAP
107 if (map->map)
108 munmap(map->map,map->size);
109#endif
110 if (map->p) free(map->p);
111 free(map);
112}
113
114
115/* this is taken from CVS */
116int piped_child(char **command,int *f_in,int *f_out)
117{
118 int pid;
119 int to_child_pipe[2];
120 int from_child_pipe[2];
121
122 if (pipe(to_child_pipe) < 0 ||
123 pipe(from_child_pipe) < 0) {
124 rprintf(FERROR,"pipe: %s\n",strerror(errno));
125 exit_cleanup(1);
126 }
127
128
129 pid = do_fork();
130 if (pid < 0) {
131 rprintf(FERROR,"fork: %s\n",strerror(errno));
132 exit_cleanup(1);
133 }
134
135 if (pid == 0)
136 {
137 extern int orig_umask;
138 if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
139 close(to_child_pipe[1]) < 0 ||
140 close(from_child_pipe[0]) < 0 ||
141 dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
142 rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
143 exit_cleanup(1);
144 }
145 if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
146 if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
147 umask(orig_umask);
148 execvp(command[0], command);
149 rprintf(FERROR,"Failed to exec %s : %s\n",
150 command[0],strerror(errno));
151 exit_cleanup(1);
152 }
153
154 if (close(from_child_pipe[1]) < 0 ||
155 close(to_child_pipe[0]) < 0) {
156 rprintf(FERROR,"Failed to close : %s\n",strerror(errno));
157 exit_cleanup(1);
158 }
159
160 *f_in = from_child_pipe[0];
161 *f_out = to_child_pipe[1];
162
163 return pid;
164}
165
166int local_child(int argc, char **argv,int *f_in,int *f_out)
167{
168 int pid;
169 int to_child_pipe[2];
170 int from_child_pipe[2];
171
172 if (pipe(to_child_pipe) < 0 ||
173 pipe(from_child_pipe) < 0) {
174 rprintf(FERROR,"pipe: %s\n",strerror(errno));
175 exit_cleanup(1);
176 }
177
178
179 pid = do_fork();
180 if (pid < 0) {
181 rprintf(FERROR,"fork: %s\n",strerror(errno));
182 exit_cleanup(1);
183 }
184
185 if (pid == 0) {
186 extern int am_sender;
187 extern int am_server;
188
189 am_sender = !am_sender;
190 am_server = 1;
191
192 if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
193 close(to_child_pipe[1]) < 0 ||
194 close(from_child_pipe[0]) < 0 ||
195 dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
196 rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
197 exit_cleanup(1);
198 }
199 if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
200 if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
201 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
202 }
203
204 if (close(from_child_pipe[1]) < 0 ||
205 close(to_child_pipe[0]) < 0) {
206 rprintf(FERROR,"Failed to close : %s\n",strerror(errno));
207 exit_cleanup(1);
208 }
209
210 *f_in = from_child_pipe[0];
211 *f_out = to_child_pipe[1];
212
213 return pid;
214}
215
216
217
218void out_of_memory(char *str)
219{
220 rprintf(FERROR,"ERROR: out of memory in %s\n",str);
221 exit_cleanup(1);
222}
223
224void overflow(char *str)
225{
226 rprintf(FERROR,"ERROR: buffer overflow in %s\n",str);
227 exit_cleanup(1);
228}
229
230
231
232int set_modtime(char *fname,time_t modtime)
233{
234 extern int dry_run;
235 if (dry_run) return 0;
236 {
237#ifdef HAVE_UTIMBUF
238 struct utimbuf tbuf;
239 tbuf.actime = time(NULL);
240 tbuf.modtime = modtime;
241 return utime(fname,&tbuf);
242#elif defined(HAVE_UTIME)
243 time_t t[2];
244 t[0] = time(NULL);
245 t[1] = modtime;
246 return utime(fname,t);
247#else
248 struct timeval t[2];
249 t[0].tv_sec = time(NULL);
250 t[0].tv_usec = 0;
251 t[1].tv_sec = modtime;
252 t[1].tv_usec = 0;
253 return utimes(fname,t);
254#endif
255 }
256}
257
258
259
260/****************************************************************************
261Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
262else
263if SYSV use O_NDELAY
264if BSD use FNDELAY
265****************************************************************************/
266int set_blocking(int fd, int set)
267{
268 int val;
269#ifdef O_NONBLOCK
270#define FLAG_TO_SET O_NONBLOCK
271#else
272#ifdef SYSV
273#define FLAG_TO_SET O_NDELAY
274#else /* BSD */
275#define FLAG_TO_SET FNDELAY
276#endif
277#endif
278
279 if((val = fcntl(fd, F_GETFL, 0)) == -1)
280 return -1;
281 if(set) /* Turn blocking on - ie. clear nonblock flag */
282 val &= ~FLAG_TO_SET;
283 else
284 val |= FLAG_TO_SET;
285 return fcntl( fd, F_SETFL, val);
286#undef FLAG_TO_SET
287}
288
289/****************************************************************************
290create any necessary directories in fname. Unfortunately we don't know
291what perms to give the directory when this is called so we need to rely
292on the umask
293****************************************************************************/
294int create_directory_path(char *fname)
295{
296 extern int orig_umask;
297 char *p;
298
299 while (*fname == '/') fname++;
300 while (strncmp(fname,"./",2)==0) fname += 2;
301
302 p = fname;
303 while ((p=strchr(p,'/'))) {
304 *p = 0;
305 do_mkdir(fname,0777 & ~orig_umask);
306 *p = '/';
307 p++;
308 }
309 return 0;
310}
311
312
313/* Write LEN bytes at PTR to descriptor DESC, retrying if interrupted.
314 Return LEN upon success, write's (negative) error code otherwise.
315
316 derived from GNU C's cccp.c.
317*/
318int full_write(int desc, char *ptr, int len)
319{
320 int total_written;
321
322 total_written = 0;
323 while (len > 0) {
324 int written = write (desc, ptr, len);
325 if (written < 0) {
326#ifdef EINTR
327 if (errno == EINTR)
328 continue;
329#endif
330 return written;
331 }
332 total_written += written;
333 ptr += written;
334 len -= written;
335 }
336 return total_written;
337}
338
339/* Read LEN bytes at PTR from descriptor DESC, retrying if interrupted.
340 Return the actual number of bytes read, zero for EOF, or negative
341 for an error.
342
343 derived from GNU C's cccp.c. */
344int safe_read(int desc, char *ptr, int len)
345{
346 int n_chars;
347
348 if (len <= 0)
349 return len;
350
351#ifdef EINTR
352 do {
353 n_chars = read(desc, ptr, len);
354 } while (n_chars < 0 && errno == EINTR);
355#else
356 n_chars = read(desc, ptr, len);
357#endif
358
359 return n_chars;
360}
361
362
363/* copy a file - this is used in conjunction with the --temp-dir option */
364int copy_file(char *source, char *dest, mode_t mode)
365{
366 int ifd;
367 int ofd;
368 char buf[1024 * 8];
369 int len; /* Number of bytes read into `buf'. */
370
371 ifd = open(source, O_RDONLY);
372 if (ifd == -1) {
373 rprintf(FERROR,"open %s: %s\n",
374 source,strerror(errno));
375 return -1;
376 }
377
378 if (do_unlink(dest) && errno != ENOENT) {
379 rprintf(FERROR,"unlink %s: %s\n",
380 dest,strerror(errno));
381 return -1;
382 }
383
384 ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode);
385 if (ofd < 0) {
386 rprintf(FERROR,"open %s: %s\n",
387 dest,strerror(errno));
388 close(ifd);
389 return -1;
390 }
391
392 while ((len = safe_read(ifd, buf, sizeof(buf))) > 0) {
393 if (full_write(ofd, buf, len) < 0) {
394 rprintf(FERROR,"write %s: %s\n",
395 dest,strerror(errno));
396 close(ifd);
397 close(ofd);
398 return -1;
399 }
400 }
401
402 close(ifd);
403 close(ofd);
404
405 if (len < 0) {
406 rprintf(FERROR,"read %s: %s\n",
407 source,strerror(errno));
408 return -1;
409 }
410
411 return 0;
412}
413
414/* sleep for a while via select */
415void u_sleep(int usec)
416{
417 struct timeval tv;
418
419 tv.tv_sec = 0;
420 tv.tv_usec = usec;
421 select(0, NULL, NULL, NULL, &tv);
422}
423
424
425static pid_t all_pids[10];
426static int num_pids;
427
428/* fork and record the pid of the child */
429pid_t do_fork(void)
430{
431 pid_t newpid = fork();
432
433 if (newpid) {
434 all_pids[num_pids++] = newpid;
435 }
436 return newpid;
437}
438
439/* kill all children */
440void kill_all(int sig)
441{
442 int i;
443 for (i=0;i<num_pids;i++) {
444 if (all_pids[i] != getpid())
445 kill(all_pids[i], sig);
446 }
447}
448
449/* like strncpy but does not 0 fill the buffer and always null
450 terminates (thus it can use maxlen+1 space in d) */
451void strlcpy(char *d, char *s, int maxlen)
452{
453 int len = strlen(s);
454 if (len > maxlen) len = maxlen;
455 memcpy(d, s, len);
456 d[len] = 0;
457}
458
459/* turn a user name into a uid */
460int name_to_uid(char *name, uid_t *uid)
461{
462 struct passwd *pass;
463 if (!name || !*name) return 0;
464 pass = getpwnam(name);
465 if (pass) {
466 *uid = pass->pw_uid;
467 return 1;
468 }
469 return 0;
470}
471
472/* turn a group name into a gid */
473int name_to_gid(char *name, gid_t *gid)
474{
475 struct group *grp;
476 if (!name || !*name) return 0;
477 grp = getgrnam(name);
478 if (grp) {
479 *gid = grp->gr_gid;
480 return 1;
481 }
482 return 0;
483}
484
485
486/****************************************************************************
487check if a process exists.
488****************************************************************************/
489int process_exists(int pid)
490{
491 return(kill(pid,0) == 0 || errno != ESRCH);
492}
493
494int lock_file(int fd)
495{
496 return flock(fd, LOCK_EX) == 0;
497}
498
499int unlock_file(int fd)
500{
501 return flock(fd, LOCK_UN) == 0;
502}