started to add some 64 bit file offset support - not complete yet
[rsync.git] / util.c
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
27 int num_waiting(int fd)
28 {
29   int len=0;
30   ioctl(fd,FIONREAD,&len);
31   return(len);
32 }
33
34
35 struct 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
57 char *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
100 void 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 */
112 int 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
163 void out_of_memory(char *str)
164 {
165   fprintf(FERROR,"out of memory in %s\n",str);
166   exit_cleanup(1);
167 }
168
169
170
171 int 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 /****************************************************************************
196 Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
197 else
198 if SYSV use O_NDELAY
199 if BSD use FNDELAY
200 ****************************************************************************/
201 int 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 /****************************************************************************
225 create any necessary directories in fname. Unfortunately we don't know
226 what perms to give the directory when this is called so we need to rely
227 on the umask
228 ****************************************************************************/
229 int 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 */
253 int 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. */
279 int 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 */
299 int 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 */
350 void 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
360 static pid_t all_pids[10];
361 static int num_pids;
362
363 /* fork and record the pid of the child */
364 pid_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 */
375 void 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 }