*** empty log message ***
[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
AT
84 (nread=read(map->fd,map->p,len)) != len) {
85 fprintf(FERROR,"EOF in map_ptr! (offset=%d len=%d nread=%d errno=%d)\n",
86 (int)offset, len, nread, errno);
34ccb63e 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
167#ifndef HAVE_STRDUP
168 char *strdup(char *s)
169{
170 int l = strlen(s) + 1;
171 char *ret = (char *)malloc(l);
172 if (ret)
173 strcpy(ret,s);
174 return ret;
175}
176#endif
177
178
179int set_modtime(char *fname,time_t modtime)
180{
181#ifdef HAVE_UTIME_H
182 struct utimbuf tbuf;
183 tbuf.actime = time(NULL);
184 tbuf.modtime = modtime;
185 return utime(fname,&tbuf);
186#elif defined(HAVE_UTIME)
187 time_t t[2];
188 t[0] = time(NULL);
189 t[1] = modtime;
190 return utime(fname,t);
191#else
192 struct timeval t[2];
193 t[0].tv_sec = time(NULL);
194 t[0].tv_usec = 0;
195 t[1].tv_sec = modtime;
196 t[1].tv_usec = 0;
197 return utimes(fname,t);
198#endif
199}
94481d91 200
720b47f2
AT
201
202
203/****************************************************************************
204Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
205else
206if SYSV use O_NDELAY
207if BSD use FNDELAY
208****************************************************************************/
209int set_blocking(int fd, int set)
210{
211 int val;
212#ifdef O_NONBLOCK
213#define FLAG_TO_SET O_NONBLOCK
214#else
215#ifdef SYSV
216#define FLAG_TO_SET O_NDELAY
217#else /* BSD */
218#define FLAG_TO_SET FNDELAY
219#endif
220#endif
221
222 if((val = fcntl(fd, F_GETFL, 0)) == -1)
223 return -1;
224 if(set) /* Turn blocking on - ie. clear nonblock flag */
225 val &= ~FLAG_TO_SET;
226 else
227 val |= FLAG_TO_SET;
228 return fcntl( fd, F_SETFL, val);
229#undef FLAG_TO_SET
230}
6574b4f7
AT
231
232/****************************************************************************
233create any necessary directories in fname. Unfortunately we don't know
234what perms to give the directory when this is called so we need to rely
235on the umask
236****************************************************************************/
237int create_directory_path(char *fname)
238{
239 extern int orig_umask;
240 char *p;
241
242 while (*fname == '/') fname++;
243 while (strncmp(fname,"./",2)==0) fname += 2;
244
245 p = fname;
246 while ((p=strchr(p,'/'))) {
247 *p = 0;
248 mkdir(fname,0777 & ~orig_umask);
249 *p = '/';
250 p++;
251 }
252 return 0;
253}
950ab32d
AT
254
255
256/* Write LEN bytes at PTR to descriptor DESC, retrying if interrupted.
257 Return LEN upon success, write's (negative) error code otherwise.
258
259 derived from GNU C's cccp.c.
260*/
261int full_write(int desc, char *ptr, int len)
262{
263 int total_written;
264
265 total_written = 0;
266 while (len > 0) {
267 int written = write (desc, ptr, len);
268 if (written < 0) {
269#ifdef EINTR
270 if (errno == EINTR)
271 continue;
272#endif
273 return written;
274 }
275 total_written += written;
276 ptr += written;
277 len -= written;
278 }
279 return total_written;
280}
281
282/* Read LEN bytes at PTR from descriptor DESC, retrying if interrupted.
283 Return the actual number of bytes read, zero for EOF, or negative
284 for an error.
285
286 derived from GNU C's cccp.c. */
287int safe_read(int desc, char *ptr, int len)
288{
289 int n_chars;
290
291 if (len <= 0)
292 return len;
293
294#ifdef EINTR
295 do {
296 n_chars = read(desc, ptr, len);
297 } while (n_chars < 0 && errno == EINTR);
298#else
299 n_chars = read(desc, ptr, len);
300#endif
301
302 return n_chars;
303}
304
305
306/* copy a file - this is used in conjunction with the --temp-dir option */
307int copy_file(char *source, char *dest, mode_t mode)
308{
309 int ifd;
310 int ofd;
311 char buf[1024 * 8];
312 int len; /* Number of bytes read into `buf'. */
313
314 ifd = open(source, O_RDONLY);
315 if (ifd == -1) {
316 fprintf(FERROR,"open %s: %s\n",
317 source,strerror(errno));
318 return -1;
319 }
320
321 if (unlink(dest) && errno != ENOENT) {
322 fprintf(FERROR,"unlink %s: %s\n",
323 dest,strerror(errno));
324 return -1;
325 }
326
327 ofd = open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode);
328 if (ofd < 0) {
329 fprintf(FERROR,"open %s: %s\n",
330 dest,strerror(errno));
331 close(ifd);
332 return -1;
333 }
334
335 while ((len = safe_read(ifd, buf, sizeof(buf))) > 0) {
336 if (full_write(ofd, buf, len) < 0) {
337 fprintf(FERROR,"write %s: %s\n",
338 dest,strerror(errno));
339 close(ifd);
340 close(ofd);
341 return -1;
342 }
343 }
344
345 close(ifd);
346 close(ofd);
347
348 if (len < 0) {
349 fprintf(FERROR,"read %s: %s\n",
350 source,strerror(errno));
351 return -1;
352 }
353
354 return 0;
355}