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