📄 syncupload.c
字号:
/*
syncupload -- Send files to a slave.
AUTHOR
Jeroen C. Kessels
Internet Engineer
http://www.kessels.com/
Copyright: Jeroen C. Kessels
Date: 19 august 2005
Version: 4.*
*/
#include "version.h"
#include <stdio.h>
#include <time.h> /* ctime(). */
#include <sys/timeb.h> /* _ftime(). */
#include <sys/stat.h> /* stat(). */
#include <io.h>
#include <winsock.h>
#include "md5.h"
#include "common.h"
#define USAGE "usage: syncupload [-c] [-d] [-h] [filename(s)]\n\
-c Do not copy and/or delete, just compare the files.\n\
-d Debug mode, show all network traffic.\n\
-h Show this usage text.\n\
filename(s) Process workfile(s) 'filename.WRK'.\n"
#define WS_VERSION_REQD 0x0101 /* The minimum winsock version required. */
#define NONE 0
#define READ 1
#define WRITE 2
#define APPEND 3
#define CHANGE 4
struct FileStruct {
char *Path;
char *LocalMask;
char *RemoteMask;
char Date[15]; /* YYYYMMDDHHMMSS */
unsigned long Size;
int CopyFlag;
struct FileStruct *Previous;
struct FileStruct *Smaller;
struct FileStruct *Bigger;
};
struct ExcludeStruct {
char *Mask;
struct ExcludeStruct *Next;
};
int Debug = 0;
void MaskTranslate(char *InputMask, char *OutputMask, char *Path) {
char s1[BUFSIZ];
char *p1;
char *p2;
char *p3;
char *p4;
char *p5;
int i;
p1 = InputMask;
p2 = OutputMask;
p3 = Path;
p4 = s1;
while (*p1 != '\0') {
/* Compare the InputMask and the Path until a wildcard, they
must be exactly the same. */
while ((*p1 != '\0') && (*p1 != '*') && (*p1 != '?')) {
if (*p1 != *p3) {
fprintf(stdout,"Error: the path does not match the inputmask.\n");
fprintf(stdout," InputMask: %s\n",InputMask);
fprintf(stdout," OutputMask: %s\n",OutputMask);
fprintf(stdout," Path: %s\n",Path);
exit(1);
}
p1++;
p3++;
}
/* Copy from the OutputMask to the Path until a wildcard. */
while ((*p2 != '\0') && (*p2 != '*') && (*p2 != '?')) *p4++ = *p2++;
if (*p1 != *p2) {
fprintf(stdout,"Error: the inputmask and outputmask do not match.\n");
fprintf(stdout," InputMask: %s\n",InputMask);
fprintf(stdout," OutputMask: %s\n",OutputMask);
fprintf(stdout," Path: %s\n",Path);
exit(1);
}
/* If the wildcard is '?' then copy a single character. */
if (*p1 == '?') {
p1++;
p2++;
*p4++ = *p3++;
continue;
}
if (*p1 != '\0') *p1++;
if (*p2 != '\0') *p2++;
p5 = p1;
i = 0;
while ((*p5 != '\0') && (*p5 != '*') && (*p5 != '?')) {
p5++;
i++;
}
while (*p3 != '\0') {
if ((i > 0) && (strncmp(p1,p3,i) == 0)) break;
*p4++ = *p3++;
}
if ((i > 0) && (*p3 == '\0')) {
fprintf(stdout,"Error: the inputmask and path do not match.\n");
fprintf(stdout," InputMask: %s\n",InputMask);
fprintf(stdout," OutputMask: %s\n",OutputMask);
fprintf(stdout," Path: %s\n",Path);
exit(1);
}
}
*p4 = '\0';
/*
fprintf(stdout,"Path translated:\n");
fprintf(stdout," Input path: %s\n",Path);
fprintf(stdout," Output path: %s\n",s1);
fprintf(stdout," InputMask: %s\n",InputMask);
fprintf(stdout," OutputMask: %s\n",OutputMask);
*/
strcpy(Path,s1);
}
/* Add a file to the linked list in memory. The list is sorted by filename. */
void AddFile(
char *Path,
char *LocalMask,
char *RemoteMask,
long Size,
char *Date,
int CopyFlag,
struct FileStruct **Top) {
struct FileStruct *Here;
struct FileStruct *Ins;
struct FileStruct *New;
int Found;
/* Search this file in the linked list. */
Here = *Top;
Ins = NULL;
Found = 1;
while ((Here != NULL) && ((Found = strcmp(Here->Path,Path)) != 0)) {
Ins = Here;
if (Found > 0)
Here = Here->Smaller;
else Here = Here->Bigger;
}
/* If the file is already in the list, then ignore. */
if (Found == 0) return;
/* Allocate a new record. */
New = (struct FileStruct *) malloc (sizeof(struct FileStruct));
if (New == NULL) {
fprintf(stdout," Error: malloc() returned NULL.\n");
exit(0);
}
New->Path = (char *) malloc (strlen(Path) + 1);
if (New->Path == NULL) {
fprintf(stdout," Error: malloc() returned NULL.\n");
exit(0);
}
New->LocalMask = (char *) malloc (strlen(LocalMask) + 1);
if (New->LocalMask == NULL) {
fprintf(stdout," Error: malloc() returned NULL.\n");
exit(0);
}
New->RemoteMask = (char *) malloc (strlen(RemoteMask) + 1);
if (New->RemoteMask == NULL) {
fprintf(stdout," Error: malloc() returned NULL.\n");
exit(0);
}
/* Fill the new record. */
strcpy(New->Path,Path);
strcpy(New->LocalMask,LocalMask);
strcpy(New->RemoteMask,RemoteMask);
New->Size = Size;
New->CopyFlag = CopyFlag;
strcpy(New->Date,Date);
/* Add to the linked list. */
New->Previous = Ins;
New->Bigger = New->Smaller = NULL;
if (Ins == NULL) {
*Top = New;
} else {
if (Found > 0) {
Ins->Smaller = New;
} else {
Ins->Bigger = New;
}
}
return;
}
/* Return the smallest item in the list. */
struct FileStruct *FileSmallest(struct FileStruct *Top) {
struct FileStruct *Here;
Here = Top;
if (Here != NULL)
while (Here->Smaller != NULL)
Here = Here->Smaller;
return(Here);
}
/* Goto the next bigger item in the list. */
struct FileStruct *FileBigger(struct FileStruct *Here) {
struct FileStruct *Temp;
if (Here == NULL) return(Here);
if (Here->Bigger != NULL) {
Here = Here->Bigger;
while (Here->Smaller != NULL) Here = Here->Smaller;
} else {
do {
Temp = Here;
Here = Here->Previous;
} while ((Here != NULL) && (Here->Bigger == Temp));
}
return(Here);
}
/* Discard an entire linked list from memory. The subroutine iterates. */
void DropFiles(struct FileStruct *Here) {
if (Here == NULL) return;
DropFiles(Here->Smaller);
DropFiles(Here->Bigger);
if (Here->Path != NULL) free(Here->Path);
if (Here->LocalMask != NULL) free(Here->LocalMask);
if (Here->RemoteMask != NULL) free(Here->RemoteMask);
free(Here);
}
/* Return YES if the path matches a mask in the Exclude list. */
int FindExclude(struct ExcludeStruct *Excludes, char *Path) {
struct ExcludeStruct *Here;
Here = Excludes;
while (Here != NULL) {
if (MatchMask(Path,Here->Mask) == YES) return(YES);
Here = Here->Next;
}
return(NO);
}
/* Include files. Walk through all files in the root directory, and add all
the files to the linked list at "Top". Iterate for subdirectories. */
long DoInclude(
char *InPath,
char *LocalMask,
char *RemoteMask,
struct FileStruct **Top,
struct ExcludeStruct *Excludes) {
char Path[BUFSIZ];
char SearchPath[BUFSIZ];
char FilePath[BUFSIZ];
long dirp;
struct _finddata_t dp;
char Date[BUFSIZ];
struct tm *DateTm;
long Counter;
char *p1;
Counter = 0;
/* Fixup the input path. We need a searchpath with a trailing '*'
and a path that ends in '/'. */
strcpy(Path,InPath);
p1 = strchr(Path,'*');
if (p1 != NULL) {
strcpy(SearchPath,Path);
*p1 = '\0';
} else {
sprintf(SearchPath,"%s*",Path);
p1 = strchr(Path,'\0');
}
while ((p1 != Path) && ((*p1 == '\0') || (strchr(DIRSEP,*p1) == NULL))) p1--;
if (strchr(DIRSEP,*p1) != NULL) p1++;
*p1 = '\0';
if (Debug > 0) fprintf(stdout," %s\n",SearchPath);
dirp = _findfirst(SearchPath,&dp);
if (dirp == -1L) return(Counter);
do {
if (strcmp(dp.name,".") == 0) continue;
if (strcmp(dp.name,"..") == 0) continue;
/* If this is a file, then list it and continue. */
if ((dp.attrib & _A_SUBDIR) != _A_SUBDIR) {
sprintf(FilePath,"%s%s",Path,dp.name);
if (FindExclude(Excludes,FilePath) == YES) continue;
DateTm = localtime(&dp.time_write);
sprintf(Date,"%04u%02u%02u%02u%02u%02u",DateTm->tm_year + 1900,
DateTm->tm_mon + 1, DateTm->tm_mday, DateTm->tm_hour, DateTm->tm_min,
DateTm->tm_sec);
AddFile(FilePath,LocalMask,RemoteMask,dp.size,Date,1,Top);
Counter = Counter + 1;
continue;
}
/* Recurse into the directory by calling myself, except if the
directory matches an Exclude mask. */
sprintf(FilePath,"%s%s%c*",Path,dp.name,*DIRSEP);
if (FindExclude(Excludes,FilePath) == YES) continue;
Counter = Counter + DoInclude(FilePath,LocalMask,RemoteMask,Top,Excludes);
} while (_findnext(dirp,&dp) == 0);
_findclose(dirp);
return(Counter);
}
/* Return a string with the error message for GetLastError(). */
void SystemErrorStr(DWORD ErrorCode, char *Out) {
char s1[BUFSIZ];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
NULL,ErrorCode,0,s1,BUFSIZ,NULL);
sprintf(Out,"error %lu: %s",ErrorCode,s1);
}
/* Return a string with the error message for WSAGetLastError(). */
void SocketErrorStr(int ErrorCode, char *Out) {
struct {
int ErrorCode;
char *ErrorText;
} ErrorArray[] = {
{WSAEINTR, "Interrupted system call"},
{WSAEBADF, "Bad file number"},
{WSAEACCES, "Permission denied"},
{WSAEFAULT, "Bad address"},
{WSAEINVAL, "Invalid argument"},
{WSAEMFILE, "Too many open files"},
{WSAEWOULDBLOCK, "Operation would block"},
{WSAEINPROGRESS, "Operation now in progress"},
{WSAEALREADY, "Operation already in progress"},
{WSAENOTSOCK, "Socket operation on non-socket"},
{WSAEDESTADDRREQ, "Destination address required"},
{WSAEMSGSIZE, "Message too long"},
{WSAEPROTOTYPE, "Protocol wrong type for socket"},
{WSAENOPROTOOPT, "Bad protocol option"},
{WSAEPROTONOSUPPORT,"Protocol not supported"},
{WSAESOCKTNOSUPPORT,"Socket type not supported"},
{WSAEOPNOTSUPP, "Operation not supported on socket"},
{WSAEPFNOSUPPORT, "Protocol family not supported"},
{WSAEAFNOSUPPORT, "Address family not supported by protocol family"},
{WSAEADDRINUSE, "Address already in use"},
{WSAEADDRNOTAVAIL, "Can't assign requested address"},
{WSAENETDOWN, "Network is down"},
{WSAENETUNREACH, "Network is unreachable"},
{WSAENETRESET, "Net dropped connection or reset"},
{WSAECONNABORTED, "Software caused connection abort"},
{WSAECONNRESET, "Connection reset by peer"},
{WSAENOBUFS, "No buffer space available"},
{WSAEISCONN, "Socket is already connected"},
{WSAENOTCONN, "Socket is not connected"},
{WSAESHUTDOWN, "Can't send after socket shutdown"},
{WSAETOOMANYREFS, "Too many references, can't splice"},
{WSAETIMEDOUT, "Connection timed out"},
{WSAECONNREFUSED, "Connection refused"},
{WSAELOOP, "Too many levels of symbolic links"},
{WSAENAMETOOLONG, "File name too long"},
{WSAEHOSTDOWN, "Host is down"},
{WSAEHOSTUNREACH, "No Route to Host"},
{WSAENOTEMPTY, "Directory not empty"},
{WSAEPROCLIM, "Too many processes"},
{WSAEUSERS, "Too many users"},
{WSAEDQUOT, "Disc Quota Exceeded"},
{WSAESTALE, "Stale NFS file handle"},
{WSAEREMOTE, "Too many levels of remote in path"},
{WSASYSNOTREADY, "Network SubSystem is unavailable"},
{WSAVERNOTSUPPORTED,"WINSOCK DLL Version out of range"},
{WSANOTINITIALISED, "Successful WSASTARTUP not yet performed"},
{WSAHOST_NOT_FOUND, "Host not found"},
{WSATRY_AGAIN, "Non-Authoritative Host not found"},
{WSANO_RECOVERY, "Non-Recoverable errors: FORMERR, REFUSED, NOTIMP"},
{WSANO_DATA, "Valid name, no data record of requested"},
{WSABASEERR, ""}
};
int i;
i = 0;
while ((ErrorArray[i].ErrorCode != ErrorCode) &&
(*ErrorArray[i].ErrorText != '\0')) i++;
sprintf(Out,"error %lu: %s",ErrorCode,ErrorArray[i].ErrorText);
}
/* Receive a single line from the remote. If the incoming data is
more than the size of the buffer then data is ignored. Return:
NO: Error, see WSAGetLastError().
YES: OK, end of line reached.
*/
int ReceiveRawLine(SOCKET Socket, char *Line, int Width) {
int Here;
int Status;
char c1;
Here = 0;
while (1) {
Status = recv(Socket,&c1,1,0); /* Receive 1 character. */
if (Status == 0) break; /* Leave if no more data. */
if (Status == SOCKET_ERROR) break; /* Leave if error. */
if (c1 == '\r') continue; /* Ignore CR. */
if (c1 == '\0') continue; /* Ignore Null. */
if (c1 == '\n') break; /* Leave after LF. */
if (Here < Width - 1) Line[Here++] = c1; /* Save in Line. */
}
Line[Here] = '\0';
if (Debug > 0) fprintf(stdout,"<<< %s\n",Line);
if (Status != 1) return(NO);
return(YES);
}
/* Send a message to the remote. */
int SendMsg(SOCKET Socket, char *Message) {
char s1[BUFSIZ];
if (Debug > 0) {
if (strlen(Message) > 500) {
StringCopyBuf(Message,s1,60);
fprintf(stdout,">>> %s....\n",s1);
} else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -