standard input on server may be nonblocking
[rsync/rsync.git] / util.c
CommitLineData
c627d613
AT
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
720b47f2 27int num_waiting(int fd)
94481d91
AT
28{
29 int len=0;
94481d91 30 ioctl(fd,FIONREAD,&len);
94481d91
AT
31 return(len);
32}
33
d9bea2dd
AT
34static int map_fd = -1;
35static off_t map_size = 0;
36static char *p = NULL;
37static int p_size = 0;
38static int p_offset = 0;
39static int p_len = 0;
40
41
c627d613
AT
42char *map_file(int fd,off_t len)
43{
d9bea2dd
AT
44 char *ret = NULL;
45#ifdef HAVE_MMAP
46 if (len < MAX_MAP_SIZE)
47 ret = (char *)mmap(NULL,len,PROT_READ,MAP_SHARED,fd,0);
48#endif
49 map_fd = fd;
50 map_size = len;
c627d613
AT
51 return ret;
52}
53
d9bea2dd
AT
54char *map_ptr(char *buf,off_t offset,int len)
55{
56 if (buf)
57 return buf+offset;
58
59 if (len == 0)
60 return NULL;
61
62 len = MIN(len,map_size-offset);
63
64 if (offset >= p_offset &&
65 offset+len <= p_offset+p_len) {
66 return (p + (offset - p_offset));
67 }
68
69 len = MAX(len,WRITE_BLOCK_SIZE);
70 len = MIN(len,map_size - offset);
71
72 if (len > p_size) {
73 if (p) free(p);
74 p = (char *)malloc(len);
75 if (!p) out_of_memory("map_ptr");
76 p_size = len;
77 }
78
79 if (lseek(map_fd,offset,SEEK_SET) != offset ||
80 read(map_fd,p,len) != len) {
81 fprintf(stderr,"EOF in map_ptr!\n");
82 exit(1);
83 }
84
85 p_offset = offset;
86 p_len = len;
87
88 return p;
89}
90
91
c627d613
AT
92void unmap_file(char *buf,off_t len)
93{
84664c10 94 if (len > 0 && buf)
c627d613 95 munmap(buf,len);
d9bea2dd
AT
96 map_fd = -1;
97 map_size = 0;
98 p_len = 0;
c627d613
AT
99}
100
101
c627d613
AT
102/* this is taken from CVS */
103int piped_child(char **command,int *f_in,int *f_out)
104{
105 int pid;
106 int to_child_pipe[2];
107 int from_child_pipe[2];
108
109 if (pipe(to_child_pipe) < 0 ||
110 pipe(from_child_pipe) < 0) {
111 fprintf(stderr,"pipe: %s\n",strerror(errno));
112 exit(1);
113 }
114
115
116 pid = fork();
117 if (pid < 0) {
118 fprintf(stderr,"fork: %s\n",strerror(errno));
119 exit(1);
120 }
121
122 if (pid == 0)
123 {
124 if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
125 close(to_child_pipe[1]) < 0 ||
126 close(from_child_pipe[0]) < 0 ||
127 dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
128 fprintf(stderr,"Failed to dup/close : %s\n",strerror(errno));
129 exit(1);
130 }
131 execvp(command[0], command);
132 fprintf(stderr,"Failed to exec %s : %s\n",
133 command[0],strerror(errno));
134 exit(1);
135 }
136
137 if (close(from_child_pipe[1]) < 0 ||
138 close(to_child_pipe[0]) < 0) {
139 fprintf(stderr,"Failed to close : %s\n",strerror(errno));
140 exit(1);
141 }
142
143 *f_in = from_child_pipe[0];
144 *f_out = to_child_pipe[1];
145
146 return pid;
147}
148
149
150void out_of_memory(char *str)
151{
152 fprintf(stderr,"out of memory in %s\n",str);
153 exit(1);
154}
155
156
157#ifndef HAVE_STRDUP
158 char *strdup(char *s)
159{
160 int l = strlen(s) + 1;
161 char *ret = (char *)malloc(l);
162 if (ret)
163 strcpy(ret,s);
164 return ret;
165}
166#endif
167
168
169int set_modtime(char *fname,time_t modtime)
170{
171#ifdef HAVE_UTIME_H
172 struct utimbuf tbuf;
173 tbuf.actime = time(NULL);
174 tbuf.modtime = modtime;
175 return utime(fname,&tbuf);
176#elif defined(HAVE_UTIME)
177 time_t t[2];
178 t[0] = time(NULL);
179 t[1] = modtime;
180 return utime(fname,t);
181#else
182 struct timeval t[2];
183 t[0].tv_sec = time(NULL);
184 t[0].tv_usec = 0;
185 t[1].tv_sec = modtime;
186 t[1].tv_usec = 0;
187 return utimes(fname,t);
188#endif
189}
94481d91 190
720b47f2
AT
191
192
193/****************************************************************************
194Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
195else
196if SYSV use O_NDELAY
197if BSD use FNDELAY
198****************************************************************************/
199int set_blocking(int fd, int set)
200{
201 int val;
202#ifdef O_NONBLOCK
203#define FLAG_TO_SET O_NONBLOCK
204#else
205#ifdef SYSV
206#define FLAG_TO_SET O_NDELAY
207#else /* BSD */
208#define FLAG_TO_SET FNDELAY
209#endif
210#endif
211
212 if((val = fcntl(fd, F_GETFL, 0)) == -1)
213 return -1;
214 if(set) /* Turn blocking on - ie. clear nonblock flag */
215 val &= ~FLAG_TO_SET;
216 else
217 val |= FLAG_TO_SET;
218 return fcntl( fd, F_SETFL, val);
219#undef FLAG_TO_SET
220}