Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenren.c
Go to the documentation of this file.
00001 /* 00002 * REN.C - rename internal command. 00003 * 00004 * 00005 * History: 00006 * 00007 * 00008 * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>) 00009 * added config.h include 00010 * 00011 * 18-Dec-1998 (Eric Kohl) 00012 * Added support for quoted long file names with spaces. 00013 * 00014 * 20-Jan-1999 (Eric Kohl) 00015 * Unicode and redirection safe! 00016 * 00017 * 17-Oct-2001 (Eric Kohl) 00018 * Implemented basic rename code. 00019 * 00020 * 30-Apr-2005 (Magnus Olsen) <magnus@greatlord.com>) 00021 * Remove all hardcode string to En.rc 00022 * 25-Nov-2008 (Victor Martinez) <vicmarcal@hotmail.com> Patch dedicated to Myrjala because her comprenhension and love :D 00023 * Fixing following Bugs: 00024 * -Wrong behavior with wildcards when Source and Destiny are Paths(FIXED). 00025 * -Wrong general behavior (MSDN:"Rename cant move files between subdirectories")(FIXED) 00026 * -Wrong behavior when renaming without path in destiny:(i.e) "ren C:\text\as.txt list.txt" it moves as.txt and then rename it(FIXED) 00027 * (MSDN: If there is a Path in Source and no Path in Destiny, then Destiny Path is Source Path,because never Ren has to be used to move.) 00028 * -Implemented checkings if SourcePath and DestinyPath are differents. 00029 * 00030 */ 00031 00032 #include <precomp.h> 00033 00034 #ifdef INCLUDE_CMD_RENAME 00035 00036 enum 00037 { 00038 REN_ATTRIBUTES = 0x001, /* /A : not implemented */ 00039 REN_ERROR = 0x002, /* /E */ 00040 REN_NOTHING = 0x004, /* /N */ 00041 REN_PROMPT = 0x008, /* /P : not implemented */ 00042 REN_QUIET = 0x010, /* /Q */ 00043 REN_SUBDIR = 0x020, /* /S */ 00044 REN_TOTAL = 0x040, /* /T */ 00045 }; 00046 00047 00048 /* 00049 * file rename internal command. 00050 * 00051 */ 00052 INT cmd_rename (LPTSTR param) 00053 { 00054 LPTSTR *arg = NULL; 00055 INT args = 0; 00056 INT nSlash = 0; 00057 INT nEvalArgs = 0; /* nunber of evaluated arguments */ 00058 DWORD dwFlags = 0; 00059 DWORD dwFiles = 0; /* number of renamedd files */ 00060 INT i; 00061 00062 00063 LPTSTR srcPattern = NULL; /* Source Argument*/ 00064 TCHAR srcPath[MAX_PATH]; /*Source Path Directories*/ 00065 LPTSTR srcFILE = NULL; /*Contains the files name(s)*/ 00066 TCHAR srcFinal[MAX_PATH]; 00067 00068 00069 LPTSTR dstPattern = NULL; /*Destiny Argument*/ 00070 TCHAR dstPath[MAX_PATH]; /*Source Path Directories*/ 00071 LPTSTR dstFILE = NULL; /*Contains the files name(s)*/ 00072 00073 TCHAR dstLast[MAX_PATH]; /*It saves the File name after unmasked with wildcarts*/ 00074 TCHAR dstFinal[MAX_PATH]; /*It saves the Final destiny Path*/ 00075 00076 BOOL bDstWildcard = FALSE; 00077 BOOL bPath = FALSE; 00078 00079 00080 00081 00082 00083 00084 LPTSTR p,q,r; 00085 00086 HANDLE hFile; 00087 WIN32_FIND_DATA f; 00088 /*If the PARAM=/? then show the help*/ 00089 if (!_tcsncmp(param, _T("/?"), 2)) 00090 { 00091 00092 00093 ConOutResPaging(TRUE,STRING_REN_HELP1); 00094 return 0; 00095 } 00096 00097 nErrorLevel = 0; 00098 00099 /* Split the argument list.Args will be saved in arg vector*/ 00100 arg = split(param, &args, FALSE, FALSE); 00101 00102 if (args < 2) 00103 { 00104 if (!(dwFlags & REN_ERROR)) 00105 error_req_param_missing(); 00106 freep(arg); 00107 return 1; 00108 } 00109 00110 /* Read options */ 00111 for (i = 0; i < args; i++) 00112 { 00113 /* Lets check if we have a special option choosen and set the flag(s)*/ 00114 if (*arg[i] == _T('/')) 00115 { 00116 if (_tcslen(arg[i]) >= 2) 00117 { 00118 switch (_totupper(arg[i][1])) 00119 { 00120 case _T('E'): 00121 dwFlags |= REN_ERROR; 00122 break; 00123 00124 case _T('N'): 00125 dwFlags |= REN_NOTHING; 00126 break; 00127 00128 case _T('P'): 00129 dwFlags |= REN_PROMPT; 00130 break; 00131 00132 case _T('Q'): 00133 dwFlags |= REN_QUIET; 00134 break; 00135 00136 case _T('S'): 00137 dwFlags |= REN_SUBDIR; 00138 break; 00139 00140 case _T('T'): 00141 dwFlags |= REN_TOTAL; 00142 break; 00143 } 00144 } 00145 nEvalArgs++;//Save the number of the options. 00146 } 00147 } 00148 00149 /* keep quiet within batch files */ 00150 if (bc != NULL) 00151 dwFlags |= REN_QUIET; 00152 00153 /* there are only options on the command line --> error!!! */ 00154 if (args < nEvalArgs + 2) 00155 { 00156 if (!(dwFlags & REN_ERROR)) 00157 error_req_param_missing(); 00158 freep(arg); 00159 return 1; 00160 } 00161 00162 00163 /* Get destination pattern and source pattern*/ 00164 for (i = 0; i < args; i++) 00165 { 00166 if (*arg[i] == _T('/'))//We have find an Option.Jump it. 00167 continue; 00168 dstPattern = arg[i]; //we save the Last argument as dstPattern 00169 srcPattern = arg[i-1]; 00170 00171 } 00172 00173 00174 00175 00176 00177 if (_tcschr(srcPattern, _T('\\'))) //Checking if the Source (srcPattern) is a Path to the file 00178 { 00179 00180 bPath= TRUE; 00181 00182 //Splitting srcPath and srcFile. 00183 00184 srcFILE = _tcschr(srcPattern, _T('\\')); 00185 nSlash++; 00186 while(_tcschr(srcFILE, _T('\\'))) 00187 { 00188 srcFILE++; 00189 if(*srcFILE==_T('\\')) nSlash++ ; 00190 if(!_tcschr(srcFILE, _T('\\'))) break; 00191 } 00192 _tcsncpy(srcPath,srcPattern,_tcslen(srcPattern)-_tcslen(srcFILE)); 00193 00194 00195 00196 if(_tcschr(dstPattern, _T('\\'))) //Checking if the Destiny (dstPattern)is also a Path.And splitting dstPattern in dstPath and srcPath. 00197 { 00198 dstFILE = _tcschr(dstPattern, _T('\\')); 00199 nSlash=0; 00200 while(_tcschr(dstFILE, _T('\\'))) 00201 { 00202 dstFILE++; 00203 if(*dstFILE==_T('\\')) nSlash++ ; 00204 if(!_tcschr(dstFILE, _T('\\'))) break; 00205 } 00206 _tcsncpy(dstPath,dstPattern,_tcslen(dstPattern)-_tcslen(dstFILE)); 00207 00208 if((_tcslen(dstPath)!=_tcslen(srcPath))||(_tcsncmp(srcPath,dstPath,_tcslen(srcPath))!=0)) //If it has a Path,then MUST be equal than srcPath 00209 { 00210 error_syntax(dstPath); 00211 freep(arg); 00212 return 1; 00213 } 00214 }else { //If Destiny hasnt a Path,then (MSDN says) srcPath is its Path. 00215 00216 _tcscpy(dstPath,srcPath); 00217 00218 dstFILE=dstPattern; 00219 00220 } 00221 00222 00223 00224 } 00225 00226 if (!_tcschr(srcPattern, _T('\\'))) //If srcPattern isnt a Path but a name: 00227 { 00228 srcFILE=srcPattern; 00229 if(_tcschr(dstPattern, _T('\\'))) 00230 { 00231 error_syntax(dstPattern); 00232 00233 freep(arg); 00234 return 1; 00235 }else dstFILE=dstPattern; 00236 } 00237 00238 //Checking Wildcards. 00239 if (_tcschr(dstFILE, _T('*')) || _tcschr(dstFILE, _T('?'))) 00240 bDstWildcard = TRUE; 00241 00242 00243 00244 TRACE("\n\nSourcePattern: %s SourcePath: %s SourceFile: %s", debugstr_aw(srcPattern),debugstr_aw(srcPath),debugstr_aw(srcFILE)); 00245 TRACE("\n\nDestinationPattern: %s Destination Path:%s Destination File: %s\n", debugstr_aw(dstPattern),debugstr_aw(dstPath),debugstr_aw(dstFILE)); 00246 00247 hFile = FindFirstFile(srcPattern, &f); 00248 00249 if (hFile == INVALID_HANDLE_VALUE) 00250 { 00251 if (!(dwFlags & REN_ERROR)) 00252 error_file_not_found(); 00253 00254 } 00255 do 00256 { 00257 /* ignore "." and ".." */ 00258 if (!_tcscmp (f.cFileName, _T(".")) || 00259 !_tcscmp (f.cFileName, _T(".."))) 00260 continue; 00261 00262 /* do not rename hidden or system files */ 00263 if (f.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) 00264 continue; 00265 00266 /* do not rename directories when the destination pattern contains 00267 * wildcards, unless option /S is used */ 00268 if ((f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 00269 && bDstWildcard 00270 && !(dwFlags & REN_SUBDIR)) 00271 continue; 00272 00273 TRACE("Found source name: %s\n", debugstr_aw(f.cFileName)); 00274 /* So here we have splitted the dstFILE and we have find a f.cFileName(thanks to srcPattern) 00275 * Now we have to use the mask (dstFILE) (which can have Wildcards) with f.cFileName to find destination file name(dstLast) */ 00276 p = f.cFileName; 00277 q = dstFILE; 00278 r = dstLast; 00279 while(*q != 0) 00280 { 00281 if (*q == '*') 00282 { 00283 q++; 00284 while (*p != 0 && *p != *q) 00285 { 00286 *r = *p; 00287 p++; 00288 r++; 00289 } 00290 } 00291 else if (*q == '?') 00292 { 00293 q++; 00294 if (*p != 0) 00295 { 00296 *r = *p; 00297 p++; 00298 r++; 00299 } 00300 } 00301 else 00302 { 00303 *r = *q; 00304 if (*p != 0) 00305 p++; 00306 q++; 00307 r++; 00308 } 00309 } 00310 *r = 0; 00311 //Well we have splitted the Paths,so now we have to paste them again(if needed),thanks bPath. 00312 if( bPath == TRUE) 00313 { 00314 00315 _tcscpy(srcFinal,srcPath); 00316 00317 _tcscat(srcFinal,f.cFileName); 00318 00319 _tcscpy(dstFinal,dstPath); 00320 _tcscat(dstFinal,dstLast); 00321 00322 00323 }else{ 00324 _tcscpy(srcFinal,f.cFileName); 00325 _tcscpy(dstFinal,dstLast); 00326 00327 } 00328 00329 00330 00331 TRACE("DestinationPath: %s\n", debugstr_aw(dstFinal)); 00332 00333 00334 if (!(dwFlags & REN_QUIET) && !(dwFlags & REN_TOTAL)) 00335 00336 ConOutPrintf(_T("%s -> %s\n"),srcFinal , dstFinal); 00337 00338 /* Rename the file */ 00339 if (!(dwFlags & REN_NOTHING)) 00340 { 00341 00342 00343 00344 if (MoveFile(srcFinal, dstFinal)) 00345 { 00346 dwFiles++; 00347 } 00348 else 00349 { 00350 if (!(dwFlags & REN_ERROR)) 00351 { 00352 ConErrResPrintf(STRING_REN_ERROR1, GetLastError()); 00353 } 00354 } 00355 } 00356 } 00357 00358 while (FindNextFile(hFile, &f)); 00359 //Closing and Printing errors. 00360 00361 FindClose(hFile); 00362 00363 00364 if (!(dwFlags & REN_QUIET)) 00365 { 00366 if (dwFiles == 1) 00367 ConOutResPrintf(STRING_REN_HELP2, dwFiles); 00368 else 00369 ConOutResPrintf(STRING_REN_HELP3, dwFiles); 00370 } 00371 00372 freep(arg); 00373 00374 return 0; 00375 } 00376 00377 #endif 00378 00379 /* EOF */ Generated on Sun May 27 2012 04:18:15 for ReactOS by
1.7.6.1
|