|
|
1.1 ! root 1: #include "parms.h" ! 2: #include "structs.h" ! 3: ! 4: #ifdef RCSIDENT ! 5: static char rcsid[] = "$Header: archiver.c,v 1.7.0.4 85/06/05 14:16:24 notes Rel $"; ! 6: #endif RCSIDENT ! 7: ! 8: /* ! 9: * archiver - archives a notesfile. Takes all articles older ! 10: * than 'daysold' days and places them, in generic format, in ! 11: * a sub-directory in the archie directory. The files are marked ! 12: * by the time that they were created. ! 13: * The deleteonly parameter is normally zero. If it is non-zero, ! 14: * no archive is taken; the old notes are merely thrown away. ! 15: * ! 16: * Ray Essick March 1982 ! 17: * ! 18: * modified so that could also toggle on the director message. ! 19: * in addition to the days untouched. ! 20: * Ray Essick June 1982 ! 21: * ! 22: * Now grabs an expiration threshold and a "working set size" ! 23: * from the notesfile itself. If zero, the values passed ! 24: * in as paramaters are used. ! 25: */ ! 26: ! 27: archiver (nfname, daysold, worksetsize, deleteonly, dirmsgflag) ! 28: char *nfname; ! 29: int daysold; ! 30: int worksetsize; ! 31: int deleteonly; ! 32: int dirmsgflag; ! 33: { ! 34: struct io_f io, ! 35: archio; ! 36: struct when_f zaptime; /* boundary time */ ! 37: struct note_f note; ! 38: struct note_f note2; ! 39: int i, ! 40: ncount, ! 41: rcount; ! 42: int dnotes, /* duplicates */ ! 43: dresps, /* in the archive */ ! 44: adopts; /* and adoptions */ ! 45: int deletable; /* how many can zap */ ! 46: int presps; ! 47: char line[WDLEN]; ! 48: char archdest[WDLEN]; /* target notesfile */ ! 49: char archbase[WDLEN]; /* target directory */ ! 50: char archend[WDLEN]; /* and nf name */ ! 51: char timeline[DATELEN]; ! 52: char *endname; ! 53: FILE * log; ! 54: int wasopen; ! 55: int locktarget; /* whether to */ ! 56: struct daddr_f where; ! 57: int rnum; /* copy responses */ ! 58: int newnum; /* note place in arch */ ! 59: int rblock, ! 60: roffset; ! 61: struct resp_f resp; ! 62: FILE * txtfile; /* for saving text */ ! 63: char txtfn[WDLEN]; /* its name */ ! 64: int dup_place; /* is in archive? */ ! 65: int dup_resp; /* dup supression */ ! 66: ! 67: if (init (&io, nfname) < 0) ! 68: return (-1); /* no notesfile */ ! 69: ! 70: ! 71: if (allow (&io, DRCTOK) == 0 && globuid != Notesuid) ! 72: { ! 73: closenf (&io); ! 74: printf ("Archiver: %s: You don't have permission to archive\n", ! 75: io.fullname); ! 76: fflush (stdout); ! 77: return (-1); ! 78: } ! 79: ! 80: if (io.descr.d_stat & ISARCH) /* can't archive an archive */ ! 81: { ! 82: closenf (&io); ! 83: printf ("Archiver: %s: You can't archive an archive\n", io.fullname); ! 84: fflush (stdout); ! 85: return (-1); ! 86: } ! 87: ! 88: /* ! 89: * select the archive name ! 90: */ ! 91: ! 92: switch (nfalias (io.fullname, archdest, ARCHALIAS)) ! 93: { ! 94: case -1: /* no file */ ! 95: case 0: /* no match */ ! 96: if (*nfname == '/') /* absolute path name */ ! 97: { ! 98: strcpy (archend, io.nf); /* get nf */ ! 99: strcpy (archbase, ARCHDIR); /* base directory */ ! 100: printf ("Archiver: WARNING: possible naming conflict in %s (%s)\n", ! 101: nfname, io.fullname); ! 102: fflush (stdout); ! 103: } ! 104: else ! 105: { ! 106: strcpy (archend, io.nf); ! 107: strcpy (archbase, ARCHDIR); /* base directory */ ! 108: } ! 109: break; ! 110: ! 111: case 1: /* an alias! */ ! 112: if (archdest[0] != '/') /* expand it */ ! 113: { ! 114: strcpy (archbase, ARCHDIR); ! 115: strcpy (archend, archdest); /* hold it */ ! 116: } ! 117: else ! 118: { ! 119: endname = rindex (archdest, '/'); ! 120: *endname++ = '\0'; /* split */ ! 121: strcpy (archbase, archdest); /* directory */ ! 122: strcpy (archend, endname); /* and nf */ ! 123: } ! 124: break; ! 125: ! 126: } ! 127: ! 128: sprintf (archdest, "%s/%s", archbase, archend); /* full name */ ! 129: sprintf (txtfn, "/tmp/nfa%d", getpid ()); /* hold texts */ ! 130: ncount = rcount = 0; /* count archived */ ! 131: dnotes = dresps = adopts = 0; /* duplicates */ ! 132: locktarget = 0; /* changed if should */ ! 133: ! 134: /* ! 135: * check notesfile specific thresholds, sizes and other options ! 136: */ ! 137: ! 138: if (io.descr.d_archtime == NEVER) /* don't archive */ ! 139: { ! 140: printf ("Archiver: %s has archive threshold of `never'\n", ! 141: nfname); ! 142: fflush (stdout); ! 143: goto docompress; /* compress anyway */ ! 144: } ! 145: ! 146: if (io.descr.d_archtime != 0) /* non-default */ ! 147: { ! 148: daysold = (int) io.descr.d_archtime; /* use this one */ ! 149: printf ("Archiver: %s specifies threshold of %d days\n", ! 150: nfname, daysold); ! 151: fflush (stdout); ! 152: } ! 153: ! 154: if (io.descr.d_workset != 0) ! 155: { ! 156: worksetsize = (int) io.descr.d_workset; ! 157: printf ("Archiver: %s specifies working set size of %d\n", ! 158: nfname, worksetsize); ! 159: fflush (stdout); ! 160: } ! 161: ! 162: if (io.descr.d_dmesgstat != DIRDFLT) /* specific */ ! 163: { ! 164: dirmsgflag = (int) io.descr.d_dmesgstat; /* set it */ ! 165: printf ("Archiver: %s specifies dirmsg status of %s for expiring\n", ! 166: nfname, ! 167: dirmsgflag == DIRON ? "ON" : ! 168: dirmsgflag == DIROFF ? "OFF" : ! 169: "NOCARE"); ! 170: fflush (stdout); ! 171: } ! 172: ! 173: if (io.descr.d_archkeep != KEEPDFLT) /* keep/delete */ ! 174: { ! 175: if (io.descr.d_archkeep == KEEPYES) ! 176: deleteonly = 0; ! 177: else ! 178: deleteonly = 1; ! 179: printf ("Archiver: %s specifies %s expired notes\n", ! 180: nfname, ! 181: deleteonly ? "deleting" : "archiving"); ! 182: fflush (stdout); ! 183: } ! 184: ! 185: deletable = ((int) io.descr.d_nnote) - ((int) io.descr.d_delnote) - worksetsize; ! 186: if (deletable <= 0) /* candidates? */ ! 187: { ! 188: if (io.descr.d_nnote - io.descr.d_delnote > 0) /* only if non-empty */ ! 189: { ! 190: printf ("Archiver: %s: %d notes <= working set size of %d\n", ! 191: nfname, ! 192: io.descr.d_nnote - io.descr.d_delnote, ! 193: worksetsize); ! 194: fflush (stdout); ! 195: } ! 196: goto docompress; ! 197: } ! 198: ! 199: gettime (&zaptime); /* threshold */ ! 200: zaptime.w_gmttime -= 60L * 60L * 24L * ((long) daysold);/* internal */ ! 201: maketime (&zaptime, zaptime.w_gmttime); /* re-format */ ! 202: ! 203: ! 204: if (!deleteonly) ! 205: { ! 206: if (init (&archio, archdest) < 0) /* not already */ ! 207: { ! 208: printf ("Archiver creating archive notesfile %s\n", archdest); ! 209: fflush (stdout); ! 210: if (buildnf (archend, archbase, 0, 0, 0) < 0)/* make one */ ! 211: { ! 212: printf ("Archiver: Problems creating %s for archival\n", ! 213: archdest); ! 214: fflush (stdout); ! 215: goto docompress; ! 216: } ! 217: if (init (&archio, archdest) < 0) /* and open it */ ! 218: { ! 219: printf ("Archiver: Problems opening %s for archival\n", ! 220: archdest); ! 221: fflush (stdout); ! 222: goto docompress; ! 223: } ! 224: locknf (&archio, DSCRLOCK); /* watch conflicts */ ! 225: getdscr (&archio, &archio.descr); ! 226: archio.descr.d_stat |= ISARCH + OPEN; ! 227: putdscr (&archio, &archio.descr); ! 228: unlocknf (&archio, DSCRLOCK); ! 229: /* ! 230: * Copy the active notesfile's access list to ! 231: * the archive notesfile. ! 232: */ ! 233: { ! 234: #ifdef FASTFORK ! 235: char old[WDLEN]; ! 236: char new[WDLEN]; ! 237: sprintf (old, "%s/%s/%s", io.basedir, io.nf, ACCESS); ! 238: sprintf (new, "%s/%s/%s", archio.basedir, archio.nf, ACCESS); ! 239: dounix (0, 0, "/bin/cp", old, new, 0, 0); ! 240: #else ! FASTFORK ! 241: char cmdline[WDLEN + WDLEN + 10]; ! 242: sprintf (cmdline, "%s %s/%s/%s %s/%s/%s", ! 243: "/bin/cp", ! 244: io.basedir, io.nf, ACCESS, ! 245: archio.basedir, archio.nf, ACCESS); ! 246: dounix (cmdline, 0, 0); ! 247: #endif ! FASTFORK ! 248: } ! 249: } ! 250: ! 251: locktarget = strcmp (io.nf, archio.nf); /* lock if differ */ ! 252: ! 253: ! 254: if (!(archio.descr.d_stat & ISARCH)) /* into archive? */ ! 255: { ! 256: printf ("Archiver: %s: Target %s is not an archive\n", ! 257: nfname, archdest); ! 258: fflush (stdout); ! 259: closenf (&archio); /* close that */ ! 260: goto docompress; /* compress him anyway */ ! 261: } ! 262: } ! 263: ! 264: ! 265: #ifdef OLDGROUP ! 266: /* ! 267: * This code looks at the directory to see if the notesfile ! 268: * has been idle long enough to be deleted. ! 269: * ! 270: * This code hasn't been tested by me. It works in the ! 271: * Salkind/Spickelmier version. ! 272: * ! 273: * Should stuff a "wait-till-expire" in the master descriptor ! 274: * of each notesfile so "junk" ones can expire faster or ! 275: * something like that. Essentially we want the age at which ! 276: * the notesfile is deleted to be grabbed from the notesfile ! 277: * itself. ! 278: * ! 279: * My personal opinion is that they shouldn't disappear ! 280: * auto-magically ! 281: * NOTE: this probably no longer works with the ! 282: * changes I've made to archiving. (Dec '83) ! 283: * ! 284: * N.B. Need some locking in here ! 285: */ ! 286: ! 287: /* delete inactive groups - RLS 1/8/83 */ ! 288: ! 289: sprintf (line, "%s/%s", MSTDIR, nfname); ! 290: stat (line, &buf); ! 291: current = time (0); ! 292: if (current - buf.st_mtime > 60 * 60 * 24 * (OLDGROUP - daysold)) ! 293: { ! 294: finish (&io); ! 295: ! 296: sprintf (line, "/bin/rm -rf %s/%s", MSTDIR, nfname); ! 297: system (line); ! 298: ! 299: gettime (&zaptime); ! 300: sprdate (&zaptime, timeline); ! 301: ! 302: /* message in nfmaint */ ! 303: sprintf (line, "Archiver: removed %s\n", nfname); ! 304: nfcomment (NOSUCHWARN, line, line, 0, 0); ! 305: ! 306: sprintf (line, "%s/%s/%s", MSTDIR, UTILITY, NETLOG); ! 307: x ((log = fopen (line, "a")) == NULL, "archiver: no logfile"); ! 308: fprintf (log, "Archiver: deleted %s at %s\n", nfname, timeline); ! 309: printf ("Archiver: deleted %s at %s\n", nfname, timeline); ! 310: fclose (log); ! 311: fflush (stdout); ! 312: return (0); ! 313: } ! 314: #endif OLDGROUP ! 315: ! 316: ! 317: locknf (&io, DSCRLOCK); /* MUTEX */ ! 318: if (locktarget) /* and target */ ! 319: locknf (&archio, DSCRLOCK); ! 320: getdscr (&io, &io.descr); ! 321: wasopen = io.descr.d_stat & OPEN; /* hold this */ ! 322: io.descr.d_stat &= NOT OPEN; /* privacy */ ! 323: putdscr (&io, &io.descr); ! 324: ! 325: for (i = 1; i <= io.descr.d_nnote && deletable; i++) ! 326: { ! 327: getnrec (&io, i, ¬e); ! 328: if (note.n_stat & DELETED) ! 329: continue; /* gone already */ ! 330: if (dirmsgflag == DIROFF && (note.n_stat & DIRMES)) ! 331: continue; /* don't if dir on */ ! 332: if (dirmsgflag == DIRON && (note.n_stat & DIRMES) == 0) ! 333: continue; /* don't if dir off */ ! 334: if (inorder (&zaptime, ¬e.n_lmod)) ! 335: continue; /* too recent */ ! 336: presps = note.n_nresp; /* response count */ ! 337: if (!deleteonly) /* save it? */ ! 338: { ! 339: /* ! 340: * check to see if this one is already in the archive ! 341: */ ! 342: dup_place = chknote (&archio, ¬e.n_id, ¬e2);/* already there? */ ! 343: if (dup_place == 0) /* not there */ ! 344: { ! 345: /* ! 346: * This code copied almost verbatim from compression routines ! 347: */ ! 348: #ifdef notdef ! 349: x ((txtfile = fopen (txtfn, "w")) == NULL, "archiver:bad txt"); ! 350: pageout (&io, ¬e.n_addr, txtfile); ! 351: fclose (txtfile); ! 352: x ((txtfile = fopen (txtfn, "r")) == NULL, "archiver: txt read"); ! 353: pagein (&archio, txtfile, &where); ! 354: fclose (txtfile); ! 355: #else ! 356: pagemove (&io, ¬e.n_addr, &archio, &where, LOCKIT); ! 357: #endif ! 358: newnum = putnote (&archio, &where, note.ntitle, note.n_stat, ¬e, ! 359: ¬e.n_auth, NOPOLICY, NOLOCKIT, NOADDID, note.n_from, NOADDTIME); ! 360: getnrec (&archio, newnum, ¬e2); /* get copy */ ! 361: } ! 362: else ! 363: { ! 364: if ((note2.n_stat & ORPHND) && /* archived is foster */ ! 365: !(note.n_stat & ORPHND)) /* and active isn't */ ! 366: { ! 367: #ifdef notdef ! 368: x ((txtfile = fopen (txtfn, "w")) == NULL, "archiver:bad txt"); ! 369: pageout (&io, ¬e.n_addr, txtfile); ! 370: fclose (txtfile); ! 371: x ((txtfile = fopen (txtfn, "r")) == NULL, "archiver: txt read"); ! 372: pagein (&archio, txtfile, &where); ! 373: fclose (txtfile); ! 374: #else ! 375: pagemove (&io, ¬e.n_addr, &archio, &where, LOCKIT); ! 376: #endif ! 377: ! 378: note.n_nresp = note2.n_nresp; /* save resp chain */ ! 379: note.n_rindx = note2.n_rindx; ! 380: note.n_addr = where; /* get text pointer */ ! 381: putnrec (&archio, dup_place, ¬e);/* replace descriptor */ ! 382: note2 = note; /* save good copy */ ! 383: adopts++; /* count 'em */ ! 384: } ! 385: else ! 386: { ! 387: dnotes++; /* count duplicate */ ! 388: } ! 389: newnum = dup_place; /* for linking resps */ ! 390: } ! 391: ! 392: for (rnum = 1; rnum <= presps; rnum++) /* process responses */ ! 393: { ! 394: if (lrsp (&io, i, rnum, &resp, &roffset, &rblock) != 0) ! 395: break; /* bad response chain - drop rest */ ! 396: if (dup_place) /* better check... */ ! 397: { ! 398: dup_resp = chkresp (&archio, &resp.r_id[roffset], ¬e2, newnum); ! 399: if (dup_resp) /* already there */ ! 400: { ! 401: dresps++; /* count doubles */ ! 402: continue; /* skip this response */ ! 403: } ! 404: } ! 405: #ifdef notdef ! 406: x ((txtfile = fopen (txtfn, "w")) == NULL, "compress:bad txt"); ! 407: pageout (&io, &resp.r_addr[roffset], txtfile); ! 408: fclose (txtfile); ! 409: x ((txtfile = fopen (txtfn, "r")) == NULL, "compress: bad txt read"); ! 410: pagein (&archio, txtfile, &where); ! 411: fclose (txtfile); ! 412: #else ! 413: pagemove (&io, &resp.r_addr[roffset], &archio, &where, LOCKIT); ! 414: #endif ! 415: putresp (&archio, &where, resp.r_stat[roffset], newnum, &resp.r_when[roffset], ! 416: &resp.r_auth[roffset], ¬e, NOLOCKIT, &resp.r_id[roffset], ! 417: NOADDID, resp.r_from[roffset], NOADDTIME, &resp.r_rcvd[roffset]); ! 418: } ! 419: } ! 420: delnote (&io, i, NOLOCKIT); /* delete entry */ ! 421: ncount++; ! 422: rcount += presps; /* and responses */ ! 423: deletable--; /* one down */ ! 424: } ! 425: ! 426: unlocknf (&io, DSCRLOCK); /* Un MUTEX */ ! 427: if (locktarget) /* and the target */ ! 428: unlocknf (&archio, DSCRLOCK); ! 429: ! 430: if (!deleteonly) ! 431: { ! 432: finish (&archio); /* close target */ ! 433: unlink (txtfn); /* don't litter */ ! 434: } ! 435: ! 436: /* ! 437: * Time to compress the notesfile and eliminate those ! 438: * unsightly holes in the data structure. ! 439: */ ! 440: docompress: ! 441: ! 442: locknf (&io, DSCRLOCK); /* MUTEX */ ! 443: if (io.descr.d_nnote != 0) /* non-empty */ ! 444: { ! 445: if (io.descr.d_delnote != 0 || io.descr.d_delresp != 0) ! 446: { /* has holes */ ! 447: int nnote, ! 448: nresp; ! 449: compress (&io, NOLOCKIT, 0, &nnote, &nresp); ! 450: printf ("Archiver: %s contains (%d,%d) after compress\n", ! 451: nfname, nnote, nresp); ! 452: fflush (stdout); ! 453: } ! 454: else /* no holes so */ ! 455: { /* don't compress */ ! 456: printf ("Archiver: %s already compressed\n", nfname); ! 457: fflush (stdout); ! 458: } ! 459: } ! 460: else /* nothing there to */ ! 461: { /* compress */ ! 462: printf ("Archiver: %s is empty.\n", nfname); ! 463: fflush (stdout); ! 464: } ! 465: ! 466: ! 467: if (wasopen) /* if it was already */ ! 468: { ! 469: getdscr (&io, &io.descr); /* open season */ ! 470: io.descr.d_stat |= OPEN; ! 471: putdscr (&io, &io.descr); /* replace in file */ ! 472: } ! 473: ! 474: unlocknf (&io, DSCRLOCK); /* all done with this */ ! 475: finish (&io); /* and close the notesfile */ ! 476: ! 477: gettime (&zaptime); ! 478: sprdate (&zaptime, timeline); ! 479: if (ncount) /* log only if did somethine */ ! 480: { ! 481: sprintf (line, "%s/%s/%s", Mstdir, UTILITY, NETLOG); ! 482: x ((log = fopen (line, "a")) == NULL, "archiver: no logfile"); ! 483: if (!deleteonly) ! 484: fprintf (log, "%s: archived (%d,%d) [%d,%d dups, %d adopted] into %s at %s\n", ! 485: nfname, ncount, rcount, dnotes, dresps, adopts, archdest, timeline); ! 486: else ! 487: fprintf (log, "%s: Archiver deleted (%d,%d) at %s\n", ! 488: nfname, ncount, rcount, timeline); ! 489: fclose (log); ! 490: } ! 491: ! 492: if (!deleteonly) ! 493: { ! 494: if (ncount) ! 495: printf ("Archiver: %s: (%d,%d) [%d,%d dups, %d adoptions] into %s at %s\n", ! 496: nfname, ncount, rcount, dnotes, dresps, adopts, archdest, timeline); ! 497: else ! 498: printf ("Archiver: %s: no notes archived\n", ! 499: nfname); ! 500: } ! 501: else ! 502: printf ("Archiver: %s: deleted (%d,%d) at %s\n", ! 503: nfname, ncount, rcount, timeline); ! 504: fflush (stdout); ! 505: return (0); /* and return */ ! 506: ! 507: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.