fixed a bug in the hlink code - it wasn't taking account of the new
[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#endif
53 return ret;
54}
55
56
57char *map_ptr(struct map_struct *map,off_t offset,int len)
58{
59 int nread = -2;
60
61 if (map->map)
62 return map->map+offset;
63
64 if (len == 0)
65 return NULL;
66
67 if (len > (map->size-offset))
68 len = map->size-offset;
69
70 if (offset >= map->p_offset &&
71 offset+len <= map->p_offset+map->p_len) {
72 return (map->p + (offset - map->p_offset));
73 }
74
75 len = MAX(len,CHUNK_SIZE);
76 if (len > (map->size-offset))
77 len = map->size-offset;
78
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;
84 }
85
86 if (lseek(map->fd,offset,SEEK_SET) != offset ||
87 (nread=read(map->fd,map->p,len)) != len) {
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);
91 }
92
93 map->p_offset = offset;
94 map->p_len = len;
95
96 return map->p;
97}
98
99
100void unmap_file(struct map_struct *map)
101{
102#ifdef HAVE_MMAP
103 if (map->map)
104 munmap(map->map,map->size);
105#endif
106 if (map->p) free(map->p);
107 free(map);
108}
109
110
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) {
120 fprintf(FERROR,"pipe: %s\n",strerror(errno));
121 exit_cleanup(1);
122 }
123
124
125 pid = do_fork();
126 if (pid < 0) {
127 fprintf(FERROR,"fork: %s\n",strerror(errno));
128 exit_cleanup(1);
129 }
130
131 if (pid == 0)
132 {
133 extern int orig_umask;
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) {
138 fprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
139 exit_cleanup(1);
140 }
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]);
143 umask(orig_umask);
144 execvp(command[0], command);
145 fprintf(FERROR,"Failed to exec %s : %s\n",
146 command[0],strerror(errno));
147 exit_cleanup(1);
148 }
149
150 if (close(from_child_pipe[1]) < 0 ||
151 close(to_child_pipe[0]) < 0) {
152 fprintf(FERROR,"Failed to close : %s\n",strerror(errno));
153 exit_cleanup(1);
154 }
155
156 *f_in = from_child_pipe[0];
157 *f_out = to_child_pipe[1];
158
159 return pid;
160}
161
162
163void out_of_memory(char *str)
164{
165 fprintf(FERROR,"ERROR: out of memory in %s\n",str);
166 exit_cleanup(1);
167}
168
169void overflow(char *str)
170{
171 fprintf(FERROR,"ERROR: buffer overflow in %s\n",str);
172 exit_cleanup(1);
173}
174
175
176
177int set_modtime(char *fname,time_t modtime)
178{
179 extern int dry_run;
180 if (dry_run) return 0;
181 {
182#ifdef HAVE_UTIMBUF
183 struct utimbuf tbuf;
184 tbuf.actime = time(NULL);
185 tbuf.modtime = modtime;
186 return utime(fname,&tbuf);
187#elif defined(HAVE_UTIME)
188 time_t t[2];
189 t[0] = time(NULL);
190 t[1] = modtime;
191 return utime(fname,t);
192#else
193 struct timeval t[2];
194 t[0].tv_sec = time(NULL);
195 t[0].tv_usec = 0;
196 t[1].tv_sec = modtime;
197 t[1].tv_usec = 0;
198 return utimes(fname,t);
199#endif
200 }
201}
202
203
204
205/****************************************************************************
206Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
207else
208if SYSV use O_NDELAY
209if BSD use FNDELAY
210****************************************************************************/
211int set_blocking(int fd, int set)
212{
213 int val;
214#ifdef O_NONBLOCK
215#define FLAG_TO_SET O_NONBLOCK
216#else
217#ifdef SYSV
218#define FLAG_TO_SET O_NDELAY
219#else /* BSD */
220#define FLAG_TO_SET FNDELAY
221#endif
222#endif
223
224 if((val = fcntl(fd, F_GETFL, 0)) == -1)
225 return -1;
226 if(set) /* Turn blocking on - ie. clear nonblock flag */
227 val &= ~FLAG_TO_SET;
228 else
229 val |= FLAG_TO_SET;
230 return fcntl( fd, F_SETFL, val);
231#undef FLAG_TO_SET
232}
233
234/****************************************************************************
235create any necessary directories in fname. Unfortunately we don't know
236what perms to give the directory when this is called so we need to rely
237on the umask
238****************************************************************************/
239int create_directory_path(char *fname)
240{
241 extern int orig_umask;
242 char *p;
243
244 while (*fname == '/') fname++;
245 while (strncmp(fname,"./",2)==0) fname += 2;
246
247 p = fname;
248 while ((p=strchr(p,'/'))) {
249 *p = 0;
250 mkdir(fname,0777 & ~orig_umask);
251 *p = '/';
252 p++;
253 }
254 return 0;
255}
256
257
258/* Write LEN bytes at PTR to descriptor DESC, retrying if interrupted.
259 Return LEN upon success, write's (negative) error code otherwise.
260
261 derived from GNU C's cccp.c.
262*/
263int full_write(int desc, char *ptr, int len)
264{
265 int total_written;
266
267 total_written = 0;
268 while (len > 0) {
269 int written = write (desc, ptr, len);
270 if (written < 0) {
271#ifdef EINTR
272 if (errno == EINTR)
273 continue;
274#endif
275 return written;
276 }
277 total_written += written;
278 ptr += written;
279 len -= written;
280 }
281 return total_written;
282}
283
284/* Read LEN bytes at PTR from descriptor DESC, retrying if interrupted.
285 Return the actual number of bytes read, zero for EOF, or negative
286 for an error.
287
288 derived from GNU C's cccp.c. */
289int safe_read(int desc, char *ptr, int len)
290{
291 int n_chars;
292
293 if (len <= 0)
294 return len;
295
296#ifdef EINTR
297 do {
298 n_chars = read(desc, ptr, len);
299 } while (n_chars < 0 && errno == EINTR);
300#else
301 n_chars = read(desc, ptr, len);
302#endif
303
304 return n_chars;
305}
306
307
308/* copy a file - this is used in conjunction with the --temp-dir option */
309int copy_file(char *source, char *dest, mode_t mode)
310{
311 int ifd;
312 int ofd;
313 char buf[1024 * 8];
314 int len; /* Number of bytes read into `buf'. */
315
316 ifd = open(source, O_RDONLY);
317 if (ifd == -1) {
318 fprintf(FERROR,"open %s: %s\n",
319 source,strerror(errno));
320 return -1;
321 }
322
323 if (do_unlink(dest) && errno != ENOENT) {
324 fprintf(FERROR,"unlink %s: %s\n",
325 dest,strerror(errno));
326 return -1;
327 }
328
329 ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode);
330 if (ofd < 0) {
331 fprintf(FERROR,"open %s: %s\n",
332 dest,strerror(errno));
333 close(ifd);
334 return -1;
335 }
336
337 while ((len = safe_read(ifd, buf, sizeof(buf))) > 0) {
338 if (full_write(ofd, buf, len) < 0) {
339 fprintf(FERROR,"write %s: %s\n",
340 dest,strerror(errno));
341 close(ifd);
342 close(ofd);
343 return -1;
344 }
345 }
346
347 close(ifd);
348 close(ofd);
349
350 if (len < 0) {
351 fprintf(FERROR,"read %s: %s\n",
352 source,strerror(errno));
353 return -1;
354 }
355
356 return 0;
357}
358
359/* sleep for a while via select */
360void u_sleep(int usec)
361{
362 struct timeval tv;
363
364 tv.tv_sec = 0;
365 tv.tv_usec = usec;
366 select(0, NULL, NULL, NULL, &tv);
367}
368
369
370static pid_t all_pids[10];
371static int num_pids;
372
373/* fork and record the pid of the child */
374pid_t do_fork(void)
375{
376 pid_t newpid = fork();
377
378 if (newpid) {
379 all_pids[num_pids++] = newpid;
380 }
381 return newpid;
382}
383
384/* kill all children */
385void kill_all(int sig)
386{
387 int i;
388 for (i=0;i<num_pids;i++) {
389 if (all_pids[i] != getpid())
390 kill(all_pids[i], sig);
391 }
392}