1 |
/********************************************************************* |
2 |
* Copyright (C) 2003 Tord Lindstrom (pukko@home.se) |
3 |
* Copyright (C) 2004 adresd (adresd_ps2dev@yahoo.com) |
4 |
* This file is subject to the terms and conditions of the PS2Link License. |
5 |
* See the file LICENSE in the main directory of this distribution for more |
6 |
* details. |
7 |
*/ |
8 |
|
9 |
// Fu*k knows why net_fio & net_fsys are separated.. |
10 |
|
11 |
#include <types.h> |
12 |
#include <ioman.h> |
13 |
#include <sysclib.h> |
14 |
#include <stdio.h> |
15 |
#include <thbase.h> |
16 |
|
17 |
#include <io_common.h> |
18 |
|
19 |
#include "ps2ip.h" |
20 |
#include "net_fio.h" |
21 |
#include "hostlink.h" |
22 |
|
23 |
#define ntohl(x) htonl(x) |
24 |
#define ntohs(x) htons(x) |
25 |
|
26 |
unsigned int remote_pc_addr = 0xffffffff; |
27 |
|
28 |
#define PACKET_MAXSIZE 4096 |
29 |
|
30 |
static char send_packet[PACKET_MAXSIZE] __attribute__((aligned(16))); |
31 |
static char recv_packet[PACKET_MAXSIZE] __attribute__((aligned(16))); |
32 |
|
33 |
static int pko_fileio_sock = -1; |
34 |
static int pko_fileio_active = 0; |
35 |
|
36 |
#ifdef DEBUG |
37 |
#define dbgprintf(args...) printf(args) |
38 |
#else |
39 |
#define dbgprintf(args...) do { } while(0) |
40 |
#endif |
41 |
|
42 |
//---------------------------------------------------------------------- |
43 |
// |
44 |
void |
45 |
pko_close_socket(void) |
46 |
{ |
47 |
int ret; |
48 |
|
49 |
ret = disconnect(pko_fileio_sock); |
50 |
if (ret < 0) { |
51 |
printf("pko_file: disconnect returned error %d\n", ret); |
52 |
} |
53 |
pko_fileio_sock = -1; |
54 |
} |
55 |
|
56 |
//---------------------------------------------------------------------- |
57 |
// |
58 |
void |
59 |
pko_close_fsys(void) |
60 |
{ |
61 |
if (pko_fileio_sock > 0) { |
62 |
disconnect(pko_fileio_sock); |
63 |
} |
64 |
pko_fileio_active = 0; |
65 |
return; |
66 |
} |
67 |
|
68 |
//---------------------------------------------------------------------- |
69 |
// XXX: Hm, this func should behave sorta like pko_recv_bytes imho.. |
70 |
// i.e. check if it was able to send just a part of the packet etc.. |
71 |
static inline int |
72 |
pko_lwip_send(int sock, void *buf, int len, int flag) |
73 |
{ |
74 |
int ret; |
75 |
ret = send(sock, buf, len, flag); |
76 |
if (ret < 0) { |
77 |
dbgprintf("pko_file: lwip_send() error %d\n", ret); |
78 |
pko_close_socket(); |
79 |
return -1; |
80 |
} |
81 |
else { |
82 |
return ret; |
83 |
} |
84 |
} |
85 |
|
86 |
|
87 |
//---------------------------------------------------------------------- |
88 |
// Do repetetive recv() calles until 'bytes' bytes are received |
89 |
// or error returned |
90 |
int pko_recv_bytes(int sock, char *buf, int bytes) |
91 |
{ |
92 |
int left; |
93 |
int len; |
94 |
|
95 |
left = bytes; |
96 |
|
97 |
while (left > 0) { |
98 |
len = recv(sock, &buf[bytes - left], left, 0); |
99 |
if (len < 0) { |
100 |
dbgprintf("pko_file: pko_recv_bytes error!!\n"); |
101 |
return -1; |
102 |
} |
103 |
left -= len; |
104 |
} |
105 |
return bytes; |
106 |
} |
107 |
|
108 |
|
109 |
//---------------------------------------------------------------------- |
110 |
// Receive a 'packet' of the expected type 'pkt_type', and lenght 'len' |
111 |
int pko_accept_pkt(int sock, char *buf, int len, int pkt_type) |
112 |
{ |
113 |
int length; |
114 |
pko_pkt_hdr *hdr; |
115 |
unsigned int hcmd; |
116 |
unsigned short hlen; |
117 |
|
118 |
|
119 |
length = pko_recv_bytes(sock, buf, sizeof(pko_pkt_hdr)); |
120 |
if (length < 0) { |
121 |
dbgprintf("pko_file: accept_pkt recv error\n"); |
122 |
return -1; |
123 |
} |
124 |
|
125 |
if (length < sizeof(pko_pkt_hdr)) { |
126 |
dbgprintf("pko_file: XXX: did not receive a full header!!!! " |
127 |
"Fix this! (%d)\n", length); |
128 |
} |
129 |
|
130 |
hdr = (pko_pkt_hdr *)buf; |
131 |
hcmd = ntohl(hdr->cmd); |
132 |
hlen = ntohs(hdr->len); |
133 |
|
134 |
if (hcmd != pkt_type) { |
135 |
dbgprintf("pko_file: pko_accept_pkt: Expected %x, got %x\n", |
136 |
pkt_type, hcmd); |
137 |
return 0; |
138 |
} |
139 |
|
140 |
if (hlen > len) { |
141 |
dbgprintf("pko_file: pko_accept_pkt: hdr->len is too large!! " |
142 |
"(%d, can only receive %d)\n", hlen, len); |
143 |
return 0; |
144 |
} |
145 |
|
146 |
// get the actual packet data |
147 |
length = pko_recv_bytes(sock, buf + sizeof(pko_pkt_hdr), |
148 |
hlen - sizeof(pko_pkt_hdr)); |
149 |
|
150 |
if (length < 0) { |
151 |
dbgprintf("pko_file: accept recv2 error!!\n"); |
152 |
return 0; |
153 |
} |
154 |
|
155 |
if (length < (hlen - sizeof(pko_pkt_hdr))) { |
156 |
dbgprintf("pko_accept_pkt: Did not receive full packet!!! " |
157 |
"Fix this! (%d)\n", length); |
158 |
} |
159 |
|
160 |
return 1; |
161 |
} |
162 |
|
163 |
//---------------------------------------------------------------------- |
164 |
// |
165 |
int pko_open_file(char *path, int flags) |
166 |
{ |
167 |
pko_pkt_open_req *openreq; |
168 |
pko_pkt_file_rly *openrly; |
169 |
|
170 |
if (pko_fileio_sock < 0) { |
171 |
return -1; |
172 |
} |
173 |
|
174 |
dbgprintf("pko_file: file open req (%s, %x)\n", path, flags); |
175 |
|
176 |
openreq = (pko_pkt_open_req *)&send_packet[0]; |
177 |
|
178 |
// Build packet |
179 |
openreq->cmd = htonl(PKO_OPEN_CMD); |
180 |
openreq->len = htons((unsigned short)sizeof(pko_pkt_open_req)); |
181 |
openreq->flags = htonl(flags); |
182 |
strncpy(openreq->path, path, PKO_MAX_PATH); |
183 |
openreq->path[PKO_MAX_PATH - 1] = 0; // Make sure it's null-terminated |
184 |
|
185 |
if (pko_lwip_send(pko_fileio_sock, openreq, sizeof(pko_pkt_open_req), 0) < 0) { |
186 |
return -1; |
187 |
} |
188 |
|
189 |
if (!pko_accept_pkt(pko_fileio_sock, recv_packet, |
190 |
sizeof(pko_pkt_file_rly), PKO_OPEN_RLY)) { |
191 |
dbgprintf("pko_file: pko_open_file: did not receive OPEN_RLY\n"); |
192 |
return -1; |
193 |
} |
194 |
|
195 |
openrly = (pko_pkt_file_rly *)recv_packet; |
196 |
|
197 |
dbgprintf("pko_file: file open reply received (ret %d)\n", ntohl(openrly->retval)); |
198 |
|
199 |
return ntohl(openrly->retval); |
200 |
} |
201 |
|
202 |
|
203 |
//---------------------------------------------------------------------- |
204 |
// |
205 |
int pko_close_file(int fd) |
206 |
{ |
207 |
pko_pkt_close_req *closereq; |
208 |
pko_pkt_file_rly *closerly; |
209 |
|
210 |
|
211 |
if (pko_fileio_sock < 0) { |
212 |
return -1; |
213 |
} |
214 |
|
215 |
dbgprintf("pko_file: file close req (fd: %d)\n", fd); |
216 |
|
217 |
closereq = (pko_pkt_close_req *)&send_packet[0]; |
218 |
closerly = (pko_pkt_file_rly *)&recv_packet[0]; |
219 |
|
220 |
closereq->cmd = htonl(PKO_CLOSE_CMD); |
221 |
closereq->len = htons((unsigned short)sizeof(pko_pkt_close_req)); |
222 |
closereq->fd = htonl(fd); |
223 |
|
224 |
if (pko_lwip_send(pko_fileio_sock, closereq, sizeof(pko_pkt_close_req), 0) < 0) { |
225 |
return -1; |
226 |
} |
227 |
|
228 |
if(!pko_accept_pkt(pko_fileio_sock, (char *)closerly, |
229 |
sizeof(pko_pkt_file_rly), PKO_CLOSE_RLY)) { |
230 |
dbgprintf("pko_file: pko_close_file: did not receive PKO_CLOSE_RLY\n"); |
231 |
return -1; |
232 |
} |
233 |
|
234 |
dbgprintf("pko_file: pko_close_file: close reply received (ret %d)\n", |
235 |
ntohl(closerly->retval)); |
236 |
|
237 |
return ntohl(closerly->retval); |
238 |
} |
239 |
|
240 |
//---------------------------------------------------------------------- |
241 |
// |
242 |
int pko_lseek_file(int fd, unsigned int offset, int whence) |
243 |
{ |
244 |
pko_pkt_lseek_req *lseekreq; |
245 |
pko_pkt_file_rly *lseekrly; |
246 |
|
247 |
|
248 |
if (pko_fileio_sock < 0) { |
249 |
return -1; |
250 |
} |
251 |
|
252 |
dbgprintf("pko_file: file lseek req (fd: %d)\n", fd); |
253 |
|
254 |
lseekreq = (pko_pkt_lseek_req *)&send_packet[0]; |
255 |
lseekrly = (pko_pkt_file_rly *)&recv_packet[0]; |
256 |
|
257 |
lseekreq->cmd = htonl(PKO_LSEEK_CMD); |
258 |
lseekreq->len = htons((unsigned short)sizeof(pko_pkt_lseek_req)); |
259 |
lseekreq->fd = htonl(fd); |
260 |
lseekreq->offset = htonl(offset); |
261 |
lseekreq->whence = htonl(whence); |
262 |
|
263 |
if(pko_lwip_send(pko_fileio_sock, lseekreq, sizeof(pko_pkt_lseek_req), 0) < 0) { |
264 |
return -1; |
265 |
} |
266 |
|
267 |
if(!pko_accept_pkt(pko_fileio_sock, (char *)lseekrly, |
268 |
sizeof(pko_pkt_file_rly), PKO_LSEEK_RLY)) { |
269 |
dbgprintf("pko_file: pko_lseek_file: did not receive PKO_LSEEK_RLY\n"); |
270 |
return -1; |
271 |
} |
272 |
|
273 |
dbgprintf("pko_file: pko_lseek_file: lseek reply received (ret %d)\n", |
274 |
ntohl(lseekrly->retval)); |
275 |
|
276 |
return ntohl(lseekrly->retval); |
277 |
|
278 |
} |
279 |
|
280 |
|
281 |
//---------------------------------------------------------------------- |
282 |
// |
283 |
int pko_write_file(int fd, char *buf, int length) |
284 |
{ |
285 |
pko_pkt_write_req *writecmd; |
286 |
pko_pkt_file_rly *writerly; |
287 |
int hlen; |
288 |
int writtenbytes; |
289 |
int nbytes; |
290 |
int retval; |
291 |
|
292 |
if (pko_fileio_sock < 0) { |
293 |
return -1; |
294 |
} |
295 |
|
296 |
dbgprintf("pko_file: file write req (fd: %d)\n", fd); |
297 |
|
298 |
writecmd = (pko_pkt_write_req *)&send_packet[0]; |
299 |
writerly = (pko_pkt_file_rly *)&recv_packet[0]; |
300 |
|
301 |
hlen = (unsigned short)sizeof(pko_pkt_write_req); |
302 |
writecmd->cmd = htonl(PKO_WRITE_CMD); |
303 |
writecmd->len = htons(hlen); |
304 |
writecmd->fd = htonl(fd); |
305 |
|
306 |
// Divide the write request |
307 |
writtenbytes = 0; |
308 |
while (writtenbytes < length) { |
309 |
|
310 |
if ((length - writtenbytes) > PKO_MAX_WRITE_SEGMENT) { |
311 |
// Need to split in several read reqs |
312 |
nbytes = PKO_MAX_READ_SEGMENT; |
313 |
} |
314 |
else { |
315 |
nbytes = length - writtenbytes; |
316 |
} |
317 |
|
318 |
writecmd->nbytes = htonl(nbytes); |
319 |
#ifdef ZEROCOPY |
320 |
/* Send the packet header. */ |
321 |
if (pko_lwip_send(pko_fileio_sock, writecmd, hlen, 0) < 0) |
322 |
return -1; |
323 |
/* Send the write() data. */ |
324 |
if (pko_lwip_send(pko_fileio_sock, &buf[writtenbytes], nbytes, 0) < 0) |
325 |
return -1; |
326 |
#else |
327 |
// Copy data to the acutal packet |
328 |
memcpy(&send_packet[sizeof(pko_pkt_write_req)], &buf[writtenbytes], |
329 |
nbytes); |
330 |
|
331 |
if (pko_lwip_send(pko_fileio_sock, writecmd, hlen + nbytes, 0) < 0) |
332 |
return -1; |
333 |
#endif |
334 |
|
335 |
|
336 |
// Get reply |
337 |
if(!pko_accept_pkt(pko_fileio_sock, (char *)writerly, |
338 |
sizeof(pko_pkt_file_rly), PKO_WRITE_RLY)) { |
339 |
dbgprintf("pko_file: pko_write_file: " |
340 |
"did not receive PKO_WRITE_RLY\n"); |
341 |
return -1; |
342 |
} |
343 |
retval = ntohl(writerly->retval); |
344 |
|
345 |
dbgprintf("pko_file: wrote %d bytes (asked for %d)\n", |
346 |
retval, nbytes); |
347 |
|
348 |
if (retval < 0) { |
349 |
// Error |
350 |
dbgprintf("pko_file: pko_write_file: received error on write req (%d)\n", |
351 |
retval); |
352 |
return retval; |
353 |
} |
354 |
|
355 |
writtenbytes += retval; |
356 |
if (retval < nbytes) { |
357 |
// EOF? |
358 |
break; |
359 |
} |
360 |
} |
361 |
return writtenbytes; |
362 |
} |
363 |
|
364 |
//---------------------------------------------------------------------- |
365 |
// |
366 |
int pko_read_file(int fd, char *buf, int length) |
367 |
{ |
368 |
int readbytes; |
369 |
int nbytes; |
370 |
int i; |
371 |
pko_pkt_read_req *readcmd; |
372 |
pko_pkt_read_rly *readrly; |
373 |
|
374 |
|
375 |
if (pko_fileio_sock < 0) { |
376 |
return -1; |
377 |
} |
378 |
|
379 |
readcmd = (pko_pkt_read_req *)&send_packet[0]; |
380 |
readrly = (pko_pkt_read_rly *)&recv_packet[0]; |
381 |
readbytes = 0; |
382 |
|
383 |
readcmd->cmd = htonl(PKO_READ_CMD); |
384 |
readcmd->len = htons((unsigned short)sizeof(pko_pkt_read_req)); |
385 |
readcmd->fd = htonl(fd); |
386 |
|
387 |
readbytes = 0; |
388 |
|
389 |
if (length < 0) { |
390 |
dbgprintf("pko_read_file: illegal req!! (whish to read < 0 bytes!)\n"); |
391 |
return -1; |
392 |
} |
393 |
|
394 |
readcmd->nbytes = htonl(length); |
395 |
|
396 |
i = send(pko_fileio_sock, readcmd, sizeof(pko_pkt_read_req), 0); |
397 |
if (i<0) |
398 |
{ |
399 |
dbgprintf("pko_file: pko_read_file: send failed (%d)\n", i); |
400 |
return -1; |
401 |
} |
402 |
|
403 |
if(!pko_accept_pkt(pko_fileio_sock, (char *)readrly, |
404 |
sizeof(pko_pkt_read_rly), PKO_READ_RLY)) { |
405 |
dbgprintf("pko_file: pko_read_file: " |
406 |
"did not receive PKO_READ_RLY\n"); |
407 |
return -1; |
408 |
} |
409 |
|
410 |
nbytes = ntohl(readrly->nbytes); |
411 |
dbgprintf("pko_file: pko_read_file: Reply said there's %d bytes to read " |
412 |
"(wanted %d)\n", nbytes, length); |
413 |
|
414 |
// Now read the actual file data |
415 |
i = pko_recv_bytes(pko_fileio_sock, &buf[0], nbytes); |
416 |
if (i < 0) { |
417 |
dbgprintf("pko_file: pko_read_file: data read error\n"); |
418 |
return -1; |
419 |
} |
420 |
return nbytes; |
421 |
return readbytes; |
422 |
} |
423 |
|
424 |
//---------------------------------------------------------------------- |
425 |
// |
426 |
int pko_ioctl(int fd, unsigned long request, void *data) |
427 |
{ |
428 |
pko_pkt_ioctl_req *ioctlreq; |
429 |
pko_pkt_file_rly *ioctlrly; |
430 |
|
431 |
if (pko_fileio_sock < 0) { |
432 |
return -1; |
433 |
} |
434 |
|
435 |
dbgprintf("pko_file: ioctl req (%x)\n", request); |
436 |
|
437 |
ioctlreq = (pko_pkt_ioctl_req *)&send_packet[0]; |
438 |
|
439 |
// Build packet |
440 |
ioctlreq->cmd = htonl(PKO_IOCTL_CMD); |
441 |
ioctlreq->len = htons((unsigned short)sizeof(pko_pkt_ioctl_req)); |
442 |
ioctlreq->fd = htonl(fd); |
443 |
ioctlreq->request = htonl(request); |
444 |
memcpy(ioctlreq->data, data, 256); |
445 |
|
446 |
if (pko_lwip_send(pko_fileio_sock, ioctlreq, sizeof(pko_pkt_ioctl_req), 0) < 0) { |
447 |
return -1; |
448 |
} |
449 |
|
450 |
if (!pko_accept_pkt(pko_fileio_sock, recv_packet, |
451 |
sizeof(pko_pkt_file_rly), PKO_IOCTL_RLY)) { |
452 |
dbgprintf("pko_file: pko_ioctl: did not receive IOCTL_RLY\n"); |
453 |
return -1; |
454 |
} |
455 |
|
456 |
ioctlrly = (pko_pkt_file_rly *)recv_packet; |
457 |
dbgprintf("pko_file: ioctl reply received (ret %d)\n", ntohl(ioctlrly->retval)); |
458 |
return ntohl(ioctlrly->retval); |
459 |
} |
460 |
|
461 |
//---------------------------------------------------------------------- |
462 |
// |
463 |
int pko_remove(char *name) |
464 |
{ |
465 |
pko_pkt_remove_req *removereq; |
466 |
pko_pkt_file_rly *removerly; |
467 |
|
468 |
if (pko_fileio_sock < 0) { |
469 |
return -1; |
470 |
} |
471 |
|
472 |
dbgprintf("pko_file: file remove req (%s)\n", name); |
473 |
|
474 |
removereq = (pko_pkt_remove_req *)&send_packet[0]; |
475 |
|
476 |
// Build packet |
477 |
removereq->cmd = htonl(PKO_REMOVE_CMD); |
478 |
removereq->len = htons((unsigned short)sizeof(pko_pkt_remove_req)); |
479 |
strncpy(removereq->name, name, PKO_MAX_PATH); |
480 |
removereq->name[PKO_MAX_PATH - 1] = 0; // Make sure it's null-terminated |
481 |
|
482 |
if (pko_lwip_send(pko_fileio_sock, removereq, sizeof(pko_pkt_remove_req), 0) < 0) { |
483 |
return -1; |
484 |
} |
485 |
|
486 |
if (!pko_accept_pkt(pko_fileio_sock, recv_packet, |
487 |
sizeof(pko_pkt_file_rly), PKO_REMOVE_RLY)) { |
488 |
dbgprintf("pko_file: pko_remove: did not receive REMOVE_RLY\n"); |
489 |
return -1; |
490 |
} |
491 |
|
492 |
removerly = (pko_pkt_file_rly *)recv_packet; |
493 |
dbgprintf("pko_file: file remove reply received (ret %d)\n", ntohl(removerly->retval)); |
494 |
return ntohl(removerly->retval); |
495 |
} |
496 |
|
497 |
//---------------------------------------------------------------------- |
498 |
// |
499 |
int pko_mkdir(char *name, int mode) |
500 |
{ |
501 |
pko_pkt_mkdir_req *mkdirreq; |
502 |
pko_pkt_file_rly *mkdirrly; |
503 |
|
504 |
if (pko_fileio_sock < 0) { |
505 |
return -1; |
506 |
} |
507 |
|
508 |
dbgprintf("pko_file: make dir req (%s)\n", name); |
509 |
|
510 |
mkdirreq = (pko_pkt_mkdir_req *)&send_packet[0]; |
511 |
|
512 |
// Build packet |
513 |
mkdirreq->cmd = htonl(PKO_MKDIR_CMD); |
514 |
mkdirreq->len = htons((unsigned short)sizeof(pko_pkt_mkdir_req)); |
515 |
mkdirreq->mode = mode; |
516 |
strncpy(mkdirreq->name, name, PKO_MAX_PATH); |
517 |
mkdirreq->name[PKO_MAX_PATH - 1] = 0; // Make sure it's null-terminated |
518 |
|
519 |
if (pko_lwip_send(pko_fileio_sock, mkdirreq, sizeof(pko_pkt_mkdir_req), 0) < 0) { |
520 |
return -1; |
521 |
} |
522 |
|
523 |
if (!pko_accept_pkt(pko_fileio_sock, recv_packet, |
524 |
sizeof(pko_pkt_file_rly), PKO_MKDIR_RLY)) { |
525 |
dbgprintf("pko_file: pko_mkdir: did not receive MKDIR_RLY\n"); |
526 |
return -1; |
527 |
} |
528 |
|
529 |
mkdirrly = (pko_pkt_file_rly *)recv_packet; |
530 |
dbgprintf("pko_file: make dir reply received (ret %d)\n", ntohl(mkdirrly->retval)); |
531 |
return ntohl(mkdirrly->retval); |
532 |
} |
533 |
|
534 |
//---------------------------------------------------------------------- |
535 |
// |
536 |
int pko_rmdir(char *name) |
537 |
{ |
538 |
pko_pkt_rmdir_req *rmdirreq; |
539 |
pko_pkt_file_rly *rmdirrly; |
540 |
|
541 |
if (pko_fileio_sock < 0) { |
542 |
return -1; |
543 |
} |
544 |
|
545 |
dbgprintf("pko_file: remove dir req (%s)\n", name); |
546 |
|
547 |
rmdirreq = (pko_pkt_rmdir_req *)&send_packet[0]; |
548 |
|
549 |
// Build packet |
550 |
rmdirreq->cmd = htonl(PKO_RMDIR_CMD); |
551 |
rmdirreq->len = htons((unsigned short)sizeof(pko_pkt_rmdir_req)); |
552 |
strncpy(rmdirreq->name, name, PKO_MAX_PATH); |
553 |
rmdirreq->name[PKO_MAX_PATH - 1] = 0; // Make sure it's null-terminated |
554 |
|
555 |
if (pko_lwip_send(pko_fileio_sock, rmdirreq, sizeof(pko_pkt_rmdir_req), 0) < 0) { |
556 |
return -1; |
557 |
} |
558 |
|
559 |
if (!pko_accept_pkt(pko_fileio_sock, recv_packet, |
560 |
sizeof(pko_pkt_file_rly), PKO_RMDIR_RLY)) { |
561 |
dbgprintf("pko_file: pko_rmdir: did not receive RMDIR_RLY\n"); |
562 |
return -1; |
563 |
} |
564 |
|
565 |
rmdirrly = (pko_pkt_file_rly *)recv_packet; |
566 |
dbgprintf("pko_file: remove dir reply received (ret %d)\n", ntohl(rmdirrly->retval)); |
567 |
return ntohl(rmdirrly->retval); |
568 |
} |
569 |
|
570 |
//---------------------------------------------------------------------- |
571 |
// |
572 |
int pko_open_dir(char *path) |
573 |
{ |
574 |
pko_pkt_open_req *openreq; |
575 |
pko_pkt_file_rly *openrly; |
576 |
|
577 |
if (pko_fileio_sock < 0) { |
578 |
return -1; |
579 |
} |
580 |
|
581 |
dbgprintf("pko_file: dir open req (%s)\n", path); |
582 |
|
583 |
openreq = (pko_pkt_open_req *)&send_packet[0]; |
584 |
|
585 |
// Build packet |
586 |
openreq->cmd = htonl(PKO_OPENDIR_CMD); |
587 |
openreq->len = htons((unsigned short)sizeof(pko_pkt_open_req)); |
588 |
openreq->flags = htonl(0); |
589 |
strncpy(openreq->path, path, PKO_MAX_PATH); |
590 |
openreq->path[PKO_MAX_PATH - 1] = 0; // Make sure it's null-terminated |
591 |
|
592 |
if (pko_lwip_send(pko_fileio_sock, openreq, sizeof(pko_pkt_open_req), 0) < 0) { |
593 |
return -1; |
594 |
} |
595 |
|
596 |
if (!pko_accept_pkt(pko_fileio_sock, recv_packet, |
597 |
sizeof(pko_pkt_file_rly), PKO_OPENDIR_RLY)) { |
598 |
dbgprintf("pko_file: pko_open_dir: did not receive OPENDIR_RLY\n"); |
599 |
return -1; |
600 |
} |
601 |
|
602 |
openrly = (pko_pkt_file_rly *)recv_packet; |
603 |
|
604 |
dbgprintf("pko_file: dir open reply received (ret %d)\n", ntohl(openrly->retval)); |
605 |
|
606 |
return ntohl(openrly->retval); |
607 |
} |
608 |
|
609 |
//---------------------------------------------------------------------- |
610 |
// |
611 |
int pko_read_dir(int fd, void *buf) |
612 |
{ |
613 |
pko_pkt_dread_req *dirreq; |
614 |
pko_pkt_dread_rly *dirrly; |
615 |
fio_dirent_t *dirent; |
616 |
|
617 |
if (pko_fileio_sock < 0) { |
618 |
return -1; |
619 |
} |
620 |
|
621 |
dbgprintf("pko_file: dir read req (%x)\n", fd); |
622 |
|
623 |
dirreq = (pko_pkt_dread_req *)&send_packet[0]; |
624 |
|
625 |
// Build packet |
626 |
dirreq->cmd = htonl(PKO_READDIR_CMD); |
627 |
dirreq->len = htons((unsigned short)sizeof(pko_pkt_dread_req)); |
628 |
dirreq->fd = htonl(fd); |
629 |
|
630 |
if (pko_lwip_send(pko_fileio_sock, dirreq, sizeof(pko_pkt_dread_req), 0) < 0) { |
631 |
return -1; |
632 |
} |
633 |
|
634 |
if (!pko_accept_pkt(pko_fileio_sock, recv_packet, |
635 |
sizeof(pko_pkt_dread_rly), PKO_READDIR_RLY)) { |
636 |
dbgprintf("pko_file: pko_open_file: did not receive OPENDIR_RLY\n"); |
637 |
return -1; |
638 |
} |
639 |
|
640 |
dirrly = (pko_pkt_dread_rly *)recv_packet; |
641 |
|
642 |
dbgprintf("pko_file: dir read reply received (ret %d)\n", ntohl(dirrly->retval)); |
643 |
|
644 |
dirent = (fio_dirent_t *) buf; |
645 |
// now handle the return buffer translation, to build reply bit |
646 |
dirent->stat.mode = ntohl(dirrly->mode); |
647 |
dirent->stat.attr = ntohl(dirrly->attr); |
648 |
dirent->stat.size = ntohl(dirrly->size); |
649 |
dirent->stat.hisize = ntohl(dirrly->hisize); |
650 |
memcpy(dirent->stat.ctime,dirrly->ctime,8*3); |
651 |
strncpy(dirent->name,dirrly->name,256); |
652 |
dirent->unknown = 0; |
653 |
|
654 |
return ntohl(dirrly->retval); |
655 |
} |
656 |
|
657 |
|
658 |
//---------------------------------------------------------------------- |
659 |
// |
660 |
int pko_close_dir(int fd) |
661 |
{ |
662 |
pko_pkt_close_req *closereq; |
663 |
pko_pkt_file_rly *closerly; |
664 |
|
665 |
|
666 |
if (pko_fileio_sock < 0) { |
667 |
return -1; |
668 |
} |
669 |
|
670 |
dbgprintf("pko_file: dir close req (fd: %d)\n", fd); |
671 |
|
672 |
closereq = (pko_pkt_close_req *)&send_packet[0]; |
673 |
closerly = (pko_pkt_file_rly *)&recv_packet[0]; |
674 |
|
675 |
closereq->cmd = htonl(PKO_CLOSEDIR_CMD); |
676 |
closereq->len = htons((unsigned short)sizeof(pko_pkt_close_req)); |
677 |
closereq->fd = htonl(fd); |
678 |
|
679 |
if (pko_lwip_send(pko_fileio_sock, closereq, sizeof(pko_pkt_close_req), 0) < 0) { |
680 |
return -1; |
681 |
} |
682 |
|
683 |
if(!pko_accept_pkt(pko_fileio_sock, (char *)closerly, |
684 |
sizeof(pko_pkt_file_rly), PKO_CLOSEDIR_RLY)) { |
685 |
dbgprintf("pko_file: pko_close_dir: did not receive PKO_CLOSEDIR_RLY\n"); |
686 |
return -1; |
687 |
} |
688 |
|
689 |
dbgprintf("pko_file: dir close reply received (ret %d)\n", |
690 |
ntohl(closerly->retval)); |
691 |
|
692 |
return ntohl(closerly->retval); |
693 |
} |
694 |
|
695 |
//---------------------------------------------------------------------- |
696 |
// Thread that waits for a PC to connect/disconnect/reconnect blah.. |
697 |
int |
698 |
pko_file_serv(void *argv) |
699 |
{ |
700 |
struct sockaddr_in server_addr; |
701 |
struct sockaddr_in client_addr; |
702 |
int sock; |
703 |
int client_sock; |
704 |
int client_len; |
705 |
int ret; |
706 |
|
707 |
dbgprintf(" - PS2 Side application -\n"); |
708 |
|
709 |
memset((void *)&server_addr, 0, sizeof(server_addr)); |
710 |
// Should perhaps specify PC side ip.. |
711 |
server_addr.sin_family = AF_INET; |
712 |
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); |
713 |
server_addr.sin_port = htons(PKO_PORT); |
714 |
|
715 |
while ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { |
716 |
dbgprintf("pko_file: socket creation error (%d)\n", sock); |
717 |
return -1; |
718 |
} |
719 |
|
720 |
ret = bind(sock, (struct sockaddr *)&server_addr, |
721 |
sizeof(server_addr)); |
722 |
if (ret < 0) { |
723 |
dbgprintf("pko_file: bind error (%d)\n", ret); |
724 |
disconnect(sock); |
725 |
return -1; |
726 |
} |
727 |
|
728 |
ret = listen(sock, 5); |
729 |
|
730 |
if (ret < 0) { |
731 |
dbgprintf("pko_file: listen error (%d)\n", ret); |
732 |
disconnect(sock); |
733 |
return -1; |
734 |
} |
735 |
|
736 |
// Active flag kinda sux, cause it wont be checked until a new client has |
737 |
// connected.. But it's better than nothing and good for now at least |
738 |
pko_fileio_active = 1; |
739 |
|
740 |
// Connection loop |
741 |
while(pko_fileio_active) |
742 |
{ |
743 |
dbgprintf("Waiting for connection\n"); |
744 |
|
745 |
client_len = sizeof(client_addr); |
746 |
client_sock = accept(sock, (struct sockaddr *)&client_addr, |
747 |
&client_len); |
748 |
if (client_sock < 0) { |
749 |
dbgprintf("pko_file: accept error (%d)", client_sock); |
750 |
continue; |
751 |
} |
752 |
|
753 |
dbgprintf("Client connected from %x\n", |
754 |
client_addr.sin_addr.s_addr); |
755 |
|
756 |
remote_pc_addr = client_addr.sin_addr.s_addr; |
757 |
|
758 |
if (pko_fileio_sock > 0) { |
759 |
dbgprintf("Client reconnected\n"); |
760 |
ret = disconnect(pko_fileio_sock); |
761 |
dbgprintf("close ret %d\n", ret); |
762 |
} |
763 |
pko_fileio_sock = client_sock; |
764 |
} |
765 |
|
766 |
if (pko_fileio_sock > 0) { |
767 |
disconnect(pko_fileio_sock); |
768 |
} |
769 |
|
770 |
disconnect(sock); |
771 |
|
772 |
ExitDeleteThread(); |
773 |
return 0; |
774 |
} |