# 2.11BSD#431 - /usr/src/bin/mv.c

##### Functions

    Perror            X
    Perror2           X
    dname             X
    error             X
    main              X
    move              X
    movewithshortname X
    query             X

##### Variables

    copyright         X
    fflag             X
    iflag             X
    s1                X
    s2                X

##### Macros

    DELIM             X
    ISDEV             X
    ISDIR             X
    ISLNK             X
    ISREG             X
    MODEBITS          X

       1: /*
       2:  * Copyright (c) 1980 Regents of the University of California.
       3:  * All rights reserved.  The Berkeley software License Agreement
       4:  * specifies the terms and conditions for redistribution.
       5:  */
       6:
       7: #if !defined(lint) && defined(DOSCCS)
       8: char copyright[] =
       9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
      10:  All rights reserved.\n";
      11:
      12: static char sccsid[] = "@(#)mv.c	5.3.1 (2.11BSD) 1996/1/5";
      13: #endif not lint
      14:
      15: /*
      16:  * mv file1 file2
      17:  */
      18: #include <sys/param.h>
      19: #include <sys/stat.h>
      20: #include <sys/time.h>
      21:
      22: #include <stdio.h>
      23: #include <sys/dir.h>
      24: #include <errno.h>
      25: #include <signal.h>
      26:
      27: #define DELIM   '/'
      28: #define MODEBITS 07777
      29:
      30: #define ISDIR(st)   (((st).st_mode&S_IFMT) == S_IFDIR)
      31: #define ISLNK(st)   (((st).st_mode&S_IFMT) == S_IFLNK)
      32: #define ISREG(st)   (((st).st_mode&S_IFMT) == S_IFREG)
      33: #define ISDEV(st) \
      34:     (((st).st_mode&S_IFMT) == S_IFCHR || ((st).st_mode&S_IFMT) == S_IFBLK)
      35:
      36: char    *sprintf();
      37: char    *dname();
      38: struct  stat s1, s2;
      39: int iflag = 0;  /* interactive mode */
      40: int fflag = 0;  /* force overwriting */
      41:
      42: main(argc, argv)
      43:     register char *argv[];
      44: {
      45:     register i, r;
      46:     register char *arg;
      47:     char *dest;
      48:
      49:     if (argc < 2)
      50:         goto usage;
      51:     while (argc > 1 && *argv[1] == '-') {
      52:         argc--;
      53:         arg = *++argv;
      54:
      55:         /*
      56: 		 * all files following a null option
      57: 		 * are considered file names
      58: 		 */
      59:         if (*(arg+1) == '\0')
      60:             break;
      61:         while (*++arg != '\0') switch (*arg) {
      62:
      63:         case 'i':
      64:             iflag++;
      65:             break;
      66:
      67:         case 'f':
      68:             fflag++;
      69:             break;
      70:
      71:         default:
      72:             goto usage;
      73:         }
      74:     }
      75:     if (argc < 3)
      76:         goto usage;
      77:     dest = argv[argc-1];
      78:     if (stat(dest, &s2) >= 0 && ISDIR(s2)) {
      79:         r = 0;
      80:         for (i = 1; i < argc-1; i++)
      81:             r |= movewithshortname(argv[i], dest);
      82:         exit(r);
      83:     }
      84:     if (argc > 3)
      85:         goto usage;
      86:     r = move(argv[1], argv[2]);
      87:     exit(r);
      88:     /*NOTREACHED*/
      89: usage:
      90:     fprintf(stderr,
      91: "usage: mv [-if] f1 f2 or mv [-if] f1 ... fn d1 (`fn' is a file or directory)\n");
      92:     return (1);
      93: }
      94:
      95: movewithshortname(src, dest)
      96:     char *src, *dest;
      97: {
      98:     register char *shortname;
      99:     char target[MAXPATHLEN + 1];
     100:
     101:     shortname = dname(src);
     102:     if (strlen(dest) + strlen(shortname) > MAXPATHLEN - 1) {
     103:         error("%s/%s: pathname too long", dest,
     104:             shortname);
     105:         return (1);
     106:     }
     107:     sprintf(target, "%s/%s", dest, shortname);
     108:     return (move(src, target));
     109: }
     110:
     111: move(source, target)
     112:     char *source, *target;
     113: {
     114:     int targetexists;
     115:
     116:     if (lstat(source, &s1) < 0) {
     117:         Perror2(source, "Cannot access");
     118:         return (1);
     119:     }
     120:     /*
     121: 	 * First, try to rename source to destination.
     122: 	 * The only reason we continue on failure is if
     123: 	 * the move is on a nondirectory and not across
     124: 	 * file systems.
     125: 	 */
     126:     targetexists = lstat(target, &s2) >= 0;
     127:     if (targetexists) {
     128:         if (s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino) {
     129:             error("%s and %s are identical", source, target);
     130:             return (1);
     131:         }
     132:         if (iflag && !fflag && isatty(fileno(stdin)) &&
     133:             query("remove %s? ", target) == 0)
     134:             return (1);
     135:         if (access(target, 2) < 0 && !fflag && isatty(fileno(stdin))) {
     136:             if (query("override protection %o for %s? ",
     137:               s2.st_mode & MODEBITS, target) == 0)
     138:                 return (1);
     139:         }
     140:     }
     141:     if (rename(source, target) >= 0)
     142:         return (0);
     143:     if (errno != EXDEV) {
     144:         Perror2(errno == ENOENT && targetexists == 0 ? target : source,
     145:             "rename");
     146:         return (1);
     147:     }
     148:     if (ISDIR(s1)) {
     149:         error("can't mv directories across file systems");
     150:         return (1);
     151:     }
     152:     if (targetexists && unlink(target) < 0) {
     153:         Perror2(target, "Cannot unlink");
     154:         return (1);
     155:     }
     156:     /*
     157: 	 * File can't be renamed, try to recreate the symbolic
     158: 	 * link or special device, or copy the file wholesale
     159: 	 * between file systems.
     160: 	 */
     161:     if (ISLNK(s1)) {
     162:         register m;
     163:         char symln[MAXPATHLEN + 1];
     164:
     165:         m = readlink(source, symln, sizeof (symln) - 1);
     166:         if (m < 0) {
     167:             Perror(source);
     168:             return (1);
     169:         }
     170:         symln[m] = '\0';
     171:
     172:         m = umask(~(s1.st_mode & MODEBITS));
     173:         if (symlink(symln, target) < 0) {
     174:             Perror(target);
     175:             return (1);
     176:         }
     177:         (void) umask(m);
     178:         goto cleanup;
     179:     }
     180:     if (ISDEV(s1)) {
     181:         struct timeval tv[2];
     182:
     183:         if (mknod(target, s1.st_mode, s1.st_rdev) < 0) {
     184:             Perror(target);
     185:             return (1);
     186:         }
     187:
     188:         tv[0].tv_sec = s1.st_atime;
     189:         tv[0].tv_usec = 0;
     190:         tv[1].tv_sec = s1.st_mtime;
     191:         tv[1].tv_usec = 0;
     192:         (void) utimes(target, tv);
     193:         goto cleanup;
     194:     }
     195:     if (ISREG(s1)) {
     196:         register int fi, fo, n;
     197:         struct timeval tv[2];
     198:         char buf[MAXBSIZE];
     199:
     200:         fi = open(source, 0);
     201:         if (fi < 0) {
     202:             Perror(source);
     203:             return (1);
     204:         }
     205:
     206:         fo = creat(target, s1.st_mode & MODEBITS);
     207:         if (fo < 0) {
     208:             Perror(target);
     209:             close(fi);
     210:             return (1);
     211:         }
     212:
     213:         for (;;) {
     214:             n = read(fi, buf, sizeof buf);
     215:             if (n == 0) {
     216:                 break;
     217:             } else if (n < 0) {
     218:                 Perror2(source, "read");
     219:                 close(fi);
     220:                 close(fo);
     221:                 return (1);
     222:             } else if (write(fo, buf, n) != n) {
     223:                 Perror2(target, "write");
     224:                 close(fi);
     225:                 close(fo);
     226:                 return (1);
     227:             }
     228:         }
     229:
     230:         close(fi);
     231:         close(fo);
     232:
     233:         tv[0].tv_sec = s1.st_atime;
     234:         tv[0].tv_usec = 0;
     235:         tv[1].tv_sec = s1.st_mtime;
     236:         tv[1].tv_usec = 0;
     237:         (void) utimes(target, tv);
     238:         goto cleanup;
     239:     }
     240:     error("%s: unknown file type %o", source, s1.st_mode);
     241:     return (1);
     242:
     243: cleanup:
     244:     if (unlink(source) < 0) {
     245:         Perror2(source, "Cannot unlink");
     246:         return (1);
     247:     }
     248:     return (0);
     249: }
     250:
     251: /*VARARGS*/
     252: query(prompt, a1, a2)
     253:     char *a1;
     254: {
     255:     register int i, c;
     256:
     257:     fprintf(stderr, prompt, a1, a2);
     258:     i = c = getchar();
     259:     while (c != '\n' && c != EOF)
     260:         c = getchar();
     261:     return (i == 'y');
     262: }
     263:
     264: char *
     265: dname(name)
     266:     register char *name;
     267: {
     268:     register char *p;
     269:
     270:     p = name;
     271:     while (*p)
     272:         if (*p++ == DELIM && *p)
     273:             name = p;
     274:     return name;
     275: }
     276:
     277: /*VARARGS*/
     278: error(fmt, a1, a2)
     279:     char *fmt;
     280: {
     281:
     282:     fprintf(stderr, "mv: ");
     283:     fprintf(stderr, fmt, a1, a2);
     284:     fprintf(stderr, "\n");
     285: }
     286:
     287: Perror(s)
     288:     char *s;
     289: {
     290:     char buf[MAXPATHLEN + 10];
     291:
     292:     sprintf(buf, "mv: %s", s);
     293:     perror(buf);
     294: }
     295:
     296: Perror2(s1, s2)
     297:     char *s1, *s2;
     298: {
     299:     char buf[MAXPATHLEN + 20];
     300:
     301:     sprintf(buf, "mv: %s: %s", s1, s2);
     302:     perror(buf);
     303: }

#### Defined functions

Perror defined in line 287; used 5 times

- in line 167, 174, 184, 202, 208

Perror2 defined in line 296; used 6 times

- in line 117, 144, 153, 218-223(2), 245

dname defined in line 264; used 2 times

- in line 37, 101

error defined in line 278; used 4 times

- in line 103, 129, 149, 240

main defined in line 42; never used
move defined in line 111; used 2 times

- in line 86, 108

movewithshortname defined in line 95; used 1 times

- in line 81

query defined in line 252; used 2 times

- in line 133-136(2)

#### Defined variables

copyright defined in line 8; never used
fflag defined in line 40; used 3 times

- in line 68, 132-135(2)

iflag defined in line 39; used 2 times

- in line 64, 132

s1 defined in line 38; used 19 times

- in line 116, 128(2), 148, 161, 172, 180-195(6), 206, 233-240(3), 296-301(3)

s2 defined in line 38; used 9 times

- in line 78(2), 126-128(3), 137, 296-301(3)

sccsid defined in line 12; never used

#### Defined macros

DELIM defined in line 27; used 1 times

- in line 272

ISDEV defined in line 33; used 1 times

- in line 180

ISDIR defined in line 30; used 2 times

- in line 78, 148

ISLNK defined in line 31; used 1 times

- in line 161

ISREG defined in line 32; used 1 times

- in line 195

MODEBITS defined in line 28; used 3 times

- in line 137, 172, 206

Last modified: 1996-01-06 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1841 |