From a766ba057061e669f8a8bbad19287f46d6391bae Mon Sep 17 00:00:00 2001 From: Jason Edmeades Date: Fri, 27 Jul 2007 21:43:37 +0100 Subject: [PATCH] cmd: Add support for wildcards in copy. --- programs/cmd/builtins.c | 113 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 87 insertions(+), 26 deletions(-) diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index af58717ead2..9c34e8f6226 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -108,7 +108,7 @@ void WCMD_change_tty (void) { * WCMD_copy * * Copy a file or wildcarded set. - * FIXME: No wildcard support + * FIXME: Add support for a+b+c type syntax */ void WCMD_copy (void) { @@ -116,21 +116,52 @@ void WCMD_copy (void) { WIN32_FIND_DATA fd; HANDLE hff; BOOL force, status; - WCHAR outpath[MAX_PATH], inpath[MAX_PATH], *infile, copycmd[3]; + WCHAR outpath[MAX_PATH], srcpath[MAX_PATH], copycmd[3]; DWORD len; static const WCHAR copyCmdW[] = {'C','O','P','Y','C','M','D','\0'}; + BOOL copyToDir = FALSE; + BOOL copyFromDir = FALSE; + WCHAR srcspec[MAX_PATH]; + DWORD attribs; + WCHAR drive[10]; + WCHAR dir[MAX_PATH]; + WCHAR fname[MAX_PATH]; + WCHAR ext[MAX_PATH]; if (param1[0] == 0x00) { WCMD_output (WCMD_LoadMessage(WCMD_NOARG)); return; } - if ((strchrW(param1,'*') != NULL) && (strchrW(param1,'%') != NULL)) { - WCMD_output (WCMD_LoadMessage(WCMD_NYI)); - return; + /* Convert source into full spec */ + WINE_TRACE("Copy source (supplied): '%s'\n", wine_dbgstr_w(param1)); + GetFullPathName (param1, sizeof(srcpath)/sizeof(WCHAR), srcpath, NULL); + if (srcpath[strlenW(srcpath) - 1] == '\\') + srcpath[strlenW(srcpath) - 1] = '\0'; + + if ((strchrW(srcpath,'*') == NULL) && (strchrW(srcpath,'?') == NULL)) { + attribs = GetFileAttributes(srcpath); + } else { + attribs = 0; } + strcpyW(srcspec, srcpath); + + /* If a directory, then add \* on the end when searching */ + if (attribs & FILE_ATTRIBUTE_DIRECTORY) { + strcatW(srcpath, slashW); + copyFromDir = TRUE; + strcatW(srcspec, slashW); + strcatW(srcspec, starW); + } else { + WCMD_splitpath(srcpath, drive, dir, fname, ext); + strcpyW(srcpath, drive); + strcatW(srcpath, dir); + } + + WINE_TRACE("Copy source (calculated): path: '%s'\n", wine_dbgstr_w(srcpath)); /* If no destination supplied, assume current directory */ + WINE_TRACE("Copy destination (supplied): '%s'\n", wine_dbgstr_w(param2)); if (param2[0] == 0x00) { strcpyW(param2, dotW); } @@ -138,15 +169,13 @@ void WCMD_copy (void) { GetFullPathName (param2, sizeof(outpath)/sizeof(WCHAR), outpath, NULL); if (outpath[strlenW(outpath) - 1] == '\\') outpath[strlenW(outpath) - 1] = '\0'; - hff = FindFirstFile (outpath, &fd); - if (hff != INVALID_HANDLE_VALUE) { - if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - GetFullPathName (param1, sizeof(inpath)/sizeof(WCHAR), inpath, &infile); - strcatW (outpath, slashW); - strcatW (outpath, infile); - } - FindClose (hff); + attribs = GetFileAttributes(outpath); + if (attribs & FILE_ATTRIBUTE_DIRECTORY) { + strcatW (outpath, slashW); + copyToDir = TRUE; } + WINE_TRACE("Copy destination (calculated): '%s'(%d)\n", + wine_dbgstr_w(outpath), copyToDir); /* /-Y has the highest priority, then /Y and finally the COPYCMD env. variable */ if (strstrW (quals, parmNoY)) @@ -158,21 +187,53 @@ void WCMD_copy (void) { force = (len && len < (sizeof(copycmd)/sizeof(WCHAR)) && ! lstrcmpiW (copycmd, parmY)); } - if (!force) { - hff = FindFirstFile (outpath, &fd); - if (hff != INVALID_HANDLE_VALUE) { - WCHAR buffer[MAXSTRING]; + /* Loop through all source files */ + WINE_TRACE("Searching for: '%s'\n", wine_dbgstr_w(srcspec)); + hff = FindFirstFile (srcspec, &fd); + if (hff != INVALID_HANDLE_VALUE) { + do { + WCHAR outname[MAX_PATH]; + WCHAR srcname[MAX_PATH]; + BOOL overwrite = force; + + /* Destination is either supplied filename, or source name in + supplied destination directory */ + strcpyW(outname, outpath); + if (copyToDir) strcatW(outname, fd.cFileName); + strcpyW(srcname, srcpath); + strcatW(srcname, fd.cFileName); + + WINE_TRACE("Copying from : '%s'\n", wine_dbgstr_w(srcname)); + WINE_TRACE("Copying to : '%s'\n", wine_dbgstr_w(outname)); + + /* Skip . and .., and directories */ + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + overwrite = FALSE; + WINE_TRACE("Skipping directories\n"); + } + + /* Prompt before overwriting */ + else if (!overwrite) { + attribs = GetFileAttributes(outname); + if (attribs != INVALID_FILE_ATTRIBUTES) { + WCHAR buffer[MAXSTRING]; + wsprintf(buffer, WCMD_LoadMessage(WCMD_OVERWRITE), outname); + overwrite = WCMD_ask_confirm(buffer, FALSE, NULL); + } + else overwrite = TRUE; + } - FindClose (hff); + /* Do the copy as appropriate */ + if (overwrite) { + status = CopyFile (srcname, outname, FALSE); + if (!status) WCMD_print_error (); + } - wsprintf(buffer, WCMD_LoadMessage(WCMD_OVERWRITE), outpath); - force = WCMD_ask_confirm(buffer, FALSE, NULL); - } - else force = TRUE; - } - if (force) { - status = CopyFile (param1, outpath, FALSE); - if (!status) WCMD_print_error (); + } while (FindNextFile(hff, &fd) != 0); + FindClose (hff); + } else { + status = ERROR_FILE_NOT_FOUND; + WCMD_print_error (); } } -- 2.11.4.GIT