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