*** empty log message ***
[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
56char *map_ptr(struct map_struct *map,off_t offset,int len)
57{
58 int nread = -2;
59
60 if (map->map)
61 return map->map+offset;
62
63 if (len == 0)
64 return NULL;
65
66 len = MIN(len,map->size-offset);
67
68 if (offset >= map->p_offset &&
69 offset+len <= map->p_offset+map->p_len) {
70 return (map->p + (offset - map->p_offset));
71 }
72
73 len = MAX(len,CHUNK_SIZE);
74 len = MIN(len,map->size - offset);
75
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;
81 }
82
83 if (lseek(map->fd,offset,SEEK_SET) != offset ||
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);
87 exit_cleanup(1);
88 }
89
90 map->p_offset = offset;
91 map->p_len = len;
92
93 return map->p;
94}
95
96
97void unmap_file(struct map_struct *map)
98{
99#ifdef HAVE_MMAP
100 if (map->map)
101 munmap(map->map,map->size);
102#endif
103 if (map->p) free(map->p);
104 free(map);
105}
106
107
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) {
117 fprintf(FERROR,"pipe: %s\n",strerror(errno));
118 exit_cleanup(1);
119 }
120
121
122 pid = fork();
123 if (pid < 0) {
124 fprintf(FERROR,"fork: %s\n",strerror(errno));
125 exit_cleanup(1);
126 }
127
128 if (pid == 0)
129 {
130 extern int orig_umask;
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) {
135 fprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
136 exit_cleanup(1);
137 }
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]);
140 umask(orig_umask);
141 execvp(command[0], command);
142 fprintf(FERROR,"Failed to exec %s : %s\n",
143 command[0],strerror(errno));
144 exit_cleanup(1);
145 }
146
147 if (close(from_child_pipe[1]) < 0 ||
148 close(to_child_pipe[0]) < 0) {
149 fprintf(FERROR,"Failed to close : %s\n",strerror(errno));
150 exit_cleanup(1);
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{
162 fprintf(FERROR,"out of memory in %s\n",str);
163 exit_cleanup(1);
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}
200
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}
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}
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}