#include #include 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); }