|
|
1.1 ! root 1: /* idistd2.c -- the non remote operations parts of the protocol */ ! 2: ! 3: /* ! 4: * $Header: /f/osi/others/idist/RCS/idistd2.c,v 7.0 89/11/23 21:58:33 mrose Rel $ ! 5: * ! 6: * Parts of the idist server which are not mixed up with remote ! 7: * operations but depend on the defined types. ! 8: * ! 9: * Julian Onions <[email protected]> ! 10: * Nottingham University Computer Science. ! 11: * ! 12: * ! 13: * $Log: idistd2.c,v $ ! 14: * Revision 7.0 89/11/23 21:58:33 mrose ! 15: * Release 6.0 ! 16: * ! 17: */ ! 18: ! 19: #ifndef lint ! 20: static char *rcsid = "$Header: /f/osi/others/idist/RCS/idistd2.c,v 7.0 89/11/23 21:58:33 mrose Rel $"; ! 21: #endif ! 22: ! 23: #include "defs.h" ! 24: #include "Idist-types.h" ! 25: ! 26: char *tp, *stp[128]; ! 27: ! 28: extern int catname; ! 29: extern char target[]; ! 30: extern FILE *cfile; ! 31: extern struct type_Idist_FileSpec *cfiletype; ! 32: extern int oumask; ! 33: extern char utmpfile[]; ! 34: extern char *tmpname; ! 35: extern struct type_Idist_IA5List *ia5list; ! 36: ! 37: static char *cannon (); ! 38: static struct type_Idist_IA5List *str2ia5list (); ! 39: static int compare (); ! 40: extern struct type_Idist_FileSpec *makefs (); ! 41: extern struct type_Idist_QueryResult *query (); ! 42: extern struct type_Idist_FileList *do_listcdir (); ! 43: ! 44: doexec (cmd) ! 45: char *cmd; ! 46: { ! 47: int fd[2], status, pid, i; ! 48: char buf[BUFSIZ]; ! 49: ! 50: if (pipe(fd) < 0) ! 51: return NOTOK; ! 52: ! 53: if ((pid = vfork ()) == 0) { ! 54: /* ! 55: * Return everything the shell commands print. ! 56: */ ! 57: (void) close(0); ! 58: (void) close(1); ! 59: (void) close(2); ! 60: (void) open("/dev/null", 0); ! 61: (void) dup(fd[1]); ! 62: (void) dup(fd[1]); ! 63: (void) close(fd[0]); ! 64: (void) close(fd[1]); ! 65: execl("/bin/sh", "sh", "-c", cmd, 0); ! 66: _exit(127); ! 67: } ! 68: if (pid == -1) ! 69: return NOTOK; ! 70: ! 71: (void) close(fd[1]); ! 72: ! 73: while ((i = read(fd[0], buf, sizeof(buf))) > 0) { ! 74: addtoia5 (buf, i); ! 75: } ! 76: ! 77: while ((i = wait(&status)) != pid && i != -1) ! 78: ; ! 79: if (i == -1) ! 80: status = -1; ! 81: (void) close(fd[0]); ! 82: ! 83: return OK; ! 84: } ! 85: ! 86: do_symlink (fs) ! 87: struct type_Idist_FileSpec *fs; ! 88: { ! 89: char *new, old[BUFSIZ], *linkname; ! 90: int i; ! 91: ! 92: new = qb2str (fs -> filename); ! 93: linkname = cannon (new); ! 94: free (new); ! 95: ! 96: new = qb2str (fs -> linkname); ! 97: (void) strcpy (old, new); ! 98: free (new); ! 99: ! 100: ! 101: if (symlink (old, linkname) < 0) { ! 102: if (errno != ENOENT || chkparent (linkname) < 0 || ! 103: symlink (old, linkname) < 0) { ! 104: nadvise (linkname, "Can't symlink %s to", old); ! 105: return NOTOK; ! 106: } ! 107: } ! 108: ! 109: if (bit_on (fs -> fileopts, bit_Idist_Options_compare)) { ! 110: char tbuf[BUFSIZ]; ! 111: ! 112: if ((i = readlink (target, tbuf, BUFSIZ)) >= 0 && ! 113: i == fs -> filesize && ! 114: strncmp (old, tbuf, fs -> filesize) == 0) { ! 115: (void) unlink (linkname); ! 116: return OK; ! 117: } ! 118: if (bit_on (fs -> fileopts, bit_Idist_Options_verify)) { ! 119: (void) unlink (linkname); ! 120: note ("need to update: %s", target); ! 121: return OK; ! 122: } ! 123: } ! 124: ! 125: if (rename (linkname, target) < 0) { ! 126: nadvise (target, "can't rename %s to", linkname); ! 127: (void) unlink (linkname); ! 128: return NOTOK; ! 129: } ! 130: if (bit_on (fs -> fileopts, bit_Idist_Options_compare)) ! 131: note ("updated %s\n", target); ! 132: return OK; ! 133: } ! 134: ! 135: static char *cannon (name) ! 136: char *name; ! 137: { ! 138: static char nname[BUFSIZ]; ! 139: char *cp; ! 140: extern char *tmpname; ! 141: ! 142: if (catname) ! 143: (void) sprintf (tp, "/%s", name); ! 144: if((cp = rindex (target, '/')) == NULL) ! 145: (void) strcpy (nname, tmpname); ! 146: else if (cp == target) ! 147: (void) sprintf (nname, "/%s", tmpname); ! 148: else { ! 149: *cp = '\0'; ! 150: (void) sprintf (nname, "%s/%s", target, tmpname); ! 151: *cp = '/'; ! 152: } ! 153: return nname; ! 154: } ! 155: ! 156: /* ! 157: * Check to see if parent directory exists and create one if not. ! 158: */ ! 159: chkparent(name) ! 160: char *name; ! 161: { ! 162: register char *cp; ! 163: struct stat stb; ! 164: ! 165: cp = rindex(name, '/'); ! 166: if (cp == NULL || cp == name) ! 167: return(0); ! 168: *cp = '\0'; ! 169: if (lstat(name, &stb) < 0) { ! 170: if (errno == ENOENT && chkparent(name) >= 0 && ! 171: mkdir(name, 0777 & ~oumask) >= 0) { ! 172: *cp = '/'; ! 173: return(0); ! 174: } ! 175: } else if (ISDIR(stb.st_mode)) { ! 176: *cp = '/'; ! 177: return(0); ! 178: } ! 179: *cp = '/'; ! 180: return(-1); ! 181: } ! 182: ! 183: do_rfile (fs) ! 184: struct type_Idist_FileSpec *fs; ! 185: { ! 186: char *name, *p; ! 187: ! 188: p = qb2str (fs -> filename); ! 189: name = cannon (p); ! 190: free (p); ! 191: ! 192: if ((cfile = fopen (name, "w")) == NULL) { ! 193: if (errno != ENOENT || chkparent (name) < 0 || ! 194: (cfile = fopen (name, "w")) == NULL) { ! 195: nadvise (name, "Can't create file"); ! 196: return NOTOK; ! 197: } ! 198: } ! 199: (void) fchmod (fileno (cfile), fs -> filemode); ! 200: ! 201: return OK; ! 202: } ! 203: ! 204: do_hardlink (fs) ! 205: struct type_Idist_FileSpec *fs; ! 206: { ! 207: char *new; ! 208: char *cp; ! 209: char old[BUFSIZ]; ! 210: struct stat stb; ! 211: int exists = 0; ! 212: ! 213: new = qb2str (fs -> filename); ! 214: cp = qb2str (fs -> linkname); ! 215: if (exptilde (old, cp) == NULL) { ! 216: free (cp); ! 217: free (new); ! 218: return NOTOK; ! 219: } ! 220: free (cp); ! 221: ! 222: if (catname) ! 223: (void) sprintf (tp, "/%s", new); ! 224: free (new); ! 225: ! 226: if (lstat(target, &stb) == 0) { ! 227: int mode = stb.st_mode & S_IFMT; ! 228: if (mode != S_IFREG && mode != S_IFLNK) { ! 229: nadvise (NULLCP, "%s: not a regular file", ! 230: host, target); ! 231: return NOTOK; ! 232: } ! 233: exists = 1; ! 234: } ! 235: if (chkparent(target) < 0 ) { ! 236: nadvise("chkparent", "%s (no parent)", target); ! 237: return NOTOK; ! 238: } ! 239: if (exists && (unlink(target) < 0)) { ! 240: nadvise ("unlink", "%s", target); ! 241: return NOTOK; ! 242: } ! 243: if (link(old, target) < 0) { ! 244: nadvise (old, "can't link %s to", target); ! 245: return NOTOK; ! 246: } ! 247: return OK; ! 248: } ! 249: ! 250: do_direct (fs) ! 251: struct type_Idist_FileSpec *fs; ! 252: { ! 253: char *cp, *name; ! 254: struct stat stb; ! 255: ! 256: cp = name = qb2str (fs -> filename); ! 257: ! 258: if (catname >= sizeof(stp)) { ! 259: nadvise (NULLCP, "Too many directory levels"); ! 260: free (name); ! 261: return NOTOK; ! 262: } ! 263: ! 264: stp[catname] = tp; ! 265: if (catname++) { ! 266: *tp ++ = '/'; ! 267: while (*tp++ = *cp ++) ! 268: ; ! 269: tp --; ! 270: } ! 271: ! 272: if (bit_on (fs -> fileopts, bit_Idist_Options_verify)) { ! 273: free (name); ! 274: return OK; ! 275: } ! 276: ! 277: if (lstat (target, &stb) == 0) { ! 278: if ((stb.st_mode & S_IFMT) == S_IFDIR) { ! 279: if ((stb.st_mode & 07777) == fs -> filemode) { ! 280: free (name); ! 281: return OK; ! 282: } ! 283: note ("%s remote node %o != local mode %o", ! 284: target, stb.st_mode & 07777, fs -> filemode); ! 285: free (name); ! 286: return OK; ! 287: } ! 288: errno = ENOTDIR; ! 289: } ! 290: else if (errno == ENOENT && (mkdir (target, fs -> filemode) == 0 || ! 291: chkparent (target) == 0 && ! 292: mkdir (target, fs -> filemode) == 0)) { ! 293: char *owner = qb2str (fs -> fileowner); ! 294: char *group = qb2str (fs -> filegroup); ! 295: ! 296: if (chog (target, owner, group, fs -> filemode) == 0) { ! 297: free (owner); ! 298: free (group); ! 299: free (name); ! 300: return OK; ! 301: } ! 302: free (owner); ! 303: free (group); ! 304: } ! 305: free (name); ! 306: nadvise (target, "Can't install directory"); ! 307: tp = stp[--catname]; ! 308: *tp = '\0'; ! 309: return NOTOK; ! 310: } ! 311: ! 312: /* ! 313: * Remove a file or directory (recursively) and send back an acknowledge ! 314: * or an error message. ! 315: */ ! 316: remove(str) ! 317: char *str; ! 318: { ! 319: DIR *d; ! 320: struct direct *dp; ! 321: struct stat stb; ! 322: char buf[BUFSIZ]; ! 323: int result = OK; ! 324: ! 325: if (lstat (str, &stb) < 0) { ! 326: nadvise (str, "Can't stat file"); ! 327: return NOTOK; ! 328: } ! 329: ! 330: switch (stb.st_mode & S_IFMT) { ! 331: case S_IFREG: ! 332: case S_IFLNK: ! 333: if (unlink(str) < 0) { ! 334: nadvise (str, "Can't unlink"); ! 335: return NOTOK; ! 336: } ! 337: note ("removed: %s", str); ! 338: return OK; ! 339: ! 340: case S_IFDIR: ! 341: break; ! 342: ! 343: default: ! 344: nadvise (NULLCP, "%s: not a plain file", target); ! 345: return NOTOK; ! 346: } ! 347: ! 348: if ((d = opendir(str)) == NULL) { ! 349: nadvise (str, "Can't open directory"); ! 350: return NOTOK; ! 351: } ! 352: ! 353: while (dp = readdir(d)) { ! 354: if (strcmp(dp->d_name, ".") == 0 || ! 355: strcmp(dp->d_name, "..") == 0) ! 356: continue; ! 357: (void) sprintf (buf, "%s/%s", str, dp -> d_name); ! 358: result = remove(buf) == OK ? result : NOTOK; ! 359: } ! 360: closedir(d); ! 361: if (rmdir(str) < 0) { ! 362: nadvise (str, "Can't remove directory", str); ! 363: return NOTOK; ! 364: } ! 365: note ("removed: %s", str); ! 366: return result; ! 367: } ! 368: ! 369: ! 370: addtoia5 (str, len) ! 371: char *str; ! 372: int len; ! 373: { ! 374: struct type_Idist_IA5List **ia5p; ! 375: ! 376: for (ia5p = &ia5list; *ia5p; ia5p = &(*ia5p) -> next) ! 377: continue; ! 378: ! 379: *ia5p = str2ia5list (str, len); ! 380: } ! 381: ! 382: struct type_Idist_QueryResult *query (str) ! 383: char *str; ! 384: { ! 385: struct type_Idist_QueryResult *qr; ! 386: struct stat stb; ! 387: ! 388: qr = (struct type_Idist_QueryResult *) malloc (sizeof *qr); ! 389: if (qr == NULL) ! 390: adios ("memory", "out of"); ! 391: ! 392: if (catname) ! 393: (void) sprintf (tp, "/%s", str); ! 394: ! 395: if (lstat (target, &stb) < 0) { ! 396: if (errno == ENOENT) { ! 397: qr -> offset = type_Idist_QueryResult_doesntExist; ! 398: } ! 399: else { ! 400: nadvise ("failed", "lstat"); ! 401: free (( char *) qr); ! 402: qr = NULL; ! 403: } ! 404: *tp = '\0'; ! 405: return qr; ! 406: } ! 407: qr -> offset = type_Idist_QueryResult_doesExist; ! 408: switch (stb.st_mode & S_IFMT) { ! 409: case S_IFREG: ! 410: case S_IFDIR: ! 411: case S_IFLNK: ! 412: qr -> un.doesExist = makefs (stb.st_mode & S_IFMT, 0, ! 413: stb.st_mode & 07777, stb.st_size, ! 414: stb.st_mtime, "", "", str, ""); ! 415: break; ! 416: ! 417: default: ! 418: nadvise (NULLCP, "%s: not a file or directory", str); ! 419: free ((char *)qr); ! 420: qr = NULL; ! 421: } ! 422: *tp = '\0'; ! 423: return qr; ! 424: } ! 425: ! 426: static struct type_Idist_IA5List *str2ia5list (s, len) ! 427: char *s; ! 428: int len; ! 429: { ! 430: register struct type_Idist_IA5List *ia5; ! 431: ! 432: if ((ia5 = (struct type_Idist_IA5List *) calloc (1, sizeof *ia5)) ! 433: == NULL) ! 434: return NULL; ! 435: ! 436: if ((ia5 -> IA5String = str2qb (s, len, 1)) == NULL) { ! 437: free ((char *) ia5); ! 438: return NULL; ! 439: } ! 440: ! 441: return ia5; ! 442: } ! 443: ! 444: struct type_Idist_FileList *do_listcdir () ! 445: { ! 446: DIR *d; ! 447: register struct direct *dp; ! 448: struct type_Idist_FileList *base, **flp; ! 449: char buf[BUFSIZ]; ! 450: struct stat stb; ! 451: ! 452: base = NULL; ! 453: flp = &base; ! 454: ! 455: if ((d = opendir (target)) == NULL) { ! 456: nadvise (target, "Can't open directory"); ! 457: return NULL; ! 458: } ! 459: ! 460: while (dp = readdir (d)) { ! 461: if (strcmp (dp -> d_name, ".") == 0 || ! 462: strcmp (dp -> d_name, "..") == 0) ! 463: continue; ! 464: (void) sprintf (buf, "%s/%s", target, dp -> d_name); ! 465: if (lstat (buf, &stb) < 0) { ! 466: nadvise (buf, "Can't stat"); ! 467: continue; ! 468: } ! 469: switch (stb.st_mode & S_IFMT) { ! 470: case S_IFDIR: ! 471: case S_IFLNK: ! 472: case S_IFREG: ! 473: break; ! 474: default: /* skip sockets, fifos et al... */ ! 475: continue; ! 476: } ! 477: if ((*flp = (struct type_Idist_FileList *) ! 478: malloc (sizeof **flp)) == NULL) ! 479: adios ("memory", "out of"); ! 480: ! 481: (*flp) -> FileSpec = makefs (stb.st_mode & S_IFMT, 0, ! 482: stb.st_mode & 07777, stb.st_size, ! 483: stb.st_mtime, "", "", ! 484: dp->d_name, ""); ! 485: (*flp) -> next = NULL; ! 486: flp = &(*flp) -> next; ! 487: } ! 488: closedir (d); ! 489: return base; ! 490: } ! 491: ! 492: fixup () ! 493: { ! 494: struct timeval tvp[2]; ! 495: char *new, *p; ! 496: char *owner, *group; ! 497: long convtime (); ! 498: ! 499: p = qb2str (cfiletype -> filename); ! 500: new = cannon (p); ! 501: free (p); ! 502: ! 503: if (bit_on (cfiletype -> fileopts, bit_Idist_Options_compare)) { ! 504: if (compare (target, new) == OK) { ! 505: (void) unlink (new); ! 506: return OK; ! 507: } ! 508: if (bit_on (cfiletype -> fileopts, bit_Idist_Options_verify)) { ! 509: (void) unlink (new); ! 510: note ("need to update: %s", target); ! 511: return OK; ! 512: } ! 513: } ! 514: ! 515: tvp[1].tv_sec = ! 516: tvp[0].tv_sec = ! 517: convtime (cfiletype -> filemtime); ! 518: tvp[0].tv_usec = tvp[1].tv_usec = 0; ! 519: if (utimes (new, tvp) < 0) ! 520: nadvise (new, "utimes failed on"); ! 521: ! 522: owner = qb2str (cfiletype -> fileowner); ! 523: group = qb2str (cfiletype -> filegroup); ! 524: ! 525: if (chog (new, owner, group, cfiletype -> filemode) < 0) { ! 526: free (owner); ! 527: free (group); ! 528: (void) unlink (new); ! 529: return NOTOK; ! 530: } ! 531: free (owner); ! 532: free (group); ! 533: ! 534: if (rename (new, target) < 0) { ! 535: nadvise (target, "Can't rename %s to", new); ! 536: return NOTOK; ! 537: } ! 538: if (bit_on (cfiletype -> fileopts, bit_Idist_Options_compare)) ! 539: note ("updated %s", target); ! 540: free_Idist_FileSpec (cfiletype); ! 541: cfiletype = NULL; ! 542: return OK; ! 543: } ! 544: ! 545: static int compare (f1, f2) ! 546: char *f1, *f2; ! 547: { ! 548: FILE *fp1, *fp2; ! 549: char buf1[BUFSIZ], buf2[BUFSIZ]; /* these two had ! 550: better be identical */ ! 551: int n1, n2; ! 552: ! 553: if ((fp1 = fopen (f1, "r")) == NULL) { ! 554: nadvise (f1, "Can't reopen file"); ! 555: return NOTOK; ! 556: } ! 557: if ((fp2 = fopen (f2, "r")) == NULL) { ! 558: nadvise (f2, "Can't reopend file"); ! 559: (void) fclose (fp1); ! 560: return NOTOK; ! 561: } ! 562: for (;;) { ! 563: n1 = fread (buf1, sizeof buf1[0], sizeof buf1, fp1); ! 564: n2 = fread (buf2, sizeof buf2[0], sizeof buf2, fp2); ! 565: if (n1 != n2 || n1 == 0) ! 566: break; ! 567: if (bcmp (buf1, buf2, n1) != 0) ! 568: break; ! 569: } ! 570: ! 571: (void) fclose (fp1); ! 572: (void) fclose (fp2); ! 573: return n1 == 0 ? OK : NOTOK; ! 574: } ! 575: ! 576: ! 577: /* ! 578: * Change owner, group and mode of file. ! 579: */ ! 580: chog(file, owner, group, mode) ! 581: char *file, *owner, *group; ! 582: int mode; ! 583: { ! 584: register int i; ! 585: int uid, gid; ! 586: extern char user[]; ! 587: extern int userid; ! 588: ! 589: uid = userid; ! 590: if (userid == 0) { ! 591: if (*owner == ':') { ! 592: uid = atoi(owner + 1); ! 593: } else if (pw == NULL || strcmp(owner, pw->pw_name) != 0) { ! 594: if ((pw = getpwnam(owner)) == NULL) { ! 595: if (mode & 04000) { ! 596: note("%s: unknown login name, clearing setuid", ! 597: host, owner); ! 598: mode &= ~04000; ! 599: uid = 0; ! 600: } ! 601: } else ! 602: uid = pw->pw_uid; ! 603: } else ! 604: uid = pw->pw_uid; ! 605: if (*group == ':') { ! 606: gid = atoi(group + 1); ! 607: goto ok; ! 608: } ! 609: } else if ((mode & 04000) && strcmp(user, owner) != 0) ! 610: mode &= ~04000; ! 611: gid = -1; ! 612: if (gr == NULL || strcmp(group, gr->gr_name) != 0) { ! 613: if ((*group == ':' && (getgrgid(gid = atoi(group + 1)) == NULL)) ! 614: || ((gr = getgrnam(group)) == NULL)) { ! 615: if (mode & 02000) { ! 616: note("%s: unknown group", group); ! 617: mode &= ~02000; ! 618: } ! 619: } else ! 620: gid = gr->gr_gid; ! 621: } else ! 622: gid = gr->gr_gid; ! 623: if (userid && gid >= 0) { ! 624: if (gr) for (i = 0; gr->gr_mem[i] != NULL; i++) ! 625: if (!(strcmp(user, gr->gr_mem[i]))) ! 626: goto ok; ! 627: mode &= ~02000; ! 628: gid = -1; ! 629: } ! 630: ok: ! 631: if (userid == 0 && chown(file, uid, gid) < 0 ) ! 632: nadvise (file, "chown failed on"); ! 633: if ((mode & 06000) && chmod(file, mode) < 0) { ! 634: nadvise (file, "chmod to 0%o failed on", mode); ! 635: } ! 636: return(0); ! 637: } ! 638: ! 639: cleanup () ! 640: { ! 641: char *p, *temp; ! 642: ! 643: if (cfiletype) { ! 644: p = qb2str (cfiletype -> filename); ! 645: temp = cannon (p); ! 646: (void) unlink (temp); ! 647: } ! 648: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.