📄 nanoftp.c.svn-base
字号:
intxmlNanoFTPCloseConnection(void *ctx) { xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; int res; fd_set rfd, efd; struct timeval tv; closesocket(ctxt->dataFd); ctxt->dataFd = -1; tv.tv_sec = 15; tv.tv_usec = 0; FD_ZERO(&rfd); FD_SET(ctxt->controlFd, &rfd); FD_ZERO(&efd); FD_SET(ctxt->controlFd, &efd); res = select(ctxt->controlFd + 1, &rfd, NULL, &efd, &tv); if (res < 0) {#ifdef DEBUG_FTP perror("select");#endif closesocket(ctxt->controlFd); ctxt->controlFd = -1; return(-1); } if (res == 0) {#ifdef DEBUG_FTP xmlGenericError(xmlGenericErrorContext, "xmlNanoFTPCloseConnection: timeout\n");#endif closesocket(ctxt->controlFd); ctxt->controlFd = -1; } else { res = xmlNanoFTPGetResponse(ctxt); if (res != 2) { closesocket(ctxt->controlFd); ctxt->controlFd = -1; return(-1); } } return(0);}/** * xmlNanoFTPParseList: * @list: some data listing received from the server * @callback: the user callback * @userData: the user callback data * * Parse at most one entry from the listing. * * Returns -1 incase of error, the length of data parsed otherwise */static intxmlNanoFTPParseList(const char *list, ftpListCallback callback, void *userData) { const char *cur = list; char filename[151]; char attrib[11]; char owner[11]; char group[11]; char month[4]; int year = 0; int minute = 0; int hour = 0; int day = 0; unsigned long size = 0; int links = 0; int i; if (!strncmp(cur, "total", 5)) { cur += 5; while (*cur == ' ') cur++; while ((*cur >= '0') && (*cur <= '9')) links = (links * 10) + (*cur++ - '0'); while ((*cur == ' ') || (*cur == '\n') || (*cur == '\r')) cur++; return(cur - list); } else if (*list == '+') { return(0); } else { while ((*cur == ' ') || (*cur == '\n') || (*cur == '\r')) cur++; if (*cur == 0) return(0); i = 0; while (*cur != ' ') { if (i < 10) attrib[i++] = *cur; cur++; if (*cur == 0) return(0); } attrib[10] = 0; while (*cur == ' ') cur++; if (*cur == 0) return(0); while ((*cur >= '0') && (*cur <= '9')) links = (links * 10) + (*cur++ - '0'); while (*cur == ' ') cur++; if (*cur == 0) return(0); i = 0; while (*cur != ' ') { if (i < 10) owner[i++] = *cur; cur++; if (*cur == 0) return(0); } owner[i] = 0; while (*cur == ' ') cur++; if (*cur == 0) return(0); i = 0; while (*cur != ' ') { if (i < 10) group[i++] = *cur; cur++; if (*cur == 0) return(0); } group[i] = 0; while (*cur == ' ') cur++; if (*cur == 0) return(0); while ((*cur >= '0') && (*cur <= '9')) size = (size * 10) + (*cur++ - '0'); while (*cur == ' ') cur++; if (*cur == 0) return(0); i = 0; while (*cur != ' ') { if (i < 3) month[i++] = *cur; cur++; if (*cur == 0) return(0); } month[i] = 0; while (*cur == ' ') cur++; if (*cur == 0) return(0); while ((*cur >= '0') && (*cur <= '9')) day = (day * 10) + (*cur++ - '0'); while (*cur == ' ') cur++; if (*cur == 0) return(0); if ((cur[1] == 0) || (cur[2] == 0)) return(0); if ((cur[1] == ':') || (cur[2] == ':')) { while ((*cur >= '0') && (*cur <= '9')) hour = (hour * 10) + (*cur++ - '0'); if (*cur == ':') cur++; while ((*cur >= '0') && (*cur <= '9')) minute = (minute * 10) + (*cur++ - '0'); } else { while ((*cur >= '0') && (*cur <= '9')) year = (year * 10) + (*cur++ - '0'); } while (*cur == ' ') cur++; if (*cur == 0) return(0); i = 0; while ((*cur != '\n') && (*cur != '\r')) { if (i < 150) filename[i++] = *cur; cur++; if (*cur == 0) return(0); } filename[i] = 0; if ((*cur != '\n') && (*cur != '\r')) return(0); while ((*cur == '\n') || (*cur == '\r')) cur++; } if (callback != NULL) { callback(userData, filename, attrib, owner, group, size, links, year, month, day, hour, minute); } return(cur - list);}/** * xmlNanoFTPList: * @ctx: an FTP context * @callback: the user callback * @userData: the user callback data * @filename: optional files to list * * Do a listing on the server. All files info are passed back * in the callbacks. * * Returns -1 incase of error, 0 otherwise */intxmlNanoFTPList(void *ctx, ftpListCallback callback, void *userData, char *filename) { xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; char buf[4096 + 1]; int len, res; int indx = 0, base; fd_set rfd, efd; struct timeval tv; if (filename == NULL) { if (xmlNanoFTPCwd(ctxt, ctxt->path) < 1) return(-1); ctxt->dataFd = xmlNanoFTPGetConnection(ctxt); if (ctxt->dataFd == -1) return(-1); snprintf(buf, sizeof(buf), "LIST -L\r\n"); } else { if (filename[0] != '/') { if (xmlNanoFTPCwd(ctxt, ctxt->path) < 1) return(-1); } ctxt->dataFd = xmlNanoFTPGetConnection(ctxt); if (ctxt->dataFd == -1) return(-1); snprintf(buf, sizeof(buf), "LIST -L %s\r\n", filename); } buf[sizeof(buf) - 1] = 0; len = strlen(buf);#ifdef DEBUG_FTP xmlGenericError(xmlGenericErrorContext, "%s", buf);#endif res = send(ctxt->controlFd, buf, len, 0); if (res < 0) { __xmlIOErr(XML_FROM_FTP, 0, "send failed"); closesocket(ctxt->dataFd); ctxt->dataFd = -1; return(res); } res = xmlNanoFTPReadResponse(ctxt); if (res != 1) { closesocket(ctxt->dataFd); ctxt->dataFd = -1; return(-res); } do { tv.tv_sec = 1; tv.tv_usec = 0; FD_ZERO(&rfd); FD_SET(ctxt->dataFd, &rfd); FD_ZERO(&efd); FD_SET(ctxt->dataFd, &efd); res = select(ctxt->dataFd + 1, &rfd, NULL, &efd, &tv); if (res < 0) {#ifdef DEBUG_FTP perror("select");#endif closesocket(ctxt->dataFd); ctxt->dataFd = -1; return(-1); } if (res == 0) { res = xmlNanoFTPCheckResponse(ctxt); if (res < 0) { closesocket(ctxt->dataFd); ctxt->dataFd = -1; ctxt->dataFd = -1; return(-1); } if (res == 2) { closesocket(ctxt->dataFd); ctxt->dataFd = -1; return(0); } continue; } if ((len = recv(ctxt->dataFd, &buf[indx], sizeof(buf) - (indx + 1), 0)) < 0) { __xmlIOErr(XML_FROM_FTP, 0, "recv"); closesocket(ctxt->dataFd); ctxt->dataFd = -1; ctxt->dataFd = -1; return(-1); }#ifdef DEBUG_FTP write(1, &buf[indx], len);#endif indx += len; buf[indx] = 0; base = 0; do { res = xmlNanoFTPParseList(&buf[base], callback, userData); base += res; } while (res > 0); memmove(&buf[0], &buf[base], indx - base); indx -= base; } while (len != 0); xmlNanoFTPCloseConnection(ctxt); return(0);}/** * xmlNanoFTPGetSocket: * @ctx: an FTP context * @filename: the file to retrieve (or NULL if path is in context). * * Initiate fetch of the given file from the server. * * Returns the socket for the data connection, or <0 in case of error */intxmlNanoFTPGetSocket(void *ctx, const char *filename) { xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; char buf[300]; int res, len; if ((filename == NULL) && (ctxt->path == NULL)) return(-1); ctxt->dataFd = xmlNanoFTPGetConnection(ctxt); if (ctxt->dataFd == -1) return(-1); snprintf(buf, sizeof(buf), "TYPE I\r\n"); len = strlen(buf);#ifdef DEBUG_FTP xmlGenericError(xmlGenericErrorContext, "%s", buf);#endif res = send(ctxt->controlFd, buf, len, 0); if (res < 0) { __xmlIOErr(XML_FROM_FTP, 0, "send failed"); closesocket(ctxt->dataFd); ctxt->dataFd = -1; return(res); } res = xmlNanoFTPReadResponse(ctxt); if (res != 2) { closesocket(ctxt->dataFd); ctxt->dataFd = -1; return(-res); } if (filename == NULL) snprintf(buf, sizeof(buf), "RETR %s\r\n", ctxt->path); else snprintf(buf, sizeof(buf), "RETR %s\r\n", filename); buf[sizeof(buf) - 1] = 0; len = strlen(buf);#ifdef DEBUG_FTP xmlGenericError(xmlGenericErrorContext, "%s", buf);#endif res = send(ctxt->controlFd, buf, len, 0); if (res < 0) { __xmlIOErr(XML_FROM_FTP, 0, "send failed"); closesocket(ctxt->dataFd); ctxt->dataFd = -1; return(res); } res = xmlNanoFTPReadResponse(ctxt); if (res != 1) { closesocket(ctxt->dataFd); ctxt->dataFd = -1; return(-res); } return(ctxt->dataFd);}/** * xmlNanoFTPGet: * @ctx: an FTP context * @callback: the user callback * @userData: the user callback data * @filename: the file to retrieve * * Fetch the given file from the server. All data are passed back * in the callbacks. The last callback has a size of 0 block. * * Returns -1 incase of error, 0 otherwise */intxmlNanoFTPGet(void *ctx, ftpDataCallback callback, void *userData, const char *filename) { xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; char buf[4096]; int len = 0, res; fd_set rfd; struct timeval tv; if ((filename == NULL) && (ctxt->path == NULL)) return(-1); if (callback == NULL) return(-1); if (xmlNanoFTPGetSocket(ctxt, filename) < 0) return(-1); do { tv.tv_sec = 1; tv.tv_usec = 0; FD_ZERO(&rfd); FD_SET(ctxt->dataFd, &rfd); res = select(ctxt->dataFd + 1, &rfd, NULL, NULL, &tv); if (res < 0) {#ifdef DEBUG_FTP perror("select");#endif closesocket(ctxt->dataFd); ctxt->dataFd = -1; return(-1); } if (res == 0) { res = xmlNanoFTPCheckResponse(ctxt); if (res < 0) { closesocket(ctxt->dataFd); ctxt->dataFd = -1; ctxt->dataFd = -1; return(-1); } if (res == 2) { closesocket(ctxt->dataFd); ctxt->dataFd = -1; return(0); } continue; } if ((len = recv(ctxt->dataFd, buf, sizeof(buf), 0)) < 0) { __xmlIOErr(XML_FROM_FTP, 0, "recv failed"); callback(userData, buf, len); closesocket(ctxt->dataFd); ctxt->dataFd = -1; return(-1); } callback(userData, buf, len); } while (len != 0); return(xmlNanoFTPCloseConnection(ctxt));}/** * xmlNanoFTPRead: * @ctx: the FTP context * @dest: a buffer * @len: the buffer length * * This function tries to read @len bytes from the existing FTP connection * and saves them in @dest. This is a blocking call. * * Returns the number of byte read. 0 is an indication of an end of connection. * -1 indicates a parameter error. */intxmlNanoFTPRead(void *ctx, void *dest, int len) { xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; if (ctx == NULL) return(-1); if (ctxt->dataFd < 0) return(0); if (dest == NULL) return(-1); if (len <= 0) return(0); len = recv(ctxt->dataFd, dest, len, 0); if (len <= 0) { __xmlIOErr(XML_FROM_FTP, 0, "recv failed"); xmlNanoFTPCloseConnection(ctxt); }#ifdef DEBUG_FTP xmlGenericError(xmlGenericErrorContext, "Recvd %d bytes\n", len);#endif return(len);}/** * xmlNanoFTPOpen: * @URL: the URL to the resource * * Start to fetch the given ftp:// resource * * Returns an FTP context, or NULL */void*xmlNanoFTPOpen(const char *URL) { xmlNanoFTPCtxtPtr ctxt; int sock; xmlNanoFTPInit(); if (URL == NULL) return(NULL); if (strncmp("ftp://", URL, 6)) return(NULL); ctxt = (xmlNanoFTPCtxtPtr) xmlNanoFTPNewCtxt(URL); if (ctxt == NULL) return(NULL); if (xmlNanoFTPConnect(ctxt) < 0) { xmlNanoFTPFreeCtxt(ctxt); return(NULL); } sock = xmlNanoFTPGetSocket(ctxt, ctxt->path); if (sock < 0) { xmlNanoFTPFreeCtxt(ctxt); return(NULL); } return(ctxt);}/** * xmlNanoFTPClose: * @ctx: an FTP context * * Close the connection and both control and transport * * Returns -1 incase of error, 0 otherwise */intxmlNanoFTPClose(void *ctx) { xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; if (ctxt == NULL) return(-1); if (ctxt->dataFd >= 0) { closesocket(ctxt->dataFd); ctxt->dataFd = -1; } if (ctxt->controlFd >= 0) { xmlNanoFTPQuit(ctxt); closesocket(ctxt->controlFd); ctxt->controlFd = -1; } xmlNanoFTPFreeCtxt(ctxt); return(0);}#ifdef STANDALONE/************************************************************************ * * * Basic test in Standalone mode * * * ************************************************************************/staticvoid ftpList(void *userData, const char *filename, const char* attrib, const char *owner, const char *group, unsigned long size, int links, int year, const char *month, int day, int hour, int minute) { xmlGenericError(xmlGenericErrorContext, "%s %s %s %ld %s\n", attrib, owner, group, size, filename);}staticvoid ftpData(void *userData, const char *data, int len) { if (userData == NULL) return; if (len <= 0) { fclose((FILE*)userData); return; } fwrite(data, len, 1, (FILE*)userData);}int main(int argc, char **argv) { void *ctxt; FILE *output; char *tstfile = NULL; xmlNanoFTPInit(); if (argc > 1) { ctxt = xmlNanoFTPNewCtxt(argv[1]); if (xmlNanoFTPConnect(ctxt) < 0) { xmlGenericError(xmlGenericErrorContext, "Couldn't connect to %s\n", argv[1]); exit(1); } if (argc > 2) tstfile = argv[2]; } else ctxt = xmlNanoFTPConnectTo("localhost", 0); if (ctxt == NULL) { xmlGenericError(xmlGenericErrorContext, "Couldn't connect to localhost\n"); exit(1); } xmlNanoFTPList(ctxt, ftpList, NULL, tstfile); output = fopen("/tmp/tstdata", "w"); if (output != NULL) { if (xmlNanoFTPGet(ctxt, ftpData, (void *) output, tstfile) < 0) xmlGenericError(xmlGenericErrorContext, "Failed to get file\n"); } xmlNanoFTPClose(ctxt); xmlMemoryDump(); exit(0);}#endif /* STANDALONE */#else /* !LIBXML_FTP_ENABLED */#ifdef STANDALONE#include <stdio.h>int main(int argc, char **argv) { xmlGenericError(xmlGenericErrorContext, "%s : FTP support not compiled in\n", argv[0]); return(0);}#endif /* STANDALONE */#endif /* LIBXML_FTP_ENABLED */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -