[Toybox] [PATCH] New toy - mv
    Georgi Chorbadzhiyski 
    gf at unixsol.org
       
    Thu Mar 15 02:33:41 PDT 2012
    
    
  
This new toy depends on CP && RM. -f is probably not working.
There is a possible generic functionality here in case of internal_exec(char *argv[])
-- 
Georgi Chorbadzhiyski
http://georgi.unixsol.org/
-------------- next part --------------
/* vi: set sw=4 ts=4:
 *
 * mv.c - Move files.
 *
 * Copyright 2012 Georgi Chorbadzhiyski <georgi at unixsol.org>
 *
 * See http://www.opengroup.org/onlinepubs/009695399/utilities/mv.html
 *
USE_MV(NEWTOY(mv, "<2fiv", TOYFLAG_BIN))
config MV
	bool "mv"
	default y
	depends on CP && RM
	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;
	struct toy_context c;
	int exitval;
	c = toys;
	toys.optargs = NULL; // Prevent freeing of original args
	which = toy_find(argv[0]);
	if (!which)
		return -1;
	toy_init(which, argv);
	toys.which->toy_main();
	free(toys.optargs);
	exitval = toys.exitval;
	toys = c;
	return exitval;
}
void mv_main(void)
{
	char *dest;
	char *fulldest;
	int fulldest_len = 0;
	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);
		}
	}
	fulldest_len = 4096;
	fulldest = xmalloc(fulldest_len);
	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;
		int flen = strlen(dest) + 1 + strlen(src) + 2;
		if (flen > fulldest_len) {
			fulldest = xrealloc(fulldest, flen);
			fulldest_len = flen;
		}
		snprintf(fulldest, flen - 1, "%s/%s", dest, src);
		fulldest[flen - 1] = '\0';
		if ((toys.optflags & FLAG_i) && !yesno("Confirm mv", 1))
			continue;
		if (toys.optflags & FLAG_v)
			xprintf("mv '%s' -> '%s'\n", src, fulldest);
		if (rename(src, fulldest) != 0) {
			if (errno == EXDEV) {
				char *cp_argv[5] = { "cp", "-af", src, fulldest, NULL };
				char *rm_argv[4] = { "rm", "-rf", src, NULL };
				if (internal_exec(cp_argv) != 0 || internal_exec(rm_argv) != 0)
					toys.exitval = 1;
			} else {
				perror_msg("%s", fulldest);
				toys.exitval = 1;
			}
		}
	}
	if (CFG_TOYBOX_FREE) {
		free(fulldest);
	}
	toys.exitval = ret;
}
    
    
More information about the Toybox
mailing list