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

Defined functions

check defined in line 259; used 1 times
chkdot defined in line 288; used 2 times
  • in line 179(2)
dname defined in line 246; used 5 times
main defined in line 24; never used
move defined in line 53; used 1 times
  • in line 46
mvdir defined in line 122; used 1 times
  • in line 38
pname defined in line 228; used 12 times

Defined variables

s1 defined in line 22; used 12 times
s2 defined in line 22; used 15 times

Defined macros

DELIM defined in line 13; used 3 times
DOT defined in line 11; used 3 times
DOTDOT defined in line 12; used 6 times
MAXN defined in line 15; used 7 times
MODEBITS defined in line 16; used 1 times
  • in line 85
ROOTINO defined in line 17; used 1 times
SDELIM defined in line 14; used 3 times
Last modified: 1979-01-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 918
Valid CSS Valid XHTML 1.0 Strict