📄 mv.c
字号:
/* * mv file1 file2 */#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/dir.h>#include <signal.h>#define DOT "."#define DOTDOT ".."#define DELIM '/'#define SDELIM "/"#define MAXN 100#define MODEBITS 07777#define ROOTINO 2char *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<argc-1; i++) r |= move(argv[i], argv[argc-1]); return(r);usage: fprintf(stderr, "usage: mv f1 f2; or mv d1 d2; or mv f1 ... fn d1\n"); return(1);}move(source, target)char *source, *target;{ register c, i; int status; char buf[MAXN]; if (stat(source, &s1) < 0) { fprintf(stderr, "mv: cannot access %s\n", source); return(1); } if ((s1.st_mode & S_IFMT) == S_IFDIR) { fprintf(stderr, "mv: directory rename only\n"); return(1); } if (stat(target, &s2) >= 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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -