*** empty log message ***
[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 #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
179 int 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 /****************************************************************************
204 Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
205 else
206 if SYSV use O_NDELAY
207 if BSD use FNDELAY
208 ****************************************************************************/
209 int 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 /****************************************************************************
233 create any necessary directories in fname. Unfortunately we don't know
234 what perms to give the directory when this is called so we need to rely
235 on the umask
236 ****************************************************************************/
237 int 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 */
261 int 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. */
287 int 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 */
307 int 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 }