1 | #include "specs.hpp" |
---|
2 | #include "nfserver.hpp" |
---|
3 | #include "dprint.hpp" |
---|
4 | #include "crc.hpp" |
---|
5 | #include "cache.hpp" |
---|
6 | #include <sys/types.h> |
---|
7 | #include <fcntl.h> |
---|
8 | #include <unistd.h> |
---|
9 | |
---|
10 | class nfs_file : public bFILE |
---|
11 | { |
---|
12 | jFILE *local; |
---|
13 | int nfs_fd; |
---|
14 | int offset; |
---|
15 | public : |
---|
16 | nfs_file(char *filename, char *mode); |
---|
17 | virtual int open_failure(); |
---|
18 | virtual int unbuffered_read(void *buf, size_t count); // returns number of bytes read |
---|
19 | int new_read(void *buf, size_t count); // returns number of bytes read |
---|
20 | virtual int unbuffered_write(void *buf, size_t count); // returns number of bytes written |
---|
21 | virtual int unbuffered_seek(long offset, int whence); // whence=SEEK_SET, SEEK_CUR, SEEK_END, ret=0=success |
---|
22 | virtual int unbuffered_tell(); |
---|
23 | virtual int file_size(); |
---|
24 | virtual ~nfs_file(); |
---|
25 | } ; |
---|
26 | |
---|
27 | bFILE *open_nfs_file(char *filename,char *mode) |
---|
28 | { |
---|
29 | return new nfs_file(filename,mode); |
---|
30 | } |
---|
31 | |
---|
32 | |
---|
33 | static out_socket *nfs_server=NULL; |
---|
34 | void connect_to_nfs_server(char *name, int port) |
---|
35 | { |
---|
36 | nfs_server=create_out_socket(name,port); |
---|
37 | if (!nfs_server) |
---|
38 | { |
---|
39 | fprintf(stderr,"%s\n",last_sock_err); |
---|
40 | exit(0); |
---|
41 | } else |
---|
42 | { |
---|
43 | set_file_opener(open_nfs_file); // from now on all files wll go through NFS creator |
---|
44 | } |
---|
45 | } |
---|
46 | |
---|
47 | static void nfs_disconnect() |
---|
48 | { |
---|
49 | if (nfs_server) |
---|
50 | { |
---|
51 | delete nfs_server; |
---|
52 | nfs_server=NULL; |
---|
53 | set_file_opener(NULL); // use local means for opening files |
---|
54 | } |
---|
55 | } |
---|
56 | |
---|
57 | |
---|
58 | nfs_file::nfs_file(char *filename, char *mode) |
---|
59 | { |
---|
60 | int local_only=0; |
---|
61 | for (char *s=mode;*s;s++) // check to see if writeable file, if so don't go through nfs |
---|
62 | if (*s=='w' || *s=='W' || *s=='a' || *s=='A') |
---|
63 | local_only=1; |
---|
64 | if (local_only) |
---|
65 | { |
---|
66 | local=new jFILE(filename,mode); |
---|
67 | nfs_fd=-1; |
---|
68 | } |
---|
69 | else |
---|
70 | { |
---|
71 | local=NULL; |
---|
72 | nfs_fd=-1; |
---|
73 | if (nfs_server) |
---|
74 | { |
---|
75 | packet pk; |
---|
76 | int do_open=0; |
---|
77 | jFILE *local_test=new jFILE(filename,mode); |
---|
78 | if (local_test->open_failure()) |
---|
79 | { |
---|
80 | delete local_test; |
---|
81 | local_test=NULL; |
---|
82 | pk.write_byte(NFS_OPEN); |
---|
83 | } |
---|
84 | else |
---|
85 | { |
---|
86 | pk.write_byte(NFS_CRC_OPEN); |
---|
87 | int fail; |
---|
88 | ulong crc=crc_man.get_crc(crc_man.get_filenumber(filename),fail); // skip crc calc if we can |
---|
89 | if (fail) crc=crc_file(local_test); |
---|
90 | pk.write_long(crc); |
---|
91 | } |
---|
92 | |
---|
93 | pk.write_byte(strlen(filename)+1); |
---|
94 | pk.write((uchar *)filename,strlen(filename)+1); |
---|
95 | pk.write_byte(strlen(mode)+1); |
---|
96 | pk.write((uchar *)mode,strlen(mode)+1); |
---|
97 | dprintf("try open %s,%s\n",filename,mode); |
---|
98 | offset=0; |
---|
99 | if (!nfs_server->send(pk)) |
---|
100 | nfs_disconnect(); |
---|
101 | else |
---|
102 | { |
---|
103 | if (!nfs_server->get(pk)) nfs_disconnect(); |
---|
104 | else |
---|
105 | { |
---|
106 | long fd; |
---|
107 | if (pk.read((uchar *)&fd,4)!=4) |
---|
108 | nfs_disconnect(); |
---|
109 | else |
---|
110 | { |
---|
111 | fd=lltl(fd); |
---|
112 | nfs_fd=fd; |
---|
113 | if (local_test && fd==-2) // confirmed that CRCs match, use local file |
---|
114 | { local=local_test; local_test=NULL; } |
---|
115 | |
---|
116 | } |
---|
117 | } |
---|
118 | } |
---|
119 | if (local_test) |
---|
120 | delete local_test; |
---|
121 | } |
---|
122 | } |
---|
123 | } |
---|
124 | |
---|
125 | |
---|
126 | int nfs_file::open_failure() { return !local && nfs_fd==-1; } |
---|
127 | |
---|
128 | int nfs_file::unbuffered_read(void *buf, size_t count) // returns number of bytes read |
---|
129 | { |
---|
130 | if (local) |
---|
131 | return local->read(buf,count); |
---|
132 | else |
---|
133 | { |
---|
134 | int ret=new_read(buf,count); |
---|
135 | void *comp=jmalloc(count,"compare"); |
---|
136 | /* ::read(check_fd,comp,count); |
---|
137 | if (memcmp(comp,buf,count)) |
---|
138 | { |
---|
139 | printf("bad read!\n"); |
---|
140 | } |
---|
141 | jfree(comp);*/ |
---|
142 | return ret; |
---|
143 | } |
---|
144 | } |
---|
145 | |
---|
146 | int nfs_file::new_read(void *buf, size_t count) // returns number of bytes read |
---|
147 | { |
---|
148 | if (local) |
---|
149 | return local->read(buf,count); |
---|
150 | else |
---|
151 | { |
---|
152 | packet pk; |
---|
153 | pk.write_byte(NFS_READ); |
---|
154 | pk.write_long(nfs_fd); |
---|
155 | pk.write_long(count); |
---|
156 | dprintf("try read %d,%d\n",nfs_fd,count); |
---|
157 | if (!nfs_server->send(pk)) |
---|
158 | { |
---|
159 | nfs_disconnect(); |
---|
160 | return 0; |
---|
161 | } |
---|
162 | else |
---|
163 | { |
---|
164 | |
---|
165 | int fail=0; |
---|
166 | int rtotal=0; |
---|
167 | ushort size=1; |
---|
168 | while (count>0 && !fail && size) |
---|
169 | { |
---|
170 | if (!nfs_server->get(pk)) fail=1; |
---|
171 | else |
---|
172 | { |
---|
173 | if (pk.read((uchar *)&size,2)!=2) fail=1; |
---|
174 | else |
---|
175 | { |
---|
176 | size=lstl(size); |
---|
177 | printf("read %d bytes\n",size); |
---|
178 | if (size) |
---|
179 | { |
---|
180 | int need_size=size>count ? count : size; |
---|
181 | |
---|
182 | if (pk.read((uchar *)buf,need_size)!=need_size) fail=1; |
---|
183 | else |
---|
184 | { |
---|
185 | count-=need_size; |
---|
186 | rtotal+=need_size; |
---|
187 | buf=(void *)(((char *)buf)+need_size); |
---|
188 | offset+=need_size; |
---|
189 | if (need_size<size) // see if there are any leftovers to buffer |
---|
190 | fprintf(stderr,"Server sent to much\n"); |
---|
191 | } |
---|
192 | if (need_size<2048) count=0; |
---|
193 | } |
---|
194 | } |
---|
195 | } |
---|
196 | } |
---|
197 | if (fail) |
---|
198 | { |
---|
199 | dprintf("nfs read failed\n"); |
---|
200 | nfs_disconnect(); |
---|
201 | } |
---|
202 | return rtotal; |
---|
203 | } |
---|
204 | } |
---|
205 | } |
---|
206 | |
---|
207 | |
---|
208 | int nfs_file::unbuffered_write(void *buf, size_t count) // returns number of bytes written |
---|
209 | { |
---|
210 | if (local) |
---|
211 | return local->write(buf,count); |
---|
212 | else |
---|
213 | { |
---|
214 | fprintf(stderr,"write to nfs file not allowed for now!\n"); |
---|
215 | exit(0); |
---|
216 | } |
---|
217 | return 0; |
---|
218 | } |
---|
219 | |
---|
220 | |
---|
221 | int nfs_file::unbuffered_seek(long off, int whence) // whence=SEEK_SET, SEEK_CUR, SEEK_END, ret=0=success |
---|
222 | { |
---|
223 | if (local) |
---|
224 | return local->seek(off,whence); |
---|
225 | else |
---|
226 | { |
---|
227 | packet pk; |
---|
228 | pk.write_byte(NFS_SEEK); |
---|
229 | pk.write_long(nfs_fd); |
---|
230 | |
---|
231 | pk.write_long(off); |
---|
232 | pk.write_long(whence); |
---|
233 | dprintf("seek %d %d %d\n",nfs_fd,off,whence); |
---|
234 | if (!nfs_server->send(pk)) |
---|
235 | { |
---|
236 | dprintf("disconnected on seek\n"); |
---|
237 | nfs_disconnect(); |
---|
238 | return 0; |
---|
239 | } |
---|
240 | } |
---|
241 | return 0; |
---|
242 | } |
---|
243 | |
---|
244 | int nfs_file::unbuffered_tell() |
---|
245 | { |
---|
246 | if (local) |
---|
247 | return local->tell(); |
---|
248 | else if (nfs_server) |
---|
249 | { |
---|
250 | packet pk; |
---|
251 | pk.write_byte(NFS_TELL); |
---|
252 | pk.write_long(nfs_fd); |
---|
253 | if (!nfs_server->send(pk)) |
---|
254 | { |
---|
255 | nfs_disconnect(); |
---|
256 | return 0; |
---|
257 | } else |
---|
258 | { |
---|
259 | if (!nfs_server->get(pk)) |
---|
260 | { |
---|
261 | nfs_disconnect(); |
---|
262 | return 0; |
---|
263 | } else |
---|
264 | { |
---|
265 | long off; |
---|
266 | if (pk.read((uchar *)&off,4)!=4) |
---|
267 | { |
---|
268 | dprintf("Disconnected on tell()\n"); |
---|
269 | nfs_disconnect(); |
---|
270 | } else return lltl(off); |
---|
271 | |
---|
272 | } |
---|
273 | } |
---|
274 | } |
---|
275 | return 0; |
---|
276 | } |
---|
277 | |
---|
278 | |
---|
279 | int nfs_file::file_size() |
---|
280 | { |
---|
281 | if (local) |
---|
282 | return local->file_size(); |
---|
283 | else if (nfs_server) |
---|
284 | { |
---|
285 | packet pk; |
---|
286 | pk.write_byte(NFS_FILESIZE); |
---|
287 | pk.write_long(nfs_fd); |
---|
288 | if (!nfs_server->send(pk)) |
---|
289 | { |
---|
290 | nfs_disconnect(); |
---|
291 | return 0; |
---|
292 | } else |
---|
293 | { |
---|
294 | if (!nfs_server->get(pk)) |
---|
295 | { |
---|
296 | nfs_disconnect(); |
---|
297 | return 0; |
---|
298 | } else |
---|
299 | { |
---|
300 | long size; |
---|
301 | if (pk.read((uchar *)&size,4)!=4) |
---|
302 | { |
---|
303 | dprintf("disconnected on filesize\n"); |
---|
304 | nfs_disconnect(); |
---|
305 | } |
---|
306 | else return lltl(size); |
---|
307 | } |
---|
308 | } |
---|
309 | } |
---|
310 | return 0; |
---|
311 | } |
---|
312 | |
---|
313 | nfs_file::~nfs_file() |
---|
314 | { |
---|
315 | flush_writes(); |
---|
316 | if (local) delete local; |
---|
317 | else if (nfs_server && !open_failure()) |
---|
318 | { |
---|
319 | packet pk; |
---|
320 | pk.write_byte(NFS_CLOSE); |
---|
321 | pk.write_long(nfs_fd); |
---|
322 | dprintf("close %d\n",nfs_fd); |
---|
323 | if (!nfs_server->send(pk)) |
---|
324 | { |
---|
325 | dprintf("disconnected on close\n"); |
---|
326 | nfs_disconnect(); |
---|
327 | } |
---|
328 | } |
---|
329 | } |
---|
330 | |
---|
331 | |
---|
332 | |
---|
333 | |
---|