From 19d28555a00060a2781d5d418ead9fe223b4ea6a Mon Sep 17 00:00:00 2001 From: Tom London Date: Fri, 19 Jan 1979 00:07:46 -0500 Subject: [PATCH] Bell 32V development Work on file usr/src/cmd/mv.c Co-Authored-By: John Reiser Synthesized-from: 32v --- usr/src/cmd/mv.c | 297 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 297 insertions(+) create mode 100644 usr/src/cmd/mv.c diff --git a/usr/src/cmd/mv.c b/usr/src/cmd/mv.c new file mode 100644 index 0000000000..0e2b7017a3 --- /dev/null +++ b/usr/src/cmd/mv.c @@ -0,0 +1,297 @@ +/* + * mv file1 file2 + */ + +#include +#include +#include +#include +#include + +#define DOT "." +#define DOTDOT ".." +#define DELIM '/' +#define SDELIM "/" +#define MAXN 100 +#define MODEBITS 07777 +#define ROOTINO 2 + +char *pname(); +char *sprintf(); +char *dname(); +struct stat s1, s2; + +main(argc, argv) +register char *argv[]; +{ + register i, r; + + if (argc < 3) + goto usage; + if (stat(argv[1], &s1) < 0) { + fprintf(stderr, "mv: cannot access %s\n", argv[1]); + return(1); + } + if ((s1.st_mode & S_IFMT) == S_IFDIR) { + if (argc != 3) + goto usage; + return mvdir(argv[1], argv[2]); + } + setuid(getuid()); + if (argc > 3) + if (stat(argv[argc-1], &s2) < 0 || (s2.st_mode & S_IFMT) != S_IFDIR) + goto usage; + r = 0; + for (i=1; i= 0) { + if ((s2.st_mode & S_IFMT) == S_IFDIR) { + sprintf(buf, "%s/%s", target, dname(source)); + target = buf; + } + if (stat(target, &s2) >= 0) { + if ((s2.st_mode & S_IFMT) == S_IFDIR) { + fprintf(stderr, "mv: %s is a directory\n", target); + return(1); + } + if (s1.st_dev==s2.st_dev && s1.st_ino==s2.st_ino) { + fprintf(stderr, "mv: %s and %s are identical\n", + source, target); + return(1); + } + if (access(target, 2) < 0 && isatty(fileno(stdin))) { + fprintf(stderr, "mv: %s: %o mode ", target, + s2.st_mode & MODEBITS); + i = c = getchar(); + while (c != '\n' && c != EOF) + c = getchar(); + if (i != 'y') + return(1); + } + if (unlink(target) < 0) { + fprintf(stderr, "mv: cannot unlink %s\n", target); + return(1); + } + } + } + if (link(source, target) < 0) { + i = fork(); + if (i == -1) { + fprintf(stderr, "mv: try again\n"); + return(1); + } + if (i == 0) { + execl("/bin/cp", "cp", source, target, 0); + fprintf(stderr, "mv: cannot exec cp\n"); + exit(1); + } + while ((c = wait(&status)) != i && c != -1) + ; + if (status != 0) + return(1); + utime(target, &s1.st_atime); + } + if (unlink(source) < 0) { + fprintf(stderr, "mv: cannot unlink %s\n", source); + return(1); + } + return(0); +} + +mvdir(source, target) +char *source, *target; +{ + register char *p; + register i; + char buf[MAXN]; + + if (stat(target, &s2) >= 0) { + if ((s2.st_mode&S_IFMT) != S_IFDIR) { + fprintf(stderr, "mv: %s exists\n", target); + return(1); + } + if (strlen(target) > MAXN-DIRSIZ-2) { + fprintf(stderr, "mv :target name too long\n"); + return(1); + } + strcpy(buf, target); + target = buf; + strcat(buf, SDELIM); + strcat(buf, dname(source)); + if (stat(target, &s2) >= 0) { + fprintf(stderr, "mv: %s exists\n", buf); + return(1); + } + } + if (strcmp(source, target) == 0) { + fprintf(stderr, "mv: ?? source == target, source exists and target doesnt\n"); + return(1); + } + p = dname(source); + if (!strcmp(p, DOT) || !strcmp(p, DOTDOT) || !strcmp(p, "") || p[strlen(p)-1]=='/') { + fprintf(stderr, "mv: cannot rename %s\n", p); + return(1); + } + if (stat(pname(source), &s1) < 0 || stat(pname(target), &s2) < 0) { + fprintf(stderr, "mv: cannot locate parent\n"); + return(1); + } + if (access(pname(target), 2) < 0) { + fprintf(stderr, "mv: no write access to %s\n", pname(target)); + return(1); + } + if (access(pname(source), 2) < 0) { + fprintf(stderr, "mv: no write access to %s\n", pname(source)); + return(1); + } + if (access(source, 2) < 0) { + fprintf(stderr, "mv: no write access to %s\n", source); + return(1); + } + if (s1.st_dev != s2.st_dev) { + fprintf(stderr, "mv: cannot move directories across devices\n"); + return(1); + } + if (s1.st_ino != s2.st_ino) { + char dst[MAXN+5]; + + if (chkdot(source) || chkdot(target)) { + fprintf(stderr, "mv: Sorry, path names including %s aren't allowed\n", DOTDOT); + return(1); + } + stat(source, &s1); + if (check(pname(target), s1.st_ino)) + return(1); + for (i = 1; i <= NSIG; i++) + signal(i, SIG_IGN); + if (link(source, target) < 0) { + fprintf(stderr, "mv: cannot link %s to %s\n", target, source); + return(1); + } + if (unlink(source) < 0) { + fprintf(stderr, "mv: %s: cannot unlink\n", source); + unlink(target); + return(1); + } + strcat(dst, target); + strcat(dst, "/"); + strcat(dst, DOTDOT); + if (unlink(dst) < 0) { + fprintf(stderr, "mv: %s: cannot unlink\n", dst); + if (link(target, source) >= 0) + unlink(target); + return(1); + } + if (link(pname(target), dst) < 0) { + fprintf(stderr, "mv: cannot link %s to %s\n", + dst, pname(target)); + if (link(pname(source), dst) >= 0) + if (link(target, source) >= 0) + unlink(target); + return(1); + } + return(0); + } + if (link(source, target) < 0) { + fprintf(stderr, "mv: cannot link %s and %s\n", + source, target); + return(1); + } + if (unlink(source) < 0) { + fprintf(stderr, "mv: ?? cannot unlink %s\n", source); + return(1); + } + return(0); +} + +char * +pname(name) +register char *name; +{ + register c; + register char *p, *q; + static char buf[MAXN]; + + p = q = buf; + while (c = *p++ = *name++) + if (c == DELIM) + q = p-1; + if (q == buf && *q == DELIM) + q++; + *q = 0; + return buf[0]? buf : DOT; +} + +char * +dname(name) +register char *name; +{ + register char *p; + + p = name; + while (*p) + if (*p++ == DELIM && *p) + name = p; + return name; +} + +check(spth, dinode) +char *spth; +ino_t dinode; +{ + char nspth[MAXN]; + struct stat sbuf; + + sbuf.st_ino = 0; + + strcpy(nspth, spth); + while (sbuf.st_ino != ROOTINO) { + if (stat(nspth, &sbuf) < 0) { + fprintf(stderr, "mv: cannot access %s\n", nspth); + return(1); + } + if (sbuf.st_ino == dinode) { + fprintf(stderr, "mv: cannot move a directory into itself\n"); + return(1); + } + if (strlen(nspth) > MAXN-2-sizeof(DOTDOT)) { + fprintf(stderr, "mv: name too long\n"); + return(1); + } + strcat(nspth, SDELIM); + strcat(nspth, DOTDOT); + } + return(0); +} + +chkdot(s) +register char *s; +{ + do { + if (strcmp(dname(s), DOTDOT) == 0) + return(1); + s = pname(s); + } while (strcmp(s, DOT) != 0 && strcmp(s, SDELIM) != 0); + return(0); +} -- 2.20.1