/* * track */ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <dk.h> #include <signal.h> #include <setjmp.h> #include <ftw.h> int vflag; /* verbose */ int nflag; /* don't actually copy */ int rflag; /* act as remote slave */ int tflag; /* update only if remote is newer */ char prefix[128]; /* alternate prefix on remote (-d flag) */ int nsize; /* amount to strip off local name */ char *descfile; extern char *optarg; extern int optind; FILE *torem; int rem; int descfd; jmp_buf almbuf; char tempfile[] = "/tmp/trckXXXXXX"; unsigned getsum(); char *remoten(); main(argc, argv) char **argv; { int consider(); char buf[128]; if (argc <= 1) { printf("track [-nvtr] {-f description | directory} machine\n"); exit(0); } for (;;) { switch (getopt(argc, argv, "vnrtf:d:")) { case 'v': vflag++; continue; case 'r': rflag++; continue; case 'n': nflag++; continue; case 't': tflag++; continue; case 'f': descfile = optarg; continue; case 'd': strcpy(prefix, optarg); continue; case '?': exit(1); case EOF: default: break; } break; } if (setjmp(almbuf)) { if (rflag==0) printf("track: alarm talking to %s\n", argv[optind]); exit(1); } if (rflag) remote(); if (descfile) { descfd = open(descfile, 0); if (descfd <= 0) { printf("track: can't open description %s", descfile); exit(1); } } else { if (optind >= argc) { printf("track: no description file\n"); exit(1); } descfile = argv[optind]; optind++; } if (optind >= argc) { printf("track: no machine given\n"); exit(1); } rem = ipcexec(argv[optind], "heavy delim", "track -r"); if (rem < 0) { printf("track: can't execute on %s\n", argv[optind]); exit(1); } torem = fdopen(rem, "w"); fprintf(torem, "testing 123\n"); fflush(torem); vgetline(rem, buf, "<startup>"); if (strncmp(buf, "ok", 2) !=0) { printf("track: can't talk to remote\n"); exit(1); } mktemp(tempfile); if (descfd <= 0) { if (prefix[0]) nsize = strlen(descfile); ftw(descfile, consider, 10); } else { while (getline(descfd, buf)) { if (prefix[0]) nsize = strlen(buf); ftw(buf, consider, 10); } } unlink(tempfile); exit(1); } remote() { char buf[1024]; struct stat statb; char name[128]; int x, ofd; char obuf[BUFSIZ]; setbuf(stdout, obuf); while (getline(0, buf) != 0) { if (sscanf(buf, "testing %d", &x) == 1) { printf("ok\n"); fflush(stdout); continue; } if (sscanf(buf, "stat %s", name) == 1) { if (stat(name, &statb) < 0) { printf("ng\n"); fflush(stdout); continue; } printf("ok %ld %ld\n", statb.st_size, statb.st_mtime); fflush(stdout); continue; } if (sscanf(buf, "sum %s", name) == 1) { printf("ok %ld\n", (long)getsum(name)); fflush(stdout); continue; } if (sscanf(buf, "send %s", name) == 1) { ofd = open(name, 0); if (ofd < 0) { printf("ng\n"); fflush(stdout); continue; } printf("ok\n"); fflush(stdout); while ((x = read(ofd, buf, 1024)) > 0) write(1, buf, x); close(ofd); write(1, buf, 0); continue; } break; } exit(0); } consider(name, statp, flag) char *name; struct stat *statp; { char buf[128]; long lsum, rsum; long size; time_t date; switch (flag) { case FTW_F: break; default: printf("track: trouble with %s (%d)\n", name, flag); case FTW_D: case FTW_DP: return(0); } alarm(60); fprintf(torem, "stat %s %ld\n", remoten(name), statp->st_size); fflush(torem); vgetline(rem, buf, name); if (sscanf(buf, "ok %ld %ld", &size, &date) != 2) { if (vflag) printf("track: %s not found (remote)\n", remoten(name)); return(0); } if (size == statp->st_size) { fprintf(torem, "sum %s\n", remoten(name)); fflush(torem); lsum = getsum(name); vgetline(rem, buf, name); if (sscanf(buf, "ok %ld", &rsum) != 1) { printf("track: can't read sum for %s\n", remoten(name)); exit(1); } if (lsum == rsum) { if (vflag > 1) printf("track: %s OK\n", name); return(0); } } if (tflag && statp->st_mtime > date) { if (vflag) printf("track: %s newer locally\n", name); return(0); } if (nflag) { printf("track: would copy %s\n", name); return(0); } printf("track: copy %s:", name); copy(name, rem, date); return(0); } copy(name, fd, date) char *name; time_t date; { char buf[1024]; int ofd, nfd, i, n; time_t ut[2]; fprintf(torem, "send %s\n", remoten(name)); fflush(torem); vgetline(fd, buf, name); if (strcmp(buf, "ok") != 0) { printf("can't open remote\n"); return; } if ((ofd = creat(tempfile, 0644)) < 0) { printf("can't open temp\n"); return; } i = 10; while ((n = read(fd, buf, 1024)) > 0) { if (write(ofd, buf, n) != n) { printf("write temp file\n"); return; } if (--i <= 0) { alarm(60); i = 10; } } close(ofd); ofd = open(tempfile, 0); if (ofd < 0) { printf("can't reopen temp\n"); return; } nfd = creat(name, 0777); if (nfd < 0) { printf("can't create new version\n"); return; } while ((n = read(ofd, buf, 1024)) > 0) { if (write(nfd, buf, n) != n) { printf("write error in copy\n"); return; } } close(ofd); close(nfd); ut[0] = time((time_t)NULL); ut[1] = date; utime(name, ut); printf("OK\n"); } char * remoten(name) register char *name; { static char rname[256]; if (prefix[0] == '\0') return(name); if (name[0] != '/') { strcpy(rname, prefix); strcat(rname, "/"); strcat(rname, name); return(rname); } strcpy(rname, prefix); strcat(rname, name+nsize); return(rname); } vgetline(fd, buf, name) char *buf, *name; { if (getline(fd, buf)==0) { printf("track: EOF on remote, file %s\n", name); exit(1); } } getline(fd, buf) char *buf; { register char *bp; bp = buf; for(;;) { if (read(fd, bp, 1) <= 0) return(0); if (*bp == '\n') { *bp = '\0'; return(1); } if (++bp >= &buf[128]) return(0); } } unsigned getsum(name) char *name; { register FILE *f; register unsigned sum; register c; if ((f = fopen(name, "r")) == NULL) return(-1); sum = 0; while ((c = getc(f)) != EOF) { if (sum & 01) sum = (sum>>1) + 0x8000; else sum >>= 1; sum += c; sum &= 0xFFFF; } fclose(f); return(sum); }