[Toybox] [PATCH, WIP] New toy - mv
Georgi Chorbadzhiyski
gf at unixsol.org
Mon Mar 12 08:58:55 PDT 2012
Ok, I have problems in mv implementation since I'm trying to use internal
cp and rm toys. I have used toy_exec() variation:
int internal_exec(char *argv[])
{
struct toy_list *which;
which = toy_find(argv[0]);
if (!which)
return -1;
toy_init(which, argv);
toys.which->toy_main();
return toys.exitval;
}
and in mv.c:
if (rename(src, toybuf) != 0) {
if (errno == EXDEV) {
char *cp_argv[5] = { "cp", "-af", src, dest, NULL };
char *rm_argv[4] = { "rm", "-rf", src, NULL };
if (internal_exec(cp_argv) != 0 || internal_exec(rm_argv) != 0) {
ret = 1;
}
} else {
perror_msg("%s", toybuf);
ret = 1;
}
}
The problem is that calling toy_init() overwrites toys.optc, toys.optflags,
toys.optargs, toys.exitval, etc. I can save and restore them but should I
do it that way?
The attached mv.c works only for the first file if copying is needed. If
args related parameters are saved and restore between internal_exec() it
should work as expected.
Maybe toy_state_push() and toy_stat_pop() function can be added?
And also yesno() really should take va_arg parameters and flush stdout
after writing to it.
--
Georgi Chorbadzhiyski
http://georgi.unixsol.org/
-------------- next part --------------
/* vi: set sw=4 ts=4:
*
* mv.c - Move files.
*
* Copyright 2008 Rob Landley <rob at landley.net>
*
* See http://www.opengroup.org/onlinepubs/009695399/utilities/mv.html
*
USE_MV(NEWTOY(mv, "<2fiv", TOYFLAG_BIN))
config MV
bool "mv"
default y
help
usage: mv -fiv SOURCE... DEST
Move files from SOURCE to DEST. If more than one SOURCE, DEST must
be a directory.
-f force overwrite
-i interactive, prompt before moving file
-v verbose
*/
#include "toys.h"
#define FLAG_f 4
#define FLAG_i 2
#define FLAG_v 1
// Remove trailing /
// Remove ./ infront
char *normalize(char *x, int xlen) {
if (!xlen)
return x;
while (x[--xlen] == '/')
x[xlen] = '\0';
if (xlen > 1) {
if (x[0] == '.' && x[1] == '/') {
x += 1;
while (x[0] == '/')
x++;
}
}
return x;
}
int internal_exec(char *argv[])
{
struct toy_list *which;
which = toy_find(argv[0]);
if (!which)
return -1;
toy_init(which, argv);
toys.which->toy_main();
return toys.exitval;
}
void mv_main(void)
{
char *dest;
struct stat st;
int i;
int ret = 0;
dest = toys.optargs[--toys.optc];
// Many sources, destination must be a directory
if (toys.optc > 1) {
if (stat(dest, &st) != 0 || !S_ISDIR(st.st_mode)) {
error_exit("'%s' is not a directory", dest);
}
}
dest = normalize(dest, strlen(dest));
for (i=0; i<toys.optc; i++) {
char *src = normalize(toys.optargs[i], strlen(toys.optargs[i]));
if (!strcmp(src, dest))
continue;
snprintf(toybuf, sizeof(toybuf) - 1, "%s/%s", dest, src);
toybuf[sizeof(toybuf) - 1] = '\0';
if ((toys.optflags & FLAG_i) && !yesno("Confirm mv", 1))
continue;
if (toys.optflags & FLAG_v)
xprintf("mv '%s' -> '%s'\n", src, toybuf);
if (rename(src, toybuf) != 0) {
if (errno == EXDEV) {
char *cp_argv[5] = { "cp", "-af", src, dest, NULL };
char *rm_argv[4] = { "rm", "-rf", src, NULL };
if (internal_exec(cp_argv) != 0 || internal_exec(rm_argv) != 0) {
ret = 1;
}
} else {
perror_msg("%s", toybuf);
ret = 1;
}
}
}
toys.exitval = ret;
}
More information about the Toybox
mailing list