started to add some 64 bit file offset support - not complete yet
[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,"out of memory in %s\n",str);
166 exit_cleanup(1);
167}
168
169
170
171int set_modtime(char *fname,time_t modtime)
172{
173#ifdef HAVE_UTIMBUF
174 struct utimbuf tbuf;
175 tbuf.actime = time(NULL);
176 tbuf.modtime = modtime;
177 return utime(fname,&tbuf);
178#elif defined(HAVE_UTIME)
179 time_t t[2];
180 t[0] = time(NULL);
181 t[1] = modtime;
182 return utime(fname,t);
183#else
184 struct timeval t[2];
185 t[0].tv_sec = time(NULL);
186 t[0].tv_usec = 0;
187 t[1].tv_sec = modtime;
188 t[1].tv_usec = 0;
189 return utimes(fname,t);
190#endif
191}
192
193
194
195/****************************************************************************
196Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
197else
198if SYSV use O_NDELAY
199if BSD use FNDELAY
200****************************************************************************/
201int set_blocking(int fd, int set)
202{
203 int val;
204#ifdef O_NONBLOCK
205#define FLAG_TO_SET O_NONBLOCK
206#else
207#ifdef SYSV
208#define FLAG_TO_SET O_NDELAY
209#else /* BSD */
210#define FLAG_TO_SET FNDELAY
211#endif
212#endif
213
214 if((val = fcntl(fd, F_GETFL, 0)) == -1)
215 return -1;
216 if(set) /* Turn blocking on - ie. clear nonblock flag */
217 val &= ~FLAG_TO_SET;
218 else
219 val |= FLAG_TO_SET;
220 return fcntl( fd, F_SETFL, val);
221#undef FLAG_TO_SET
222}
223
224/****************************************************************************
225create any necessary directories in fname. Unfortunately we don't know
226what perms to give the directory when this is called so we need to rely
227on the umask
228****************************************************************************/
229int create_directory_path(char *fname)
230{
231 extern int orig_umask;
232 char *p;
233
234 while (*fname == '/') fname++;
235 while (strncmp(fname,"./",2)==0) fname += 2;
236
237 p = fname;
238 while ((p=strchr(p,'/'))) {
239 *p = 0;
240 mkdir(fname,0777 & ~orig_umask);
241 *p = '/';
242 p++;
243 }
244 return 0;
245}
246
247
248/* Write LEN bytes at PTR to descriptor DESC, retrying if interrupted.
249 Return LEN upon success, write's (negative) error code otherwise.
250
251 derived from GNU C's cccp.c.
252*/
253int full_write(int desc, char *ptr, int len)
254{
255 int total_written;
256
257 total_written = 0;
258 while (len > 0) {
259 int written = write (desc, ptr, len);
260 if (written < 0) {
261#ifdef EINTR
262 if (errno == EINTR)
263 continue;
264#endif
265 return written;
266 }
267 total_written += written;
268 ptr += written;
269 len -= written;
270 }
271 return total_written;
272}
273
274/* Read LEN bytes at PTR from descriptor DESC, retrying if interrupted.
275 Return the actual number of bytes read, zero for EOF, or negative
276 for an error.
277
278 derived from GNU C's cccp.c. */
279int safe_read(int desc, char *ptr, int len)
280{
281 int n_chars;
282
283 if (len <= 0)
284 return len;
285
286#ifdef EINTR
287 do {
288 n_chars = read(desc, ptr, len);
289 } while (n_chars < 0 && errno == EINTR);
290#else
291 n_chars = read(desc, ptr, len);
292#endif
293
294 return n_chars;
295}
296
297
298/* copy a file - this is used in conjunction with the --temp-dir option */
299int copy_file(char *source, char *dest, mode_t mode)
300{
301 int ifd;
302 int ofd;
303 char buf[1024 * 8];
304 int len; /* Number of bytes read into `buf'. */
305
306 ifd = open(source, O_RDONLY);
307 if (ifd == -1) {
308 fprintf(FERROR,"open %s: %s\n",
309 source,strerror(errno));
310 return -1;
311 }
312
313 if (unlink(dest) && errno != ENOENT) {
314 fprintf(FERROR,"unlink %s: %s\n",
315 dest,strerror(errno));
316 return -1;
317 }
318
319 ofd = open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode);
320 if (ofd < 0) {
321 fprintf(FERROR,"open %s: %s\n",
322 dest,strerror(errno));
323 close(ifd);
324 return -1;
325 }
326
327 while ((len = safe_read(ifd, buf, sizeof(buf))) > 0) {
328 if (full_write(ofd, buf, len) < 0) {
329 fprintf(FERROR,"write %s: %s\n",
330 dest,strerror(errno));
331 close(ifd);
332 close(ofd);
333 return -1;
334 }
335 }
336
337 close(ifd);
338 close(ofd);
339
340 if (len < 0) {
341 fprintf(FERROR,"read %s: %s\n",
342 source,strerror(errno));
343 return -1;
344 }
345
346 return 0;
347}
348
349/* sleep for a while via select */
350void u_sleep(int usec)
351{
352 struct timeval tv;
353
354 tv.tv_sec = 0;
355 tv.tv_usec = usec;
356 select(0, NULL, NULL, NULL, &tv);
357}
358
359
360static pid_t all_pids[10];
361static int num_pids;
362
363/* fork and record the pid of the child */
364pid_t do_fork(void)
365{
366 pid_t newpid = fork();
367
368 if (newpid) {
369 all_pids[num_pids++] = newpid;
370 }
371 return newpid;
372}
373
374/* kill all children */
375void kill_all(int sig)
376{
377 int i;
378 for (i=0;i<num_pids;i++) {
379 if (all_pids[i] != getpid())
380 kill(all_pids[i], sig);
381 }
382}