Solaris 2.6 doesn't support "signed char". What a broken system!
[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
bcacc18b 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
0b910560 56
bcacc18b 57char *map_ptr(struct map_struct *map,OFF_T offset,int len)
d9bea2dd 58{
0cfcfa29
AT
59 int nread = -2;
60
c6e7fcb4
AT
61 if (map->map)
62 return map->map+offset;
d9bea2dd
AT
63
64 if (len == 0)
65 return NULL;
66
0b910560
AT
67 if (len > (map->size-offset))
68 len = map->size-offset;
d9bea2dd 69
c6e7fcb4
AT
70 if (offset >= map->p_offset &&
71 offset+len <= map->p_offset+map->p_len) {
72 return (map->p + (offset - map->p_offset));
d9bea2dd
AT
73 }
74
34ccb63e 75 len = MAX(len,CHUNK_SIZE);
0b910560
AT
76 if (len > (map->size-offset))
77 len = map->size-offset;
d9bea2dd 78
c6e7fcb4
AT
79 if (len > map->p_size) {
80 if (map->p) free(map->p);
81 map->p = (char *)malloc(len);
82 if (!map->p) out_of_memory("map_ptr");
83 map->p_size = len;
d9bea2dd
AT
84 }
85
c6e7fcb4 86 if (lseek(map->fd,offset,SEEK_SET) != offset ||
0cfcfa29 87 (nread=read(map->fd,map->p,len)) != len) {
feaa89c4
AT
88 fprintf(FERROR,"EOF in map_ptr! (offset=%d len=%d nread=%d errno=%d)\n",
89 (int)offset, len, nread, errno);
90 exit_cleanup(1);
d9bea2dd
AT
91 }
92
c6e7fcb4
AT
93 map->p_offset = offset;
94 map->p_len = len;
d9bea2dd 95
c6e7fcb4 96 return map->p;
d9bea2dd
AT
97}
98
99
c6e7fcb4 100void unmap_file(struct map_struct *map)
c627d613 101{
7bec6a5c 102#ifdef HAVE_MMAP
c6e7fcb4
AT
103 if (map->map)
104 munmap(map->map,map->size);
7bec6a5c 105#endif
c6e7fcb4
AT
106 if (map->p) free(map->p);
107 free(map);
c627d613
AT
108}
109
110
c627d613
AT
111/* this is taken from CVS */
112int piped_child(char **command,int *f_in,int *f_out)
113{
114 int pid;
115 int to_child_pipe[2];
116 int from_child_pipe[2];
117
118 if (pipe(to_child_pipe) < 0 ||
119 pipe(from_child_pipe) < 0) {
dc5ddbcc 120 fprintf(FERROR,"pipe: %s\n",strerror(errno));
34ccb63e 121 exit_cleanup(1);
c627d613
AT
122 }
123
124
3ba62a83 125 pid = do_fork();
c627d613 126 if (pid < 0) {
dc5ddbcc 127 fprintf(FERROR,"fork: %s\n",strerror(errno));
34ccb63e 128 exit_cleanup(1);
c627d613
AT
129 }
130
131 if (pid == 0)
132 {
6574b4f7 133 extern int orig_umask;
c627d613
AT
134 if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
135 close(to_child_pipe[1]) < 0 ||
136 close(from_child_pipe[0]) < 0 ||
137 dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
dc5ddbcc 138 fprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
34ccb63e 139 exit_cleanup(1);
c627d613 140 }
773f2bd4
AT
141 if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
142 if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
6574b4f7 143 umask(orig_umask);
c627d613 144 execvp(command[0], command);
dc5ddbcc 145 fprintf(FERROR,"Failed to exec %s : %s\n",
c627d613 146 command[0],strerror(errno));
34ccb63e 147 exit_cleanup(1);
c627d613
AT
148 }
149
150 if (close(from_child_pipe[1]) < 0 ||
151 close(to_child_pipe[0]) < 0) {
dc5ddbcc 152 fprintf(FERROR,"Failed to close : %s\n",strerror(errno));
34ccb63e 153 exit_cleanup(1);
c627d613
AT
154 }
155
156 *f_in = from_child_pipe[0];
157 *f_out = to_child_pipe[1];
158
159 return pid;
160}
161
366345fe
AT
162int local_child(int argc, char **argv,int *f_in,int *f_out)
163{
164 int pid;
165 int to_child_pipe[2];
166 int from_child_pipe[2];
167
168 if (pipe(to_child_pipe) < 0 ||
169 pipe(from_child_pipe) < 0) {
170 fprintf(FERROR,"pipe: %s\n",strerror(errno));
171 exit_cleanup(1);
172 }
173
174
175 pid = do_fork();
176 if (pid < 0) {
177 fprintf(FERROR,"fork: %s\n",strerror(errno));
178 exit_cleanup(1);
179 }
180
181 if (pid == 0) {
182 extern int am_sender;
183 extern int am_server;
184
185 am_sender = !am_sender;
186 am_server = 1;
187
188 if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
189 close(to_child_pipe[1]) < 0 ||
190 close(from_child_pipe[0]) < 0 ||
191 dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
192 fprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
193 exit_cleanup(1);
194 }
195 if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
196 if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
197 start_server(argc, argv);
198 }
199
200 if (close(from_child_pipe[1]) < 0 ||
201 close(to_child_pipe[0]) < 0) {
202 fprintf(FERROR,"Failed to close : %s\n",strerror(errno));
203 exit_cleanup(1);
204 }
205
206 *f_in = from_child_pipe[0];
207 *f_out = to_child_pipe[1];
208
209 return pid;
210}
211
212
c627d613
AT
213
214void out_of_memory(char *str)
215{
575f2fca
AT
216 fprintf(FERROR,"ERROR: out of memory in %s\n",str);
217 exit_cleanup(1);
218}
219
220void overflow(char *str)
221{
222 fprintf(FERROR,"ERROR: buffer overflow in %s\n",str);
34ccb63e 223 exit_cleanup(1);
c627d613
AT
224}
225
226
c627d613
AT
227
228int set_modtime(char *fname,time_t modtime)
229{
31e12522
AT
230 extern int dry_run;
231 if (dry_run) return 0;
232 {
1e9f155a 233#ifdef HAVE_UTIMBUF
31e12522
AT
234 struct utimbuf tbuf;
235 tbuf.actime = time(NULL);
236 tbuf.modtime = modtime;
237 return utime(fname,&tbuf);
c627d613 238#elif defined(HAVE_UTIME)
31e12522
AT
239 time_t t[2];
240 t[0] = time(NULL);
241 t[1] = modtime;
242 return utime(fname,t);
c627d613 243#else
31e12522
AT
244 struct timeval t[2];
245 t[0].tv_sec = time(NULL);
246 t[0].tv_usec = 0;
247 t[1].tv_sec = modtime;
248 t[1].tv_usec = 0;
249 return utimes(fname,t);
c627d613 250#endif
31e12522 251 }
c627d613 252}
94481d91 253
720b47f2
AT
254
255
256/****************************************************************************
257Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
258else
259if SYSV use O_NDELAY
260if BSD use FNDELAY
261****************************************************************************/
262int set_blocking(int fd, int set)
263{
264 int val;
265#ifdef O_NONBLOCK
266#define FLAG_TO_SET O_NONBLOCK
267#else
268#ifdef SYSV
269#define FLAG_TO_SET O_NDELAY
270#else /* BSD */
271#define FLAG_TO_SET FNDELAY
272#endif
273#endif
274
275 if((val = fcntl(fd, F_GETFL, 0)) == -1)
276 return -1;
277 if(set) /* Turn blocking on - ie. clear nonblock flag */
278 val &= ~FLAG_TO_SET;
279 else
280 val |= FLAG_TO_SET;
281 return fcntl( fd, F_SETFL, val);
282#undef FLAG_TO_SET
283}
6574b4f7
AT
284
285/****************************************************************************
286create any necessary directories in fname. Unfortunately we don't know
287what perms to give the directory when this is called so we need to rely
288on the umask
289****************************************************************************/
290int create_directory_path(char *fname)
291{
292 extern int orig_umask;
293 char *p;
294
295 while (*fname == '/') fname++;
296 while (strncmp(fname,"./",2)==0) fname += 2;
297
298 p = fname;
299 while ((p=strchr(p,'/'))) {
300 *p = 0;
1b2d733a 301 do_mkdir(fname,0777 & ~orig_umask);
6574b4f7
AT
302 *p = '/';
303 p++;
304 }
305 return 0;
306}
950ab32d
AT
307
308
309/* Write LEN bytes at PTR to descriptor DESC, retrying if interrupted.
310 Return LEN upon success, write's (negative) error code otherwise.
311
312 derived from GNU C's cccp.c.
313*/
314int full_write(int desc, char *ptr, int len)
315{
316 int total_written;
317
318 total_written = 0;
319 while (len > 0) {
320 int written = write (desc, ptr, len);
321 if (written < 0) {
322#ifdef EINTR
323 if (errno == EINTR)
324 continue;
325#endif
326 return written;
327 }
328 total_written += written;
329 ptr += written;
330 len -= written;
331 }
332 return total_written;
333}
334
335/* Read LEN bytes at PTR from descriptor DESC, retrying if interrupted.
336 Return the actual number of bytes read, zero for EOF, or negative
337 for an error.
338
339 derived from GNU C's cccp.c. */
340int safe_read(int desc, char *ptr, int len)
341{
342 int n_chars;
343
344 if (len <= 0)
345 return len;
346
347#ifdef EINTR
348 do {
349 n_chars = read(desc, ptr, len);
350 } while (n_chars < 0 && errno == EINTR);
351#else
352 n_chars = read(desc, ptr, len);
353#endif
354
355 return n_chars;
356}
357
358
359/* copy a file - this is used in conjunction with the --temp-dir option */
360int copy_file(char *source, char *dest, mode_t mode)
361{
362 int ifd;
363 int ofd;
364 char buf[1024 * 8];
365 int len; /* Number of bytes read into `buf'. */
366
367 ifd = open(source, O_RDONLY);
368 if (ifd == -1) {
369 fprintf(FERROR,"open %s: %s\n",
370 source,strerror(errno));
371 return -1;
372 }
373
31e12522 374 if (do_unlink(dest) && errno != ENOENT) {
950ab32d
AT
375 fprintf(FERROR,"unlink %s: %s\n",
376 dest,strerror(errno));
377 return -1;
378 }
379
31e12522 380 ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode);
950ab32d
AT
381 if (ofd < 0) {
382 fprintf(FERROR,"open %s: %s\n",
383 dest,strerror(errno));
384 close(ifd);
385 return -1;
386 }
387
388 while ((len = safe_read(ifd, buf, sizeof(buf))) > 0) {
389 if (full_write(ofd, buf, len) < 0) {
390 fprintf(FERROR,"write %s: %s\n",
391 dest,strerror(errno));
392 close(ifd);
393 close(ofd);
394 return -1;
395 }
396 }
397
398 close(ifd);
399 close(ofd);
400
401 if (len < 0) {
402 fprintf(FERROR,"read %s: %s\n",
403 source,strerror(errno));
404 return -1;
405 }
406
407 return 0;
408}
feaa89c4
AT
409
410/* sleep for a while via select */
411void u_sleep(int usec)
412{
413 struct timeval tv;
414
415 tv.tv_sec = 0;
416 tv.tv_usec = usec;
417 select(0, NULL, NULL, NULL, &tv);
418}
3ba62a83
AT
419
420
421static pid_t all_pids[10];
422static int num_pids;
423
424/* fork and record the pid of the child */
425pid_t do_fork(void)
426{
427 pid_t newpid = fork();
428
429 if (newpid) {
430 all_pids[num_pids++] = newpid;
431 }
432 return newpid;
433}
434
435/* kill all children */
436void kill_all(int sig)
437{
438 int i;
439 for (i=0;i<num_pids;i++) {
440 if (all_pids[i] != getpid())
441 kill(all_pids[i], sig);
442 }
443}