Initial revision
[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 static int total_written = 0;
28 static int total_read = 0;
29
30 extern int verbose;
31
32 int write_total(void)
33 {
34   return total_written;
35 }
36
37 int read_total(void)
38 {
39   return total_read;
40 }
41
42 void write_int(int f,int x)
43 {
44   char b[4];
45   SIVAL(b,0,x);
46   if (write(f,b,4) != 4) {
47     fprintf(stderr,"write_int failed : %s\n",strerror(errno));
48     exit(1);
49   }
50   total_written += 4;
51 }
52
53 void write_buf(int f,char *buf,int len)
54 {
55   if (write(f,buf,len) != len) {
56     fprintf(stderr,"write_buf failed : %s\n",strerror(errno));
57     exit(1);
58   }
59   total_written += len;
60 }
61
62 void write_flush(int f)
63 {
64 }
65
66
67 int readfd(int fd,char *buffer,int N)
68 {
69   int  ret;
70   int total=0;  
71  
72   while (total < N)
73     {
74       ret = read(fd,buffer + total,N - total);
75
76       if (ret <= 0)
77         return total;
78       total += ret;
79     }
80   return total;
81 }
82
83
84 int read_int(int f)
85 {
86   char b[4];
87   if (readfd(f,b,4) != 4) {
88     if (verbose > 1) 
89       fprintf(stderr,"Error reading %d bytes : %s\n",4,strerror(errno));
90     exit(1);
91   }
92   total_read += 4;
93   return IVAL(b,0);
94 }
95
96 void read_buf(int f,char *buf,int len)
97 {
98   if (readfd(f,buf,len) != len) {
99     if (verbose > 1) 
100       fprintf(stderr,"Error reading %d bytes : %s\n",len,strerror(errno));
101     exit(1);
102   }
103   total_read += len;
104 }
105
106
107 char *map_file(int fd,off_t len)
108 {
109   char *ret = (char *)mmap(NULL,len,PROT_READ,MAP_SHARED,fd,0);
110   return ret;
111 }
112
113 void unmap_file(char *buf,off_t len)
114 {
115   if (len > 0)
116     munmap(buf,len);
117 }
118
119
120 int read_write(int fd_in,int fd_out,int size)
121 {
122   static char *buf=NULL;
123   static int bufsize = WRITE_BLOCK_SIZE;
124   int total=0;
125   
126   if (!buf) {
127     buf = (char *)malloc(bufsize);
128     if (!buf) out_of_memory("read_write");
129   }
130
131   while (total < size) {
132     int n = MIN(size-total,bufsize);
133     read_buf(fd_in,buf,n);
134     if (write(fd_out,buf,n) != n)
135       return total;
136     total += n;
137   }
138   return total;
139 }
140
141
142 /* this is taken from CVS */
143 int piped_child(char **command,int *f_in,int *f_out)
144 {
145   int pid;
146   int to_child_pipe[2];
147   int from_child_pipe[2];
148
149   if (pipe(to_child_pipe) < 0 ||
150       pipe(from_child_pipe) < 0) {
151     fprintf(stderr,"pipe: %s\n",strerror(errno));
152     exit(1);
153   }
154
155
156   pid = fork();
157   if (pid < 0) {
158     fprintf(stderr,"fork: %s\n",strerror(errno));
159     exit(1);
160   }
161
162   if (pid == 0)
163     {
164       if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
165           close(to_child_pipe[1]) < 0 ||
166           close(from_child_pipe[0]) < 0 ||
167           dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
168         fprintf(stderr,"Failed to dup/close : %s\n",strerror(errno));
169         exit(1);
170       }
171       execvp(command[0], command);
172       fprintf(stderr,"Failed to exec %s : %s\n",
173               command[0],strerror(errno));
174       exit(1);
175     }
176
177   if (close(from_child_pipe[1]) < 0 ||
178       close(to_child_pipe[0]) < 0) {
179     fprintf(stderr,"Failed to close : %s\n",strerror(errno));   
180     exit(1);
181   }
182
183   *f_in = from_child_pipe[0];
184   *f_out = to_child_pipe[1];
185   
186   return pid;
187 }
188
189
190 void out_of_memory(char *str)
191 {
192   fprintf(stderr,"out of memory in %s\n",str);
193   exit(1);
194 }
195
196
197 #ifndef HAVE_STRDUP
198  char *strdup(char *s)
199 {
200   int l = strlen(s) + 1;
201   char *ret = (char *)malloc(l);
202   if (ret)
203     strcpy(ret,s);
204   return ret;
205 }
206 #endif
207
208
209 int set_modtime(char *fname,time_t modtime)
210 {
211 #ifdef HAVE_UTIME_H
212   struct utimbuf tbuf;  
213   tbuf.actime = time(NULL);
214   tbuf.modtime = modtime;
215   return utime(fname,&tbuf);
216 #elif defined(HAVE_UTIME)
217   time_t t[2];
218   t[0] = time(NULL);
219   t[1] = modtime;
220   return utime(fname,t);
221 #else
222   struct timeval t[2];
223   t[0].tv_sec = time(NULL);
224   t[0].tv_usec = 0;
225   t[1].tv_sec = modtime;
226   t[1].tv_usec = 0;
227   return utimes(fname,t);
228 #endif
229 }