[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