Merge 14551:14980 from trunk
[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
28 #include "precomp.h"
29 #include "resource.h"
30
31 #ifdef INCLUDE_CMD_MOVE
32
33
34 #define OVERWRITE_NO 0
35 #define OVERWRITE_YES 1
36 #define OVERWRITE_ALL 2
37 #define OVERWRITE_CANCEL 3
38
39
40 static INT Overwrite (LPTSTR fn)
41 {
42 TCHAR szMsg[RC_STRING_MAX_SIZE];
43 TCHAR inp[10];
44 LPTSTR p;
45
46 LoadString(GetModuleHandle(NULL), STRING_MOVE_HELP1, szMsg, RC_STRING_MAX_SIZE);
47 ConOutPrintf(szMsg, fn);
48 ConInString(inp, 10);
49
50 _tcsupr (inp);
51 for (p = inp; _istspace(*p); p++)
52 ;
53
54 if (*p != szMsg[0] && *p != szMsg[2])
55 return OVERWRITE_NO;
56 if (*p == szMsg[2])
57 return OVERWRITE_ALL;
58
59 return OVERWRITE_YES;
60 }
61
62
63
64 INT cmd_move (LPTSTR cmd, LPTSTR param)
65 {
66 TCHAR szMsg[RC_STRING_MAX_SIZE];
67 LPTSTR *arg;
68 INT argc, i, nFiles;
69 TCHAR szDestPath[MAX_PATH];
70 TCHAR szSrcPath[MAX_PATH];
71 BOOL bPrompt = TRUE;
72 LPTSTR p;
73 WIN32_FIND_DATA findBuffer;
74 HANDLE hFile;
75 LPTSTR pszFile;
76 BOOL bNothing = FALSE;
77
78 if (!_tcsncmp (param, _T("/?"), 2))
79 {
80 #if 0
81 ConOutPuts (_T("Moves files and renames files and directories.\n\n"
82 "To move one or more files:\n"
83 "MOVE [/N][/Y|/-Y][drive:][path]filename1[,...] destination\n"
84 "\n"
85 "To rename a directory:\n"
86 "MOVE [/N][/Y|/-Y][drive:][path]dirname1 dirname2\n"
87 "\n"
88 " [drive:][path]filename1 Specifies the location and name of the file\n"
89 " or files you want to move.\n"
90 " /N Nothing. Don everthing but move files or direcories.\n"
91 " /Y\n"
92 " /-Y\n"
93 "..."));
94 #else
95 LoadString(GetModuleHandle(NULL), STRING_MOVE_HELP2, szMsg, RC_STRING_MAX_SIZE);
96 ConOutPuts(szMsg);
97 #endif
98 return 0;
99 }
100
101 arg = split (param, &argc, FALSE);
102 nFiles = argc;
103
104 /* read options */
105 for (i = 0; i < argc; i++)
106 {
107 p = arg[i];
108
109 if (*p == _T('/'))
110 {
111 p++;
112 if (*p == _T('-'))
113 {
114 p++;
115 if (_totupper (*p) == _T('Y'))
116 bPrompt = TRUE;
117 }
118 else
119 {
120 if (_totupper (*p) == _T('Y'))
121 bPrompt = FALSE;
122 else if (_totupper (*p) == _T('N'))
123 bNothing = TRUE;
124 }
125 nFiles--;
126 }
127 }
128
129 if (nFiles < 2)
130 {
131 /* there must be at least two pathspecs */
132 error_req_param_missing ();
133 return 1;
134 }
135
136 /* get destination */
137 GetFullPathName (arg[argc - 1], MAX_PATH, szDestPath, NULL);
138 #ifdef _DEBUG
139 DebugPrintf (_T("Destination: %s\n"), szDestPath);
140 #endif
141
142 /* move it*/
143 for (i = 0; i < argc - 1; i++)
144 {
145 if (*arg[i] == _T('/'))
146 continue;
147
148 hFile = FindFirstFile (arg[i], &findBuffer);
149 if (hFile == INVALID_HANDLE_VALUE)
150 {
151 ErrorMessage (GetLastError (), arg[i]);
152 freep (arg);
153 return 1;
154 }
155
156 do
157 {
158 GetFullPathName (findBuffer.cFileName, MAX_PATH, szSrcPath, &pszFile);
159
160 if (GetFileAttributes (szSrcPath) & FILE_ATTRIBUTE_DIRECTORY)
161 {
162 /* source is directory */
163
164 #ifdef _DEBUG
165 DebugPrintf (_T("Move directory \'%s\' to \'%s\'\n"),
166 szSrcPath, szDestPath);
167 #endif
168 if (!bNothing)
169 {
170 MoveFile (szSrcPath, szDestPath);
171 }
172 }
173 else
174 {
175 /* source is file */
176
177 if (IsExistingFile (szDestPath))
178 {
179 /* destination exists */
180 if (GetFileAttributes (szDestPath) & FILE_ATTRIBUTE_DIRECTORY)
181 {
182 /* destination is existing directory */
183
184 TCHAR szFullDestPath[MAX_PATH];
185
186 _tcscpy (szFullDestPath, szDestPath);
187 _tcscat (szFullDestPath, _T("\\"));
188 _tcscat (szFullDestPath, pszFile);
189
190 ConOutPrintf (_T("%s => %s"), szSrcPath, szFullDestPath);
191
192 if (!bNothing)
193 {
194 if (MoveFile (szSrcPath, szFullDestPath))
195 LoadString(GetModuleHandle(NULL), STRING_MOVE_ERROR1, szMsg, RC_STRING_MAX_SIZE);
196 else
197 LoadString(GetModuleHandle(NULL), STRING_MOVE_ERROR2, szMsg, RC_STRING_MAX_SIZE);
198 ConOutPrintf(szMsg);
199 }
200 }
201 else
202 {
203 /* destination is existing file */
204 INT nOverwrite;
205
206 /* must get the overwrite code */
207 if ((nOverwrite = Overwrite (szDestPath)))
208 {
209 #if 0
210 if (nOverwrite == OVERWRITE_ALL)
211 *lpFlags |= FLAG_OVERWRITE_ALL;
212 #endif
213 ConOutPrintf (_T("%s => %s"), szSrcPath, szDestPath);
214
215 if (!bNothing)
216 {
217 if (MoveFile (szSrcPath, szDestPath))
218 LoadString(GetModuleHandle(NULL), STRING_MOVE_ERROR1, szMsg, RC_STRING_MAX_SIZE);
219 else
220 LoadString(GetModuleHandle(NULL), STRING_MOVE_ERROR2, szMsg, RC_STRING_MAX_SIZE);
221 ConOutPrintf(szMsg);
222 }
223 }
224 }
225 }
226 else
227 {
228 /* destination does not exist */
229 TCHAR szFullDestPath[MAX_PATH];
230
231 GetFullPathName (szDestPath, MAX_PATH, szFullDestPath, NULL);
232
233 ConOutPrintf (_T("%s => %s"), szSrcPath, szFullDestPath);
234
235 if (!bNothing)
236 {
237 if (MoveFile (szSrcPath, szFullDestPath))
238 LoadString(GetModuleHandle(NULL), STRING_MOVE_ERROR1, szMsg, RC_STRING_MAX_SIZE);
239 else
240 LoadString(GetModuleHandle(NULL), STRING_MOVE_ERROR2, szMsg, RC_STRING_MAX_SIZE);
241 ConOutPrintf(szMsg);
242 }
243 }
244 }
245 }
246 while (FindNextFile (hFile, &findBuffer));
247
248 FindClose (hFile);
249 }
250
251 freep (arg);
252
253 return 0;
254 }
255
256 #endif /* INCLUDE_CMD_MOVE */