ReactOS  0.4.13-dev-563-g0561610
ren.c
Go to the documentation of this file.
1 /*
2  * REN.C - rename internal command.
3  *
4  *
5  * History:
6  *
7  *
8  * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
9  * added config.h include
10  *
11  * 18-Dec-1998 (Eric Kohl)
12  * Added support for quoted long file names with spaces.
13  *
14  * 20-Jan-1999 (Eric Kohl)
15  * Unicode and redirection safe!
16  *
17  * 17-Oct-2001 (Eric Kohl)
18  * Implemented basic rename code.
19  *
20  * 30-Apr-2005 (Magnus Olsen <magnus@greatlord.com>)
21  * Remove all hardcoded strings in En.rc
22  *
23  * 25-Nov-2008 (Victor Martinez <vicmarcal@hotmail.com>)
24  * Patch dedicated to Myrjala because her comprehension and love :D
25  * Fixing following Bugs:
26  * -Wrong behavior with wildcards when Source and Destiny are Paths(FIXED).
27  * -Wrong general behavior (MSDN:"Rename cant move files between subdirectories")(FIXED)
28  * -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)
29  * (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.)
30  * -Implemented checkings if SourcePath and DestinyPath are differents.
31  *
32  */
33 
34 #include "precomp.h"
35 
36 #ifdef INCLUDE_CMD_RENAME
37 
38 enum
39 {
40  REN_ATTRIBUTES = 0x001, /* /A : not implemented */
41  REN_ERROR = 0x002, /* /E */
42  REN_NOTHING = 0x004, /* /N */
43  REN_PROMPT = 0x008, /* /P : not implemented */
44  REN_QUIET = 0x010, /* /Q */
45  REN_SUBDIR = 0x020, /* /S */
46  REN_TOTAL = 0x040, /* /T */
47 };
48 
49 
50 /*
51  * file rename internal command.
52  */
54 {
55  LPTSTR *arg = NULL;
56  INT args = 0;
57  INT nSlash = 0;
58  INT nEvalArgs = 0; /* number of evaluated arguments */
59  DWORD dwFlags = 0;
60  DWORD dwFiles = 0; /* number of renamed files */
61  INT i;
62 
63  LPTSTR srcPattern = NULL; /* Source Argument*/
64  TCHAR srcPath[MAX_PATH]; /*Source Path Directories*/
65  LPTSTR srcFILE = NULL; /*Contains the files name(s)*/
66  TCHAR srcFinal[MAX_PATH];
67 
68  LPTSTR dstPattern = NULL; /*Destiny Argument*/
69  TCHAR dstPath[MAX_PATH]; /*Source Path Directories*/
70  LPTSTR dstFILE = NULL; /*Contains the files name(s)*/
71 
72  TCHAR dstLast[MAX_PATH]; /*It saves the File name after unmasked with wildcards*/
73  TCHAR dstFinal[MAX_PATH]; /*It saves the Final destiny Path*/
74 
75  BOOL bDstWildcard = FALSE;
76  BOOL bPath = FALSE;
77 
78  LPTSTR p,q,r;
79 
80  HANDLE hFile;
82  /*If the PARAM=/? then show the help*/
83  if (!_tcsncmp(param, _T("/?"), 2))
84  {
86  return 0;
87  }
88 
89  nErrorLevel = 0;
90 
91  /* Split the argument list.Args will be saved in arg vector*/
92  arg = split(param, &args, FALSE, FALSE);
93 
94  if (args < 2)
95  {
96  if (!(dwFlags & REN_ERROR))
98  freep(arg);
99  return 1;
100  }
101 
102  /* Read options */
103  for (i = 0; i < args; i++)
104  {
105  /* Lets check if we have a special option chosen and set the flag(s)*/
106  if (*arg[i] == _T('/'))
107  {
108  if (_tcslen(arg[i]) >= 2)
109  {
110  switch (_totupper(arg[i][1]))
111  {
112  case _T('E'):
113  dwFlags |= REN_ERROR;
114  break;
115 
116  case _T('N'):
117  dwFlags |= REN_NOTHING;
118  break;
119 
120  case _T('P'):
121  dwFlags |= REN_PROMPT;
122  break;
123 
124  case _T('Q'):
125  dwFlags |= REN_QUIET;
126  break;
127 
128  case _T('S'):
129  dwFlags |= REN_SUBDIR;
130  break;
131 
132  case _T('T'):
133  dwFlags |= REN_TOTAL;
134  break;
135  }
136  }
137  nEvalArgs++;//Save the number of the options.
138  }
139  }
140 
141  /* keep quiet within batch files */
142  if (bc != NULL)
143  dwFlags |= REN_QUIET;
144 
145  /* there are only options on the command line --> error!!! */
146  if (args < nEvalArgs + 2)
147  {
148  if (!(dwFlags & REN_ERROR))
150  freep(arg);
151  return 1;
152  }
153 
154  /* Get destination pattern and source pattern*/
155  for (i = 0; i < args; i++)
156  {
157  if (*arg[i] == _T('/'))//We have find an Option.Jump it.
158  continue;
159  dstPattern = arg[i]; //we save the Last argument as dstPattern
160  srcPattern = arg[i-1];
161  }
162 
163  if (_tcschr(srcPattern, _T('\\'))) //Checking if the Source (srcPattern) is a Path to the file
164  {
165  bPath= TRUE;
166 
167  //Splitting srcPath and srcFile.
168 
169  srcFILE = _tcschr(srcPattern, _T('\\'));
170  nSlash++;
171  while(_tcschr(srcFILE, _T('\\')))
172  {
173  srcFILE++;
174  if (*srcFILE==_T('\\')) nSlash++ ;
175  if (!_tcschr(srcFILE, _T('\\'))) break;
176  }
177  _tcsncpy(srcPath,srcPattern,_tcslen(srcPattern)-_tcslen(srcFILE));
178 
179  if (_tcschr(dstPattern, _T('\\'))) //Checking if the Destiny (dstPattern)is also a Path.And splitting dstPattern in dstPath and srcPath.
180  {
181  dstFILE = _tcschr(dstPattern, _T('\\'));
182  nSlash=0;
183  while(_tcschr(dstFILE, _T('\\')))
184  {
185  dstFILE++;
186  if (*dstFILE==_T('\\')) nSlash++ ;
187  if (!_tcschr(dstFILE, _T('\\'))) break;
188  }
189  _tcsncpy(dstPath,dstPattern,_tcslen(dstPattern)-_tcslen(dstFILE));
190 
191  if ((_tcslen(dstPath)!=_tcslen(srcPath))||(_tcsncmp(srcPath,dstPath,_tcslen(srcPath))!=0)) //If it has a Path,then MUST be equal than srcPath
192  {
193  error_syntax(dstPath);
194  freep(arg);
195  return 1;
196  }
197  }
198  else
199  { //If Destiny hasnt a Path,then (MSDN says) srcPath is its Path.
200  _tcscpy(dstPath,srcPath);
201  dstFILE=dstPattern;
202  }
203  }
204 
205  if (!_tcschr(srcPattern, _T('\\'))) //If srcPattern isn't a Path but a name:
206  {
207  srcFILE=srcPattern;
208  if (_tcschr(dstPattern, _T('\\')))
209  {
210  error_syntax(dstPattern);
211  freep(arg);
212  return 1;
213  }
214  else
215  {
216  dstFILE=dstPattern;
217  }
218  }
219 
220  //Checking Wildcards.
221  if (_tcschr(dstFILE, _T('*')) || _tcschr(dstFILE, _T('?')))
222  bDstWildcard = TRUE;
223 
224  TRACE("\n\nSourcePattern: %s SourcePath: %s SourceFile: %s", debugstr_aw(srcPattern),debugstr_aw(srcPath),debugstr_aw(srcFILE));
225  TRACE("\n\nDestinationPattern: %s Destination Path:%s Destination File: %s\n", debugstr_aw(dstPattern),debugstr_aw(dstPath),debugstr_aw(dstFILE));
226 
227  hFile = FindFirstFile(srcPattern, &f);
228 
230  {
232  }
233  do
234  {
235  /* ignore "." and ".." */
236  if (!_tcscmp (f.cFileName, _T(".")) || !_tcscmp (f.cFileName, _T("..")))
237  continue;
238 
239  /* do not rename hidden or system files */
240  if (f.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM))
241  continue;
242 
243  /* do not rename directories when the destination pattern contains
244  * wildcards, unless option /S is used */
245  if ((f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
246  bDstWildcard && !(dwFlags & REN_SUBDIR))
247  {
248  continue;
249  }
250 
251  TRACE("Found source name: %s\n", debugstr_aw(f.cFileName));
252  /* So here we have splitted the dstFILE and we have find a f.cFileName(thanks to srcPattern)
253  * Now we have to use the mask (dstFILE) (which can have Wildcards) with f.cFileName to find destination file name(dstLast) */
254  p = f.cFileName;
255  q = dstFILE;
256  r = dstLast;
257  while(*q != 0)
258  {
259  if (*q == '*')
260  {
261  q++;
262  while (*p != 0 && *p != *q)
263  {
264  *r = *p;
265  p++;
266  r++;
267  }
268  }
269  else if (*q == '?')
270  {
271  q++;
272  if (*p != 0)
273  {
274  *r = *p;
275  p++;
276  r++;
277  }
278  }
279  else
280  {
281  *r = *q;
282  if (*p != 0) p++;
283  q++;
284  r++;
285  }
286  }
287  *r = 0;
288  //Well we have splitted the Paths,so now we have to paste them again(if needed),thanks bPath.
289  if (bPath != FALSE)
290  {
291  _tcscpy(srcFinal,srcPath);
292  _tcscat(srcFinal,f.cFileName);
293  _tcscpy(dstFinal,dstPath);
294  _tcscat(dstFinal,dstLast);
295  }
296  else
297  {
298  _tcscpy(srcFinal,f.cFileName);
299  _tcscpy(dstFinal,dstLast);
300  }
301 
302  TRACE("DestinationPath: %s\n", debugstr_aw(dstFinal));
303 
304  if (!(dwFlags & REN_QUIET) && !(dwFlags & REN_TOTAL))
305  ConOutPrintf(_T("%s -> %s\n"),srcFinal , dstFinal);
306 
307  /* Rename the file */
308  if (!(dwFlags & REN_NOTHING))
309  {
310  if (MoveFile(srcFinal, dstFinal))
311  {
312  dwFiles++;
313  }
314  else
315  {
316  if (!(dwFlags & REN_ERROR))
318  }
319  }
320  }
321  while (FindNextFile(hFile, &f));
322 
323  //Closing and Printing errors.
324  FindClose(hFile);
325 
326  if (!(dwFlags & REN_QUIET))
327  {
328  if (dwFiles == 1)
330  else
332  }
333 
334  freep(arg);
335  return 0;
336 }
337 
338 #endif
339 
340 /* EOF */
INT nErrorLevel
Definition: cmd.c:157
#define STRING_REN_HELP1
Definition: resource.h:168
#define STRING_REN_HELP3
Definition: resource.h:170
#define TRUE
Definition: types.h:120
Definition: ren.c:45
#define STRING_REN_HELP2
Definition: resource.h:169
LPBATCH_CONTEXT bc
Definition: batch.c:66
int _tcscmp(const _TCHAR *s1, const _TCHAR *s2)
Definition: tcscmp.h:8
#define FILE_ATTRIBUTE_SYSTEM
Definition: nt_native.h:704
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
_TCHAR * _tcsncpy(_TCHAR *dst, const _TCHAR *src, size_t n)
Definition: tcsncpy.h:9
#define debugstr_aw
Definition: precomp.h:43
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
_TCHAR * _tcscpy(_TCHAR *to, const _TCHAR *from)
Definition: tcscpy.h:8
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define ConOutPrintf(szStr,...)
Definition: console.h:42
VOID ConOutResPaging(BOOL StartPaging, UINT resID)
Definition: console.c:182
#define STRING_REN_ERROR1
Definition: resource.h:56
#define _totupper
Definition: tchar.h:1509
INT cmd_rename(LPTSTR param)
Definition: ren.c:53
Definition: match.c:390
int32_t INT
Definition: typedefs.h:56
CHAR * LPTSTR
Definition: xmlstorage.h:192
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
unsigned int BOOL
Definition: ntddk_ex.h:94
#define ConErrResPrintf(uID,...)
Definition: console.h:51
VOID error_req_param_missing(VOID)
Definition: error.c:108
GLuint srcPath
Definition: glext.h:11718
size_t __cdecl _tcslen(const _TCHAR *str)
Definition: tcslen.h:9
static VOID freep(LPSTR *p)
Definition: cmdcons.c:98
smooth NULL
Definition: ftsmooth.c:416
#define FindFirstFile
Definition: winbase.h:3596
_TCHAR * _tcschr(const _TCHAR *s, _XINT c)
Definition: tcschr.h:4
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
char TCHAR
Definition: xmlstorage.h:189
GLfloat f
Definition: glext.h:7540
#define _T(x)
Definition: vfdio.h:22
#define TRACE(s)
Definition: solgame.cpp:4
Definition: ren.c:46
#define FindNextFile
Definition: winbase.h:3602
GLfloat param
Definition: glext.h:5796
#define MAX_PATH
Definition: compat.h:26
static LPSTR * split(LPSTR s, LPINT args)
Definition: cmdcons.c:163
#define ConOutResPrintf(uID,...)
Definition: console.h:48
unsigned long DWORD
Definition: ntddk_ex.h:95
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
VOID error_file_not_found(VOID)
Definition: error.c:91
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
_In_ HANDLE hFile
Definition: mswsock.h:90
Definition: ren.c:41
Definition: ren.c:44
VOID error_syntax(LPTSTR)
Definition: error.c:150
#define MoveFile
Definition: winbase.h:3691
Definition: ren.c:43
#define f
Definition: ke_i.h:83
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
_TCHAR * _tcscat(_TCHAR *s, const _TCHAR *append)
Definition: tcscat.h:8
GLfloat GLfloat p
Definition: glext.h:8902
#define args
Definition: format.c:66
int _tcsncmp(const _TCHAR *s1, const _TCHAR *s2, size_t n)
Definition: tcsncmp.h:9
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502