diff options
Diffstat (limited to 'sys/cmd/mv/mv.c')
-rw-r--r-- | sys/cmd/mv/mv.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/sys/cmd/mv/mv.c b/sys/cmd/mv/mv.c new file mode 100644 index 0000000..0d19248 --- /dev/null +++ b/sys/cmd/mv/mv.c @@ -0,0 +1,130 @@ +#include <u.h> +#include <libn.h> + +static struct Flags +{ + uchar f : 1; + uchar i : 1; + uchar v : 1; +} flag; + +static +char * +strcpyn(char *dst, char *src, int n) +{ + while(*src && n-->0) + *dst++ = *src++; + + *dst = 0; + return dst; +} + +static +int +mv(char *from, char *to) +{ + io·Stat src, dst; + + if(lstat(from, &src)) { + errorf("%s", from); + return 1; + } + + if(!flag.f && !access(to, F_OK)) { + int ask = 1; + int ch, first; + + if(flag.i && !access(from, F_OK)) + fprintf(stderr, "overwrite %s? ", to); + else + ask = 0; + + if (ask) { + first = ch = getchar(); + while (ch != '\n' && ch != EOF) + ch = getchar(); + + if (first != 'y' || first != 'Y') + return 0; + } + } + + if(!rename(from, to)) { + if (flag.v) + fprintf(stdout, "%s -> %s\n", from, to); + return 0; + } + + /* TODO: errno = EXDEV */ + errorf("rename: %s to %s: %s", from, to, strerror(errno)); + return 1; +} + +static +void +usage(void) +{ + fputs("usage: mv [-fiv] source ... dest\n", stderr); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + int err, len; + io·Stat info; + char *arg, *nm, *e, path[4096]; + + ARGBEGIN{ + case 'f': + flag.f++; + break; + case 'i': + flag.i++; + break; + case 'v': + flag.v++; + break; + default: + usage(); + }ARGEND; + + if(argc < 2) + usage(); + + if(stat(argv[argc-1],&info) || !S_ISDIR(info.st_mode)) { + if (argc > 2) + usage(); + exit(mv(argv[0], argv[1])); + } + + /* we know the last argument is a directory */ + e = strcpyn(path, argv[argc-1], sizeof path-1); + *e++ = '/'; + + for(err=0; --argc; ++argv) { + arg = argv[0]; + + if ((nm = strrchr(arg, '/')) == nil) + nm = arg; + else { + /* case: name/ */ + if (!nm[1]) { + while(nm >= arg && nm[0] == '/') + nm--; + while(nm >= arg && nm[0] != '/') + nm--; + } + nm++; + } + + if ((len = strlen(nm)) >= arrend(path)-e) { + errorf("%s: path name overflow\n", arg); + err++; + continue; + } + memmove(e, nm, len+1); + err += mv(arg, path); + } + exit(err); +} |