Date: Thu, 1 Feb 1996 18:50:37 +0100 (MET) From: haury@sagem.fr To: hackers@freebsd.org Subject: CTM: evolutions of ctm Message-ID: <199602011750.SAA05008@sagem.fr>
next in thread | raw e-mail | index | archive | help
I hope it's the right list for that and not <ctm@freebsd.org> : Have been using CTM for a while and have changed it a little bit according to Poul-Henning Kamp's future plans (Handbook 14.5.5 and sources comments). These changes seem to work (I'have been testing them for 3 weeks now with official ctm inputs on my -current tree) - I hope these patches could help the community. Evolutions : 2 new options -b <basedir> path (relative or absolute) prepend on every files names -V <level> verbose level added to current one ( -V 2 == -v -v and -V 2 -v == -v -v -v ) *and* possibility of local modifications to the tree : before working on a file <name>, CTM first checks for the existence of the file <name>#ctm. If this file exists, CTM works on it instead. this substitution works for : FM : CTM exits if <file>#ctm exists (and no -F) FS : CTM substitutes the contents of file <file>#ctm FE, FN : CTM edits <file>#ctm FR : CTM removes *only* <file>#ctm AS : CTM changes permissions of <file>#ctm side effects : DR : CTM *does not* check for the existance of <dir>#ctm and the contents of <dir> before removing it. I didn't find a real good idea to manage dependencies between <file> and <file>#ctm with make since it seems that make : - does not understand suffix rules like %\#ctm %: production - does not check any dependencies for Makefile itself before working. So I have added several targets on the Top Makefile. The idea is : if <file> is created then <file>#ctm is created with null size if <file> is modified then <file>#ctm is created with the original content <file>#ctm *is* the reference <file> is produced by patching <file>#ctm with <file>.diff I have put the patch of the top Makefile to show you what kind of rules I use. The patch script below works on the top of the source directory and modifies : in . : Makefile: $Id: Makefile,v 1.74 1996/01/30 05:46:35 nate Exp $ in ./usr.sbin/ctm/ctm : ctm.1: $Id: ctm.1,v 1.3 1996/01/31 01:58:29 nate Exp $ ctm.c: $Id: ctm.c,v 1.11 1995/05/30 03:47:19 rgrimes Exp $ ctm.h: $Id: ctm.h,v 1.7 1995/05/30 03:47:21 rgrimes Exp $ ctm_input.c: $Id: ctm_input.c,v 1.4 1994/09/22 02:49:18 phk Exp $ ctm_pass1.c: $Id: ctm_pass1.c,v 1.11 1995/07/12 09:16:08 phk Exp $ ctm_pass2.c: $Id: ctm_pass2.c,v 1.10 1995/11/10 12:17:23 phk Exp $ ctm_pass3.c: $Id: ctm_pass3.c,v 1.11 1995/07/12 09:16:13 phk Exp $ ctm_syntax.c: $Id: ctm_syntax.c,v 1.5 1995/05/30 03:47:28 rgrimes Exp $ ==== CUT HERE (and don't forget to remove my signature) ==== *** ./Makefile#ctm Wed Jan 31 20:34:35 1996 --- ./Makefile Thu Feb 1 12:08:43 1996 *************** *** 355,358 **** --- 355,414 ---- cd ${.CURDIR}/usr.sbin/zic && \ ${MAKE} depend all install ${CLEANDIR} ${OBJDIR} + # CTM Hack + + _CTM_SRC_CUR= ${.CURDIR}/../CTM/deltas + _CTM_STATUS= .ctm_status + _CTM_LIST= .ctm_list + + ctm: $(_CTM_LIST) ctm-diff + @echo "Starting CTM" + @perl -e 'while(<>){chop;$$l=$$1+1 if(/^src-cur\s+(\d+)$$/); \ + while(1){$$f="$(_CTM_SRC_CUR)/src-cur.$$l.gz"; \ + last unless -f $$f; print "$$f\n"; $$l++}}' \ + $(_CTM_STATUS) | while read file; do \ + echo ctm -V 2 $${file}; \ + ctm -V 2 $${file}; \ + done + @echo "DONE" + @echo "Starting file checking" + @perl -e 'while(<>){chop;foreach $$s ("",".diff","#ctm"){ \ + $$f="$$_$$s";print "Warning : $$f not found\n" unless -f $$f;}}' \ + $(_CTM_LIST) + @echo "DONE" + + ctm-list: + find . -name '*#ctm' -print | sed 's/#ctm$$//' > $(_CTM_LIST) + @cat $(_CTM_LIST) + + ctm-diff: + @echo "Starting DIFF" + @perl -e 'while(<>){chop;print"$$_\n" \ + if(!-f$$_.".diff"||-C$$_.".diff">-C$$_);}' \ + $(_CTM_LIST) | while read file; do \ + echo diff -c $${file}\#ctm $${file} \> $${file}.diff; \ + diff -c $${file}\#ctm $${file} > $${file}.diff \ + && ( echo "NO DIFFERENCE !!!!!"; rm -f $${file}.diff; exit 1 ) \ + || case $$? in 1);; *) exit $$?;; esac; \ + done; + @echo "DONE" + + ctm-patch: + @echo "Starting PATCH" + @perl -e 'while(<>){chop;print"$$_\n"if(!-f$$_||-C$$_>-C$$_."#ctm");}' \ + $(_CTM_LIST) | while read file; do \ + if [ -f $${file}.diff ]; then \ + dest=`basename $${file}`; \ + echo "Patching $${file} from $${file}#ctm"; \ + cp $${file}\#ctm /tmp/$${dest}; \ + patch /tmp/$${dest} $${file}.diff || exit 1; \ + mv /tmp/$${dest} $${file}; \ + rm -f /tmp/$${dest}.orig; \ + else \ + echo "No diffs to create $${file} from $${file}#ctm"; \ + exit 1; \ + fi; \ + done; + @echo "DONE" + .include <bsd.subdir.mk> *** ctm.1#ctm Thu Feb 1 16:54:55 1996 --- ctm.1 Thu Feb 1 17:49:14 1996 *************** *** 21,27 **** --- 21,29 ---- .Sh SYNOPSIS .Nm ctm .Op Fl cFpPqv + .Op Fl b Ar basedir .Op Fl T Ar tmpdir + .Op Fl V Ar level .Ar file Op ... .Sh DESCRIPTION .Nm Ctm *************** *** 53,58 **** --- 55,69 ---- command runs in a number of passes. It will process the entire input file in each pass, before commencing with the next pass. + Before working one a file + .Ar name + .Nm ctm + first checks for the existence of the file + .Ar name#ctm . + If this file exists, + .Nm ctm + works on it instead. + Pass 1 will validate that the input file is OK. The syntax, the data and the global MD5 checksum will be checked. If any of these fail, .Nm ctm *************** *** 77,82 **** --- 88,98 ---- .Bl -tag -width indent -compact + .It Fl b Ar basedir + Prepend the path + .Ar basedir + on every filename. + .It Fl c Check it out, don't do anything. *************** *** 98,103 **** --- 114,124 ---- .It Fl v Tell us more. + + .It Fl V Ar level + Tell us more. + .Ar Level + is the level of verbosity. .El *** ./usr.sbin/ctm/ctm/ctm.c#ctm Thu Feb 1 11:10:16 1996 --- ./usr.sbin/ctm/ctm/ctm.c Thu Feb 1 10:20:09 1996 *************** *** 14,20 **** * Options we'd like to see: * * -a Attempt best effort. - * -b <dir> Base-dir * -B <file> Backup to tar-file. * -d <int> Debug TBD. * -m <mail-addr> Email me instead. --- 14,19 ---- *************** *** 22,27 **** --- 21,27 ---- * -R <file> Read list of files to reconstruct. * * Options we have: + * -b <dir> Base-dir * -c Check it out, don't do anything. * -F Force * -p Less paranoid. *************** *** 29,34 **** --- 29,35 ---- * -q Tell us less. * -T <tmpdir>. Temporary files. * -v Tell us more. + * -V <level> Tell us more level = number of -v * */ *************** *** 46,61 **** int c; extern int optopt,optind; extern char * optarg; - FILE *statfile; unsigned applied = 0; Verbose = 1; Paranoid = 1; setbuf(stderr,0); setbuf(stdout,0); ! while((c=getopt(argc,argv,"ab:B:cd:Fm:pPqr:R:T:Vv")) != -1) { switch (c) { case 'c': CheckIt++; break; /* Only check it */ case 'p': Paranoid--; break; /* Less Paranoid */ case 'P': Paranoid++; break; /* More Paranoid */ --- 47,65 ---- int c; extern int optopt,optind; extern char * optarg; unsigned applied = 0; + FILE *statfile; + u_char * basedir; + basedir = NULL; Verbose = 1; Paranoid = 1; setbuf(stderr,0); setbuf(stdout,0); ! while((c=getopt(argc,argv,"ab:B:cd:Fm:pPqr:R:T:V:v")) != -1) { switch (c) { + case 'b': basedir = optarg; break; /* Base Directory */ case 'c': CheckIt++; break; /* Only check it */ case 'p': Paranoid--; break; /* Less Paranoid */ case 'P': Paranoid++; break; /* More Paranoid */ *************** *** 63,68 **** --- 67,75 ---- case 'v': Verbose++; break; /* Verbose */ case 'T': TmpDir = optarg; break; case 'F': Force = 1; break; + case 'V': sscanf(optarg,"%d", &c); /* Verbose */ + Verbose += c; + break; case ':': fprintf(stderr,"Option '%c' requires an argument.\n",optopt); stat++; *************** *** 85,92 **** argc -= optind; argv += optind; ! if((statfile = fopen(CTM_STATUS, "r")) == NULL) ! fprintf(stderr, "Warning: " CTM_STATUS " not found.\n"); else { fscanf(statfile, "%*s %u", &applied); fclose(statfile); --- 92,114 ---- argc -= optind; argv += optind; ! if (basedir == NULL) { ! Buffer = (u_char *)malloc(BUFSIZ + strlen(SUBSUFF) +1); ! CatPtr = Buffer; ! *Buffer = '\0'; ! } else { ! Buffer = (u_char *)malloc(strlen(basedir)+ BUFSIZ + strlen(SUBSUFF) +1); ! strcpy(Buffer, basedir); ! CatPtr = Buffer + strlen(basedir); ! if (CatPtr[-1] != '/') { ! strcat(Buffer, "/"); ! CatPtr++; ! } ! } ! strcat(Buffer, CTM_STATUS); ! ! if((statfile = fopen(Buffer, "r")) == NULL) ! fprintf(stderr, "Warning: %s not found.\n", Buffer); else { fscanf(statfile, "%*s %u", &applied); fclose(statfile); *** ./usr.sbin/ctm/ctm/ctm.h#ctm Tue Jan 30 11:44:21 1996 --- ./usr.sbin/ctm/ctm/ctm.h Wed Jan 31 16:40:52 1996 *************** *** 24,29 **** --- 24,32 ---- #define VERSION "2.0" #define MAXSIZE (1024*1024*10) + #define SUBSUFF "#ctm" + #define TMPSUFF ".ctm" + /* The fields... */ #define CTM_F_MASK 0xff #define CTM_F_Name 0x01 *************** *** 39,44 **** --- 42,48 ---- #define CTM_Q_Name_File 0x0100 #define CTM_Q_Name_Dir 0x0200 #define CTM_Q_Name_New 0x0400 + #define CTM_Q_Name_Subst 0x0800 #define CTM_Q_MD5_After 0x0100 #define CTM_Q_MD5_Before 0x0200 #define CTM_Q_MD5_Chunk 0x0400 *************** *** 63,70 **** EXTERN u_char *TimeStamp; EXTERN u_char *Prefix; EXTERN u_char *FileName; - EXTERN u_char *BaseDir; EXTERN u_char *TmpDir; /* * Paranoid -- Just in case they should be after us... --- 67,75 ---- EXTERN u_char *TimeStamp; EXTERN u_char *Prefix; EXTERN u_char *FileName; EXTERN u_char *TmpDir; + EXTERN u_char *CatPtr; + EXTERN u_char *Buffer; /* * Paranoid -- Just in case they should be after us... *************** *** 115,120 **** --- 120,126 ---- #define WRONG {Assert(); return Exit_Mess;} u_char * Ffield(FILE *fd, MD5_CTX *ctx,u_char term); + u_char * Fname(FILE *fd, MD5_CTX *ctx,u_char term,int qual, int verbose); int Fbytecnt(FILE *fd, MD5_CTX *ctx, u_char term); *************** *** 124,129 **** --- 130,136 ---- #define GETFIELDCOPY(p,q) if(!((p)=Ffield(fd,&ctx,(q)))) return BADREAD; else p=String(p) #define GETBYTECNT(p,q) if(0 >((p)= Fbytecnt(fd,&ctx,(q)))) return BADREAD #define GETDATA(p,q) if(!((p) = Fdata(fd,(q),&ctx))) return BADREAD + #define GETNAMECOPY(p,q,r,v) if(!((p)=Fname(fd,&ctx,(q),(r),(v)))) return BADREAD; else p=String(p) int Pass1(FILE *fd, unsigned applied); int Pass2(FILE *fd); *** ./usr.sbin/ctm/ctm/ctm_input.c#ctm Thu Feb 1 10:52:53 1996 --- ./usr.sbin/ctm/ctm/ctm_input.c Thu Feb 1 11:55:34 1996 *************** *** 111,113 **** --- 111,146 ---- p[u_chars] = '\0'; return p; } + + /*---------------------------------------------------------------------------*/ + /* get the filename in the next field, prepend BaseDir and give back the result + strings. The sustitute filename is return (the one with the suffix SUBSUFF) + if it exists and the qualifier contains CTM_Q_Name_Subst + NOTA: Buffer is already initialize with BaseDir, CatPtr is the insertion + point on this buffer + the length test in Ffield() is enough for Fname() */ + + u_char * + Fname(FILE *fd, MD5_CTX *ctx,u_char term,int qual, int verbose) + { + u_char * p; + struct stat st; + + if ((p = Ffield(fd,ctx,term)) == NULL) return(NULL); + + strcpy(CatPtr, p); + + if (!(qual & CTM_Q_Name_Subst)) return(Buffer); + + p = Buffer + strlen(Buffer); + + strcat(Buffer, SUBSUFF); + + if ( -1 == stat(Buffer, &st) ) { + *p = '\0'; + } else { + if(verbose > 2) + fprintf(stderr,"Using %s as substitute file\n", Buffer); + } + + return (Buffer); + } *** ./usr.sbin/ctm/ctm/ctm_pass1.c#ctm Tue Jan 30 11:44:21 1996 --- ./usr.sbin/ctm/ctm/ctm_pass1.c Thu Feb 1 09:46:04 1996 *************** *** 184,189 **** --- 184,193 ---- putc('\n',stderr); continue; } + + if(md5) Free(md5); + if(trash) Free(trash); + q = MD5End (&ctx,md5_1); if(Verbose > 2) printf("Expecting Global MD5 <%s>\n",q); *** ./usr.sbin/ctm/ctm/ctm_pass2.c#ctm Tue Jan 30 11:44:21 1996 --- ./usr.sbin/ctm/ctm/ctm_pass2.c Thu Feb 1 09:46:05 1996 *************** *** 69,75 **** switch (j & CTM_F_MASK) { case CTM_F_Name: ! GETFIELDCOPY(name,sep); /* XXX Check DR DM rec's for parent-dir */ if(j & CTM_Q_Name_New) { /* XXX Check DR FR rec's for item */ --- 69,75 ---- switch (j & CTM_F_MASK) { case CTM_F_Name: ! GETNAMECOPY(name,sep,j,0); /* XXX Check DR DM rec's for parent-dir */ if(j & CTM_Q_Name_New) { /* XXX Check DR FR rec's for item */ *************** *** 171,176 **** --- 171,181 ---- } } } + + if(trash) Free(trash); + if(name) Free(name); + if(md5) Free(md5); + q = MD5End (&ctx,md5_1); GETFIELD(p,'\n'); /* <MD5> */ if(strcmp(q,p)) WRONG *** ./usr.sbin/ctm/ctm/ctm_pass3.c#ctm Tue Jan 30 11:44:21 1996 --- ./usr.sbin/ctm/ctm/ctm_pass3.c Thu Feb 1 09:46:06 1996 *************** *** 69,75 **** sep = '\n'; switch (j & CTM_F_MASK) { ! case CTM_F_Name: GETFIELDCOPY(name,sep); break; case CTM_F_Uid: GETFIELDCOPY(uid,sep); break; case CTM_F_Gid: GETFIELDCOPY(gid,sep); break; case CTM_F_Mode: GETFIELDCOPY(mode,sep); break; --- 69,75 ---- sep = '\n'; switch (j & CTM_F_MASK) { ! case CTM_F_Name: GETNAMECOPY(name,sep,j, Verbose); break; case CTM_F_Uid: GETFIELDCOPY(uid,sep); break; case CTM_F_Gid: GETFIELDCOPY(gid,sep); break; case CTM_F_Mode: GETFIELDCOPY(mode,sep); break; *************** *** 132,138 **** } if(!strcmp(sp->Key,"FN")) { strcpy(buf,name); ! strcat(buf,".ctm"); i = ctm_edit(trash,cnt,name,buf); if(i) { fprintf(stderr," %s %s Edit failed with code %d.\n", --- 132,138 ---- } if(!strcmp(sp->Key,"FN")) { strcpy(buf,name); ! strcat(buf,TMPSUFF); i = ctm_edit(trash,cnt,name,buf); if(i) { fprintf(stderr," %s %s Edit failed with code %d.\n", *************** *** 177,182 **** --- 177,191 ---- } WRONG } + + if(md5) Free(md5); + if(uid) Free(uid); + if(gid) Free(gid); + if(mode) Free(mode); + if(md5before) Free(md5before); + if(trash) Free(trash); + if(name) Free(name); + q = MD5End (&ctx,md5_1); GETFIELD(p,'\n'); if(strcmp(q,p)) WRONG *** ./usr.sbin/ctm/ctm/ctm_syntax.c#ctm Tue Jan 30 11:44:21 1996 --- ./usr.sbin/ctm/ctm/ctm_syntax.c Thu Feb 1 09:46:07 1996 *************** *** 25,52 **** #define File CTM_Q_Name_File #define Dir CTM_Q_Name_Dir #define New CTM_Q_Name_New #define After CTM_Q_MD5_After #define Before CTM_Q_MD5_Before #define Chunk CTM_Q_MD5_Chunk #define Force CTM_Q_MD5_Force static int ctmFM[] = /* File Make */ ! { Name|File|New, Uid, Gid, Mode, MD5|After|Chunk, Count, Bytes,0 }; static int ctmFS[] = /* File Substitute */ ! { Name|File, Uid, Gid, Mode, MD5|Before|Force, MD5|After|Chunk, Count, Bytes,0 }; static int ctmFE[] = /* File Edit */ ! { Name|File, Uid, Gid, Mode, MD5|Before, MD5|After, Count, Bytes,0 }; static int ctmFR[] = /* File Remove */ ! { Name|File, MD5|Before, 0 }; static int ctmAS[] = /* Attribute Substitute */ ! { Name, Uid, Gid, Mode, 0 }; static int ctmDM[] = /* Directory Make */ { Name|Dir|New , Uid, Gid, Mode, 0 }; --- 25,53 ---- #define File CTM_Q_Name_File #define Dir CTM_Q_Name_Dir #define New CTM_Q_Name_New + #define Subst CTM_Q_Name_Subst #define After CTM_Q_MD5_After #define Before CTM_Q_MD5_Before #define Chunk CTM_Q_MD5_Chunk #define Force CTM_Q_MD5_Force static int ctmFM[] = /* File Make */ ! { Name|File|New|Subst, Uid, Gid, Mode, MD5|After|Chunk, Count, Bytes,0 }; static int ctmFS[] = /* File Substitute */ ! { Name|File|Subst, Uid, Gid, Mode, MD5|Before|Force, MD5|After|Chunk, Count, Bytes,0 }; static int ctmFE[] = /* File Edit */ ! { Name|File|Subst, Uid, Gid, Mode, MD5|Before, MD5|After, Count, Bytes,0 }; static int ctmFR[] = /* File Remove */ ! { Name|File|Subst, MD5|Before, 0 }; static int ctmAS[] = /* Attribute Substitute */ ! { Name|Subst, Uid, Gid, Mode, 0 }; static int ctmDM[] = /* Directory Make */ { Name|Dir|New , Uid, Gid, Mode, 0 }; -- =Christian Haury (Christian.Haury@sagem.fr) --------------------------------------------------------- | SAGEM Eragny - Avenue du Gros Chene - Eragny BP 51 | | 95612 Cergy Pontoise Cedex - France | | phone : +33 (1) 34 30 53 93 | telex : 607387F | | fax : +33 (1) 34 30 50 28 | teletex : 933-130731770 | ---------------------------------------------------------
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi? <199602011750.SAA05008>