added a --relative (== -R) option. This is what Anthony Thyssen
[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 #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 }