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

📄 syncput.c

📁 实现ftp协议客户端的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* NcFTPSyncPut.c * * Utility to synchronize a remote site.  This version only does incremental * updates by comparing recursive local directory listing to a previous listing. * This utility does not consider the actual contents of the remote directory, * so if you change files directly on the server this utility will not know * that those files have been changed. */#define VERSION "1.0.0"#ifdef HAVE_CONFIG_H#	include <config.h>#endif#include <ncftp.h>				/* Library header. */#include <Strn.h>				/* Library header. */#if defined(WIN32) || defined(_WINDOWS)#	include "..\ncftpget\gpshare.h"#else#	include "../ncftpget/gpshare.h"#endif#ifdef HAVE_UTIME_H#	include <utime.h>#else	struct utimbuf { time_t actime, modtime; };#endifFTPLibraryInfo gLib;FTPConnectionInfo gConn;char gLDir[256];char gRDir[256];char gRDirActual[256];char gCatalogFile[256];char *gCatalogFileNameOnly;	/* filename only */char gDebugCurCatalogFile[256];char gConfigFileNameOnly[80];	/* filename only */char gUmaskStr[16];int gDeleteRemoteFiles = 1;#ifdef WIN32int gRPathsToLowercase = 0;#endifFTPFileInfoList gFiles, gFilesToDelete, gPrevCatalog, gCurCatalog;char gTextExts[256] = ".txt;.html;.htm;.xml;.ini;.sh;.pl;.hqx;.cfg;.c;.h;.cpp;.hpp;.ps;.bat;.m3u;.pls";extern int gFirewallType;extern char gFirewallHost[64];extern char gFirewallUser[32];extern char gFirewallPass[32];extern unsigned int gFirewallPort;static voidPruneUnwantedFilesFromFileList(FTPFileInfoListPtr filp){	FTPFileInfoPtr fip, nextfip;	char *cp;	for (fip = filp->first; fip != NULL; fip = nextfip) {		nextfip = fip->next;		cp = StrRFindLocalPathDelim(fip->lname);		if (cp == NULL)			cp = fip->lname;		else			cp++;		if ((fip->type != '-') && (fip->type != 'l'))			nextfip = RemoveFileInfo(filp, fip);		else if (strcasecmp(cp, gConfigFileNameOnly) == 0)			nextfip = RemoveFileInfo(filp, fip);		else if (strcasecmp(fip->lname, gCatalogFileNameOnly) == 0)			nextfip = RemoveFileInfo(filp, fip);#ifdef WIN32		else if (gRPathsToLowercase != 0) {			strlwr(fip->lname);			strlwr(fip->relname);		}#endif	}}	/* PruneUnwantedFilesFromFileList */static voidPrintFileList(FTPFileInfoListPtr filp){	FTPFileInfoPtr fip;	struct tm *ltp, lt;	int i, n;	char mdtmstr[64];		n = filp->nFileInfos;	for (i=0; i<n; i++) {		fip = filp->vec[i];		ltp = Localtime(fip->mdtm, &lt);		if (ltp == NULL)			STRNCPY(mdtmstr, "(modtime unknown)");		else			strftime(mdtmstr, sizeof(mdtmstr), "%Y-%m-%d %H:%M:%S", ltp);		printf("%c  %s  size=%-10d  %s\n",			fip->type,			mdtmstr,			(int) fip->size,			fip->lname		);	}}	/* PrintFileList */static intBreadthFirstCaseCmp(const void *a, const void *b){	char *cp, *cpa, *cpb;	int depth, deptha, depthb;	int c;	const FTPFileInfo *const *fipa;	const FTPFileInfo *const *fipb;	fipa = (const FTPFileInfo *const *) a;	fipb = (const FTPFileInfo *const *) b;	cpa = (**fipa).relname;	cpb = (**fipb).relname;	for (cp = cpa, depth = 0;;) {		c = *cp++;		if (c == '\0')			break;		if ((c == '/') || (c == '\\')) {			depth++;		}	}	deptha = depth;	for (cp = cpb, depth = 0;;) {		c = *cp++;		if (c == '\0')			break;		if ((c == '/') || (c == '\\')) {			depth++;		}	}	depthb = depth;	if (deptha < depthb)		return (-1);	else if (deptha > depthb)		return (1);#ifdef WIN32	/* Paths are generally not case-sensitive. */	return (stricmp(cpa, cpb));#elif defined(HAVE_SETLOCALE)	return (strcoll(cpa, cpb));#else	return (strcmp(cpa, cpb));#endif}	/* BreadthFirstCaseCmp */static voidLoadCatalogFromFile(const char *const catalogFileName, FTPFileInfoListPtr const filp){	FILE *fp;	char line[1024];	char *cp;	char *tokstart;	FTPFileInfo fi;	int havesz, havemt;	unsigned int mt;	InitFileInfoList(filp);	fp = fopen(		catalogFileName,#ifdef WIN32		"rt"#else		"r"#endif		);	if (fp == NULL) {		/* No previous catalog -- this is OK,		 * since this could be the first time		 * doing an update.		 */		return;	}	InitFileInfo(&fi);	havesz = 0;	havemt = 0;	memset(line, 0, sizeof(line));	while (fgets(line, sizeof(line) - 1, fp) != NULL) {		cp = line;		while (*cp && isspace((int) *cp))			cp++;		if ((*cp == '\0') || (cp[0] == '#') || (cp[0] == '[') || (cp[0] == ';') || (isspace((int) cp[0])))			continue;		tokstart = cp;		cp = line + strlen(line) - 1;		if (*cp == '\n') {			*cp-- = '\0';			if (*cp == '\r')				*cp-- = '\0';		}		if (strncasecmp(tokstart, "File: ",  6) == 0) {			InitFileInfo(&fi);			cp = tokstart + 6;			fi.relnameLen = strlen(cp);			fi.relname = StrDup(cp);			fi.lname = StrDup(cp);			fi.type = '-';			havesz = 0;			havemt = 0;		} else if (strncasecmp(tokstart, "Size: ",  6) == 0) {			cp = tokstart + 6;			(void) sscanf(cp, SCANF_LONG_LONG, (longest_int *) &fi.size);			havesz++;		} else if (strncasecmp(tokstart, "Date: ",  6) == 0) {			cp = tokstart + 6;			(void) sscanf(cp, "%u", (unsigned int *) &mt);			fi.mdtm = (time_t) mt;			havemt++;		}		if ((fi.relnameLen != 0) && (havesz != 0) && (havemt != 0)) {			(void) AddFileInfo(filp, &fi);			/* The FileInfo and its StrDup'ed contents			 * are now property of the list and will be			 * disposed of when the list is disposed of.			 */			/* Clear out the structure for re-use. */			InitFileInfo(&fi);		}	}	(void) fclose(fp);	PruneUnwantedFilesFromFileList(filp);	VectorizeFileInfoList(filp);	if (filp->nFileInfos > 1) {		qsort(filp->vec, (size_t) filp->nFileInfos,			sizeof(FTPFileInfoPtr), BreadthFirstCaseCmp);	}}	/* LoadCatalogFromFile */static voidLoadPreviousCatalogFile(void){	LoadCatalogFromFile(gCatalogFile, &gPrevCatalog);}	/* LoadPreviousCatalogFile */static voidComputeCurrentCatalog(void){	FTPLineList directories;	int result;	InitFileInfoList(&gCurCatalog);	InitLineList(&directories);	AddLine(&directories, gLDir);	result = FTPLocalRecursiveFileList2(&gConn, &directories, &gCurCatalog, 1);	if (result < 0) {		(void) fprintf(stderr, "NcFTPSyncPut: could not traverse %s: %s.\n", gLDir, FTPStrError(result));		DisposeWinsock();		DisposeLineListContents(&directories);		exit(1);	}	DisposeLineListContents(&directories);	PruneUnwantedFilesFromFileList(&gCurCatalog);	VectorizeFileInfoList(&gCurCatalog);	if (gCurCatalog.nFileInfos > 1) {		qsort(gCurCatalog.vec, (size_t) gCurCatalog.nFileInfos,			sizeof(FTPFileInfoPtr), BreadthFirstCaseCmp);	}}	/* ComputeCurrentCatalog */static intCopyFileInfoAndAddToFileList(FTPFileInfoPtr lp, FTPFileInfoListPtr filp){	FTPFileInfo newfi;	newfi = *lp;	newfi.relname = StrDup(lp->relname);	newfi.lname = StrDup(lp->lname);	newfi.rname = StrDup(lp->rname);	newfi.rlinkto = StrDup(lp->rlinkto);	newfi.plug = StrDup(lp->plug);	if (AddFileInfo(filp, &newfi) == NULL)		return (-1);	return 0;}	/* CopyFileInfoAndAddToFileList */static voidCollectListOfChangedFiles(void){	FTPFileInfoPtr prevfip, curfip;	int iPrev, iCur;	int cmprc;	InitFileInfoList(&gFiles);	InitFileInfoList(&gFilesToDelete);	LoadPreviousCatalogFile();	if (gDebugCurCatalogFile[0] != '\0')		LoadCatalogFromFile(gDebugCurCatalogFile, &gCurCatalog);	/* for testing */	else		ComputeCurrentCatalog();	/* We now have both the old catalog and current catalog	 * ready to compare.  We next need to create a new list	 * containing just the list of files that we need to	 * update.	 */	iPrev = 0;	iCur = 0;	for (;;) {		if (gCurCatalog.vec == NULL)			break;	/* done */		curfip = gCurCatalog.vec[iCur];		if (curfip == NULL)			break;	/* done */				for (;;) {			if (				(gPrevCatalog.vec == NULL) ||				((prevfip = gPrevCatalog.vec[iPrev]) == NULL)			) {				/* Prev list did not have this file. */				(void) CopyFileInfoAndAddToFileList(curfip, &gFiles);				break;			}					cmprc = BreadthFirstCaseCmp(&prevfip, &curfip);			if (cmprc == 0) {				/* Prev list _did_ have the file.				 * Now compare it by time/size.				 */				if ((prevfip->mdtm != curfip->mdtm) || (prevfip->size != curfip->size))					(void) CopyFileInfoAndAddToFileList(curfip, &gFiles);				iPrev++;				break;			} else if (cmprc < 0) {				/* Current list did not have file.				 * That means the file was deleted				 * since last run.				 */				(void) CopyFileInfoAndAddToFileList(prevfip, &gFilesToDelete);				iPrev++;				/* continue... */			} else /* if (cmprc > 0) */ {				/* Previous list did not have this file.				 * That means we need to upload this file				 * which had been added since the last run.				 */				(void) CopyFileInfoAndAddToFileList(curfip, &gFiles);				break;			}		}		iCur++;	}	for (;;) {		if (gPrevCatalog.vec == NULL)			break;		prevfip = gPrevCatalog.vec[iPrev];		if (prevfip == NULL) {			break;		}		/* Current list did not have file.		 * That means the file was deleted		 * since last run.		 */		(void) CopyFileInfoAndAddToFileList(prevfip, &gFilesToDelete);		iPrev++;	}	VectorizeFileInfoList(&gFiles);	if (gFiles.nFileInfos > 1) {		qsort(gFiles.vec, (size_t) gFiles.nFileInfos,			sizeof(FTPFileInfoPtr), BreadthFirstCaseCmp);	}	VectorizeFileInfoList(&gFilesToDelete);	if (gFilesToDelete.nFileInfos > 1) {		qsort(gFilesToDelete.vec, (size_t) gFilesToDelete.nFileInfos,			sizeof(FTPFileInfoPtr), BreadthFirstCaseCmp);	}}	/* CollectListOfChangedFiles */static voidUsage(void){	FILE *fp;	fp = OpenPager();	(void) fprintf(fp, "NcFTPSyncPut %s.\n\n", VERSION);	(void) fprintf(fp, "Usage:\n");	(void) fprintf(fp, "  NcFTPSyncPut [flags] config.file\n");	(void) fprintf(fp, "\nFlags:\n\  -d XX  Use the file XX for debug logging.\n\  -UU    Update catalog file only, no uploading.\n\  -t XX  Timeout after XX seconds.\n");	(void) fprintf(fp, "\  -v/-V  Do (do not) use progress meters.\n\  -F     Use passive (PASV) data connections.\n\  -y     Try using \"SITE UTIME\" to preserve timestamps on remote host.\n");	(void) fprintf(fp, "\nExample minimal configuration file:\n\  [main]\n\  host=www.example.com\n\  user=gleason\n\  pass=mypassword\n\  ldir=/home/gleason/reports\n\  rdir=/users/g/gleason/public_html/report_dir\n\  catalog-file=/home/gleason/files/catalog.file\n");	(void) fprintf(fp, "\n\Other config file options:\n\  debug-log                (same as \"-d\"; default is off)\n\  passive                  (yes/no, default: no)\n\  sync-deletes             (yes/no, default: yes)\n\  port                     (default: 21)\n\  umask                    (default depends on server)\n\  textexts                 (default: %s)\n", gTextExts);#ifdef WIN32	(void) fprintf(fp, "\n\  pathnames-to-lowercase   (default: no)\n");#endif	(void) fprintf(fp, "\n\Note: If you choose to put the config file and/or the timestamp\n\      file in the directory to synchronize, NcFTPSyncPut will _not_\n\      upload those files _if_ they are detected.\n");	(void) fprintf(fp, "\nLibrary version: %s.\n", gLibNcFTPVersion + 5);	(void) fprintf(fp, "\nThis is a freeware program by Mike Gleason (http://www.NcFTP.com/contact/).\n");	(void) fprintf(fp, "This was built using LibNcFTP (http://www.ncftp.com/libncftp).\n");	ClosePager(fp);	DisposeWinsock();	exit(kExitUsage);}	/* Usage */static voidAbort(int sigNum){	signal(sigNum, Abort);	/* Hopefully the I/O operation in progress	 * will complete, and we'll abort before	 * it starts a new block.	 */	gConn.cancelXfer++;	/* If the user appears to be getting impatient,	 * restore the default signal handler so the	 * next ^C abends the program.	 */	if (gConn.cancelXfer >= 2)		signal(sigNum, SIG_DFL);}	/* Abort */static intUpdateCatalogFile(void){	FILE *fp;	FTPFileInfoPtr fip;	int i, n;	char mdtmstr[64];	fp = fopen(		gCatalogFile,#ifdef WIN32		"wt"#else		"w"#endif		);	if (fp == NULL) {		perror(gCatalogFile);		return (-1);	}	n = gCurCatalog.nFileInfos;	for (i=0; i<n; i++) {		fip = gCurCatalog.vec[i];		(void) strftime(mdtmstr, sizeof(mdtmstr), "%Y-%m-%d %H:%M:%S", localtime(&fip->mdtm));		(void) fprintf(fp, "File: %s\nSize: ", fip->relname);		(void) fprintf(fp, PRINTF_LONG_LONG, fip->size);		(void) fprintf(fp, "\nDate: %lu (%s)\n\n", (unsigned long) fip->mdtm, mdtmstr);		if (fflush(fp) < 0) {			(void) fclose(fp);			return (-1);		}	}	return (0);}	/* UpdateCatalogFile */static intGetFileTypeBasedOffOfExtension(const char *const fname){	char buf[256], *tok, extbuf[16];	const char *delims;	const char *ext;	int len;	int i;

⌨️ 快捷键说明

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