delta.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 904 行 · 第 1/2 页
C
904 行
#ifndef lintstatic char *sccsid = "@(#)delta.c 4.1 (ULTRIX) 7/17/90";#endif lint/************************************************************************ * * * Copyright (c) 1984, 1985, 1988 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//* * Modification History: * * 19 Nov 84 -- depp * Change method of finding "bdiff" path, added "paths.h" * 7 Dec 84 -- depp * Fix UID problem so that delta forks a child to manipulate * files in user directory * 14 Dec 84 -- depp * Removed diagnostic from wait() return after manipulation of "g" file * 28 Jun 88 -- D. Long * Use atomic rename operation in xremove instead of link and unlink. * Also don't use return value from fputs, Ultrix is not SVID * compliant here and returns undefined. Use ferror instead. * 14 Sep 88 -- D. Long * Use new constant LINEWIDTH throughtout for maximum text line length * instead of hard coded constants and BUFSIZ. Also check to make * sure input lines do not exceed this size. * 14 Sep 88 -- D. Long * Don't try and sprintf entire comment string onto 1K buffer. * */# include "defines.h"# include "had.h"# include "paths.h"struct stat Statbuf;char Null[1];char Error[128];char Diffpgm[] = PROGPATH(bdiff);FILE *Diffin;FILE *Gin;int Debug = 0;struct packet gpkt;struct sid sid;int num_files;char had[26];char *ilist, *elist, *glist;char *Comments,Cmrs[300],*Mrs,*Nsid;char *auxf(), *logname(), *sid_ba();int Domrs;int verbosity;int Did_id;long Szqfile;char Pfilename[FILESIZE];FILE *fdfopen();char *Cassin;extern FILE *Xiop;extern int Xcreate;main(argc,argv)int argc;register char *argv[];{ register int i; register char *p; char c; char *sid_ab(); int testmore; extern delta(); extern char *savecmt(); extern int Fcnt; Fflags = FTLEXIT | FTLMSG | FTLCLN; for(i=1; i<argc; i++) if(argv[i][0] == '-' && (c=argv[i][1])) { p = &argv[i][2]; testmore = 0; switch (c) { case 'r': if (!p[0]) { argv[i] = 0; continue; } chksid(sid_ab(p,&sid),&sid); break; case 'g': glist = p; break; case 'y': Comments = p; break; case 'm': Mrs = p; repl(Mrs,'\n',' '); break; case 'p': case 'n': case 's': testmore++; break; case 'z': Cassin = p; break; default: fatal("unknown key letter (cm1)"); } if (testmore) { testmore = 0; if (*p) { sprintf(Error, "value after %c arg (cm7)",c); fatal(Error); } } if (had[c - 'a']++) fatal("key letter twice (cm2)"); argv[i] = 0; } else num_files++; if(num_files == 0) fatal("missing file arg (cm3)"); if (!HADS) verbosity = -1; setsig(); Fflags &= ~FTLEXIT; Fflags |= FTLJMP; for (i=1; i<argc; i++) if (p=argv[i]) do_file(p,delta); exit(Fcnt ? 1 : 0);}delta(file)char *file;{ static int first = 1; int n, linenum; char type; register int ser; extern char had_dir, had_standinp; extern char *Sflags[]; char nsid[50]; char dfilename[FILESIZE]; char gfilename[FILESIZE]; char line[LINEWIDTH+1]; char *getline(); FILE *dodiff(); struct stats stats; struct pfile *pp, *rdpfile(); struct stat sbuf; struct idel *dodelt(); int inserted, deleted, orig; int newser; int status, i; int diffloop; int difflim; int holduid,holdgid; if (setjmp(Fjmp)) return; sinit(&gpkt,file,1); if (first) { first = 0; dohist(file); } if (lockit(auxf(gpkt.p_file,'z'),2,getpid())) fatal("cannot create lock file (cm4)"); gpkt.p_reopen = 1; gpkt.p_stdout = stdout; copy(auxf(gpkt.p_file,'g'),gfilename); Gin = xfopen(gfilename,0); pp = rdpfile(&gpkt,&sid); if (pp->pf_cmrlist) { strcpy(Cmrs,pp->pf_cmrlist); } else { Cmrs[0] = '\0'; } if(!pp->pf_nsid.s_br) { sprintf(nsid,"%d.%d",pp->pf_nsid.s_rel,pp->pf_nsid.s_lev); } else { sprintf(nsid,"%d.%d.%d.%d",pp->pf_nsid.s_rel,pp->pf_nsid.s_lev,pp->pf_nsid.s_br,pp->pf_nsid.s_seq); } Nsid=nsid; gpkt.p_cutoff = pp->pf_date; ilist = pp->pf_ilist; elist = pp->pf_elist; if (dodelt(&gpkt,&stats,(struct sid *) 0,0) == 0) fmterr(&gpkt); if ((ser = sidtoser(&pp->pf_gsid,&gpkt)) == 0 || sidtoser(&pp->pf_nsid,&gpkt)) fatal("invalid sid in p-file (de3)"); doie(&gpkt,ilist,elist,glist); setup(&gpkt,ser); finduser(&gpkt); doflags(&gpkt); gpkt.p_reqsid = pp->pf_nsid; permiss(&gpkt); flushto(&gpkt,EUSERTXT,1); gpkt.p_chkeof = 1; copy(auxf(gpkt.p_file,'d'),dfilename); gpkt.p_gout = xfcreat(dfilename,0444); while(readmod(&gpkt)) { chkid(gpkt.p_line); fputs(gpkt.p_line,gpkt.p_gout); if(ferror(gpkt.p_gout)) FAILPUT; } if(fclose(gpkt.p_gout)==EOF) FAILPUT; orig = gpkt.p_glnno; gpkt.p_glnno = 0; gpkt.p_verbose = verbosity; Did_id = 0; while (fgets(line,sizeof(line),Gin) != NULL && !chkid(line)) ; fclose(Gin); if (gpkt.p_verbose && (num_files > 1 || had_dir || had_standinp)) fprintf(gpkt.p_stdout,"\n%s:\n",gpkt.p_file); if (!Did_id) if (Sflags[IDFLAG - 'a']) fatal("no id keywords (cm6)"); else if (gpkt.p_verbose) fprintf(stderr,"No id keywords (cm7)\n"); /* The following while loop executes 'bdiff' on g-file and d-file. If 'bdiff' fails (usually because segmentation limit it is using is too large for 'diff'), it is invoked again, with a lower segmentation limit. */ difflim = 3500; diffloop = 0; while (1) { inserted = deleted = 0; gpkt.p_glnno = 0; gpkt.p_upd = 1; gpkt.p_wrttn = 1; getline(&gpkt); gpkt.p_wrttn = 1; newser = mkdelt(&gpkt,&pp->pf_nsid,&pp->pf_gsid, diffloop,orig); diffloop = 1; flushto(&gpkt,EUSERTXT,0); Diffin = dodiff(auxf(gpkt.p_file,'g'),dfilename,difflim); while (n = getdiff(&type,&linenum)) { if (type == INS) { inserted += n; insert(&gpkt,linenum,n,newser); } else { deleted += n; delete(&gpkt,linenum,n,newser); } } fclose(Diffin); if (gpkt.p_iop) while (readmod(&gpkt)) ; wait(&status); if (status) { /* diff failed */ /* Check top byte (exit code of child). */ if (((status >> 8) & 0377) == 32) { /* 'execl' failed */ sprintf(Error, "cannot execute '%s' (de12)",Diffpgm); fatal(Error); } /* Re-try. */ if (difflim -= 500) { /* reduce segmentation */ fprintf(stderr, "'%s' failed, re-trying, segmentation = %d (de13)\n", Diffpgm,difflim); if(fclose(Xiop)==EOF) /* set up */ FAILPUT; Xiop = 0; /* for new x-file */ Xcreate = 0; /* Re-open s-file. */ gpkt.p_iop = xfopen(gpkt.p_file,0); setbuf(gpkt.p_iop,gpkt.p_buf); /* Reset counters. */ gpkt.p_slnno = 0; gpkt.p_ihash = 0; gpkt.p_chash = 0; gpkt.p_nhash = 0; gpkt.p_keep = 0; } else /* tried up to 500 lines, can't go on */ fatal("diff failed (de4)"); } else { /* no need to try again, worked */ break; /* exit while loop */ } } fgetchk(gfilename,&gpkt); unlink(dfilename); stats.s_ins = inserted; stats.s_del = deleted; stats.s_unc = orig - deleted; if (gpkt.p_verbose) { fprintf(gpkt.p_stdout,"%u inserted\n",stats.s_ins); fprintf(gpkt.p_stdout,"%u deleted\n",stats.s_del); fprintf(gpkt.p_stdout,"%u unchanged\n",stats.s_unc); } flushline(&gpkt,&stats); stat(gpkt.p_file,&sbuf); xrename(auxf(gpkt.p_file,'x'),gpkt.p_file); chown(gpkt.p_file,sbuf.st_uid,sbuf.st_gid); if (Szqfile) xrename(auxf(gpkt.p_file,'q'),Pfilename); else { xunlink(Pfilename); xunlink(auxf(gpkt.p_file,'q')); } clean_up(0); if (!HADN) { fflush(gpkt.p_stdout); if ((i = fork()) < 0) fatal("cannot fork, try again"); if (i == 0) { setuid(getuid()); setgid(getgid()); unlink(gfilename); exit(0); } else wait(0); }}mkdelt(pkt,sp,osp,diffloop,orig_nlines)struct packet *pkt;struct sid *sp, *osp;int diffloop;int orig_nlines;{ extern long Timenow; struct deltab dt; char str[LINEWIDTH+1]; char *del_ba(); int newser; extern char *Sflags[]; register char *p; int ser_inc, opred, nulldel; if (!diffloop && pkt->p_verbose) { sid_ba(sp,str); fprintf(pkt->p_stdout,"%s\n",str); fflush(pkt->p_stdout); } sprintf(str,"%c%c00000\n",CTLCHAR,HEAD); putline(pkt,str); newstats(pkt,str,"0"); dt.d_sid = *sp; /* Check if 'null' deltas should be inserted (only if 'null' flag is in file and releases are being skipped) and set 'nulldel' indicator appropriately. */ if (Sflags[NULLFLAG - 'a'] && (sp->s_rel > osp->s_rel + 1) && !sp->s_br && !sp->s_seq && !osp->s_br && !osp->s_seq) nulldel = 1; else nulldel = 0; /* Calculate how many serial numbers are needed. */ if (nulldel) ser_inc = sp->s_rel - osp->s_rel; else ser_inc = 1; /* Find serial number of the new delta. */ newser = dt.d_serial = maxser(pkt) + ser_inc; /* Find old predecessor's serial number. */ opred = sidtoser(osp,pkt); if (nulldel) dt.d_pred = newser - 1; /* set predecessor to 'null' delta */ else dt.d_pred = opred; dt.d_datetime = Timenow; strncpy(dt.d_pgmr,logname(),LOGSIZE-1); dt.d_type = 'D'; del_ba(&dt,str); putline(pkt,str); if (ilist) mkixg(pkt,INCLUSER,INCLUDE); if (elist) mkixg(pkt,EXCLUSER,EXCLUDE); if (glist) mkixg(pkt,IGNRUSER,IGNORE); if (Mrs) { if (!(p = Sflags[VALFLAG - 'a'])) fatal("MRs not allowed (de8)"); if (*p && !diffloop && valmrs(pkt,p)) fatal("invalid MRs (de9)"); putmrs(pkt); } else if (Sflags[VALFLAG - 'a']) fatal("MRs required (de10)");/*** CMF enhancement**/ if(Sflags[CMFFLAG - 'a'])
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?