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:
parent
486405ca25
commit
b8439c2769
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=13917
@ -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
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 };
|
||||
|
Loading…
Reference in New Issue
Block a user