/*++ Copyright (c) 1988-1999 Microsoft Corporation Module Name: cfile.c Abstract: File manipulation support --*/ #include "cmd.h" #define Wild(spec) ((spec)->flags & (CI_NAMEWILD)) extern int LastRetCode ; extern jmp_buf CmdJBuf2 ; extern TCHAR Fmt19[], Fmt17[]; extern TCHAR CurDrvDir[] ; extern TCHAR YesChar, NoChar ; extern TCHAR *SaveDir ; extern TCHAR PathChar, TmpBuf[], SwitChar; extern unsigned DosErr ; extern unsigned flgwd ; /* M021 */ extern int LastRetCode ; extern BOOL CtrlCSeen; extern PTCHAR pszTitleCur; extern BOOLEAN fTitleChanged; // // Internal prototypes // PCPYINFOSetFsSetSaveDir() ; /*** ErrorDisplayAndJumnp - handle errors * * Purpose: * eRename and eMove error handler. Returns to routine via longjmp * * ErrorDisplayAndJump(unsigned int errmsg) * * * Args: * errmsg - the error message to print * */ void ErrorDisplayAndJump( unsigned int errmsg ) { PutStdErr( errmsg, NOARGS ); RestoreSavedDirectory( ); longjmp( CmdJBuf2, 1 ) ; } /* ** This routine returns the longest pathlength possible from the input path ** It assumes that the input path is a buffer that it can extend by a ** wildcard '\*' to search the file, if it is a directory. ** The input path must be fully qualified, eg: "c:\winnt\system32\kernel32.dll" ** ** Input: ** pPath fully qualified Pathname ** pCch pointer to length of pathname ** Returns: ** TRUE succeeded, pCch contains length ** FALSE error occurred */ BOOL GreatestLength( TCHAR *pPath, int *pCch ) { WIN32_FIND_DATA fd; HANDLE hFind; DWORD err; int cch; int cchThis; DWORD attr; TCHAR *pLast; BOOL MoreFiles; /* assume a file, or empty directory */ *pCch = cch = _tcslen(pPath) - 2; /* _tcslen(TEXT("C:")) */ if ((attr=GetFileAttributes(pPath)) == 0xffffffff) { PutStdErr(GetLastError(), NOARGS); return FALSE; } if ( !(attr & FILE_ATTRIBUTE_DIRECTORY)) { /* if just a file... */ return TRUE; } /* path is a directory, search it ... */ pLast = pPath + _tcslen(pPath); if (*(pLast-1) == BSLASH) { *pLast = STAR; *(pLast+1) = NULLC; } else { *pLast = BSLASH; *(pLast+1) = STAR; *(pLast+2) = NULLC; } if ((hFind=FindFirstFile(pPath, &fd)) == INVALID_HANDLE_VALUE) { // // Check that failure was not due to some system error such // as an abort on access to floppy // err = GetLastError(); FindClose(hFind); if (err != ERROR_FILE_NOT_FOUND && err != ERROR_NO_MORE_FILES) { PutStdErr(err, NOARGS); return FALSE; } return TRUE; } MoreFiles = TRUE; do { if (!_tcscmp(fd.cFileName, TEXT("."))) continue; if (!_tcscmp(fd.cFileName, TEXT(".."))) continue; if (_tcslen( fd.cFileName ) == 0) { continue; } if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { TCHAR path[MAX_PATH]; _tcscpy(path, pPath); *(path+_tcslen(path)-1) = NULLC; /* zap asterisk */ _tcscat(path, fd.cFileName); if (!GreatestLength(path, &cchThis)) break; *pCch = max(*pCch, cch + cchThis); } else { *pCch = max(*pCch, (int) _tcslen(fd.cFileName)); } } while ( MoreFiles = FindNextFile(hFind, &fd) ); err = GetLastError(); FindClose(hFind); if ( MoreFiles ) { return FALSE; } else if ( err != ERROR_NO_MORE_FILES ) { PutStdErr(err, NOARGS); return FALSE; } return TRUE; } void RestoreSavedDirectory( void ) { if (SaveDir) { mystrcpy( CurDrvDir, SaveDir ); SaveDir = NULL; } } BOOL GetPromptOkay( const TCHAR *arg, BOOL *promptokay ) { BOOL Result; const TCHAR *p, *p1; Result = TRUE; if (arg != NULL) { p = arg; while (*p && *p <= SPACE) p += 1; p1 = p; while (*p1 && *p1 > SPACE) p1 += 1; if (!_tcsnicmp(p, TEXT("/Y"),(UINT)(p1-p))) *promptokay = FALSE; else if (!_tcsnicmp(p, TEXT("/-Y"),(UINT)(p1-p))) *promptokay = TRUE; else Result = FALSE; } return Result; } int eCopy(n) struct cmdnode *n ; { return(LastRetCode = copy(n->argptr)) ; } int eDelete(n) struct cmdnode *n ; { int DelWork() ; return(LastRetCode = DelWork(n->argptr)); } /********************* START OF SPECIFICATION **************************/ /* */ /* SUBROUTINE NAME: eRename */ /* */ /* DESCRIPTIVE NAME: Rename Internal Command */ /* */ /* FUNCTION: Rename files and subdirectories. Wildcards only applies */ /* to file names. */ /* */ /* NOTES: @@5* */ /* */ /* ENTRY POINT: eRename */ /* LINKAGE: NEAR */ /* */ /* INPUT: */ /* n - the parse tree node containing the rename command */ /* */ /* OUTPUT: None. */ /* */ /* EXIT-NORMAL: */ /* Return SUCCESS to the caller. */ /* */ /* EXIT-ERROR: */ /* Return FAILURE to the caller. */ /* */ /* EFFECTS: None. */ /* */ /* INTERNAL REFERENCES: */ /* ROUTINES: */ /* RenWork - Worker routine for rename. */ /* */ /* EXTERNAL REFERENCES: */ /* ROUTINES: */ /* None */ /* */ /********************** END OF SPECIFICATION **************************/ int eRename(n) struct cmdnode *n ; { int RenWork(); /* @@ */ return(LastRetCode = RenWork( n )); /* @@ */ } /********************* START OF SPECIFICATION **************************/ /* */ /* SUBROUTINE NAME: RenWork */ /* */ /* DESCRIPTIVE NAME: Rename Internal Command Worker */ /* */ /* FUNCTION: Rename files and subdirectories. Wildcards only applies */ /* to file names. */ /* */ /* NOTES: @@5* */ /* */ /* ENTRY POINT: RenWork */ /* LINKAGE: NEAR */ /* */ /* INPUT: */ /* n - The parse tree node containing the rename command */ /* */ /* OUTPUT: None. */ /* */ /* EXIT-NORMAL: */ /* Return SUCCESS to the caller. */ /* */ /* EXIT-ERROR: */ /* Return FAILURE to the caller. */ /* */ /* EFFECTS: None. */ /* */ /* INTERNAL REFERENCES: */ /* ROUTINES: */ /* ffirst - Find the first matching specified file. */ /* fnext - Find the next matching specified file handle*/ /* findclose - Close the file with the specified file handle, */ /* hnFirst which is given by ffirst or fnext. */ /* TokStr - Tokenize argument strings. */ /* wildcard_rename - Obtain name based on wildcard specification.*/ /* SetFsSetSaveDir - Save the current directory. */ /* GetDir - Get the specified directory. */ /* ChangeDir - Change to the specified directory. */ /* PutStdErr - Displays an error message. */ /* Wild - check if the arg contains wild card. */ /* */ /* EXTERNAL REFERENCES: */ /* ROUTINES: */ /* None */ /* DOSMOVE - Rename file and directory names. */ /* DOSCASEMAP - Change lower case character to upper case. */ /* DOSFILEMODE - Get attribute of specified file. */ /* */ /********************** END OF SPECIFICATION **************************/ int RenWork(n) /* @@ */ struct cmdnode *n ; { TCHAR *arg1 ; /* Ptr to 1st arg */ TCHAR *arg2 ; /* Ptr to 2nd arg */ PCPYINFO a1info ; /* Holds arg1 fspec info */ PCPYINFO SetFsSetSaveDir(); TCHAR Source[MAX_PATH]; TCHAR bufdst[MAX_PATH]; /* path of destination file*/ TCHAR Replacement[MAX_PATH]; int wlen; /* length of source path */ int rc; /* return code */ HANDLE hnFirst ; /* Findfirst handle */ unsigned attr ; unsigned i; /* Temp Return Code */ TCHAR *j ; /* Temp Ptr to dir name */ unsigned wild_flag ; /* wildcard flag */ TCHAR pcstr[3] ; unsigned retval = SUCCESS; DEBUG((FCGRP, RELVL, "RENAME: arptr = `%ws'", n->argptr)) ; if (setjmp(CmdJBuf2)) return(FAILURE) ; /* There should be only two arguments */ if (!*(arg1 = TokStr(n->argptr, NULL, TS_NOFLAGS)) || !*(arg2 = arg1 + mystrlen(arg1) + 1) || *(arg2 + mystrlen(arg2) +1)) { /* @@5g */ ErrorDisplayAndJump( MSG_BAD_SYNTAX ); } mystrcpy( arg1, StripQuotes(arg1) ); /* 509 */ mystrcpy( arg2, StripQuotes(arg2) ); /* 509 */ if ((a1info = SetFsSetSaveDir(arg1)) == (PCPYINFO)FAILURE) { ErrorDisplayAndJump( DosErr ); } mystrcpy( Source, CurDrvDir ); mystrcpy(bufdst,CurDrvDir); /* save path of dest */ wlen = mystrlen( Source ); /* get len of src path */ if ( (a1info->buf->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0 ) { mystrcpy(&Source[wlen],a1info->fnptr); } else { Source[--wlen] = NULLC ; bufdst[wlen] = NULLC ; } /* if not wild since */ if (!Wild(a1info)) { a1info->buf->dwFileAttributes = GetFileAttributes( StripQuotes(Source) ); if (a1info->buf->dwFileAttributes == -1 ) { ErrorDisplayAndJump( GetLastError( )) ; } } if (*(arg2+1) == COLON || mystrchr(arg2,PathChar)) { ErrorDisplayAndJump( MSG_BAD_SYNTAX ); } /**********************************************/ /* M009 - Always specifiy drive, filename, */ /* and extension. Note, it is */ /* assumed that SaveDir always starts */ /* with a drive letter */ /**********************************************/ Replacement[0] = CurDrvDir[0] ; /* @@5h */ Replacement[1] = COLON ; /**********************************************/ /* Set flag whether arg1 contains */ /* wildcard or not. */ /**********************************************/ pcstr[0] = STAR ; pcstr[1] = QMARK ; pcstr[2] = NULLC ; wild_flag = ((mystrcspn(arg1,pcstr)) < mystrlen(arg1)) ; /**********************************************/ /* Issue ffirst for a file name */ /**********************************************/ if ( !ffirst(Source, attr = FILE_ATTRIBUTE_ARCHIVE, a1info->buf, &hnFirst )) { /*********************************************/ /* Issue ffirst for a directory name */ /*********************************************/ if (!ffirst(Source, attr = FILE_ATTRIBUTE_DIRECTORY, a1info->buf, &hnFirst )) { if (DosErr == ERROR_NO_MORE_FILES) { DosErr = ERROR_FILE_NOT_FOUND; } ErrorDisplayAndJump( DosErr ); } else { if (wild_flag) { findclose( hnFirst ); ErrorDisplayAndJump( MSG_BAD_SYNTAX ); } } } Source[wlen] = NULLC; /* make filename = NULL */ rc = 0 ; /* @@5 */ do { if (CtrlCSeen) { findclose(hnFirst) ; RestoreSavedDirectory( ); return(FAILURE); } /**********************************************/ /* if the file attribute of Source is */ /* directory then concatenate arg2 after the */ /* last "\" character of bufdst */ /**********************************************/ if ( a1info->buf->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) { /* @@5c*/ j = mystrrchr(bufdst,PathChar) ; /* @@5 */ if ( !j ) { ErrorDisplayAndJump( MSG_REN_INVAL_PATH_FILENAME ); } *(++j) = NULLC; if ( (mystrlen(arg2) + 1 + mystrlen(bufdst)) > MAX_PATH ) { ErrorDisplayAndJump( MSG_REN_INVAL_PATH_FILENAME ); } mystrcpy(j,arg2); /* @@5 */ bufdst[mystrlen(bufdst)] = NULLC ; /* @@5 */ } /* @@5 */ else { /* @@5 */ mystrcpy(&Source[wlen],a1info->buf->cFileName); wildcard_rename( Replacement, arg2, &Source[wlen], MAX_PATH ); if ( (wlen + 1 + mystrlen( Replacement )) > MAX_PATH ) { ErrorDisplayAndJump( MSG_REN_INVAL_PATH_FILENAME ); } mystrcpy(&bufdst[wlen],&Replacement[0]); /*@@4 @J1*/ } /**********************************************/ /* Rename a file or directory */ /**********************************************/ DEBUG((FCGRP, RELVL, "RENAME: src:`%ws', dst:`%ws'", Source, bufdst)) ; if ( !MoveFile( Source, bufdst ) ) { /**********************************************/ /* rename fails */ /**********************************************/ i = GetLastError(); if (i == ERROR_ALREADY_EXISTS) { i = MSG_DUP_FILENAME_OR_NOT_FD; } rc = i ; /* @@5 Save the error code*/ PutStdErr(rc,NOARGS); /* @@5 Put our err message*/ } } while (fnext(a1info->buf, attr, hnFirst )); /**********************************************/ /* No more file is found */ /**********************************************/ findclose(hnFirst) ; RestoreSavedDirectory( ); return( rc ? FAILURE : SUCCESS ); /* @@5 */ } /********************* START OF SPECIFICATION **************************/ /* */ /* SUBROUTINE NAME: eMove */ /* */ /* DESCRIPTIVE NAME: Move Internal Command */ /* */ /* FUNCTION: Parse the parameter passed and */ /* moves one or more files from directory to another */ /* directory on the same drive. If you prefer you can give */ /* the files different names. */ /* */ /* NOTES: ( New routine for Relaese 1.2 ) @@5* */ /* */ /* ENTRY POINT: eMove */ /* LINKAGE: NEAR */ /* */ /* INPUT: */ /* n - the parse tree node containing the copy command */ /* */ /* OUTPUT: None. */ /* */ /* EXIT-NORMAL: */ /* Return SUCCESS to the caller. */ /* */ /* EXIT-ERROR: */ /* Return FAILURE to caller. */ /* */ /* EFFECTS: None. */ /* */ /* INTERNAL REFERENCES: */ /* ROUTINES: */ /* MoveParse - parse move command parameter */ /* Move - routine which actually call DosMove to move */ /* file or directory. */ /* */ /* EXTERNAL REFERENCES: */ /* ROUTINES: */ /* None */ /* */ /********************** END OF SPECIFICATION **************************/ int eMove(n) struct cmdnode *n ; { unsigned i; BOOL PromptOnOverwrite; TCHAR arg1[MAX_PATH] ; /* Ptr to 1st arg */ TCHAR arg2[MAX_PATH] ; /* Ptr to 2nd arg */ PCPYINFO a1info ; /* Holds arg1 fspec info */ unsigned int is_dest_dir; /* generated by MoveParse(), used by Move() */ DEBUG((FCGRP, RELVL, "RENAME: arptr = `%ws'", n->argptr)) ; if (setjmp(CmdJBuf2)) return(LastRetCode = FAILURE) ; // // Get default prompt okay flag from COPYCMD variable. Allow // user to override with /Y or /-Y switch. Always assume /Y // if command executed from inside batch script or via CMD.EXE // command line switch (/C or /K) // if (SingleBatchInvocation || SingleCommandInvocation || CurrentBatchFile != 0) PromptOnOverwrite = FALSE; // Assume /Y else PromptOnOverwrite = TRUE; // Assume /-Y /* MoveParse parses the command line parameters to arg1 */ /* and arg1. In addition, a1info holds the fspec */ /* information for arg1. */ /* Based on arg1 and arg2, Move moves file(s)/directory. */ /* Move uses a1info to determine that arg1 contains */ /* wildcard. */ i = MoveParse( n, &PromptOnOverwrite, arg1, arg2, &a1info, &is_dest_dir, MAX_PATH, MAX_PATH ); if (!i) { i = Move( arg1, arg2, PromptOnOverwrite, a1info, is_dest_dir ) ; } return(LastRetCode = i) ; } /********************* START OF SPECIFICATION **************************/ /* */ /* SUBROUTINE NAME: MoveParse */ /* */ /* DESCRIPTIVE NAME: Move Parser */ /* */ /* FUNCTION: Move Internal Function Parser */ /* */ /* NOTES: This parser breaks up the command line information */ /* into two parameters. */ /* ( New routine for Relaese 1.2 ) @@5* */ /* */ /* ENTRY POINT: MoveParse */ /* LINKAGE: NEAR */ /* */ /* INPUT: */ /* n - the parse tree node containing the move command */ /* */ /* OUTPUT: ptr1 - pointer to [drive:][path]filename to be moved from */ /* ptr2 - pointer to [path]filename to be moved to */ /* a1info - pointer to cpyinfo which has arg1 fspec info */ /* is_dest_dir - flag used by Move() */ /* */ /* EXIT-NORMAL: */ /* Return SUCCESS to the caller. */ /* */ /* EXIT-ERROR: */ /* Return FAILURE to the caller. */ /* */ /* EFFECTS: None. */ /* */ /* INTERNAL REFERENCES: */ /* ROUTINES: */ /* TokStr - Tokenize argument strings. */ /* FullPath - Figure out the full path for a file. */ /* SetFsSetSaveDir - Save current directory. */ /* */ /* EXTERNAL REFERENCES: */ /* ROUTINES: */ /* DOSQFILEMODE - Get file mode of the specified file/dir. */ /* */ /********************** END OF SPECIFICATION **************************/ int MoveParse(n, promptokay, source, target , a1info, is_dest_dir, sizpath1, sizpath2) struct cmdnode *n ; BOOL *promptokay ; TCHAR *source ; /* Ptr to source file(s)/directory name */ TCHAR *target ; /* Ptr to target file(s)/directory name */ PCPYINFO* a1info ; /* Holds arg1 fspec information */ unsigned int *is_dest_dir; /* to pass to move */ unsigned sizpath1; /* size of source buffer */ unsigned sizpath2; /* size of target buffer */ { PCPYINFO SetFsSetSaveDir() ; TCHAR *arg1 ; /* Ptr to 1st arg */ TCHAR *arg2 ; /* Ptr to 2nd arg */ TCHAR *p1; TCHAR *p2; TCHAR arg22[MAX_PATH] ; /* Ptr to modified 2nd arg */ unsigned i; unsigned concat_flag ; unsigned att ; /*509*/unsigned arg1len, arg2len; // // Get default prompt okay flag from COPYCMD variable. Allow // user to override with first token after command. // GetPromptOkay(MyGetEnvVarPtr(TEXT("COPYCMD")), promptokay); arg1 = TokStr(n->argptr, NULL, TS_NOFLAGS); if (GetPromptOkay(arg1, promptokay)) while (*arg1++) ; /* Get arg1. If fail to get arg1, display error message. */ arg1len = mystrlen(arg1); if (arg1len == 0) { ErrorDisplayAndJump( MSG_BAD_SYNTAX ); } else if ( arg1len >= MAX_PATH) { ErrorDisplayAndJump( MSG_REN_INVAL_PATH_FILENAME ); } /*CurDrvDir = current directory or directory which is specified in arg1*/ /*509*/mystrcpy( arg1, StripQuotes( arg1 ) ); if (((*a1info) = SetFsSetSaveDir(arg1)) == (PCPYINFO)FAILURE) { ErrorDisplayAndJump( DosErr ); } /* */ /* Get arg2 out of arg1 */ arg2 = arg1 + arg1len + 1; if ( !(*arg2) ) { arg22[0] = SaveDir[0]; /* get current drive */ arg22[1] = COLON; arg22[2] = NULLC; } else if (*(arg2 + mystrlen(arg2) + 1)) { /* @@5g */ ErrorDisplayAndJump( MSG_BAD_SYNTAX ); } /*509*/ else if ( (arg2len = mystrlen(arg2)) > MAX_PATH) { ErrorDisplayAndJump( MSG_REN_INVAL_PATH_FILENAME ); } else { /* If arg2 conatins a drive name, display an error message. */ /*509*/ mystrcpy ( arg2, StripQuotes( arg2 ) ); // UNC names fix if ( ( *(arg2+1) != COLON ) && ( ! ( ( *arg2 == BSLASH ) && ( *(arg2+1) == BSLASH ) ) ) ) { arg22[0] = SaveDir[0]; /* get drive we're using */ arg22[1] = COLON; arg22[2] = NULLC; if ((mystrlen(arg22) + mystrlen(arg2)+1) > MAX_PATH) { ErrorDisplayAndJump( MSG_REN_INVAL_PATH_FILENAME ); } mystrcat( arg22, arg2 ) ; } else { mystrcpy(arg22,arg2) ; } } /* source = complete path for arg1 */ if ( i = FullPath(source, arg1,sizpath1) ) { ErrorDisplayAndJump( MSG_REN_INVAL_PATH_FILENAME ); } // // If preserve file name portion from arg1 as FullPath will map *. to * which // is not what the user wants. // if (!((*a1info)->buf->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { p1 = mystrrchr(source,PathChar) ; if (p1 != NULL) p1 += 1; else p1 = source; p2 = mystrrchr((*a1info)->fnptr,PathChar) ; if (p2 == NULL) p2 = (*a1info)->fnptr; mystrcpy(p1, p2); } /* target = complete path for arg2 */ if ( i = FullPath(target, arg22,sizpath2) ) { ErrorDisplayAndJump( MSG_REN_INVAL_PATH_FILENAME ); } concat_flag = FALSE ; DosErr = NO_ERROR ; SetLastError(NO_ERROR); *is_dest_dir = 0; if (*lastc(target) == PathChar) { /* test for last non DBCS character path char @@5@J3 */ concat_flag = TRUE ; target[mystrlen(target)-1] = NULLC ; }; if ( (att = GetFileAttributes( target )) != -1 ) { if (att & FILE_ATTRIBUTE_DIRECTORY) { /* if target is a directory, copy the file */ /* name from source. */ *is_dest_dir = 1; concat_flag = TRUE ; }; } else if ( (DosErr = GetLastError()) && ( ( DosErr != ERROR_FILE_NOT_FOUND ) && ( DosErr != ERROR_PATH_NOT_FOUND ) ) ) { ErrorDisplayAndJump( DosErr ); }; if (concat_flag) { arg1 = mystrrchr(source,PathChar); if ((mystrlen(arg1) + mystrlen(target) + 1) > MAX_PATH) { ErrorDisplayAndJump( MSG_REN_INVAL_PATH_FILENAME ); } mystrcat( target, arg1 ) ; }; return(SUCCESS) ; } BOOL MyMoveFile( TCHAR *src, TCHAR *dst, BOOL *promptokay, BOOL *file_moved ) { DWORD dwFlags; dwFlags = MOVEFILE_COPY_ALLOWED; if (!*promptokay) { dwFlags |= MOVEFILE_REPLACE_EXISTING; } *file_moved = FALSE; if (!MoveFileEx(src, dst, dwFlags)) { if (GetLastError() == ERROR_ALREADY_EXISTS) { switch (PromptUser(dst, MSG_MOVE_COPY_OVERWRITE, MSG_NOYESALL_RESPONSE_DATA)) { case 0: // No return TRUE; break; case 2: // All *promptokay = FALSE; default: // Yes dwFlags |= MOVEFILE_REPLACE_EXISTING; return(*file_moved = MoveFileEx(src, dst, dwFlags)); break; } } return FALSE; } else { *file_moved = TRUE; return TRUE; } } /********************* START OF SPECIFICATION **************************/ /* */ /* SUBROUTINE NAME: Move */ /* */ /* DESCRIPTIVE NAME: Move Process */ /* */ /* FUNCTION: Moves one or more files from directory to another */ /* directory on the same drive. If you prefer you can give */ /* the files different names. */ /* */ /* NOTES: ( New routine for Release 1.2 ) @@5* */ /* */ /* ENTRY POINT: eMove */ /* LINKAGE: NEAR */ /* */ /* INPUT: ptr1 - pointer to [drive:][path]filename to be moved from */ /* ptr2 - pointer to [path]filename to be moved to */ /* a1info - pointer to cpyinfo which has arg1 fspec info */ /* is_dest_dir - from MoveParse() */ /* */ /* OUTPUT: None. */ /* */ /* EXIT-NORMAL: */ /* Return Success to the caller. */ /* */ /* EXIT-ERROR: */ /* Return error code from DosMove API. */ /* */ /* EFFECTS: None. */ /* */ /* INTERNAL REFERENCES: */ /* ROUTINES: */ /* ChangeDir - Change back to the original directory. */ /* ffirst - Find the first file which matches the specified */ /* file name that may contain * or ?. */ /* fnext - Find the next file which matches the specified */ /* file name that may contain * or ?. */ /* findclose - Close the file with the specified file handle, */ /* hnFirst which is given by ffirst or fnext. */ /* PutStdErr - Displays an error message. */ /* PutStdOut - Displays a message. */ /* Wild - check if the arg contains wild card. */ /* */ /* EXTERNAL REFERENCES: */ /* ROUTINES: */ /* DOSMOVE - move directories and files. */ /* */ /********************** END OF SPECIFICATION **************************/ int Move( arg1, arg2, promptokay, a1info, is_dest_dir ) TCHAR *arg1 ; /* Ptr to 1st arg */ TCHAR *arg2 ; /* Ptr to 2nd arg */ BOOL promptokay ; PCPYINFO a1info ; /* Holds arg1 fspec info */ unsigned int is_dest_dir; /* flag if set--> dest. is a dir */ { unsigned attr ; unsigned i, n; unsigned long number_of_files_moved ; TCHAR Source[MAX_PATH]; /* path of source file */ TCHAR bufdst[MAX_PATH]; /* path of destination file*/ HANDLE hnFirst ; /* Findfirst handle */ TCHAR *j, *k,*l; /* Tmp Ptr */ unsigned wild_flag ; /* wildcard flag */ BOOL file_moved; unsigned save_error ; /* Saved error code */ TCHAR pcstr[3] ; unsigned rc; int retc; int how_many_src=0; /* =f_RET_DIR if dir; =0 if none; = else */ char type_format_dest=0; /* decide on how to format dest */ char fl_move_once=0; /* if =1 execute move once only */ how_many_src = f_how_many (arg1, (ULONG) (attr=FILE_ATTRIBUTE_ARCHIVE) ); /**********************************************/ /* Set flag whether arg1 contains */ /* wildcard or not. */ /**********************************************/ pcstr[0] = STAR ; pcstr[1] = QMARK ; pcstr[2] = NULLC ; wild_flag = ((mystrcspn(arg1,pcstr)) < mystrlen(arg1)) ; // Decide on what to do depending on: <1.multiple/single src; 2.is dest dir ?> if (how_many_src == f_RET_DIR) { if (is_dest_dir) { if (!MyMoveFile(arg1, arg2, &promptokay, &file_moved) ) { i = GetLastError(); if (i == ERROR_ALREADY_EXISTS) { i = MSG_DUP_FILENAME_OR_NOT_FD; } ErrorDisplayAndJump( i ); } else { RestoreSavedDirectory( ); PutStdOut(MSG_DIRS_MOVED, ONEARG, argstr1( TEXT( "%9d" ), 1 )) ; return(SUCCESS) ; } } else { type_format_dest = 2; fl_move_once = 1; } } else if (how_many_src > 1 ) { if (is_dest_dir) { type_format_dest = 1; fl_move_once = 0; } else { ErrorDisplayAndJump( MSG_MOVE_MULTIPLE_FAIL ); } } else { // single source or source doesn't exist if (is_dest_dir) { type_format_dest = 1; fl_move_once = 1; } else { type_format_dest = 2; fl_move_once = 1; } } /**********************************************/ /* Issue ffirst for a file name */ /**********************************************/ /*M006*/ if (!ffirst(arg1, attr = FILE_ATTRIBUTE_ARCHIVE, a1info->buf, &hnFirst )) { /**********************************************/ /* Issue ffirst for a directory name */ /**********************************************/ rc = ffirst(arg1, attr = FILE_ATTRIBUTE_DIRECTORY, a1info->buf, &hnFirst ) ; if ( !rc) { /**********************************************/ /* No file or directory which arg1 */ /* specifies found */ /**********************************************/ if (!rc && DosErr == ERROR_NO_MORE_FILES) { /* @@5e */ rc = ERROR_FILE_NOT_FOUND; } else if (wild_flag) { rc = MSG_DUP_FILENAME_OR_NOT_FD; } else { rc = DosErr; } ErrorDisplayAndJump( rc ); } } number_of_files_moved = 0 ; /* Reset the counter to zero */ save_error = NO_ERROR ; /* Reset error code to zero */ mystrcpy(Source,arg1) ; j = mystrrchr(Source,PathChar) ; ++j; /* get to filename area */ do { if (CtrlCSeen) { findclose(hnFirst) ; RestoreSavedDirectory( ); return(FAILURE); } /**********************************************/ /* build bufdst */ /**********************************************/ mystrcpy(j,a1info->buf->cFileName) ; mystrcpy(bufdst,arg2); if (type_format_dest == 1 ) { l = mystrrchr(bufdst,PathChar); ++l; mystrcpy(l,a1info->buf->cFileName) ; if ((mystrlen(bufdst) ) > MAX_PATH) { ErrorDisplayAndJump( MSG_REN_INVAL_PATH_FILENAME ) ; } } /**********************************************/ /* check to see if filename is legal */ /**********************************************/ { TCHAR TempBuffer[MAX_PATH]; DWORD Length; Length = GetFullPathName( bufdst, MAX_PATH, TempBuffer, NULL ); if (Length == 0 || Length >= MAX_PATH) { goto badness; } n = _tcslen( TempBuffer ); Length = GetFullPathName( Source, MAX_PATH, TempBuffer, NULL ); if (Length == 0 || Length >= MAX_PATH) { goto badness; } if (!GreatestLength( TempBuffer, &i)) continue; i -= _tcslen( TempBuffer ); } if (n + i > MAX_PATH) { i = ERROR_FILENAME_EXCED_RANGE; goto badness2; } /**********************************************/ /* Move a file or directory */ /**********************************************/ if (!MyMoveFile(Source, bufdst, &promptokay, &file_moved)) { /**********************************************/ /* Move fails */ /**********************************************/ badness: i = GetLastError(); badness2: if (i == ERROR_ALREADY_EXISTS) { i = MSG_DUP_FILENAME_OR_NOT_FD; } save_error = i ; /* Save the error code */ PutStdErr(i, NOARGS); /* Put out an error message */ i = mystrlen(bufdst) ; if ( bufdst[--i] == DOT ) { /* @@5a */ bufdst[i] = 0 ; /* @@5a */ } /* @@5a */ /* @@5a */ /*509*/if (!_tcsicmp(Source,bufdst)) { /* @@5a */ break ; /* @@5a */ } /* @@5a */ } else if (file_moved) { number_of_files_moved += 1; if ( wild_flag ) { /* If wild card is used */ cmd_printf(Fmt17,Source); /* display the file name*/ } } if (fl_move_once) break; } while (fnext(a1info->buf, attr, hnFirst )); /**********************************************/ /* No more files to be found */ /**********************************************/ findclose(hnFirst) ; RestoreSavedDirectory( ); /**********************************************/ /* Display the total number of file(s) moved */ /**********************************************/ if ( (a1info->buf->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0 ) { PutStdOut(MSG_FILES_MOVED, ONEARG, argstr1(TEXT("%9d"), (unsigned long)number_of_files_moved)) ; } else { PutStdOut(MSG_DIRS_MOVED, ONEARG, argstr1(TEXT("%9d"), (unsigned long)number_of_files_moved)) ; } return(save_error == NO_ERROR ? SUCCESS : FAILURE) ; } int eTitle ( IN struct cmdnode *pcmdnode ) { LPTSTR NewTitle; if (!pszTitleCur) { pszTitleCur = HeapAlloc(GetProcessHeap(), 0, MAX_PATH*sizeof(TCHAR) + 2*sizeof(TCHAR)); if (pszTitleCur == NULL) { PutStdErr(ERROR_NOT_ENOUGH_MEMORY, NOARGS); return( FAILURE ); } } if (mystrlen(pcmdnode->argptr) >= MAX_PATH) { PutStdErr(ERROR_NOT_ENOUGH_MEMORY, NOARGS); return( FAILURE ); } NewTitle = EatWS(pcmdnode->argptr, NULL); if (NewTitle && *NewTitle) { mystrcpy(pszTitleCur,NewTitle); } SetConsoleTitle(pszTitleCur); // // This insures that ResetConTitle does not undo what // we have just done // fTitleChanged = FALSE; return( SUCCESS ); } /*** eStart - Entry point for Start routine * * Purpose: * to call Start and pass it a pointer to the command line * arguments * * Args: * a pointer to the command node structure * */ int eStart( n ) /* @@ */ struct cmdnode *n; /* @@ */ { /* @@ */ DBG_UNREFERENCED_PARAMETER( n ); return( Start(n->argptr) ); } /* @@ */