⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nanoftp.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 4 页
字号:
 */

static int
xmlNanoFTPParseList(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
 */

int
xmlNanoFTPList(void *ctx, ftpListCallback callback, void *userData,
	       const 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 (ctxt == NULL) return (-1);
    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
 */


int
xmlNanoFTPGetSocket(void *ctx, const char *filename) {
    xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
    char buf[300];
    int res, len;
    if (ctx == NULL)
	return(-1);
    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
 */

int
xmlNanoFTPGet(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 (ctxt == NULL) return(-1);
    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.
 */
int
xmlNanoFTPRead(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) {
	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
 */

int
xmlNanoFTPClose(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			*
 * 									*
 ************************************************************************/
static
void 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);
}
static
void 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 */
#define bottom_nanoftp
#include "elfgcchack.h"

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -