part1 of move bug from a volume to another have been solve, the part two are in React...
[reactos.git] / reactos / subsys / system / cmd / move.c
1 /*
2 * MOVE.C - move internal command.
3 *
4 *
5 * History:
6 *
7 * 14-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
8 * Started.
9 *
10 * 18-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
11 * Unicode safe!
12 * Preliminary version!!!
13 *
14 * 20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
15 * Redirection safe!
16 *
17 * 27-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
18 * Added help text ("/?").
19 * Added more error checks.
20 *
21 * 03-Feb-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
22 * Added "/N" option.
23 *
24 * 30-Apr-2005 (Magnus Olsen) <magnus@greatlord.com>)
25 * Remove all hardcode string to En.rc
26 *
27 * 24-Jun-2005 (Brandon Turner) <turnerb7@msu.edu>)
28 * Fixed bug to allow MS style wildcards + code clean up
29 * added /y and /-y
30 */
31
32 #include <precomp.h>
33 #include "resource.h"
34
35 #ifdef INCLUDE_CMD_MOVE
36
37
38 enum
39 {
40 MOVE_NOTHING = 0x001, /* /N */
41 MOVE_OVER_YES = 0x002, /* /Y */
42 MOVE_OVER_NO = 0x004, /* /-Y */
43 };
44
45 static INT Overwrite (LPTSTR fn)
46 {
47 /*ask the user if they want to override*/
48 TCHAR szMsg[RC_STRING_MAX_SIZE];
49 INT res;
50 LoadString(CMD_ModuleHandle, STRING_MOVE_HELP1, szMsg, RC_STRING_MAX_SIZE);
51 ConOutPrintf(szMsg,fn);
52 res = FilePromptYNA ("");
53 return res;
54 }
55
56
57
58 INT cmd_move (LPTSTR cmd, LPTSTR param)
59 {
60 TCHAR szMsg[RC_STRING_MAX_SIZE];
61 LPTSTR *arg;
62 INT argc, i, nFiles;
63 TCHAR szDestPath[MAX_PATH];
64 TCHAR szSrcPath[MAX_PATH];
65 DWORD dwFlags = 0;
66 INT nOverwrite = 0;
67 WIN32_FIND_DATA findBuffer;
68 HANDLE hFile;
69 LPTSTR pszFile;
70
71
72 if (!_tcsncmp (param, _T("/?"), 2))
73 {
74 #if 0
75 ConOutPuts (_T("Moves files and renames files and directories.\n\n"
76 "To move one or more files:\n"
77 "MOVE [/N][/Y|/-Y][drive:][path]filename1[,...] destination\n"
78 "\n"
79 "To rename a directory:\n"
80 "MOVE [/N][/Y|/-Y][drive:][path]dirname1 dirname2\n"
81 "\n"
82 " [drive:][path]filename1 Specifies the location and name of the file\n"
83 " or files you want to move.\n"
84 " /N Nothing. Don everthing but move files or direcories.\n"
85 " /Y\n"
86 " /-Y\n"
87 "..."));
88 #else
89 ConOutResPaging(TRUE,STRING_MOVE_HELP2);
90 #endif
91 return 0;
92 }
93
94 arg = split (param, &argc, FALSE);
95 nFiles = argc;
96
97 /* read options */
98 for (i = 0; i < argc; i++)
99 {
100 if (*arg[i] == _T('/'))
101 {
102 if (_tcslen(arg[i]) >= 2)
103 {
104 switch (_totupper(arg[i][1]))
105 {
106 case _T('N'):
107 dwFlags |= MOVE_NOTHING;
108 break;
109
110 case _T('Y'):
111 dwFlags |= MOVE_OVER_YES;
112 break;
113
114 case _T('-'):
115 dwFlags |= MOVE_OVER_NO;
116 break;
117 }
118 }
119 nFiles--;
120 }
121 }
122
123 if (nFiles < 2)
124 {
125 /* there must be at least two pathspecs */
126 error_req_param_missing ();
127 return 1;
128 }
129
130 if (_tcschr (arg[argc - 1], _T('*')) != NULL)
131 {
132 /*'*' in dest, this doesnt happen. give folder name instead*/
133 error_parameter_format('2');
134 return 1;
135 }
136
137 /* get destination */
138 GetFullPathName (arg[argc - 1], MAX_PATH, szDestPath, NULL);
139 #ifdef _DEBUG
140 DebugPrintf (_T("Destination: %s\n"), szDestPath);
141 #endif
142
143 /* move it */
144 for (i = 0; i < argc - 1; i++)
145 {
146 if (*arg[i] == _T('/'))
147 continue;
148
149 hFile = FindFirstFile (arg[i], &findBuffer);
150 if (hFile == INVALID_HANDLE_VALUE)
151 {
152 ErrorMessage (GetLastError (), arg[i]);
153 freep (arg);
154 return 1;
155 }
156
157 do
158 {
159
160 nOverwrite = 1;
161 GetFullPathName (findBuffer.cFileName, MAX_PATH, szSrcPath, &pszFile);
162
163 if (GetFileAttributes (szSrcPath) & FILE_ATTRIBUTE_DIRECTORY)
164 {
165 /* source is directory */
166
167 #ifdef _DEBUG
168 DebugPrintf (_T("Move directory \'%s\' to \'%s\'\n"),
169 szSrcPath, szDestPath);
170 #endif
171 if (!(dwFlags & MOVE_NOTHING))
172 continue;
173 MoveFileEx (szSrcPath, szDestPath, MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH | MOVEFILE_COPY_ALLOWED);
174 }
175 else
176 {
177 /* source is file */
178 if (GetFileAttributes (szDestPath) & FILE_ATTRIBUTE_DIRECTORY)
179 {
180 /* destination is existing directory */
181
182 /*build the dest string(accounts for *)*/
183 TCHAR szFullDestPath[MAX_PATH];
184 _tcscpy (szFullDestPath, szDestPath);
185 /*check to see if there is an ending slash, if not add one*/
186 if(szFullDestPath[_tcslen(szFullDestPath) - 1] != _T('\\'))
187 _tcscat (szFullDestPath, _T("\\"));
188
189 _tcscat (szFullDestPath, findBuffer.cFileName);
190
191 /*checks to make sure user wanted/wants the override*/
192 if((dwFlags & MOVE_OVER_NO) && IsExistingFile (szFullDestPath))
193 continue;
194 if(!(dwFlags & MOVE_OVER_YES) && IsExistingFile (szFullDestPath))
195 nOverwrite = Overwrite (szFullDestPath);
196 if (nOverwrite == PROMPT_NO || nOverwrite == PROMPT_BREAK)
197 continue;
198 if (nOverwrite == PROMPT_ALL)
199 dwFlags |= MOVE_OVER_YES;
200
201 /*delete the file that might be there first*/
202 DeleteFile(szFullDestPath);
203 ConOutPrintf (_T("%s => %s"), szSrcPath, szFullDestPath);
204
205 if ((dwFlags & MOVE_NOTHING))
206 continue;
207
208 /*delete the file that might be there first*/
209 DeleteFile(szFullDestPath);
210 /*move the file*/
211 if (MoveFileEx (szSrcPath, szFullDestPath, MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH | MOVEFILE_COPY_ALLOWED))
212 LoadString(CMD_ModuleHandle, STRING_MOVE_ERROR1, szMsg, RC_STRING_MAX_SIZE);
213 else
214 LoadString(CMD_ModuleHandle, STRING_MOVE_ERROR2, szMsg, RC_STRING_MAX_SIZE);
215
216 ConOutPrintf(szMsg);
217 }
218 else
219 {
220 /* destination is a file */
221
222 if (_tcschr (arg[argc - 2], _T('*')) != NULL)
223 {
224 /*'*' in src but there should't be one in the dest*/
225 error_parameter_format('1');
226 return 1;
227 }
228
229 /*bunch of checks to see if we the user wanted/wants
230 to really override the files*/
231 if((dwFlags & MOVE_OVER_NO) && IsExistingFile (szDestPath))
232 continue;
233 if(!(dwFlags & MOVE_OVER_YES) && IsExistingFile (szDestPath))
234 nOverwrite = Overwrite (szDestPath);
235 if (nOverwrite == PROMPT_NO || nOverwrite == PROMPT_BREAK)
236 continue;
237 if (nOverwrite == PROMPT_ALL)
238 dwFlags |= MOVE_OVER_YES;
239
240 ConOutPrintf (_T("%s => %s"), szSrcPath, szDestPath);
241
242 if ((dwFlags & MOVE_NOTHING))
243 continue;
244
245 /*delete the file first just to get ride of it
246 if it was already there*/
247 DeleteFile(szDestPath);
248 /*do the moving*/
249 if (MoveFileEx (szSrcPath, szDestPath, MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH | MOVEFILE_COPY_ALLOWED))
250 LoadString(CMD_ModuleHandle, STRING_MOVE_ERROR1, szMsg, RC_STRING_MAX_SIZE);
251 else
252 LoadString(CMD_ModuleHandle, STRING_MOVE_ERROR2, szMsg, RC_STRING_MAX_SIZE);
253
254 ConOutPrintf(szMsg);
255
256 }
257 }
258 }
259 while (FindNextFile (hFile, &findBuffer));
260 FindClose (hFile);
261 }
262
263 freep (arg);
264 return 0;
265 }
266
267 #endif /* INCLUDE_CMD_MOVE */