static char *sccsid = "%W%"; #include "parms.h" #include "structs.h" /* * compress(io) struct io_f * compresses the notefile specified. All wasted space * reclaimed. The process is a simple one which, like dcheck, * does not work so well on active file systems. * As a consequence, the director options (which call this) * require the notefile to be closed before allowing compression * to take place. * The code generates 3 scratch files, corresponding with the * two index files and the text file. These are made to * represent a virgin notefile. The descriptor is copied over * with the appropriate fields zapped, and then we go through * a cycle of (read note; write note; (read resp; write resp)) * until all the notes and responses are moved over. * the new files are then copied back into place. * * Returns: 0 - all successful * -1 - if notesfiles compressed already * * otherwise will core dump with the notefile * in a shambles from the users view point, * but still recoverable by a hotshot-pro. * * Original Coding: Ray Essick January 1981 */ compress(io, lockflag, numnotes, numresps) struct io_f *io; int lockflag; int *numnotes, *numresps; { struct io_f tmpio; /* scratch notefile */ struct note_f note; /* hold a note record */ struct resp_f resp; /* hold the response format */ char fn1[WDLEN], fn2[WDLEN], fn3[WDLEN]; char on1[WDLEN], on2[WDLEN], on3[WDLEN]; char txtfn[WDLEN]; /* hold text going between files */ char cmd[CMDLEN]; /* monster move command */ struct daddr_f where; FILE *txtfile; int nnotes, nresps, dint, roffset, num, rblock; register int newnum, presps, rnum; struct daddr_f daddr; /* build names of files - in notefile directory */ sprintf(fn1, "%s/%s/tmp.%s", MSTDIR, io->nf, INDEXN); /* new files */ sprintf(fn2, "%s/%s/tmp.%s", MSTDIR, io->nf, INDEXR); sprintf(fn3, "%s/%s/tmp.%s", MSTDIR, io->nf, TEXT); sprintf(on1, "%s/%s/%s", MSTDIR, io->nf, INDEXN);/* old files */ sprintf(on2, "%s/%s/%s", MSTDIR, io->nf, INDEXR); sprintf(on3, "%s/%s/%s", MSTDIR, io->nf, TEXT); /* * if the notesfile is not already locked, * do so now. This also insures signals will * be ignored */ if (lockflag) lock(io, 'n'); /* lock up the notefile */ x ((tmpio.fidndx = creat(fn1, 0600)) < 0, "compress: create nindex"); x ((tmpio.fidrdx = creat(fn2, 0600)) < 0, "compress: create rindex"); x ((tmpio.fidtxt = creat(fn3, 0600)) < 0, "compress: create txt"); dint = 0; /* resp index free pointer */ daddr.addr = sizeof daddr; /* and for text file */ x (write(tmpio.fidrdx, &dint, sizeof(dint)) != sizeof(dint), "compress: resp ptr"); x (write(tmpio.fidtxt, &daddr, sizeof(daddr)) != sizeof(daddr), "Compress: text ptr"); closenf(&tmpio); /* close them up */ #ifdef BSD4.1c /* open R/W */ x ((tmpio.fidndx = open(fn1, O_RDWR, 0)) < 0, "compress: reopen 1"); x ((tmpio.fidrdx = open(fn2, O_RDWR, 0)) < 0, "compress: reopen 2"); x ((tmpio.fidtxt = open(fn3, O_RDWR, 0)) < 0, "compress: reopen 3"); #else x ((tmpio.fidndx = open(fn1, 2)) < 0, "compress: reopen 1"); x ((tmpio.fidrdx = open(fn2, 2)) < 0, "compress: reopen 2"); x ((tmpio.fidtxt = open(fn3, 2)) < 0, "compress: reopen 3"); #endif BSD4.1c strmove(io->nf, tmpio.nf); /* copy over notefile name */ getdscr(io, &tmpio.descr); /* grab descriptor */ if (io->descr.d_stat & NFINVALID) { /* fix to clean up things, from Steve Potter, Tektronix */ closenf(&tmpio); x (unlink(fn1) < 0, "compress: remove tmp 1"); x (unlink(fn2) < 0, "compress: remove tmp 2"); x (unlink(fn3) < 0, "compress: remove tmp 3"); /* end of fix */ if (lockflag) unlock(io, 'n'); return(-1); } nnotes = nresps = 0; /* init counts of living notes */ sprintf(txtfn, "/tmp/nfc%d", getpid()); tmpio.descr.d_nnote = 0; /* reset note count */ putdscr(&tmpio, &tmpio.descr); /* place it into the file */ if (io->descr.d_plcy) { /* copy the policy note over */ getnrec(io, 0, ¬e); /* descriptor */ x ((txtfile = fopen(txtfn, "w")) == NULL, "compress:bad txt"); pageout(io, ¬e.n_addr, txtfile); fclose(txtfile); x ((txtfile = fopen(txtfn, "r")) == NULL, "compress: bad txt read"); pagein(&tmpio, txtfile, &where); fclose(txtfile); putnote(&tmpio, &where, note.ntitle, note.n_stat, ¬e, ¬e.n_auth, POLICY, NOLOCKIT, NOADDID, note.n_from, NOADDTIME); } for (num = 1; num <= io->descr.d_nnote; num++) { getnrec(io, num, ¬e); if (note.n_stat & DELETED) continue; /* deleted - we throw away */ x ((txtfile = fopen(txtfn, "w")) == NULL, "compress:bad txt"); pageout(io, ¬e.n_addr, txtfile); fclose(txtfile); x ((txtfile = fopen(txtfn, "r")) == NULL, "compress: bad txt read"); pagein(&tmpio, txtfile, &where); fclose(txtfile); /* save max number of responses */ presps = note.n_nresp; newnum = putnote (&tmpio, &where, note.ntitle, note.n_stat, ¬e, ¬e.n_auth, NOPOLICY, NOLOCKIT, NOADDID, note.n_from, NOADDTIME); nnotes++; /* add a note */ for (rnum = 1; rnum <= presps; rnum++) { /* process responses */ if (lrsp(io, num, rnum, &resp, &roffset, &rblock) != 0) { /* bad response chain - drop rest */ break; } x ((txtfile = fopen(txtfn, "w")) == NULL, "compress:bad txt"); pageout(io, &resp.r_addr[roffset], txtfile); fclose(txtfile); x ((txtfile = fopen(txtfn, "r")) == NULL, "compress: bad txt read"); pagein(&tmpio, txtfile, &where); fclose(txtfile); putresp(&tmpio, &where, resp.r_stat[roffset], newnum, &resp.r_when[roffset], &resp.r_auth[roffset], ¬e, NOLOCKIT, &resp.r_id[roffset], NOADDID, resp.r_from[roffset], NOADDTIME, &resp.r_rcvd[roffset]); nresps++; /* count responses */ } } /* * well, we have now copied the entire notefile over, * so the time has come to move it back into the correct * file names - we will do this by linking */ closenf(&tmpio); /* close the new one */ getdscr(io, &io->descr); io->descr.d_stat |= NFINVALID; /* mark it bad */ putdscr(io, &io->descr); closenf(io); /* close the old one */ #ifdef BSD4.1c x (rename(fn1,on1) < 0, "compress: rename 1"); x (rename(fn2,on2) < 0, "compress: rename 1"); x (rename(fn3,on3) < 0, "compress: rename 1"); #else x (unlink(on1) < 0, "compress: remove old 1"); x (link(fn1, on1) < 0, "compress: link new 1"); x (unlink(fn1) < 0, "compress: remove tmp 1"); x (unlink(on2) < 0, "compress: remove old 2"); x (link(fn2, on2) < 0, "compress: link new 2"); x (unlink(fn2) < 0, "compress: remove tmp 2"); x (unlink(on3) < 0, "compress: remove old 3"); x (link(fn3, on3) < 0, "compress: link new 3"); x (unlink(fn3) < 0, "compress: remove tmp 3"); #endif BSD4.1c unlink(txtfn); opennf(io, io->nf); /* relink to new one */ getdscr(io, &io->descr); /* get the new descriptor */ if (lockflag) unlock(io, 'n'); *numnotes = nnotes; *numresps = nresps; return(0); /* return ok */ }