|
NCBI Home IEB Home C Toolkit docs C++ Toolkit source browser C Toolkit source browser (2) |
NCBI C Toolkit Cross ReferenceC/connect/ncbi_ftp_connector.c |
source navigation diff markup identifier search freetext search file search |
1 /* $Id: ncbi_ftp_connector.c,v 1.29 2009/09/30 14:34:42 kazimird Exp $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Anton Lavrentiev
27 *
28 * File Description:
29 * FTP CONNECTOR
30 * See also: RFCs 959 (STD 9), 1634 (FYI 24),
31 * and IETF 9-2002 "Extensions to FTP".
32 *
33 * See <connect/ncbi_connector.h> for the detailed specification of
34 * the connector's methods and structures.
35 *
36 */
37
38 #include "ncbi_ansi_ext.h"
39 #include "ncbi_assert.h"
40 #include "ncbi_priv.h"
41 #include <connect/ncbi_ftp_connector.h>
42 #include <connect/ncbi_socket.h>
43 #include <ctype.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46
47 #define NCBI_USE_ERRCODE_X Connect_FTP
48
49
50 /***********************************************************************
51 * INTERNAL -- Auxiliary types and static functions
52 ***********************************************************************/
53
54 typedef enum {
55 fFtpFeature_MDTM = 1,
56 fFtpFeature_SIZE = 2
57 } EFTP_Feature;
58 typedef unsigned int TFTP_Features; /* bitwise OR of individual EFtpFeature's */
59
60
61 /* All internal data necessary to perform the (re)connect and i/o
62 */
63 typedef struct {
64 const char* host;
65 unsigned short port;
66 const char* user;
67 const char* pass;
68 const char* path;
69 const char* name;
70 TFTP_Features feat;
71 TFCDC_Flags flag;
72 SOCK cntl; /* control connection */
73 SOCK data; /* data connection */
74 BUF wbuf; /* write buffer */
75 EIO_Status r_status; /* pertains to data connection IO */
76 EIO_Status w_status; /* pertains to control connection IO */
77 } SFTPConnector;
78
79
80 static const STimeout kFTPFailsafeTimeout = {10, 0};
81
82
83 static EIO_Status s_ReadReply(SOCK sock, int* code,
84 char* line, size_t maxlinelen)
85 {
86 int/*bool*/ first = 1/*true*/;
87 for (;;) {
88 int c, m;
89 size_t n;
90 char buf[1024];
91 EIO_Status status = SOCK_ReadLine(sock, buf, sizeof(buf), &n);
92 /* All FTP replies are at least '\n'-terminated, no ending with EOF */
93 if (status != eIO_Success)
94 return status;
95 if (n == sizeof(buf))
96 return eIO_Unknown/*line too long*/;
97 if (first || isdigit((unsigned char) *buf)) {
98 if (sscanf(buf, "%d%n", &c, &m) < 1)
99 return eIO_Unknown;
100 } else
101 c = 0;
102 if (first) {
103 if (m != 3 || code == 0)
104 return eIO_Unknown;
105 if (line)
106 strncpy0(line, &buf[m + 1], maxlinelen);
107 *code = c;
108 if (buf[m] != '-') {
109 if (buf[m] == ' ')
110 break;
111 return eIO_Unknown;
112 }
113 first = 0/*false*/;
114 } else if (c == *code && m == 3 && buf[m] == ' ')
115 break;
116 }
117 return eIO_Success;
118 }
119
120
121 static EIO_Status s_FTPReply(SFTPConnector* xxx, int* code,
122 char* line, size_t maxlinelen)
123 {
124 int c = 0;
125 EIO_Status status = eIO_Closed;
126 if (xxx->cntl) {
127 status = s_ReadReply(xxx->cntl, &c, line, maxlinelen);
128 if (status == eIO_Success && c == 421)
129 status = eIO_Closed;
130 if (status == eIO_Closed || (status == eIO_Success && c == 221)) {
131 SOCK_Close(xxx->cntl);
132 xxx->cntl = 0;
133 if (xxx->data) {
134 SOCK_Close(xxx->data);
135 xxx->data = 0;
136 }
137 }
138 }
139 if (code)
140 *code = c;
141 return status;
142 }
143
144
145 static EIO_Status s_FTPDrainReply(SFTPConnector* xxx, int* code, int cXX)
146 {
147 EIO_Status status;
148 int c;
149 while ((status = s_FTPReply(xxx, &c, 0, 0)) == eIO_Success
150 && (!cXX || c/100 != cXX)) {
151 *code = c;
152 }
153 return status;
154 }
155
156
157 static EIO_Status s_WriteCommand(SOCK sock,
158 const char* cmd, const char* arg)
159 {
160 size_t cmdlen = strlen(cmd);
161 size_t arglen = arg ? strlen(arg) : 0;
162 size_t linelen = cmdlen + (arglen ? 1/* */ + arglen : 0) + 2/*\r\n*/;
163 char* line = (char*) malloc(linelen + 1/*\0*/);
164 EIO_Status status = eIO_Unknown;
165 if (line) {
166 memcpy(line, cmd, cmdlen);
167 if (arglen) {
168 line[cmdlen++] = ' ';
169 memcpy(line + cmdlen, arg, arglen);
170 cmdlen += arglen;
171 }
172 line[cmdlen++] = '\r';
173 line[cmdlen++] = '\n';
174 line[cmdlen] = '\0';
175 status = SOCK_Write(sock, line, linelen, 0, eIO_WritePersist);
176 free(line);
177 }
178 return status;
179 }
180
181
182 static EIO_Status s_FTPCommand(SFTPConnector* xxx,
183 const char* cmd, const char* arg)
184 {
185 return xxx->cntl ? s_WriteCommand(xxx->cntl, cmd, arg) : eIO_Closed;
186 }
187
188
189 static EIO_Status s_FTPLogin(SFTPConnector* xxx, const STimeout* timeout)
190 {
191 EIO_Status status;
192 int code;
193
194 assert(xxx->cntl && xxx->user && xxx->pass);
195 SOCK_SetTimeout(xxx->cntl, eIO_ReadWrite, timeout);
196 status = s_FTPReply(xxx, &code, 0, 0);
197 if (status != eIO_Success)
198 return status;
199 if (code != 220 || !*xxx->user)
200 return eIO_Unknown;
201 status = s_FTPCommand(xxx, "USER", xxx->user);
202 if (status != eIO_Success)
203 return status;
204 status = s_FTPReply(xxx, &code, 0, 0);
205 if (status != eIO_Success)
206 return status;
207 if (code == 230)
208 return eIO_Success;
209 if (code != 331 || !*xxx->pass)
210 return eIO_Unknown;
211 status = s_FTPCommand(xxx, "PASS", xxx->pass);
212 if (status != eIO_Success)
213 return status;
214 status = s_FTPReply(xxx, &code, 0, 0);
215 if (status != eIO_Success)
216 return status;
217 if (code == 230)
218 return eIO_Success;
219 else
220 return eIO_Unknown;
221 }
222
223
224 static EIO_Status s_FTPChdir(SFTPConnector* xxx, const char* cmd)
225 {
226 if (cmd || xxx->path) {
227 int code;
228 EIO_Status status = s_FTPCommand(xxx,
229 cmd ? cmd : "CWD",
230 cmd ? 0 : xxx->path);
231 if (status != eIO_Success)
232 return status;
233 status = s_FTPReply(xxx, &code, 0, 0);
234 if (status != eIO_Success)
235 return status;
236 if (code != 250)
237 return eIO_Unknown;
238 }
239 return eIO_Success;
240 }
241
242
243 static EIO_Status s_FTPBinary(SFTPConnector* xxx)
244 {
245 int code;
246 EIO_Status status = s_FTPCommand(xxx, "TYPE", "I");
247 if (status != eIO_Success)
248 return status;
249 status = s_FTPReply(xxx, &code, 0, 0);
250 if (status != eIO_Success)
251 return status;
252 if (code == 200)
253 return eIO_Success;
254 else
255 return eIO_Unknown;
256 }
257
258
259 static EIO_Status s_FTPAbort(SFTPConnector* xxx,
260 const STimeout* timeout,
261 int/*bool*/ quit)
262 {
263 EIO_Status status = eIO_Success;
264 int code;
265 size_t n;
266
267 if (!xxx->data)
268 return status;
269 if (quit || !xxx->cntl) {
270 status = SOCK_Abort(xxx->data);
271 xxx->data = 0;
272 return status;
273 }
274 if (!timeout)
275 timeout = &kFTPFailsafeTimeout;
276 SOCK_SetTimeout(xxx->cntl, eIO_ReadWrite, timeout);
277 SOCK_SetTimeout(xxx->data, eIO_ReadWrite, timeout);
278 if (/* Send TELNET IP (Interrupt Process) command */
279 (status = SOCK_Write(xxx->cntl, "\377\364", 2, &n, eIO_WritePersist))
280 != eIO_Success || n != 2 ||
281 /* Send TELNET DM (Data Mark) command to complete SYNCH, RFC 854 */
282 (status = SOCK_Write(xxx->cntl, "\377\362", 2, &n, eIO_WriteOutOfBand))
283 != eIO_Success || n != 2 ||
284 (status = s_FTPCommand(xxx, "ABOR", 0)) != eIO_Success) {
285 SOCK_Abort(xxx->data);
286 xxx->data = 0;
287 return status == eIO_Success ? eIO_Unknown : status;
288 }
289 while (SOCK_Read(xxx->data, 0, 1024*1024/*drain up*/, 0, eIO_ReadPlain)
290 == eIO_Success) {
291 continue;
292 }
293 if (SOCK_Status(xxx->data, eIO_Read) == eIO_Closed) {
294 SOCK_Close(xxx->data);
295 xxx->data = 0;
296 }
297 if ((status = s_FTPDrainReply(xxx, &code, 2/*2xx*/)) == eIO_Success
298 /* Microsoft FTP is known to return 225 (instead of 226) */
299 && code != 225 && code != 226) {
300 status = eIO_Unknown;
301 }
302 if (xxx->data) {
303 if (status == eIO_Success)
304 status = SOCK_Close(xxx->data);
305 else {
306 if (status == eIO_Timeout) {
307 CORE_LOG_X(1, eLOG_Warning,
308 "[FTP] Timed out in data connection abort");
309 }
310 SOCK_Abort(xxx->data);
311 }
312 xxx->data = 0;
313 }
314 return status;
315 }
316
317
318 static EIO_Status s_FTPPasv(SFTPConnector* xxx)
319 {
320 static const STimeout instant = {0, 0};
321 unsigned int host, i;
322 unsigned short port;
323 EIO_Status status;
324 int code, o[6];
325 char buf[128];
326
327 status = s_FTPCommand(xxx, "PASV", 0);
328 if (status != eIO_Success)
329 return status;
330 status = s_FTPReply(xxx, &code, buf, sizeof(buf) - 1);
331 if (status != eIO_Success || code != 227)
332 return eIO_Unknown;
333 buf[sizeof(buf) - 1] = '\0';
334 for (;;) {
335 char* c;
336 /* RFC 1123 4.1.2.6 says that ()'s in PASV reply must not be assumed */
337 for (c = buf; *c; c++) {
338 if (isdigit((unsigned char)(*c)))
339 break;
340 }
341 if (!*c)
342 return eIO_Unknown;
343 if (sscanf(c, "%d,%d,%d,%d,%d,%d%n",
344 &o[0], &o[1], &o[2], &o[3], &o[4], &o[5], &code) >= 6) {
345 break;
346 }
347 memmove(buf, c + code, strlen(c + code) + 1);
348 }
349 for (i = 0; i < (unsigned int)(sizeof(o)/sizeof(o[0])); i++) {
350 if (o[i] < 0 || o[i] > 255)
351 return eIO_Unknown;
352 }
353 i = (((((o[0] << 8) | o[1]) << 8) | o[2]) << 8) | o[3];
354 host = SOCK_HostToNetLong(i);
355 i = (o[4] << 8) | o[5];
356 port = (unsigned short) i;
357 if (SOCK_ntoa(host, buf, sizeof(buf)) != 0)
358 return eIO_Unknown;
359 if ((status = SOCK_CreateEx(buf, port, &instant, &xxx->data, 0, 0,
360 xxx->flag & fFCDC_LogData
361 ? fSOCK_LogOn
362 : fSOCK_LogDefault)) != eIO_Success) {
363 CORE_LOGF_X(2, eLOG_Error,
364 ("[FTP] Cannot open data connection to %s:%hu: %s",
365 buf, port, IO_StatusStr(status)));
366 s_FTPAbort(xxx, 0, 0/*!quit*/);
367 return eIO_Unknown;
368 }
369 return eIO_Success;
370 }
371
372
373 static EIO_Status s_FTPRetrieve(SFTPConnector* xxx,
374 const char* cmd)
375 {
376 int code;
377 EIO_Status status = s_FTPPasv(xxx);
378 if (status != eIO_Success)
379 return status;
380 status = s_FTPCommand(xxx, cmd, 0);
381 if (status != eIO_Success)
382 return status;
383 status = s_FTPReply(xxx, &code, 0, 0);
384 if (status != eIO_Success)
385 return status;
386 if (code == 150)
387 return eIO_Success;
388 if (code == 450 && (strncasecmp(cmd, "NLST", 4) == 0 ||
389 strncasecmp(cmd, "LIST", 4) == 0)) {
390 /* server usually drops data connection on 450: no files ...*/
391 if (xxx->data) {
392 /* ... so do we :-/ */
393 SOCK_Abort(xxx->data);
394 xxx->data = 0;
395 }
396 /* with no data connection open, user gets eIO_Closed on read */
397 return eIO_Success;
398 }
399 s_FTPAbort(xxx, 0, 0/*!quit*/);
400 return eIO_Unknown;
401 }
402
403
404 static EIO_Status s_FTPExecute(SFTPConnector* xxx, const STimeout* timeout)
405 {
406 EIO_Status status;
407 size_t size;
408 char* s;
409
410 if ((status = s_FTPAbort(xxx, timeout, 0/*!quit*/)) != eIO_Success)
411 return status;
412 verify((size = BUF_Size(xxx->wbuf)) > 0);
413 if (!(s = (char*) malloc(size + 1)))
414 return eIO_Unknown;
415 if (BUF_Read(xxx->wbuf, s, size) == size) {
416 const char* c;
417 assert(!memchr(s, '\n', size));
418 if (s[size - 1] == '\r')
419 --size;
420 s[size] = '\0';
421 if (!(c = (const char*) memchr(s, ' ', size)))
422 c = s + size;
423 else
424 size = (size_t)(c - s);
425 if (size == 3 || size == 4) {
426 SOCK_SetTimeout(xxx->cntl, eIO_ReadWrite, timeout);
427 if (size == 3 && strncasecmp(s, "CWD", 3) == 0) {
428 status = s_FTPChdir(xxx, s);
429 } else if (size == 4 && (strncasecmp(s, "LIST", 4) == 0 ||
430 strncasecmp(s, "NLST", 4) == 0 ||
431 strncasecmp(s, "RETR", 4) == 0)) {
432 status = s_FTPRetrieve(xxx, s);
433 } else if (size == 4 && strncasecmp(s, "REST", 4) == 0) {
434 status = s_FTPCommand(xxx, s, 0);
435 if (status == eIO_Success) {
436 int code;
437 status = s_FTPReply(xxx, &code, 0, 0);
438 if (status == eIO_Success && code != 350)
439 status = eIO_Unknown;
440 }
441 } else
442 status = eIO_Unknown;
443 } else
444 status = eIO_Unknown;
445 } else
446 status = eIO_Unknown;
447 free(s);
448 return status;
449 }
450
451
452 /***********************************************************************
453 * INTERNAL -- "s_VT_*" functions for the "virt. table" of connector methods
454 ***********************************************************************/
455
456 #ifdef __cplusplus
457 extern "C" {
458 #endif /* __cplusplus */
459 static const char* s_VT_GetType (CONNECTOR connector);
460 static EIO_Status s_VT_Open (CONNECTOR connector,
461 const STimeout* timeout);
462 static EIO_Status s_VT_Wait (CONNECTOR connector,
463 EIO_Event event,
464 const STimeout* timeout);
465 static EIO_Status s_VT_Write (CONNECTOR connector,
466 const void* buf,
467 size_t size,
468 size_t* n_written,
469 const STimeout* timeout);
470 static EIO_Status s_VT_Read (CONNECTOR connector,
471 void* buf,
472 size_t size,
473 size_t* n_read,
474 const STimeout* timeout);
475 static EIO_Status s_VT_Flush (CONNECTOR connector,
476 const STimeout* timeout);
477 static EIO_Status s_VT_Status (CONNECTOR connector,
478 EIO_Event dir);
479 static EIO_Status s_VT_Close (CONNECTOR connector,
480 const STimeout* timeout);
481 static void s_Setup (SMetaConnector* meta,
482 CONNECTOR connector);
483 static void s_Destroy (CONNECTOR connector);
484 # ifdef IMPLEMENTED__CONN_WaitAsync
485 static EIO_Status s_VT_WaitAsync(void* connector,
486 FConnectorAsyncHandler func,
487 SConnectorAsyncHandler* data);
488 # endif
489 #ifdef __cplusplus
490 } /* extern "C" */
491 #endif /* __cplusplus */
492
493
494 /*ARGSUSED*/
495 static const char* s_VT_GetType
496 (CONNECTOR connector)
497 {
498 return "FTP";
499 }
500
501
502 static EIO_Status s_VT_Open
503 (CONNECTOR connector,
504 const STimeout* timeout)
505 {
506 SFTPConnector* xxx = (SFTPConnector*) connector->handle;
507 EIO_Status status;
508
509 assert(!xxx->data && !xxx->cntl);
510 /* only clean state reopen is allowed */
511 if (xxx->r_status != eIO_Success || xxx->w_status != eIO_Success)
512 return eIO_Closed;
513 status = SOCK_CreateEx(xxx->host, xxx->port, timeout, &xxx->cntl, 0, 0,
514 xxx->flag & fFCDC_LogControl
515 ? fSOCK_LogOn : fSOCK_LogDefault);
516 if (status == eIO_Success)
517 status = s_FTPLogin(xxx, timeout);
518 if (status == eIO_Success)
519 status = s_FTPChdir(xxx, 0);
520 if (status == eIO_Success)
521 status = s_FTPBinary(xxx);
522 if (status != eIO_Success) {
523 if (xxx->cntl) {
524 SOCK_Close(xxx->cntl);
525 xxx->cntl = 0;
526 }
527 }
528 xxx->r_status = status;
529 xxx->w_status = status;
530 return status;
531 }
532
533
534 static EIO_Status s_VT_Write
535 (CONNECTOR connector,
536 const void* buf,
537 size_t size,
538 size_t* n_written,
539 const STimeout* timeout)
540 {
541 SFTPConnector* xxx = (SFTPConnector*) connector->handle;
542 EIO_Status status;
543 const char* c;
544
545 if (!xxx->cntl)
546 return eIO_Closed;
547 if (!size)
548 return eIO_Success;
549
550 if (((c = (const char*) memchr((const char*) buf, '\n', size)) != 0
551 && c < (const char*) buf + size - 1)
552 || !BUF_Write(&xxx->wbuf, buf, size - (c ? 1 : 0))) {
553 return eIO_Unknown;
554 }
555
556 status = c ? s_FTPExecute(xxx, timeout) : eIO_Success;
557 if (status == eIO_Success)
558 *n_written = size;
559 if (status != eIO_Timeout)
560 xxx->w_status = status;
561 return status;
562 }
563
564
565 static EIO_Status s_VT_Read
566 (CONNECTOR connector,
567 void* buf,
568 size_t size,
569 size_t* n_read,
570 const STimeout* timeout)
571 {
572 SFTPConnector* xxx = (SFTPConnector*) connector->handle;
573 EIO_Status status = eIO_Closed;
574 if (xxx->cntl && xxx->data) {
575 SOCK_SetTimeout(xxx->data, eIO_Read, timeout);
576 status = SOCK_Read(xxx->data, buf, size, n_read, eIO_ReadPlain);
577 if (status == eIO_Closed) {
578 int code;
579 SOCK_Close(xxx->data);
580 xxx->data = 0;
581 SOCK_SetTimeout(xxx->cntl, eIO_Read, timeout);
582 if (s_FTPReply(xxx, &code, 0, 0) != eIO_Success
583 || (code != 225 && code != 226)) {
584 status = eIO_Unknown;
585 }
586 }
587 if (status != eIO_Timeout)
588 xxx->r_status = status;
589 }
590 return status;
591 }
592
593
594 static EIO_Status s_VT_Wait
595 (CONNECTOR connector,
596 EIO_Event event,
597 const STimeout* timeout)
598 {
599 SFTPConnector* xxx = (SFTPConnector*) connector->handle;
600 if (!xxx->cntl)
601 return eIO_Closed;
602 if (event & eIO_Write)
603 return eIO_Success;
604 if (!xxx->data) {
605 EIO_Status status;
606 if (!BUF_Size(xxx->wbuf))
607 return eIO_Closed;
608 if ((status = s_FTPExecute(xxx, timeout)) != eIO_Success)
609 return status;
610 if (!xxx->data)
611 return eIO_Closed;
612 }
613 return SOCK_Wait(xxx->data, eIO_Read, timeout);
614 }
615
616
617 static EIO_Status s_VT_Flush
618 (CONNECTOR connector,
619 const STimeout* timeout)
620 {
621 SFTPConnector* xxx = (SFTPConnector*) connector->handle;
622 return BUF_Size(xxx->wbuf) ? s_FTPExecute(xxx, timeout) : eIO_Success;
623 }
624
625
626 static EIO_Status s_VT_Status
627 (CONNECTOR connector,
628 EIO_Event dir)
629 {
630 SFTPConnector* xxx = (SFTPConnector*) connector->handle;
631
632 switch (dir) {
633 case eIO_Read:
634 return xxx->data ? xxx->r_status : eIO_Closed;
635 case eIO_Write:
636 return xxx->cntl ? xxx->w_status : eIO_Closed;
637 default:
638 assert(0); /* should never happen as checked by connection */
639 break;
640 }
641 return eIO_InvalidArg;
642 }
643
644
645 static EIO_Status s_VT_Close
646 (CONNECTOR connector,
647 const STimeout* timeout)
648 {
649 SFTPConnector* xxx = (SFTPConnector*) connector->handle;
650 EIO_Status status;
651
652 if ((status = s_FTPAbort(xxx, timeout, 1/*quit*/)) == eIO_Success) {
653 if (xxx->cntl) {
654 int code;
655 if (!timeout)
656 timeout = &kFTPFailsafeTimeout;
657 SOCK_SetTimeout(xxx->cntl, eIO_ReadWrite, timeout);
658 status = s_FTPCommand(xxx, "QUIT", 0);
659 if (status == eIO_Success)
660 status = s_FTPDrainReply(xxx, &code, 0);
661 if (status != eIO_Closed || code != 221)
662 status = eIO_Unknown;
663 }
664 }
665 if (xxx->cntl) {
666 assert(status != eIO_Success);
667 if (status == eIO_Timeout)
668 SOCK_Abort(xxx->cntl);
669 else
670 SOCK_Close(xxx->cntl);
671 xxx->cntl = 0;
672 }
673 /* NB: connector is going to be killed, anyways;
674 * but for consistency, allow reuse only of properly closed ones
675 */
676 xxx->r_status = eIO_Success;
677 xxx->w_status = eIO_Success;
678 return status != eIO_Closed ? status : eIO_Success;
679 }
680
681
682 static void s_Setup
683 (SMetaConnector* meta,
684 CONNECTOR connector)
685 {
686 /* initialize virtual table */
687 CONN_SET_METHOD(meta, get_type, s_VT_GetType, connector);
688 CONN_SET_METHOD(meta, open, s_VT_Open, connector);
689 CONN_SET_METHOD(meta, wait, s_VT_Wait, connector);
690 CONN_SET_METHOD(meta, write, s_VT_Write, connector);
691 CONN_SET_METHOD(meta, flush, s_VT_Flush, connector);
692 CONN_SET_METHOD(meta, read, s_VT_Read, connector);
693 CONN_SET_METHOD(meta, status, s_VT_Status, connector);
694 CONN_SET_METHOD(meta, close, s_VT_Close, connector);
695 #ifdef IMPLEMENTED__CONN_WaitAsync
696 CONN_SET_METHOD(meta, wait_async, s_VT_WaitAsync, connector);
697 #endif
698 meta->default_timeout = 0/*infinite*/;
699 }
700
701
702 static void s_Destroy
703 (CONNECTOR connector)
704 {
705 SFTPConnector* xxx = (SFTPConnector*) connector->handle;
706 free((void*) xxx->host);
707 free((void*) xxx->user);
708 free((void*) xxx->pass);
709 if (xxx->path)
710 free((void*) xxx->path);
711 if (xxx->name)
712 free((void*) xxx->name);
713 BUF_Destroy(xxx->wbuf);
714 free(xxx);
715 connector->handle = 0;
716 free(connector);
717 }
718
719
720 /***********************************************************************
721 * EXTERNAL -- the connector's "constructors"
722 ***********************************************************************/
723
724 extern CONNECTOR FTP_CreateDownloadConnector(const char* host,
725 unsigned short port,
726 const char* user,
727 const char* pass,
728 const char* path,
729 TFCDC_Flags flag)
730 {
731 CONNECTOR ccc = (SConnector*) malloc(sizeof(SConnector));
732 SFTPConnector* xxx = (SFTPConnector*) malloc(sizeof(*xxx));
733
734 assert(!(flag & ~fFCDC_LogAll));
735
736 xxx->data = 0;
737 xxx->cntl = 0;
738 xxx->wbuf = 0;
739 xxx->host = strdup(host);
740 xxx->port = port ? port : 21;
741 xxx->user = strdup(user ? user : "ftp");
742 xxx->pass = strdup(pass ? pass : "-none");
743 xxx->path = path && *path ? strdup(path) : 0;
744 xxx->name = 0;
745 xxx->flag = flag;
746 /* allow reuse only in clean state */
747 xxx->r_status = eIO_Success;
748 xxx->w_status = eIO_Success;
749
750 /* initialize connector data */
751 ccc->handle = xxx;
752 ccc->next = 0;
753 ccc->meta = 0;
754 ccc->setup = s_Setup;
755 ccc->destroy = s_Destroy;
756
757 return ccc;
758 }
759 |
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more information. |