Add support for local modifications to the tree, by using FOO.ctm instead

of FOO if present.  Various other tweaks.

Submitted by:	Christian Haury <Christian.Haury@sagem.fr>
This commit is contained in:
Poul-Henning Kamp 1996-02-05 16:06:55 +00:00
parent 486405ca25
commit b8439c2769
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=13917
8 changed files with 144 additions and 50 deletions

View File

@ -10,7 +10,7 @@
.\"
.\" CTM and ctm(1) by <phk@login.dknet.dk>
.\"
.\" $Id: ctm.1,v 1.2 1995/03/26 20:09:46 phk Exp $
.\" $Id: ctm.1,v 1.3 1996/01/31 01:58:29 nate Exp $
.\"
.Dd Mar 25, 1995
.Os
@ -21,7 +21,9 @@
.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,6 +55,15 @@ The
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,6 +88,11 @@ are explicitly prohibited as a security measure.
.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.
@ -99,6 +115,11 @@ Put temporary files under
.It Fl v
Tell us more.
.It Fl V Ar level
Tell us more.
.Ar Level
is the level of verbosity.
.El

View File

@ -6,7 +6,7 @@
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*
* $Id: ctm.c,v 1.10 1995/03/26 20:09:50 phk Exp $
* $Id: ctm.c,v 1.11 1995/05/30 03:47:19 rgrimes Exp $
*
* This is the client program of 'CTM'. It will apply a CTM-patch to a
* collection of files.
@ -14,7 +14,6 @@
* 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.
@ -22,6 +21,7 @@
* -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,6 +29,7 @@
* -q Tell us less.
* -T <tmpdir>. Temporary files.
* -v Tell us more.
* -V <level> Tell us more level = number of -v
*
*/
@ -46,16 +47,19 @@ main(int argc, char **argv)
int c;
extern int optopt,optind;
extern char * optarg;
FILE *statfile;
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:Vv")) != -1) {
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,6 +67,9 @@ main(int argc, char **argv)
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,8 +92,23 @@ main(int argc, char **argv)
argc -= optind;
argv += optind;
if((statfile = fopen(CTM_STATUS, "r")) == NULL)
fprintf(stderr, "Warning: " CTM_STATUS " not found.\n");
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);
@ -119,7 +141,7 @@ Proc(char *filename, unsigned applied)
p = 0;
f = stdin;
} else if(p && (!strcmp(p,".gz") || !strcmp(p,".Z"))) {
p = Malloc(100);
p = alloca(20 + strlen(filename));
strcpy(p,"gunzip < ");
strcat(p,filename);
f = popen(p,"r");
@ -136,7 +158,7 @@ Proc(char *filename, unsigned applied)
if(Verbose > 1)
fprintf(stderr,"Working on <%s>\n",filename);
if(FileName) Free(FileName);
Delete(FileName);
FileName = String(filename);
/* If we cannot seek, we're doomed, so copy to a tmp-file in that case */
@ -199,12 +221,11 @@ Proc(char *filename, unsigned applied)
i=Pass3(f);
exit_and_close:
if(!p) {
if(!p)
fclose(f);
} else {
else
pclose(f);
Free(p);
}
if(i)
return i;

View File

@ -6,7 +6,7 @@
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*
* $Id: ctm.h,v 1.6 1995/03/04 20:36:45 phk Exp $
* $Id: ctm.h,v 1.7 1995/05/30 03:47:21 rgrimes Exp $
*
*/
@ -24,6 +24,9 @@
#define VERSION "2.0"
#define MAXSIZE (1024*1024*10)
#define SUBSUFF ".ctm"
#define TMPSUFF ".ctmtmp"
/* The fields... */
#define CTM_F_MASK 0xff
#define CTM_F_Name 0x01
@ -39,6 +42,7 @@
#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
@ -53,6 +57,8 @@ extern struct CTM_Syntax Syntax[];
#define Malloc malloc
#define Free free
#define Delete(foo) if (!foo) ; else {Free(foo); foo = 0; }
#define String(foo) strdup(foo)
#ifndef EXTERN
# define EXTERN extern
@ -63,8 +69,9 @@ EXTERN u_char *Nbr;
EXTERN u_char *TimeStamp;
EXTERN u_char *Prefix;
EXTERN u_char *FileName;
EXTERN u_char *BaseDir;
EXTERN u_char *TmpDir;
EXTERN u_char *CatPtr;
EXTERN u_char *Buffer;
/*
* Paranoid -- Just in case they should be after us...
@ -108,13 +115,13 @@ EXTERN int CheckIt;
#define Exit_Done 64
#define Exit_Version 128
char * String(char *s);
void Fatal_(int ln, char *fn, char *kind);
#define Fatal(foo) Fatal_(__LINE__,__FILE__,foo)
#define Assert() Fatal_(__LINE__,__FILE__,"Assert failed.")
#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,6 +131,7 @@ u_char * Fdata(FILE *fd, int u_chars, MD5_CTX *ctx);
#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);

View File

@ -6,20 +6,12 @@
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*
* $Id$
* $Id: ctm_input.c,v 1.4 1994/09/22 02:49:18 phk Exp $
*
*/
#include "ctm.h"
/*---------------------------------------------------------------------------*/
char *
String(char *s)
{
char *p = malloc(strlen(s) + 1);
strcpy(p,s);
return p;
}
/*---------------------------------------------------------------------------*/
void
Fatal_(int ln, char *fn, char *kind)
@ -111,3 +103,36 @@ Fdata(FILE *fd, int u_chars, MD5_CTX *ctx)
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);
}

View File

@ -6,7 +6,7 @@
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*
* $Id: ctm_pass1.c,v 1.10 1995/05/30 03:47:23 rgrimes Exp $
* $Id: ctm_pass1.c,v 1.11 1995/07/12 09:16:08 phk Exp $
*
*/
@ -63,8 +63,8 @@ Pass1(FILE *fd, unsigned applied)
}
for(;;) {
if(md5) {Free(md5), md5 = 0;}
if(trash) {Free(trash), trash = 0;}
Delete(md5);
Delete(trash);
cnt = -1;
GETFIELD(p,' '); /* CTM_something */
@ -184,6 +184,10 @@ Pass1(FILE *fd, unsigned applied)
putc('\n',stderr);
continue;
}
Delete(md5);
Delete(trash);
q = MD5End (&ctx,md5_1);
if(Verbose > 2)
printf("Expecting Global MD5 <%s>\n",q);

View File

@ -6,7 +6,7 @@
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*
* $Id: ctm_pass2.c,v 1.9 1995/07/12 09:16:10 phk Exp $
* $Id: ctm_pass2.c,v 1.10 1995/11/10 12:17:23 phk Exp $
*
*/
@ -44,9 +44,9 @@ Pass2(FILE *fd)
/* XXX drop or use ? */
for(;;) {
if(trash) {Free(trash), trash = 0;}
if(name) {Free(name), name = 0;}
if(md5) {Free(md5), md5 = 0;}
Delete(trash);
Delete(name);
Delete(md5);
cnt = -1;
GETFIELD(p,' ');
@ -69,7 +69,7 @@ Pass2(FILE *fd)
switch (j & CTM_F_MASK) {
case CTM_F_Name:
GETFIELDCOPY(name,sep);
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 */
@ -163,7 +163,7 @@ Pass2(FILE *fd)
return ret;
}
unlink(p);
free(p);
Free(p);
}
break;
@ -171,6 +171,11 @@ Pass2(FILE *fd)
}
}
}
Delete(trash);
Delete(name);
Delete(md5);
q = MD5End (&ctx,md5_1);
GETFIELD(p,'\n'); /* <MD5> */
if(strcmp(q,p)) WRONG

View File

@ -6,7 +6,7 @@
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*
* $Id: ctm_pass3.c,v 1.10 1995/05/30 03:47:27 rgrimes Exp $
* $Id: ctm_pass3.c,v 1.11 1995/07/12 09:16:13 phk Exp $
*
*/
@ -41,13 +41,13 @@ Pass3(FILE *fd)
GETFIELD(p,'\n'); if(strcmp(Prefix,p)) WRONG
for(;;) {
if(md5) {Free(md5), md5 = 0;}
if(uid) {Free(uid), uid = 0;}
if(gid) {Free(gid), gid = 0;}
if(mode) {Free(mode), mode = 0;}
if(md5before) {Free(md5before), md5before = 0;}
if(trash) {Free(trash), trash = 0;}
if(name) {Free(name), name = 0;}
Delete(md5);
Delete(uid);
Delete(gid);
Delete(mode);
Delete(md5before);
Delete(trash);
Delete(name);
cnt = -1;
GETFIELD(p,' ');
@ -69,7 +69,7 @@ Pass3(FILE *fd)
sep = '\n';
switch (j & CTM_F_MASK) {
case CTM_F_Name: GETFIELDCOPY(name,sep); break;
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,7 +132,7 @@ Pass3(FILE *fd)
}
if(!strcmp(sp->Key,"FN")) {
strcpy(buf,name);
strcat(buf,".ctm");
strcat(buf,TMPSUFF);
i = ctm_edit(trash,cnt,name,buf);
if(i) {
fprintf(stderr," %s %s Edit failed with code %d.\n",
@ -177,6 +177,15 @@ Pass3(FILE *fd)
}
WRONG
}
Delete(md5);
Delete(uid);
Delete(gid);
Delete(mode);
Delete(md5before);
Delete(trash);
Delete(name);
q = MD5End (&ctx,md5_1);
GETFIELD(p,'\n');
if(strcmp(q,p)) WRONG

View File

@ -6,7 +6,7 @@
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*
* $Id: ctm_syntax.c,v 1.4 1994/09/22 02:49:21 phk Exp $
* $Id: ctm_syntax.c,v 1.5 1995/05/30 03:47:28 rgrimes Exp $
*
*/
@ -25,28 +25,29 @@
#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, Uid, Gid, Mode,
{ Name|File|New|Subst, Uid, Gid, Mode,
MD5|After|Chunk, Count, Bytes,0 };
static int ctmFS[] = /* File Substitute */
{ Name|File, Uid, Gid, Mode,
{ Name|File|Subst, Uid, Gid, Mode,
MD5|Before|Force, MD5|After|Chunk, Count, Bytes,0 };
static int ctmFE[] = /* File Edit */
{ Name|File, Uid, Gid, Mode,
{ Name|File|Subst, Uid, Gid, Mode,
MD5|Before, MD5|After, Count, Bytes,0 };
static int ctmFR[] = /* File Remove */
{ Name|File, MD5|Before, 0 };
{ Name|File|Subst, MD5|Before, 0 };
static int ctmAS[] = /* Attribute Substitute */
{ Name, Uid, Gid, Mode, 0 };
{ Name|Subst, Uid, Gid, Mode, 0 };
static int ctmDM[] = /* Directory Make */
{ Name|Dir|New , Uid, Gid, Mode, 0 };