|
|
1.1 ! root 1: /* install.c - installation of files on remote host */ ! 2: ! 3: /* ! 4: * $Header: /f/osi/others/idist/RCS/install.c,v 7.0 89/11/23 21:58:34 mrose Rel $ ! 5: * ! 6: * Installation of files on remote host - the routines here drive the ! 7: * protocol for installation, comparision and deletion etc. The ! 8: * protocol is basically similar to the original rdist, except it is ! 9: * fully client/server in this model with the daemon only responding ! 10: * to requests. In the old version, the two sides occasionally swapped ! 11: * around for some operations. Parts of this file were originally in ! 12: * the file server.c. ! 13: * ! 14: * Julian Onions <[email protected]> ! 15: * Nottingham University Computer Science ! 16: * ! 17: * ! 18: * $Log: install.c,v $ ! 19: * Revision 7.0 89/11/23 21:58:34 mrose ! 20: * Release 6.0 ! 21: * ! 22: */ ! 23: ! 24: /* ! 25: * Copyright (c) 1983 Regents of the University of California. ! 26: * All rights reserved. The Berkeley software License Agreement ! 27: * specifies the terms and conditions for redistribution. ! 28: */ ! 29: ! 30: #ifndef lint ! 31: static char sccsid[] = "@(#)server.c 5.3 (Berkeley) 6/7/86"; ! 32: static char rcsid[] = "$Header: /f/osi/others/idist/RCS/install.c,v 7.0 89/11/23 21:58:34 mrose Rel $"; ! 33: #endif ! 34: ! 35: #include "defs.h" ! 36: #include <sys/file.h> ! 37: ! 38: struct linkbuf *ihead; /* list of files with more than one link */ ! 39: char target[BUFSIZ]; /* target/source directory name */ ! 40: char basename[BUFSIZ]; /* base of directory operations */ ! 41: char *tp; /* pointer to end of target name */ ! 42: char *Tdest; /* pointer to last T dest*/ ! 43: int catname; /* cat name to target name */ ! 44: char *stp[128]; /* stack of saved tp's for directories */ ! 45: int oumask; /* old umask for creating files */ ! 46: char tranbuf[1024*8]; /* 8K at a time... */ ! 47: ! 48: extern FILE *lfp; /* log file for mailing changes */ ! 49: ! 50: int cleanup(); ! 51: struct linkbuf *savelink(); ! 52: extern char *getstring (); ! 53: ! 54: /* ! 55: * Update the file(s) if they are different. ! 56: * destdir = 1 if destination should be a directory ! 57: * (i.e., more than one source is being copied to the same destination). ! 58: */ ! 59: install(src, dest, destdir, opts) ! 60: char *src, *dest; ! 61: int destdir, opts; ! 62: { ! 63: char *rname; ! 64: char destcopy[BUFSIZ]; ! 65: ! 66: if (dest == NULL) { ! 67: opts &= ~WHOLE; /* WHOLE mode only useful if renaming */ ! 68: dest = src; ! 69: } ! 70: ! 71: if (nflag || debug) { ! 72: printf("%s%s%s%s%s%s %s %s\n", ! 73: opts & VERIFY ? "verify":"install", ! 74: opts & WHOLE ? " -w" : "", ! 75: opts & YOUNGER ? " -y" : "", ! 76: opts & COMPARE ? " -b" : "", ! 77: opts & REMOVE ? " -R" : "", ! 78: opts & QUERYM ? " -Q" : "", src, dest); ! 79: if (nflag) ! 80: return; ! 81: } ! 82: ! 83: rname = exptilde(target, src); ! 84: if (rname == NULL) ! 85: return; ! 86: tp = target; ! 87: (void) strcpy (basename, target); ! 88: while (*tp) ! 89: tp++; ! 90: /* ! 91: * If we are renaming a directory and we want to preserve ! 92: * the directory heirarchy (-w), we must strip off the leading ! 93: * directory name and preserve the rest. ! 94: */ ! 95: if (opts & WHOLE) { ! 96: rname = target; ! 97: while (*rname == '/') ! 98: rname++; ! 99: destdir = 1; ! 100: } else { ! 101: rname = rindex(target, '/'); ! 102: if (rname == NULL) ! 103: rname = target; ! 104: else ! 105: rname++; ! 106: } ! 107: if (debug) ! 108: printf("target = %s, rname = %s\n", target, rname); ! 109: /* ! 110: * Pass the destination file/directory name to remote. ! 111: */ ! 112: if (initdir (destdir, dest) < 0) ! 113: return; ! 114: ! 115: (void) strcpy(destcopy, dest); ! 116: Tdest = destcopy; ! 117: ! 118: sendf(rname, opts); ! 119: Tdest = 0; ! 120: } ! 121: ! 122: #define protoname() (pw ? pw->pw_name : user) ! 123: #define protogroup() (gr ? gr->gr_name : group) ! 124: /* ! 125: * Transfer the file or directory in target[]. ! 126: * rname is the name of the file on the remote host. ! 127: */ ! 128: sendf(rname, opts) ! 129: char *rname; ! 130: int opts; ! 131: { ! 132: register struct subcmd *sc; ! 133: struct stat stb; ! 134: int sizerr, f, u, len; ! 135: off_t i; ! 136: DIR *d; ! 137: struct direct *dp; ! 138: char *otp, *cp; ! 139: extern struct subcmd *subcmds; ! 140: char buf[BUFSIZ]; ! 141: static char uname[15], group[15]; ! 142: ! 143: if (debug) ! 144: printf("sendf(%s, %x)\n", rname, opts); ! 145: ! 146: if (except(target)) ! 147: return; ! 148: if ((opts & FOLLOW ? stat(target, &stb) : lstat(target, &stb)) < 0) { ! 149: advise (target, "Can't stat"); ! 150: return; ! 151: } ! 152: if ((u = update(rname, opts, &stb)) == 0) { ! 153: if ((stb.st_mode & S_IFMT) == S_IFREG && stb.st_nlink > 1) ! 154: (void) savelink(&stb, opts); ! 155: return; ! 156: } ! 157: ! 158: if (pw == NULL || pw->pw_uid != stb.st_uid) ! 159: if ((pw = getpwuid(stb.st_uid)) == NULL) { ! 160: log(lfp, "%s: no password entry for uid \n", target); ! 161: pw = NULL; ! 162: (void) sprintf(uname, ":%d", stb.st_uid); ! 163: } ! 164: if (gr == NULL || gr->gr_gid != stb.st_gid) ! 165: if ((gr = getgrgid(stb.st_gid)) == NULL) { ! 166: log(lfp, "%s: no name for group %d\n", target); ! 167: gr = NULL; ! 168: (void) sprintf(group, ":%d", stb.st_gid); ! 169: } ! 170: if (u == 1) { ! 171: #ifdef UW ! 172: if (opts & NOINSTALL) { ! 173: log(lfp, "does not exist, did not install: %s\n", target); ! 174: goto dospecial; ! 175: } ! 176: #endif UW ! 177: if (opts & VERIFY) { ! 178: log(lfp, "need to install: %s\n", target); ! 179: goto dospecial; ! 180: } ! 181: log(lfp, "installing: %s\n", target); ! 182: opts &= ~(COMPARE|REMOVE); ! 183: } ! 184: ! 185: switch (stb.st_mode & S_IFMT) { ! 186: case S_IFDIR: ! 187: if ((d = opendir(target)) == NULL) { ! 188: advise (target, "Can't open directory"); ! 189: return; ! 190: } ! 191: if (transfer (stb.st_mode & S_IFMT, opts, ! 192: stb.st_mode & 07777, (off_t)0, (time_t)0, ! 193: protoname (), protogroup (), ! 194: rname, "") < 0) { ! 195: closedir (d); ! 196: return; ! 197: } ! 198: ! 199: if (opts & REMOVE) ! 200: (void) rmchk(opts); ! 201: ! 202: otp = tp; ! 203: len = tp - target; ! 204: while (dp = readdir(d)) { ! 205: if (!strcmp(dp->d_name, ".") || ! 206: !strcmp(dp->d_name, "..")) ! 207: continue; ! 208: if (len + 1 + strlen(dp->d_name) >= BUFSIZ - 1) { ! 209: advise (NULLCP, "%s/%s name too long", ! 210: target, dp->d_name); ! 211: continue; ! 212: } ! 213: tp = otp; ! 214: *tp++ = '/'; ! 215: cp = dp->d_name; ! 216: while (*tp++ = *cp++) ! 217: ; ! 218: tp--; ! 219: sendf(dp->d_name, opts); ! 220: } ! 221: closedir(d); ! 222: (void) terminate (S_IFDIR, OK); ! 223: tp = otp; ! 224: *tp = '\0'; ! 225: return; ! 226: ! 227: case S_IFLNK: ! 228: if (u != 1) ! 229: opts |= COMPARE; ! 230: if (stb.st_nlink > 1) { ! 231: struct linkbuf *lp; ! 232: ! 233: if ((lp = savelink(&stb, opts)) != NULL) { ! 234: if (*lp -> target == 0) ! 235: (void) strcpy (buf, lp -> pathname); ! 236: else (void) sprintf (buf, "%s/%s", ! 237: lp -> target, ! 238: lp -> pathname); ! 239: (void) transfer ((unsigned short)0, opts, ! 240: (unsigned short)0, (off_t)0, ! 241: (time_t)0, "", "", ! 242: rname, buf); ! 243: return; ! 244: } ! 245: } ! 246: sizerr = (readlink(target, buf, BUFSIZ) != stb.st_size); ! 247: if (debug) ! 248: printf("readlink = %.*s\n", stb.st_size, buf); ! 249: if (transfer (stb.st_mode & S_IFMT, opts, stb.st_mode & 07777, ! 250: stb.st_size, stb.st_mtime, ! 251: protoname (), protogroup (), rname, ! 252: buf) < 0) ! 253: return; ! 254: goto done; ! 255: ! 256: case S_IFREG: ! 257: break; ! 258: ! 259: default: ! 260: advise (NULLCP, "%s: not a file or directory", target); ! 261: return; ! 262: } ! 263: ! 264: if (u == 2) { ! 265: if (opts & VERIFY) { ! 266: log(lfp, "need to update: %s\n", target); ! 267: goto dospecial; ! 268: } ! 269: log(lfp, "updating: %s\n", target); ! 270: } ! 271: ! 272: if (stb.st_nlink > 1) { ! 273: struct linkbuf *lp; ! 274: ! 275: if ((lp = savelink(&stb, opts)) != NULL) { ! 276: if (*lp -> target == 0) ! 277: (void) strcpy (buf, lp -> pathname); ! 278: else (void) sprintf (buf, "%s/%s", ! 279: lp -> target, ! 280: lp -> pathname); ! 281: (void) transfer ((unsigned short)0, opts, ! 282: (unsigned short)0, (off_t)0, ! 283: (time_t)0, "", "", ! 284: rname, buf); ! 285: return; ! 286: } ! 287: } ! 288: ! 289: if ((f = open(target, O_RDONLY, 0)) < 0) { ! 290: advise (target, "Can't open file"); ! 291: return; ! 292: } ! 293: if ( transfer ((unsigned short)S_IFREG, opts, stb.st_mode & 07777, ! 294: stb.st_size, ! 295: stb.st_mtime, protoname (), protogroup (), ! 296: rname, "") < 0) { ! 297: (void) close (f); ! 298: return; ! 299: } ! 300: sizerr = 0; ! 301: for (i = 0; i < stb.st_size; i += sizeof tranbuf) { ! 302: int amt = sizeof tranbuf; ! 303: if (i + amt > stb.st_size) ! 304: amt = stb.st_size - i; ! 305: if (sizerr == 0 && read(f, tranbuf, amt) != amt) ! 306: sizerr = 1; ! 307: if (tran_data (tranbuf, amt) == NOTOK) ! 308: break; ! 309: } ! 310: (void) close(f); ! 311: if (sizerr) { ! 312: advise (NULLCP, "%s: file changed size", target); ! 313: if (terminate (S_IFREG, NOTOK) < 0) ! 314: return; ! 315: } else { ! 316: if (terminate (S_IFREG, OK) < 0) ! 317: return; ! 318: } ! 319: done: ! 320: if (opts & COMPARE) ! 321: return; ! 322: dospecial: ! 323: for (sc = subcmds; sc != NULL; sc = sc->sc_next) { ! 324: if (sc->sc_type != SPECIAL) ! 325: continue; ! 326: #ifdef UW ! 327: if (opts & NOINSTALL) /* don't do specials associated with ! 328: non-installation notices */ ! 329: continue; ! 330: #endif UW ! 331: if (sc->sc_args != NULL && !inlist(sc->sc_args, target)) ! 332: continue; ! 333: log(lfp, "special \"%s\"\n", sc->sc_name); ! 334: if (opts & VERIFY) ! 335: continue; ! 336: (void) sprintf(buf, "FILE=%s;export FILE;%s", ! 337: target, sc->sc_name); ! 338: (void) runspecial (buf); ! 339: ! 340: } ! 341: } ! 342: ! 343: struct linkbuf * ! 344: savelink(sp, opts) ! 345: struct stat *sp; ! 346: int opts; ! 347: { ! 348: struct linkbuf *lp; ! 349: extern char *makestr (); ! 350: ! 351: for (lp = ihead; lp != NULL; lp = lp->nextp) ! 352: if (lp->inum == sp->st_ino && lp->devnum == sp->st_dev) { ! 353: lp->count--; ! 354: return(lp); ! 355: } ! 356: lp = (struct linkbuf *) malloc(sizeof(*lp)); ! 357: if (lp == NULL) ! 358: log(lfp, "out of memory, link information lost\n"); ! 359: else { ! 360: lp->nextp = ihead; ! 361: ihead = lp; ! 362: lp->inum = sp->st_ino; ! 363: lp->devnum = sp->st_dev; ! 364: lp->count = sp->st_nlink - 1; ! 365: if (opts & WHOLE) ! 366: lp->pathname = makestr (target); ! 367: else { ! 368: if (strncmp (target, basename, strlen(basename)) == 0) ! 369: lp -> pathname = makestr (target + ! 370: strlen(basename) + 1); ! 371: else ! 372: lp -> pathname = makestr (target); ! 373: } ! 374: ! 375: if (Tdest) ! 376: lp->target = makestr (Tdest); ! 377: else ! 378: *lp->target = 0; ! 379: } ! 380: return(NULL); ! 381: } ! 382: ! 383: update(rname, opts, sp) ! 384: char *rname; ! 385: int opts; ! 386: struct stat *sp; ! 387: { ! 388: off_t size; ! 389: time_t mtime; ! 390: unsigned short mode; ! 391: int retval; ! 392: ! 393: if (debug) ! 394: printf("update(%s, %x, %x)\n", rname, opts, sp); ! 395: ! 396: /* ! 397: * Check to see if the file exists on the remote machine. ! 398: */ ! 399: switch (retval = rquery (rname, &mtime, &size, &mode)) { ! 400: case DONE: /* file doesn't exist so install it */ ! 401: if ((opts & QUERYM) && !query ("Install", ! 402: (sp ->st_mode & S_IFMT), ! 403: NULLCP)) ! 404: return 0; ! 405: return(1); ! 406: ! 407: case NOTOK: /* something went wrong! */ ! 408: nerrs++; ! 409: return(0); ! 410: ! 411: case OK: ! 412: break; ! 413: ! 414: default: ! 415: advise (NULLCP, "update: unexpected response %d", retval); ! 416: return(0); ! 417: } ! 418: ! 419: if (mode == S_IFDIR) ! 420: return (2); ! 421: ! 422: if (opts & COMPARE) { ! 423: if ((opts & QUERYM) && !query ("Compare and update", mode, NULLCP)) ! 424: return 0; ! 425: return(3); ! 426: } ! 427: ! 428: /* ! 429: * File needs to be updated? ! 430: */ ! 431: if (opts & YOUNGER) { ! 432: if (sp->st_mtime == mtime) ! 433: return(0); ! 434: if (sp->st_mtime < mtime) { ! 435: log(lfp, "Warning: %s: remote copy is newer\n", target); ! 436: return(0); ! 437: } ! 438: } else if (sp->st_mtime == mtime && sp->st_size == size) ! 439: return(0); ! 440: if ((opts & QUERYM) && !query ("Update", ! 441: sp -> st_mode & S_IFMT, NULLCP)) ! 442: return 0; ! 443: return(2); ! 444: } ! 445: ! 446: ! 447: ! 448: /*VARARGS2*/ ! 449: log(fp, fmt, a1, a2, a3) ! 450: FILE *fp; ! 451: char *fmt; ! 452: int a1, a2, a3; ! 453: { ! 454: /* Print changes locally if not quiet mode */ ! 455: if (!qflag) ! 456: printf(fmt, a1, a2, a3); ! 457: ! 458: /* Save changes (for mailing) if really updating files */ ! 459: if (!(options & VERIFY) && fp != NULL) ! 460: fprintf(fp, fmt, a1, a2, a3); ! 461: } ! 462: ! 463: /* ! 464: * Remove temporary files and do any cleanup operations before exiting. ! 465: */ ! 466: cleanup() ! 467: { ! 468: (void) unlink(utmpfile); ! 469: exit(1); ! 470: } ! 471: ! 472: query (mess, mode, name) ! 473: int mode; ! 474: char *mess, *name; ! 475: { ! 476: char buf[BUFSIZ]; ! 477: char *cp; ! 478: ! 479: switch (mode) { ! 480: case S_IFDIR: ! 481: cp = "directory"; ! 482: break; ! 483: case 0: ! 484: case S_IFREG: ! 485: cp = "file"; ! 486: break; ! 487: case S_IFLNK: ! 488: cp = "symbolic link"; ! 489: break; ! 490: default: ! 491: cp = "unknown file type"; ! 492: break; ! 493: } ! 494: ! 495: (void) sprintf (buf, "%s %s %s? ", mess, cp, ! 496: name == NULLCP ? target : name); ! 497: for (;;) { ! 498: cp = getstring (buf); ! 499: if (cp == NULLCP) ! 500: continue; ! 501: if (*cp == 'y' || *cp == 'Y' || *cp == 'n' || *cp == 'N') ! 502: break; ! 503: } ! 504: ! 505: if (*cp == 'y' || *cp == 'Y') ! 506: return 1; ! 507: return 0; ! 508: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.