*** empty log message ***
[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   if (map->map)
59     return map->map+offset;
60
61   if (len == 0) 
62     return NULL;
63
64   len = MIN(len,map->size-offset);
65
66   if (offset >= map->p_offset && 
67       offset+len <= map->p_offset+map->p_len) {
68     return (map->p + (offset - map->p_offset));
69   }
70
71   len = MAX(len,CHUNK_SIZE);
72   len = MIN(len,map->size - offset);  
73
74   if (len > map->p_size) {
75     if (map->p) free(map->p);
76     map->p = (char *)malloc(len);
77     if (!map->p) out_of_memory("map_ptr");
78     map->p_size = len;
79   }
80
81   if (lseek(map->fd,offset,SEEK_SET) != offset ||
82       read(map->fd,map->p,len) != len) {
83     fprintf(FERROR,"EOF in map_ptr!\n");
84     exit_cleanup(1);
85   }
86
87   map->p_offset = offset;
88   map->p_len = len;
89
90   return map->p; 
91 }
92
93
94 void unmap_file(struct map_struct *map)
95 {
96 #ifdef HAVE_MMAP
97   if (map->map)
98     munmap(map->map,map->size);
99 #endif
100   if (map->p) free(map->p);
101   free(map);
102 }
103
104
105 /* this is taken from CVS */
106 int piped_child(char **command,int *f_in,int *f_out)
107 {
108   int pid;
109   int to_child_pipe[2];
110   int from_child_pipe[2];
111
112   if (pipe(to_child_pipe) < 0 ||
113       pipe(from_child_pipe) < 0) {
114     fprintf(FERROR,"pipe: %s\n",strerror(errno));
115     exit_cleanup(1);
116   }
117
118
119   pid = fork();
120   if (pid < 0) {
121     fprintf(FERROR,"fork: %s\n",strerror(errno));
122     exit_cleanup(1);
123   }
124
125   if (pid == 0)
126     {
127       if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
128           close(to_child_pipe[1]) < 0 ||
129           close(from_child_pipe[0]) < 0 ||
130           dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
131         fprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
132         exit_cleanup(1);
133       }
134       execvp(command[0], command);
135       fprintf(FERROR,"Failed to exec %s : %s\n",
136               command[0],strerror(errno));
137       exit_cleanup(1);
138     }
139
140   if (close(from_child_pipe[1]) < 0 ||
141       close(to_child_pipe[0]) < 0) {
142     fprintf(FERROR,"Failed to close : %s\n",strerror(errno));   
143     exit_cleanup(1);
144   }
145
146   *f_in = from_child_pipe[0];
147   *f_out = to_child_pipe[1];
148   
149   return pid;
150 }
151
152
153 void out_of_memory(char *str)
154 {
155   fprintf(FERROR,"out of memory in %s\n",str);
156   exit_cleanup(1);
157 }
158
159
160 #ifndef HAVE_STRDUP
161  char *strdup(char *s)
162 {
163   int l = strlen(s) + 1;
164   char *ret = (char *)malloc(l);
165   if (ret)
166     strcpy(ret,s);
167   return ret;
168 }
169 #endif
170
171
172 int set_modtime(char *fname,time_t modtime)
173 {
174 #ifdef HAVE_UTIME_H
175   struct utimbuf tbuf;  
176   tbuf.actime = time(NULL);
177   tbuf.modtime = modtime;
178   return utime(fname,&tbuf);
179 #elif defined(HAVE_UTIME)
180   time_t t[2];
181   t[0] = time(NULL);
182   t[1] = modtime;
183   return utime(fname,t);
184 #else
185   struct timeval t[2];
186   t[0].tv_sec = time(NULL);
187   t[0].tv_usec = 0;
188   t[1].tv_sec = modtime;
189   t[1].tv_usec = 0;
190   return utimes(fname,t);
191 #endif
192 }
193
194
195
196 /****************************************************************************
197 Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
198 else
199 if SYSV use O_NDELAY
200 if BSD use FNDELAY
201 ****************************************************************************/
202 int set_blocking(int fd, int set)
203 {
204   int val;
205 #ifdef O_NONBLOCK
206 #define FLAG_TO_SET O_NONBLOCK
207 #else
208 #ifdef SYSV
209 #define FLAG_TO_SET O_NDELAY
210 #else /* BSD */
211 #define FLAG_TO_SET FNDELAY
212 #endif
213 #endif
214
215   if((val = fcntl(fd, F_GETFL, 0)) == -1)
216         return -1;
217   if(set) /* Turn blocking on - ie. clear nonblock flag */
218         val &= ~FLAG_TO_SET;
219   else
220     val |= FLAG_TO_SET;
221   return fcntl( fd, F_SETFL, val);
222 #undef FLAG_TO_SET
223 }