NCBI C Toolkit Cross Reference

C/connect/ncbi_ftp_connector.c


  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 

source navigation ]   [ diff markup ]   [ identifier search ]   [ freetext search ]   [ file search ]  

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.