|
|
1.1 ! root 1: /* ! 2: * mv file1 file2 ! 3: */ ! 4: ! 5: #include <stdio.h> ! 6: #include <sys/types.h> ! 7: #include <sys/stat.h> ! 8: #include <sys/dir.h> ! 9: #include <signal.h> ! 10: ! 11: #define DOT "." ! 12: #define DOTDOT ".." ! 13: #define DELIM '/' ! 14: #define SDELIM "/" ! 15: #define MAXN 100 ! 16: #define MODEBITS 07777 ! 17: ! 18: char *pname(); ! 19: char *sprintf(); ! 20: char *dname(); ! 21: struct stat s1, s2; ! 22: ! 23: main(argc, argv) ! 24: register char *argv[]; ! 25: { ! 26: register i, r; ! 27: ! 28: if (argc < 3) ! 29: goto usage; ! 30: if (stat(argv[1], &s1) < 0) { ! 31: fprintf(stderr, "mv: cannot access %s\n", argv[1]); ! 32: return(1); ! 33: } ! 34: if ((s1.st_mode & S_IFMT) == S_IFDIR) { ! 35: if (argc != 3) ! 36: goto usage; ! 37: return mvdir(argv[1], argv[2]); ! 38: } ! 39: setuid(getuid()); ! 40: if (argc > 3) ! 41: if (stat(argv[argc-1], &s2) < 0 || (s2.st_mode & S_IFMT) != S_IFDIR) ! 42: goto usage; ! 43: r = 0; ! 44: for (i=1; i<argc-1; i++) ! 45: r |= move(argv[i], argv[argc-1]); ! 46: return(r); ! 47: usage: ! 48: fprintf(stderr, "usage: mv f1 f2; or mv d1 d2; or mv f1 ... fn d1\n"); ! 49: return(1); ! 50: } ! 51: ! 52: move(source, target) ! 53: char *source, *target; ! 54: { ! 55: register c, i; ! 56: int status; ! 57: char buf[MAXN]; ! 58: ! 59: if (stat(source, &s1) < 0) { ! 60: fprintf(stderr, "mv: cannot access %s\n", source); ! 61: return(1); ! 62: } ! 63: if ((s1.st_mode & S_IFMT) == S_IFDIR) { ! 64: fprintf(stderr, "mv: directory rename only\n"); ! 65: return(1); ! 66: } ! 67: if (stat(target, &s2) >= 0) { ! 68: if ((s2.st_mode & S_IFMT) == S_IFDIR) { ! 69: sprintf(buf, "%s/%s", target, dname(source)); ! 70: target = buf; ! 71: } ! 72: if (stat(target, &s2) >= 0) { ! 73: if ((s2.st_mode & S_IFMT) == S_IFDIR) { ! 74: fprintf(stderr, "mv: %s is a directory\n", target); ! 75: return(1); ! 76: } ! 77: if (s1.st_dev==s2.st_dev && s1.st_ino==s2.st_ino) { ! 78: fprintf(stderr, "mv: %s and %s are identical\n", ! 79: source, target); ! 80: return(1); ! 81: } ! 82: if (access(target, 2) < 0 && isatty(fileno(stdin))) { ! 83: fprintf(stderr, "mv: %s: %o mode ", target, ! 84: s2.st_mode & MODEBITS); ! 85: i = c = getchar(); ! 86: while (c != '\n' && c != EOF) ! 87: c = getchar(); ! 88: if (i != 'y') ! 89: return(1); ! 90: } ! 91: if (unlink(target) < 0) { ! 92: fprintf(stderr, "mv: cannot unlink %s\n", target); ! 93: return(1); ! 94: } ! 95: } ! 96: } ! 97: if (link(source, target) < 0) { ! 98: i = fork(); ! 99: if (i == -1) { ! 100: fprintf(stderr, "mv: try again\n"); ! 101: return(1); ! 102: } ! 103: if (i == 0) { ! 104: execl("/bin/cp", "cp", source, target, 0); ! 105: fprintf(stderr, "mv: cannot exec cp\n"); ! 106: exit(1); ! 107: } ! 108: while ((c = wait(&status)) != i && c != -1) ! 109: ; ! 110: if (status != 0) ! 111: return(1); ! 112: utime(target, &s1.st_atime); ! 113: } ! 114: if (unlink(source) < 0) { ! 115: fprintf(stderr, "mv: cannot unlink %s\n", source); ! 116: return(1); ! 117: } ! 118: return(0); ! 119: } ! 120: ! 121: mvdir(source, target) ! 122: char *source, *target; ! 123: { ! 124: register char *p; ! 125: register i; ! 126: char buf[MAXN]; ! 127: ! 128: if (stat(target, &s2) >= 0) { ! 129: if ((s2.st_mode&S_IFMT) != S_IFDIR) { ! 130: fprintf(stderr, "mv: %s exists\n", target); ! 131: return(1); ! 132: } ! 133: if (strlen(target) > MAXN-DIRSIZ-2) { ! 134: fprintf(stderr, "mv :target name too long\n"); ! 135: return(1); ! 136: } ! 137: strcpy(buf, target); ! 138: target = buf; ! 139: strcat(buf, SDELIM); ! 140: strcat(buf, dname(source)); ! 141: if (stat(target, &s2) >= 0) { ! 142: fprintf(stderr, "mv: %s exists\n", buf); ! 143: return(1); ! 144: } ! 145: } ! 146: if (strcmp(source, target) == 0) { ! 147: fprintf(stderr, "mv: ?? source == target, source exists and target doesnt\n"); ! 148: return(1); ! 149: } ! 150: p = dname(source); ! 151: if (!strcmp(p, DOT) || !strcmp(p, DOTDOT) || !strcmp(p, "") || p[strlen(p)-1]=='/') { ! 152: fprintf(stderr, "mv: cannot rename %s\n", p); ! 153: return(1); ! 154: } ! 155: if (stat(pname(source), &s1) < 0 || stat(pname(target), &s2) < 0) { ! 156: fprintf(stderr, "mv: cannot locate parent\n"); ! 157: return(1); ! 158: } ! 159: if (access(pname(target), 2) < 0) { ! 160: fprintf(stderr, "mv: no write access to %s\n", pname(target)); ! 161: return(1); ! 162: } ! 163: if (access(pname(source), 2) < 0) { ! 164: fprintf(stderr, "mv: no write access to %s\n", pname(source)); ! 165: return(1); ! 166: } ! 167: if (access(source, 2) < 0) { ! 168: fprintf(stderr, "mv: no write access to %s\n", source); ! 169: return(1); ! 170: } ! 171: if (s1.st_dev != s2.st_dev) { ! 172: fprintf(stderr, "mv: cannot move directories across devices\n"); ! 173: return(1); ! 174: } ! 175: if (s1.st_ino != s2.st_ino) { ! 176: char dst[MAXN+5]; ! 177: ! 178: if (chkdot(source) || chkdot(target)) { ! 179: fprintf(stderr, "mv: Sorry, path names including %s aren't allowed\n", DOTDOT); ! 180: return(1); ! 181: } ! 182: stat(source, &s1); ! 183: if (check(pname(target), s1.st_ino)) ! 184: return(1); ! 185: for (i = 1; i <= NSIG; i++) ! 186: signal(i, SIG_IGN); ! 187: if (link(source, target) < 0) { ! 188: fprintf(stderr, "mv: cannot link %s to %s\n", target, source); ! 189: return(1); ! 190: } ! 191: if (unlink(source) < 0) { ! 192: fprintf(stderr, "mv: %s: cannot unlink\n", source); ! 193: unlink(target); ! 194: return(1); ! 195: } ! 196: strcpy(dst, target); ! 197: strcat(dst, "/"); ! 198: strcat(dst, DOTDOT); ! 199: if (unlink(dst) < 0) { ! 200: fprintf(stderr, "mv: %s: cannot unlink\n", dst); ! 201: if (link(target, source) >= 0) ! 202: unlink(target); ! 203: return(1); ! 204: } ! 205: if (link(pname(target), dst) < 0) { ! 206: fprintf(stderr, "mv: cannot link %s to %s\n", ! 207: dst, pname(target)); ! 208: if (link(pname(source), dst) >= 0) ! 209: if (link(target, source) >= 0) ! 210: unlink(target); ! 211: return(1); ! 212: } ! 213: return(0); ! 214: } ! 215: if (link(source, target) < 0) { ! 216: fprintf(stderr, "mv: cannot link %s and %s\n", ! 217: source, target); ! 218: return(1); ! 219: } ! 220: if (unlink(source) < 0) { ! 221: fprintf(stderr, "mv: ?? cannot unlink %s\n", source); ! 222: return(1); ! 223: } ! 224: return(0); ! 225: } ! 226: ! 227: char * ! 228: pname(name) ! 229: register char *name; ! 230: { ! 231: register c; ! 232: register char *p, *q; ! 233: static char buf[MAXN]; ! 234: ! 235: p = q = buf; ! 236: while (c = *p++ = *name++) ! 237: if (c == DELIM) ! 238: q = p-1; ! 239: if (q == buf && *q == DELIM) ! 240: q++; ! 241: *q = 0; ! 242: return buf[0]? buf : DOT; ! 243: } ! 244: ! 245: char * ! 246: dname(name) ! 247: register char *name; ! 248: { ! 249: register char *p; ! 250: ! 251: p = name; ! 252: while (*p) ! 253: if (*p++ == DELIM && *p) ! 254: name = p; ! 255: return name; ! 256: } ! 257: ! 258: check(spth, dinode) ! 259: char *spth; ! 260: ino_t dinode; ! 261: { ! 262: char nspth[MAXN]; ! 263: struct stat sbuf; ! 264: ! 265: sbuf.st_ino = 0; ! 266: ! 267: strcpy(nspth, spth); ! 268: while (sbuf.st_ino != ROOTINO) { ! 269: if (stat(nspth, &sbuf) < 0) { ! 270: fprintf(stderr, "mv: cannot access %s\n", nspth); ! 271: return(1); ! 272: } ! 273: if (sbuf.st_ino == dinode) { ! 274: fprintf(stderr, "mv: cannot move a directory into itself\n"); ! 275: return(1); ! 276: } ! 277: if (strlen(nspth) > MAXN-2-sizeof(DOTDOT)) { ! 278: fprintf(stderr, "mv: name too long\n"); ! 279: return(1); ! 280: } ! 281: strcat(nspth, SDELIM); ! 282: strcat(nspth, DOTDOT); ! 283: } ! 284: return(0); ! 285: } ! 286: ! 287: chkdot(s) ! 288: register char *s; ! 289: { ! 290: do { ! 291: if (strcmp(dname(s), DOTDOT) == 0) ! 292: return(1); ! 293: s = pname(s); ! 294: } while (strcmp(s, DOT) != 0 && strcmp(s, SDELIM) != 0); ! 295: return(0); ! 296: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.