# 2.11BSD#431 - /usr/src/new/notes/src/archiver.c

##### Functions

    archiver          X

       1: #include "parms.h"
       2: #include "structs.h"
       3:
       4: #ifdef  RCSIDENT
       5: static char rcsid[] = "$Header: archiver.c,v 1.7.0.6 86/01/25 22:54:08 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:         dirmsgflag == DIRANYON ? "ANYON" :
     170:         "NOCARE");
     171:     fflush (stdout);
     172:     }
     173:
     174:     if (io.descr.d_archkeep != KEEPDFLT)        /* keep/delete */
     175:     {
     176:     if (io.descr.d_archkeep == KEEPYES)
     177:         deleteonly = 0;
     178:     else
     179:         deleteonly = 1;
     180:     printf ("Archiver: %s specifies %s expired notes\n",
     181:         nfname,
     182:         deleteonly ? "deleting" : "archiving");
     183:     fflush (stdout);
     184:     }
     185:
     186:     deletable = ((int) io.descr.d_nnote) - ((int) io.descr.d_delnote) - worksetsize;
     187:     if (deletable <= 0)                 /* candidates? */
     188:     {
     189:     if (io.descr.d_nnote - io.descr.d_delnote > 0)  /* only if non-empty */
     190:     {
     191:         printf ("Archiver: %s: %d notes <= working set size of %d\n",
     192:             nfname,
     193:             io.descr.d_nnote - io.descr.d_delnote,
     194:             worksetsize);
     195:         fflush (stdout);
     196:     }
     197:     goto docompress;
     198:     }
     199:
     200:     gettime (&zaptime);                 /* threshold */
     201:     zaptime.w_gmttime -= 60L * 60L * 24L * ((long) daysold);/* internal */
     202:     maketime (&zaptime, zaptime.w_gmttime);     /* re-format */
     203:
     204:
     205:     if (!deleteonly)
     206:     {
     207:     if (init (&archio, archdest) < 0)       /* not already */
     208:     {
     209:         printf ("Archiver creating archive notesfile %s\n", archdest);
     210:         fflush (stdout);
     211:         if (buildnf (archend, archbase, 0, 0, 0) < 0)/* make one */
     212:         {
     213:         printf ("Archiver: Problems creating %s for archival\n",
     214:             archdest);
     215:         fflush (stdout);
     216:         goto docompress;
     217:         }
     218:         if (init (&archio, archdest) < 0)       /* and open it */
     219:         {
     220:         printf ("Archiver: Problems opening %s for archival\n",
     221:             archdest);
     222:         fflush (stdout);
     223:         goto docompress;
     224:         }
     225:         locknf (&archio, DSCRLOCK);         /* watch conflicts */
     226:         getdscr (&archio, &archio.descr);
     227:         archio.descr.d_stat |= ISARCH + OPEN;
     228:         putdscr (&archio, &archio.descr);
     229:         unlocknf (&archio, DSCRLOCK);
     230:         /*
     231: 	     *	Copy the active notesfile's access list to
     232: 	     *	the archive notesfile.
     233: 	     */
     234:         {
     235: #ifdef  FASTFORK
     236:         char    old[WDLEN];
     237:         char    new[WDLEN];
     238:         sprintf (old, "%s/%s/%s", io.basedir, io.nf, ACCESS);
     239:         sprintf (new, "%s/%s/%s", archio.basedir, archio.nf, ACCESS);
     240:         dounix (0, 0, "/bin/cp", old, new, 0, 0);
     241: #else   ! FASTFORK
     242:         char    cmdline[WDLEN + WDLEN + 32];
     243:         sprintf (cmdline, "%s %s/%s/%s %s/%s/%s",
     244:             "/bin/cp",
     245:             io.basedir, io.nf, ACCESS,
     246:             archio.basedir, archio.nf, ACCESS);
     247:         dounix (cmdline, 0, 0);
     248: #endif	! FASTFORK
     249:         }
     250:     }
     251:
     252:     locktarget = strcmp (io.nf, archio.nf);     /* lock if differ */
     253:
     254:
     255:     if (!(archio.descr.d_stat & ISARCH))        /* into archive? */
     256:     {
     257:         printf ("Archiver: %s: Target %s is not an archive\n",
     258:             nfname, archdest);
     259:         fflush (stdout);
     260:         closenf (&archio);              /* close that */
     261:         goto docompress;                /* compress him anyway */
     262:     }
     263:     }
     264:
     265:
     266: #ifdef OLDGROUP
     267: /*
     268:  *	This code looks at the directory to see if the notesfile
     269:  *	has been idle long enough to be deleted.
     270:  *
     271:  *	This code hasn't been tested by me. It works in the
     272:  *	Salkind/Spickelmier version.
     273:  *
     274:  *	Should stuff a "wait-till-expire" in the master descriptor
     275:  *	of each notesfile so "junk" ones can expire faster or
     276:  *	something like that.  Essentially we want the age at which
     277:  *	the notesfile is deleted to be grabbed from the notesfile
     278:  *	itself.
     279:  *
     280:  *	My personal opinion is that they shouldn't disappear
     281:  *	auto-magically
     282:  *		NOTE: this probably no longer works with the
     283:  *		changes I've made to archiving.   (Dec '83)
     284:  *
     285:  *	N.B. Need some locking in here
     286:  */
     287:
     288:     /* delete inactive groups - RLS 1/8/83 */
     289:
     290:     sprintf (line, "%s/%s", MSTDIR, nfname);
     291:     stat (line, &buf);
     292:     current = time (0);
     293:     if (current - buf.st_mtime > 60 * 60 * 24 * (OLDGROUP - daysold))
     294:     {
     295:     finish (&io);
     296:
     297:     sprintf (line, "/bin/rm -rf %s/%s", MSTDIR, nfname);
     298:     system (line);
     299:
     300:     gettime (&zaptime);
     301:     sprdate (&zaptime, timeline);
     302:
     303:     /* message in nfmaint */
     304:     sprintf (line, "Archiver: removed %s\n", nfname);
     305:     nfcomment (NOSUCHWARN, line, line, 0, 0);
     306:
     307:     sprintf (line, "%s/%s/%s", MSTDIR, UTILITY, NETLOG);
     308:     x ((log = fopen (line, "a")) == NULL, "archiver: no logfile");
     309:     fprintf (log, "Archiver: deleted %s at %s\n", nfname, timeline);
     310:     printf ("Archiver: deleted %s at %s\n", nfname, timeline);
     311:     fclose (log);
     312:     fflush (stdout);
     313:     return (0);
     314:     }
     315: #endif	OLDGROUP
     316:
     317:
     318:     locknf (&io, DSCRLOCK);             /* MUTEX */
     319:     if (locktarget)                 /* and target */
     320:     locknf (&archio, DSCRLOCK);
     321:     getdscr (&io, &io.descr);
     322:     wasopen = io.descr.d_stat & OPEN;           /* hold this */
     323:     io.descr.d_stat &= NOT OPEN;            /* privacy */
     324:     putdscr (&io, &io.descr);
     325:
     326:     for (i = 1; i <= io.descr.d_nnote && deletable; i++)
     327:     {
     328:     getnrec (&io, i, &note);
     329:     if (note.n_stat & DELETED)          /* already gone */
     330:         continue;
     331:     if (inorder (&zaptime, &note.n_lmod))       /* check times */
     332:         continue;                   /* too recent */
     333:     if (dirmsgflag == DIROFF && (note.n_stat & DIRMES))
     334:         continue;                   /* only dir off */
     335:     if (dirmsgflag == DIRON && (note.n_stat & DIRMES) == 0)
     336:         continue;                   /* only dir on */
     337:     if (dirmsgflag == DIRANYON)         /* any w/dir on */
     338:     {
     339:         /*
     340: 	     * if anything in the note string has dir message on,
     341: 	     * expire the sucker.
     342: 	     */
     343:         if (note.n_stat & DIRMES)           /* note has dir */
     344:         goto killit;                /* so expire it */
     345:         for (rnum = 1; rnum <= note.n_nresp; rnum++)
     346:         {                       /* for each response */
     347:         if (lrsp (&io, i, rnum, &resp, &roffset, &rblock) != 0)
     348:             break;              /* busted resp chain */
     349:         if (resp.r_stat[roffset] & DIRMES)  /* is dir message */
     350:             goto killit;            /* so expire */
     351:         }
     352:         continue;                   /* do not expire */
     353:     }
     354: killit:                         /* goto target */
     355:     presps = note.n_nresp;              /* response count */
     356:     if (!deleteonly)                /* save it? */
     357:     {
     358:         /*
     359: 	     * check to see if this one is already in the archive
     360: 	     */
     361:         dup_place = chknote (&archio, &note.n_id, &note2);/* already there? */
     362:         if (dup_place == 0)             /* not there */
     363:         {
     364:         /*
     365: 		 *	This code copied almost verbatim from compression routines
     366: 		 */
     367: #ifdef  notdef
     368:         x ((txtfile = fopen (txtfn, "w")) == NULL, "archiver:bad txt");
     369:         pageout (&io, &note.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, &note.n_addr, &archio, &where, LOCKIT);
     376: #endif
     377:         newnum = putnote (&archio, &where, note.ntitle, note.n_stat, &note,
     378:             &note.n_auth, NOPOLICY, NOLOCKIT, NOADDID, note.n_from, NOADDTIME);
     379:         getnrec (&archio, newnum, &note2);  /* get copy */
     380:         }
     381:         else
     382:         {
     383:         if ((note2.n_stat & ORPHND) &&      /* archived is foster */
     384:             !(note.n_stat & ORPHND))    /* and active isn't */
     385:         {
     386: #ifdef  notdef
     387:             x ((txtfile = fopen (txtfn, "w")) == NULL, "archiver:bad txt");
     388:             pageout (&io, &note.n_addr, txtfile);
     389:             fclose (txtfile);
     390:             x ((txtfile = fopen (txtfn, "r")) == NULL, "archiver: txt read");
     391:             pagein (&archio, txtfile, &where);
     392:             fclose (txtfile);
     393: #else
     394:             pagemove (&io, &note.n_addr, &archio, &where, LOCKIT);
     395: #endif
     396:
     397:             note.n_nresp = note2.n_nresp;   /* save resp chain */
     398:             note.n_rindx = note2.n_rindx;
     399:             note.n_addr = where;        /* get text pointer */
     400:             putnrec (&archio, dup_place, &note);/* replace descriptor */
     401:             note2 = note;           /* save good copy */
     402:             adopts++;               /* count 'em */
     403:         }
     404:         else
     405:         {
     406:             dnotes++;               /* count duplicate */
     407:         }
     408:         newnum = dup_place;         /* for linking resps */
     409:         }
     410:
     411:         for (rnum = 1; rnum <= presps; rnum++)  /* process responses */
     412:         {
     413:         if (lrsp (&io, i, rnum, &resp, &roffset, &rblock) != 0)
     414:             break;              /* bad response chain - drop rest */
     415:         if (dup_place)              /* better check... */
     416:         {
     417:             dup_resp = chkresp (&archio, &resp.r_id[roffset], &note2, newnum);
     418:             if (dup_resp)           /* already there */
     419:             {
     420:             dresps++;           /* count doubles */
     421:             continue;           /* skip this response */
     422:             }
     423:         }
     424: #ifdef  notdef
     425:         x ((txtfile = fopen (txtfn, "w")) == NULL, "compress:bad txt");
     426:         pageout (&io, &resp.r_addr[roffset], txtfile);
     427:         fclose (txtfile);
     428:         x ((txtfile = fopen (txtfn, "r")) == NULL, "compress: bad txt read");
     429:         pagein (&archio, txtfile, &where);
     430:         fclose (txtfile);
     431: #else
     432:         pagemove (&io, &resp.r_addr[roffset], &archio, &where, LOCKIT);
     433: #endif
     434:         putresp (&archio, &where, resp.r_stat[roffset], newnum, &resp.r_when[roffset],
     435:             &resp.r_auth[roffset], &note, NOLOCKIT, &resp.r_id[roffset],
     436:             NOADDID, resp.r_from[roffset], NOADDTIME, &resp.r_rcvd[roffset]);
     437:         }
     438:     }
     439:     delnote (&io, i, NOLOCKIT);         /* delete entry */
     440:     ncount++;
     441:     rcount += presps;               /* and responses */
     442:     deletable--;                    /* one down */
     443:     }
     444:
     445:     unlocknf (&io, DSCRLOCK);               /* Un MUTEX */
     446:     if (locktarget)                 /* and the target */
     447:     unlocknf (&archio, DSCRLOCK);
     448:
     449:     if (!deleteonly)
     450:     {
     451:     finish (&archio);               /* close target */
     452:     unlink (txtfn);                 /* don't litter */
     453:     }
     454:
     455: /*
     456:  *	Time to compress the notesfile and eliminate those
     457:  *	unsightly holes in the data structure.
     458:  */
     459: docompress:
     460:
     461:     locknf (&io, DSCRLOCK);             /* MUTEX */
     462:     if (io.descr.d_nnote != 0)              /* non-empty */
     463:     {
     464:     if (io.descr.d_delnote != 0 || io.descr.d_delresp != 0)
     465:     {                       /* has holes */
     466:         int     nnote,
     467:                 nresp;
     468:         compress (&io, NOLOCKIT, 0, &nnote, &nresp);
     469:         printf ("Archiver: %s contains (%d,%d) after compress\n",
     470:             nfname, nnote, nresp);
     471:         fflush (stdout);
     472:     }
     473:     else                        /* no holes so */
     474:     {                       /* don't compress */
     475:         printf ("Archiver: %s already compressed\n", nfname);
     476:         fflush (stdout);
     477:     }
     478:     }
     479:     else                        /* nothing there to */
     480:     {                           /* compress */
     481:     printf ("Archiver: %s is empty.\n", nfname);
     482:     fflush (stdout);
     483:     }
     484:
     485:
     486:     if (wasopen)                    /* if it was already */
     487:     {
     488:     getdscr (&io, &io.descr);           /* open season */
     489:     io.descr.d_stat |= OPEN;
     490:     putdscr (&io, &io.descr);           /* replace in file */
     491:     }
     492:
     493:     unlocknf (&io, DSCRLOCK);               /* all done with this */
     494:     finish (&io);                   /* and close the notesfile */
     495:
     496:     gettime (&zaptime);
     497:     sprdate (&zaptime, timeline);
     498:     if (ncount)                     /* log only if did somethine */
     499:     {
     500:     sprintf (line, "%s/%s/%s", Mstdir, UTILITY, NETLOG);
     501:     x ((log = fopen (line, "a")) == NULL, "archiver: no logfile");
     502:     if (!deleteonly)
     503:         fprintf (log, "%s: archived (%d,%d) [%d,%d dups, %d adopted] into %s at %s\n",
     504:             nfname, ncount, rcount, dnotes, dresps, adopts, archdest, timeline);
     505:     else
     506:         fprintf (log, "%s: Archiver deleted (%d,%d) at %s\n",
     507:             nfname, ncount, rcount, timeline);
     508:     fclose (log);
     509:     }
     510:
     511:     if (!deleteonly)
     512:     {
     513:     if (ncount)
     514:         printf ("Archiver: %s: (%d,%d) [%d,%d dups, %d adoptions] into %s at %s\n",
     515:             nfname, ncount, rcount, dnotes, dresps, adopts, archdest, timeline);
     516:     else
     517:         printf ("Archiver: %s: no notes archived\n",
     518:             nfname);
     519:     }
     520:     else
     521:     printf ("Archiver: %s: deleted (%d,%d) at %s\n",
     522:         nfname, ncount, rcount, timeline);
     523:     fflush (stdout);
     524:     return (0);                     /* and return */
     525:
     526: }

#### Defined functions

archiver defined in line 27; used 1 times

- in /usr/src/new/notes/src/nfarchive.c line 26

#### Defined variables

rcsid defined in line 5; never used

Last modified: 1986-01-26 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1380 |