📄 copy.c
字号:
/* $Id: copy.c,v 1.2 2004/02/15 23:42:15 pfalcon Exp $ * * COPY.C -- copy internal command. * * * History: * * 01-Aug-98 (Rob Lake z63rrl@morgan.ucs.mun.ca) * started * * 13-Aug-1998 (John P. Price) * fixed memory leak problem in copy function. * fixed copy function so it would work with wildcards in the source * * 13-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>) * Added COPY command to CMD. * * 26-Jan-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>) * Replaced CRT io functions by Win32 io functions. * * 27-Oct-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>) * Disabled prompting when used in batch mode. */#include "config.h"#ifdef INCLUDE_CMD_COPY#include "cmd.h"#define _VERIFY_ 1 /* VERIFY Switch */#define BINARY 2 /* File is to be copied as BINARY */#define ASCII 4 /* File is to be copied as ASCII */#define PROMPT 8 /* Prompt before overwriting files */#define NPROMPT 16 /* Do not prompt before overwriting files */#define HELP 32 /* Help was asked for */#define SOURCE 128 /* File is a source */typedef struct tagFILES{ struct tagFILES *next; TCHAR szFile[MAX_PATH]; DWORD dwFlag; /* BINARY -xor- ASCII */} FILES, *LPFILES;static BOOL DoSwitches (LPTSTR, LPDWORD);static BOOL AddFile (LPFILES, TCHAR *, int *, int *, LPDWORD);static BOOL AddFiles (LPFILES, TCHAR *, int *, int *, int *, LPDWORD);static BOOL GetDestination (LPFILES, LPFILES);static INT ParseCommand (LPFILES, int, TCHAR **, LPDWORD);static VOID DeleteFileList (LPFILES);static INT Overwrite (LPTSTR);static BOOLIsDirectory (LPTSTR fn){ if (!IsValidFileName (fn)) return FALSE; return (GetFileAttributes (fn) & FILE_ATTRIBUTE_DIRECTORY);}static BOOLDoSwitches (LPTSTR arg, LPDWORD lpdwFlags){ if (!_tcsicmp (arg, _T("/-Y"))) { *lpdwFlags |= PROMPT; *lpdwFlags &= ~NPROMPT; return TRUE; } else if (_tcslen (arg) > 2) { error_too_many_parameters (_T("")); return FALSE; } switch (_totupper (arg[1])) { case _T('V'): *lpdwFlags |= _VERIFY_; break; case _T('A'): *lpdwFlags |= ASCII; *lpdwFlags &= ~BINARY; break; case _T('B'): *lpdwFlags |= BINARY; *lpdwFlags &= ~ASCII; break; case _T('Y'): *lpdwFlags &= ~PROMPT; *lpdwFlags |= NPROMPT; break; default: error_invalid_switch (arg[1]); return FALSE; } return TRUE;}static BOOLAddFile (LPFILES f, TCHAR *arg, int *source, int *dest, LPDWORD flags){ if (*dest) { error_too_many_parameters (_T("")); return FALSE; } if (*source) { *dest = 1; f->dwFlag = 0; } else { *source = 1; f->dwFlag = SOURCE; } _tcscpy(f->szFile, arg); f->dwFlag |= *flags & ASCII ? ASCII : BINARY; if ((f->next = (LPFILES)malloc (sizeof (FILES))) == NULL) { error_out_of_memory (); return FALSE; } f = f->next; f->dwFlag = 0; f->next = NULL; return TRUE;}static BOOLAddFiles (LPFILES f, TCHAR *arg, int *source, int *dest, int *count, LPDWORD flags){ TCHAR t[128]; int j; int k; if (*dest) { error_too_many_parameters (_T("")); return FALSE; } j = 0; k = 0; while (arg[j] == _T('+')) j++; while (arg[j] != _T('\0')) { t[k] = arg[j++]; if (t[k] == '+' || arg[j] == _T('\0')) { if (!k) continue; if (arg[j] == _T('\0') && t[k] != _T('+')) k++; t[k] = _T('\0'); *count += 1; _tcscpy (f->szFile, t); *source = 1; if (*flags & ASCII) f->dwFlag |= *flags | SOURCE | ASCII; else f->dwFlag |= *flags | BINARY | SOURCE; if ((f->next = (LPFILES)malloc (sizeof (FILES))) == NULL) { error_out_of_memory (); return FALSE; } f = f->next; f->next = NULL; k = 0; f->dwFlag = 0; continue; } k++; } if (arg[--j] == _T('+')) *source = 0; return 1;}static BOOLGetDestination (LPFILES f, LPFILES dest){ LPFILES p = NULL; LPFILES start = f; while (f->next != NULL) { p = f; f = f->next; } f = p; if ((f->dwFlag & SOURCE) == 0) { free (p->next); p->next = NULL; _tcscpy (dest->szFile, f->szFile); dest->dwFlag = f->dwFlag; dest->next = NULL; f = start; return TRUE; } return FALSE;}static INTParseCommand (LPFILES f, int argc, TCHAR **arg, LPDWORD lpdwFlags){ INT i; INT dest; INT source; INT count; dest = 0; source = 0; count = 0; for (i = 0; i < argc; i++) { if (arg[i][0] == _T('/')) { if (!DoSwitches (arg[i], lpdwFlags)) return -1; } else { if (!_tcscmp(arg[i], _T("+"))) source = 0; else if (!_tcschr(arg[i], _T('+')) && source) { if (!AddFile(f, arg[i], &source, &dest, lpdwFlags)) return -1; f = f->next; count++; } else { if (!AddFiles(f, arg[i], &source, &dest, &count, lpdwFlags)) return -1; while (f->next != NULL) f = f->next; } } }#ifdef _DEBUG DebugPrintf (_T("ParseCommand: flags has %s\n"), *lpdwFlags & ASCII ? _T("ASCII") : _T("BINARY"));#endif return count;}static VOIDDeleteFileList (LPFILES f){ LPFILES temp; while (f != NULL) { temp = f; f = f->next; free (temp); }}static INTOverwrite (LPTSTR fn){ TCHAR inp[10]; LPTSTR p; ConOutPrintf (_T("Overwrite %s (Yes/No/All)? "), fn); ConInString (inp, 10); ConOutPuts (_T("")); _tcsupr (inp); for (p = inp; _istspace (*p); p++) ; if (*p != _T('Y') && *p != _T('A')) return 0; if (*p == _T('A')) return 2; return 1;}#define BUFF_SIZE 16384 /* 16k = max buffer size */int copy (LPTSTR source, LPTSTR dest, int append, LPDWORD lpdwFlags){ FILETIME srctime; HANDLE hFileSrc; HANDLE hFileDest; LPBYTE buffer; DWORD dwAttrib; DWORD dwRead; DWORD dwWritten; DWORD i; BOOL bEof = FALSE;#ifdef _DEBUG DebugPrintf (_T("checking mode\n"));#endif if (!IsValidFileName (dest)) {#ifdef _DEBUG DebugPrintf (_T("opening/creating\n"));#endif CopyFile(source, dest, TRUE); return 1; } dwAttrib = GetFileAttributes (source); hFileSrc = CreateFile (source, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hFileSrc == INVALID_HANDLE_VALUE) { ConErrPrintf (_T("Error: Cannot open source - %s!\n"), source); return 0; }#ifdef _DEBUG DebugPrintf (_T("getting time\n"));#endif GetFileTime (hFileSrc, &srctime, NULL, NULL);#ifdef _DEBUG DebugPrintf (_T("copy: flags has %s\n"), *lpdwFlags & ASCII ? "ASCII" : "BINARY");#endif if (!append) { if (!_tcscmp (dest, source)) { ConErrPrintf (_T("Error: Can't copy onto itself!\n")); CloseHandle (hFileSrc); return 0; }#ifdef _DEBUG DebugPrintf (_T("SetFileAttributes (%s, FILE_ATTRIBUTE_NORMAL);\n"), dest);#endif SetFileAttributes (dest, FILE_ATTRIBUTE_NORMAL);#ifdef _DEBUG DebugPrintf (_T("DeleteFile (%s);\n"), dest);#endif DeleteFile (dest); hFileDest = CreateFile (dest, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); } else { LONG lFilePosHigh = 0; hFileDest = CreateFile (dest, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); if (!_tcscmp (dest, source)) { CloseHandle (hFileSrc); return 0; }#ifdef _DEBUG DebugPrintf (_T("opening/appending\n"));#endif hFileDest = CreateFile (dest, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); SetFilePointer (hFileDest, 0, &lFilePosHigh,FILE_END); } if (hFileDest == INVALID_HANDLE_VALUE) { CloseHandle (hFileSrc); error_path_not_found (); return 0; } buffer = (LPBYTE)malloc (BUFF_SIZE); if (buffer == NULL) { CloseHandle (hFileDest); CloseHandle (hFileSrc); error_out_of_memory (); return 0; } do { ReadFile (hFileSrc, buffer, BUFF_SIZE, &dwRead, NULL); if (*lpdwFlags & ASCII) { for (i = 0; i < dwRead; i++) { if (((LPTSTR)buffer)[i] == 0x1A) { bEof = TRUE; break; } } dwRead = i; } if (dwRead == 0) break; WriteFile (hFileDest, buffer, dwRead, &dwWritten, NULL); if (dwWritten != dwRead) { ConErrPrintf (_T("Error writing destination!\n")); free (buffer); CloseHandle (hFileDest); CloseHandle (hFileSrc); return 0; } } while (dwRead && !bEof);#ifdef _DEBUG DebugPrintf (_T("setting time\n"));#endif SetFileTime (hFileDest, &srctime, NULL, NULL); if (*lpdwFlags & ASCII) { ((LPTSTR)buffer)[0] = 0x1A; ((LPTSTR)buffer)[1] = _T('\0');#ifdef _DEBUG DebugPrintf (_T("appending ^Z\n"));#endif WriteFile (hFileDest, buffer, sizeof(TCHAR), &dwWritten, NULL); } free (buffer); CloseHandle (hFileDest); CloseHandle (hFileSrc);#ifdef _DEBUG DebugPrintf (_T("setting mode\n"));#endif SetFileAttributes (dest, dwAttrib); return 1;}static INTSetupCopy (LPFILES sources, TCHAR **p, BOOL bMultiple, TCHAR *drive_d, TCHAR *dir_d, TCHAR *file_d, TCHAR *ext_d, int *append, LPDWORD lpdwFlags){ WIN32_FIND_DATA find; TCHAR drive_s[_MAX_PATH]; TCHAR dir_s[_MAX_PATH]; TCHAR file_s[_MAX_PATH]; TCHAR ext_s[_MAX_PATH]; TCHAR from_merge[_MAX_PATH]; LPTSTR real_source; LPTSTR real_dest; INT nCopied = 0; BOOL bAll = FALSE; BOOL bDone; HANDLE hFind;#ifdef _DEBUG DebugPrintf (_T("SetupCopy\n"));#endif real_source = (LPTSTR)malloc (MAX_PATH * sizeof(TCHAR)); real_dest = (LPTSTR)malloc (MAX_PATH * sizeof(TCHAR)); if (!real_source || !real_dest) { error_out_of_memory (); DeleteFileList (sources); free (real_source); free (real_dest); freep (p); return 0; } while (sources->next != NULL) { TCHAR FullPath[MAX_PATH]; TCHAR *FilePart; GetFullPathName(sources->szFile,MAX_PATH, FullPath, &FilePart); _tsplitpath (sources->szFile, drive_s, dir_s, file_s, ext_s); hFind = FindFirstFile (FullPath, &find); if (hFind == INVALID_HANDLE_VALUE) { error_file_not_found(); freep(p); free(real_source); free(real_dest); return 0; } do { if (find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) goto next; _tmakepath(from_merge, drive_d, dir_d, file_d, ext_d); if (from_merge[_tcslen(from_merge) - 1] == _T('\\')) from_merge[_tcslen(from_merge) - 1] = 0; if (IsDirectory (from_merge)) { bMultiple = FALSE; _tcscat (from_merge, _T("\\")); _tcscat (from_merge, find.cFileName); } else bMultiple = TRUE;#ifdef FULL_CRT _tcscpy (real_dest, from_merge); _tmakepath (real_source, drive_s, dir_s, find.cFileName, NULL);#else GetFullPathName(from_merge, MAX_PATH, real_dest, &FilePart); GetFullPathName(find.cFileName ,MAX_PATH, real_source, &FilePart); #endif #ifdef _DEBUG DebugPrintf (_T("copying %s -> %s (%sappending%s)\n"), real_source, real_dest, *append ? _T("") : _T("not "), sources->dwFlag & ASCII ? _T(", ASCII") : _T(", BINARY"));#endif if (IsValidFileName (real_dest) && !bAll) { /* Don't prompt in a batch file */ if (bc != NULL) { bAll = TRUE; } else { int over; over = Overwrite (real_dest); if (over == 2) bAll = TRUE; else if (over == 0) goto next; else if (bMultiple) bAll = TRUE; } } if (copy (real_source, real_dest, *append, lpdwFlags)) nCopied++; next: bDone = FindNextFile (hFind, &find); if (bMultiple) *append = 1; } while (bDone); FindClose (hFind); sources = sources->next; } free (real_source); free (real_dest); return nCopied;}INT cmd_copy (LPTSTR first, LPTSTR rest){ TCHAR **p; TCHAR drive_d[_MAX_PATH]; TCHAR dir_d[_MAX_PATH]; TCHAR file_d[_MAX_PATH]; TCHAR ext_d[_MAX_PATH]; int argc; int append; int files; int copied; LPFILES sources = NULL; LPFILES start = NULL; FILES dest; BOOL bMultiple; BOOL bWildcards; BOOL bDestFound; DWORD dwFlags = 0; if (!_tcsncmp (rest, _T("/?"), 2)) { ConOutPuts (_T("Copies one or more files to another location.\n" _T("\n") _T("COPY [/V][/Y|/-Y][/A|/B] source [/A|/B]\n") _T(" [+ source [/A|/B] [+ ...]] [destination [/A|/B]]\n") _T("\n") _T(" source Specifies the file or files to be copied.\n") _T(" /A Indicates an ASCII text file.\n") _T(" /B Indicates a binary file.\n") _T(" destination Specifies the directory and/or filename for the new file(s).\n") _T(" /V Verifies that new files are written correctly.\n") _T(" /Y Suppresses prompting to confirm you want to overwrite an\n") _T(" existing destination file.\n") _T(" /-Y Causes prompting to confirm you want to overwrite an\n") _T(" existing destination file.\n") _T("\n") _T("The switch /Y may be present in the COPYCMD environment variable.\n") _T("..."))); return 1; } p = split (rest, &argc); if (argc == 0) { error_req_param_missing (); return 0; } sources = (LPFILES)malloc (sizeof (FILES)); if (!sources) { error_out_of_memory (); return 0; } sources->next = NULL; sources->dwFlag = 0; if ((files = ParseCommand (sources, argc, p, &dwFlags)) == -1) { DeleteFileList (sources); freep (p); return 0; } else if (files == 0) { error_req_param_missing(); DeleteFileList (sources); freep (p); return 0; } start = sources; bDestFound = GetDestination (sources, &dest); if (bDestFound) { _tsplitpath (dest.szFile, drive_d, dir_d, file_d, ext_d); if (IsDirectory (dest.szFile)) { _tcscat (dir_d, file_d); _tcscat (dir_d, ext_d); file_d[0] = _T('\0'); ext_d[0] = _T('\0'); } } if (_tcschr (dest.szFile, _T('*')) || _tcschr (dest.szFile, _T('?'))) bWildcards = TRUE; else bWildcards = FALSE; if (_tcschr(rest, _T('+'))) bMultiple = TRUE; else bMultiple = FALSE; append = 0; copied = 0; if (bDestFound && !bWildcards) { copied = SetupCopy (sources, p, bMultiple, drive_d, dir_d, file_d, ext_d, &append, &dwFlags); } else if (bDestFound && bWildcards) { ConErrPrintf (_T("Error: Not implemented yet!\n")); DeleteFileList (sources); freep (p); return 0; } else if (!bDestFound && !bMultiple) { _tsplitpath (sources->szFile, drive_d, dir_d, file_d, ext_d); if (IsDirectory (sources->szFile)) { _tcscat (dir_d, file_d); _tcscat (dir_d, ext_d); file_d[0] = _T('\0'); ext_d[0] = _T('\0'); } copied = SetupCopy (sources, p, FALSE, _T(""), _T(""), file_d, ext_d, &append, &dwFlags); } else { _tsplitpath(sources->szFile, drive_d, dir_d, file_d, ext_d); if (IsDirectory (sources->szFile)) { _tcscat (dir_d, file_d); _tcscat (dir_d, ext_d); file_d[0] = _T('\0'); ext_d[0] = _T('\0'); } ConOutPuts (sources->szFile); append = 1; copied = SetupCopy (sources->next, p, bMultiple, drive_d, dir_d, file_d, ext_d, &append, &dwFlags) + 1; } DeleteFileList (sources); freep (p); ConOutPrintf (_T(" %d file(s) copied\n"), copied); return 1;}#endif /* INCLUDE_CMD_COPY *//* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -