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>
