Backport and version tag
[AROS.git] / workbench / c / Rename.c
blobfc71e1e93c0ce6e6327680939aaf4a4b0c1d7621
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
5 Rename CLI command.
6 */
8 /*****************************************************************************
10 NAME
12 Rename
14 SYNOPSIS
16 Rename [{FROM}] <name> [TO|AS] <name> [QUIET]
18 FROM/A/M,TO=AS/A,QUIET/S
20 LOCATION
24 FUNCTION
26 Renames a directory or file. Rename can also act like the UNIX mv
27 command, which moves a file or files to another location on disk.
29 INPUTS
31 FROM -- The name(s) of the file(s) to rename or move. There may
32 be many files specified, this is used when moving files
33 into a new directory.
35 TO|AS -- The name which we wish to call the file.
37 QUIET -- Suppress any output from the command.
39 RESULT
41 Standard DOS error codes.
43 NOTES
45 EXAMPLE
47 Rename letter1.doc letter2.doc letters
49 Moves letter1.doc and letter2.doc to the directory letters.
51 Rename ram:a ram:b quiet
52 Rename from ram:a to ram:b quiet
53 Rename from=ram:a to=ram:b quiet
55 All versions, renames file "a" to "b" and does not output any
56 diagnostic information.
58 BUGS
60 SEE ALSO
62 INTERNALS
64 Rename() can only move a file to another directory, if and only if
65 the to path has the from filename appended to the end.
67 e.g.
68 Rename("ram:a", "ram:clipboards/a");
69 not
70 Rename("ram:a", "ram:clipboards/");
72 ******************************************************************************/
74 #define DEBUG 0
75 #include <aros/debug.h>
77 #include <proto/dos.h>
78 #include <proto/exec.h>
80 #include <dos/dos.h>
81 #include <dos/dosasl.h>
82 #include <dos/rdargs.h>
83 #include <exec/memory.h>
84 #include <exec/types.h>
86 #include <string.h>
88 #define ARG_TEMPLATE "FROM/A/M,TO=AS/A,QUIET/S"
90 #define APPNAME "Rename"
92 enum
94 ARG_FROM,
95 ARG_TO,
96 ARG_QUIET,
97 NOOFARGS
101 #define MAX_PATH_LEN 2048
103 const TEXT version[] = "$VER: Rename 41.3 (3.4.2014)\n";
106 int doRename(STRPTR *from, STRPTR to, BOOL quiet);
109 int __nocommandline;
111 int main(void)
113 struct RDArgs *rda;
115 IPTR args[NOOFARGS] = { (IPTR) NULL, (IPTR) NULL, FALSE };
117 int retval = RETURN_FAIL;
119 rda = ReadArgs(ARG_TEMPLATE, args, NULL);
121 if(rda != NULL)
123 STRPTR *from = (STRPTR *)args[ARG_FROM];
124 STRPTR to = (STRPTR)args[ARG_TO];
125 BOOL quiet = args[ARG_QUIET] != 0;
127 retval = doRename(from, to, quiet);
129 FreeArgs(rda);
131 else
133 PrintFault(IoErr(), APPNAME);
134 retval = RETURN_ERROR;
137 return retval;
141 int doRename(STRPTR *from, STRPTR to, BOOL quiet)
143 #define ERROR(n) retval = (n); goto cleanup
145 struct AnchorPath *ap;
147 UBYTE *pathName;
148 STRPTR fileStart;
149 BOOL destIsDir = FALSE;
150 LONG match;
151 BPTR tolock = BNULL;
152 ULONG i;
153 int retval;
154 LONG ioerr = 0;
155 UBYTE itsWild;
156 BOOL isSingle;
158 ap = (struct AnchorPath *)AllocVec(sizeof(struct AnchorPath) + MAX_PATH_LEN + MAX_PATH_LEN,
159 MEMF_ANY | MEMF_CLEAR);
160 if (!ap)
162 ioerr = IoErr();
163 ERROR(RETURN_FAIL);
166 pathName = ((UBYTE *) (ap + 1)) + MAX_PATH_LEN;
168 ap->ap_BreakBits = SIGBREAKF_CTRL_C;
169 ap->ap_Flags = APF_DOWILD;
170 ap->ap_Strlen = MAX_PATH_LEN;
171 if (MatchFirst(from[0], ap) != 0)
173 ioerr = IoErr();
174 if (ioerr == ERROR_OBJECT_NOT_FOUND)
176 Printf("Can't rename %s as %s because ", from[0], to);
178 ERROR(RETURN_FAIL);
180 itsWild = ap->ap_Flags & APF_ITSWILD;
181 MatchEnd(ap);
183 /* First we check if the destination is a directory */
184 tolock = Lock(to, SHARED_LOCK);
185 if (tolock)
187 struct FileInfoBlock *fib = AllocDosObject(DOS_FIB, NULL);
188 LONG entrytype;
190 if (!fib)
192 PrintFault(IoErr(), APPNAME);
194 ERROR(RETURN_FAIL);
197 i = Examine(tolock, fib);
198 ioerr = IoErr();
199 entrytype = fib->fib_EntryType;
200 FreeDosObject(DOS_FIB, fib);
202 if (i)
204 ioerr = 0;
205 if (entrytype >= 0)
207 destIsDir = TRUE;
210 else
212 PrintFault(ioerr, APPNAME);
213 ioerr = 0;
215 ERROR(RETURN_FAIL);
220 /* Check if dest is not a dir and src is pattern or multi */
221 if (!destIsDir && (itsWild || from[1]))
223 Printf("Destination \"%s\" is not a directory.\n", to);
224 ERROR(RETURN_FAIL);
228 /* Handle single file name change */
229 isSingle =!destIsDir;
230 /* 15th Jan 2004 bugfix, (destIsDir && ...) not (!destisDir && ...) ! - Piru */
231 if (destIsDir && !from[1])
233 BPTR fromlock;
235 fromlock = Lock(from[0], ACCESS_READ);
236 if (fromlock)
238 isSingle = SameLock(fromlock, tolock) == LOCK_SAME;
240 UnLock(fromlock);
243 /* 4th May 2003 bugfix: be quiet about single object renames - Piru */
244 quiet = TRUE;
246 if (isSingle)
248 if (ParsePattern(from[0], pathName, MAX_PATH_LEN) > -1 &&
249 Rename(pathName, to))
251 ERROR(RETURN_OK);
254 ioerr = IoErr();
255 Printf("Can't rename %s as %s because ", from[0], to);
256 ERROR(RETURN_FAIL);
259 if (tolock)
261 if (!NameFromLock(tolock, pathName, MAX_PATH_LEN))
263 if (IoErr() == ERROR_LINE_TOO_LONG)
265 PrintFault(IoErr(), APPNAME);
267 ERROR(RETURN_FAIL);
270 pathName[0] = '\0';
274 if (!pathName[0])
276 stccpy(pathName, to, MAX_PATH_LEN);
280 /* Now either only one specific file should be renamed or the
281 destination is really a directory. We can use the same routine
282 for both cases! */
284 fileStart = pathName + strlen(pathName);
286 ap->ap_BreakBits = SIGBREAKF_CTRL_C;
287 ap->ap_Strlen = MAX_PATH_LEN;
289 for (i = 0; from[i]; i++)
291 for (match = MatchFirst(from[i], ap); match == 0; match = MatchNext(ap))
293 /* Check for identical 'from' and 'to'? */
295 if (destIsDir)
297 /* Clear former filename */
298 *fileStart = '\0';
299 if (!AddPart(pathName, FilePart(ap->ap_Buf), MAX_PATH_LEN))
301 MatchEnd(ap);
303 PrintFault(ERROR_LINE_TOO_LONG, APPNAME);
304 SetIoErr(ERROR_LINE_TOO_LONG);
306 ERROR(RETURN_FAIL);
310 if (!quiet)
312 Printf("Renaming %s as %s\n", ap->ap_Buf, pathName);
315 if (!Rename(ap->ap_Buf, pathName))
317 ioerr = IoErr();
318 MatchEnd(ap);
320 Printf("Can't rename %s as %s because ", ap->ap_Buf, pathName);
321 ERROR(RETURN_FAIL);
325 MatchEnd(ap);
328 if (ap->ap_FoundBreak & SIGBREAKF_CTRL_C)
330 PrintFault(ERROR_BREAK, NULL);
332 retval = RETURN_WARN;
334 else
336 retval = RETURN_OK;
339 cleanup:
340 if (tolock)
342 UnLock(tolock);
345 if (ioerr)
347 //MatchEnd(ap);
348 PrintFault(ioerr, NULL);
349 //retval = ERROR_FAIL;
352 FreeVec(ap);
354 return retval;