minor updates
[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       if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
135       if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
136       execvp(command[0], command);
137       fprintf(FERROR,"Failed to exec %s : %s\n",
138               command[0],strerror(errno));
139       exit_cleanup(1);
140     }
141
142   if (close(from_child_pipe[1]) < 0 ||
143       close(to_child_pipe[0]) < 0) {
144     fprintf(FERROR,"Failed to close : %s\n",strerror(errno));   
145     exit_cleanup(1);
146   }
147
148   *f_in = from_child_pipe[0];
149   *f_out = to_child_pipe[1];
150   
151   return pid;
152 }
153
154
155 void out_of_memory(char *str)
156 {
157   fprintf(FERROR,"out of memory in %s\n",str);
158   exit_cleanup(1);
159 }
160
161
162 #ifndef HAVE_STRDUP
163  char *strdup(char *s)
164 {
165   int l = strlen(s) + 1;
166   char *ret = (char *)malloc(l);
167   if (ret)
168     strcpy(ret,s);
169   return ret;
170 }
171 #endif
172
173
174 int set_modtime(char *fname,time_t modtime)
175 {
176 #ifdef HAVE_UTIME_H
177   struct utimbuf tbuf;  
178   tbuf.actime = time(NULL);
179   tbuf.modtime = modtime;
180   return utime(fname,&tbuf);
181 #elif defined(HAVE_UTIME)
182   time_t t[2];
183   t[0] = time(NULL);
184   t[1] = modtime;
185   return utime(fname,t);
186 #else
187   struct timeval t[2];
188   t[0].tv_sec = time(NULL);
189   t[0].tv_usec = 0;
190   t[1].tv_sec = modtime;
191   t[1].tv_usec = 0;
192   return utimes(fname,t);
193 #endif
194 }
195
196
197
198 /****************************************************************************
199 Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
200 else
201 if SYSV use O_NDELAY
202 if BSD use FNDELAY
203 ****************************************************************************/
204 int set_blocking(int fd, int set)
205 {
206   int val;
207 #ifdef O_NONBLOCK
208 #define FLAG_TO_SET O_NONBLOCK
209 #else
210 #ifdef SYSV
211 #define FLAG_TO_SET O_NDELAY
212 #else /* BSD */
213 #define FLAG_TO_SET FNDELAY
214 #endif
215 #endif
216
217   if((val = fcntl(fd, F_GETFL, 0)) == -1)
218         return -1;
219   if(set) /* Turn blocking on - ie. clear nonblock flag */
220         val &= ~FLAG_TO_SET;
221   else
222     val |= FLAG_TO_SET;
223   return fcntl( fd, F_SETFL, val);
224 #undef FLAG_TO_SET
225 }