summaryrefslogtreecommitdiffstats
path: root/usr.sbin/ctm
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>1996-08-30 10:21:00 +0000
committerphk <phk@FreeBSD.org>1996-08-30 10:21:00 +0000
commitd564e1831385a2423f7a027b94d614558a09d924 (patch)
tree3a20c2d604808479b1443b9686cfdce973836775 /usr.sbin/ctm
parent31060e30d73e1f88c3b5fa85b5e547fde68fc7ba (diff)
downloadFreeBSD-src-d564e1831385a2423f7a027b94d614558a09d924.zip
FreeBSD-src-d564e1831385a2423f7a027b94d614558a09d924.tar.gz
Some new options, useful for restoring single files or subtrees from the
deltas. Submitted by: A JOSEPH KOSHY <koshy@fakir.india.hp.com>
Diffstat (limited to 'usr.sbin/ctm')
-rw-r--r--usr.sbin/ctm/ctm/Makefile4
-rw-r--r--usr.sbin/ctm/ctm/ctm.1147
-rw-r--r--usr.sbin/ctm/ctm/ctm.c125
-rw-r--r--usr.sbin/ctm/ctm/ctm.h25
-rw-r--r--usr.sbin/ctm/ctm/ctm_pass1.c84
-rw-r--r--usr.sbin/ctm/ctm/ctm_pass2.c55
-rw-r--r--usr.sbin/ctm/ctm/ctm_pass3.c43
-rw-r--r--usr.sbin/ctm/ctm/ctm_passb.c142
-rw-r--r--usr.sbin/ctm/ctm/ctm_syntax.c20
9 files changed, 562 insertions, 83 deletions
diff --git a/usr.sbin/ctm/ctm/Makefile b/usr.sbin/ctm/ctm/Makefile
index 567b203..0d1e044 100644
--- a/usr.sbin/ctm/ctm/Makefile
+++ b/usr.sbin/ctm/ctm/Makefile
@@ -6,13 +6,13 @@
# this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
# ----------------------------------------------------------------------------
#
-# $Id: Makefile,v 1.8 1995/03/25 18:14:22 joerg Exp $
+# $Id: Makefile,v 1.9 1995/07/12 18:35:22 bde Exp $
#
PROG= ctm
NOTYET= ctm_ed.c
SRCS= ctm.c ctm_input.c ctm_pass1.c ctm_pass2.c ctm_pass3.c \
- ctm_syntax.c ctm_ed.c
+ ctm_passb.c ctm_syntax.c ctm_ed.c
LDADD+= -lmd
DPADD+= ${LIBMD}
MAN1= ctm.1
diff --git a/usr.sbin/ctm/ctm/ctm.1 b/usr.sbin/ctm/ctm/ctm.1
index c28da41..e359857 100644
--- a/usr.sbin/ctm/ctm/ctm.1
+++ b/usr.sbin/ctm/ctm/ctm.1
@@ -10,7 +10,7 @@
.\"
.\" CTM and ctm(1) by <phk@login.dknet.dk>
.\"
-.\" $Id: ctm.1,v 1.6 1996/05/27 22:46:21 wosch Exp $
+.\" $Id: ctm.1,v 1.7 1996/07/24 21:36:48 phk Exp $
.\"
.Dd Mar 25, 1995
.Os
@@ -20,11 +20,15 @@
.Nd source code mirror program
.Sh SYNOPSIS
.Nm ctm
-.Op Fl cFpPquv
+.Op Fl cFklquv
.Op Fl b Ar basedir
+.Op Fl B Ar backup-file
+.Op Fl e Ar include-regex
+.Op Fl t Ar tar-command
.Op Fl T Ar tmpdir
.Op Fl V Ar level
-.Ar file Op ...
+.Op Fl x Ar exclude-regex
+.Ar file...
.Sh DESCRIPTION
.Nm Ctm
was originally
@@ -55,7 +59,7 @@ 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
+Before working on a file
.Ar name
.Nm ctm
first checks for the existence of the file
@@ -64,17 +68,45 @@ If this file exists,
.Nm ctm
works on it instead.
-Pass 1 will validate that the input file is OK. The syntax, the data
+Pass 1 will verify 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
-will never be able to do anything with the file, so it will simply
-reject it.
+will simply reject the input file.
Pass 2 will validate that the directory tree is in the state expected by
the CTM delta. This is done by looking for files and directories which
-should/should not exists and by checking the MD5 checksums of files.
+should/should not exist and by checking the MD5 checksums of files.
-Pass 3 will actually apply the delta.
+If a
+.Ar backup-file
+had been specified using the
+.Fl B
+option, all files that would be modified by this
+.Nm ctm
+invocation are backed up
+to this file using the archiver command specified by the
+.Fl t
+option. The default archiver command is
+.Nm "tar -rf %s -T -" .
+
+Pass 3 will actually apply the delta.
+
+The list of files that would be modified by
+.Nm ctm
+is subject to filtering regular expressions specified
+using the
+.Fl e
+and
+.Fl x
+options.
+The
+.Fl e
+and
+.Fl x
+options are applied in order of appearance on the command line. The last
+filter that matched a given file name determines whether the file would be
+operated on or left alone by
+.Nm ctm .
.Nm Ctm
will extract the file hierarchy below its working directory. Absolute
@@ -91,23 +123,76 @@ are explicitly prohibited as a security measure.
.It Fl b Ar basedir
Prepend the path
.Ar basedir
-on every filename.
+to every filename.
+
+.It Fl B Ar backup-file
+Backup all files that would be modified by this CTM run to
+.Ar backup-file .
+If any filters are specified using the
+.Fl e
+and
+.Fl x
+options, then the final set of files backed up are those that would be
+modified by CTM after the filters are applied.
.It Fl c
Check it out, don't do anything.
+.It Fl e Ar regular_expression
+Match each name in the CTM file against
+.Ar regular_expression ,
+and if it matches process the file, otherwise leave it alone. There may be
+any number of these options. Use of this option disables the
+.Pa .ctm_status
+sequence number checks. For example, the expression
+.Ic ^usr.sbin/ctm
+for example, will select the
+.Nm usr.sbin/ctm
+source directory and all pathnames under it.
+
+Pathnames can be disabled from being considered by CTM using the
+.Fl x
+option.
+
.It Fl F
Force.
-.It Fl p
-Less paranoid.
+.It Fl k
+Keep files and directories and don't remove them even if the CTM file
+specifies they are to be removed. If the
+.Fl B
+option is specified, these files and directories will not be backed up.
+
+.It Fl l
+List files that would be modified by this invocation of CTM and the
+actions that would be performed on them. Use of the
+.Fl l
+option disables the
+.Pa .ctm_status
+checks and integrity checks on the source tree being operated on. The
+.Fl l
+option can be combined with the
+.Fl e
+and
+.Fl x
+options to determine which files would be modified by the given set of
+command line options.
-.It Fl P
-Paranoid.
.It Fl q
Tell us less.
+.It Fl t Ar tar-command
+Use
+.Ar tar-command
+instead of the default archiver
+.Nm tar .
+This option takes effect only if a backup file had been specified using the
+.Fl B
+option. A %s in the tar command will be replaced by the name of the backup
+file.
+
+
.It Fl T Ar tmpdir
Put temporary files under
.Ar tmpdir .
@@ -124,6 +209,18 @@ Tell us more.
.Ar Level
is the level of verbosity.
+.It Fl x Ar regular_expression
+Match each name in the CTM file against
+.Ar regular_expression
+and if it matches, leave the file alone. There may be any number of these
+options. Use of this option disables the
+.Pa .ctm_status
+sequence number checks.
+
+Pathnames can be selected for CTM's consideration using the
+.Fl e
+option.
+
.El
.Sh ENVIRONMENT
@@ -144,6 +241,14 @@ contains the sequence number of the last CTM delta applied. Changing
or removing this file will greatly confuse
.Nm ctm .
+Using the
+.Fl e
+and
+.Fl x
+options can update a partial subset of the source tree and causes sources
+to be in an inconsistent state. It is assumed that you know what you are
+doing when you use these options.
+
.Sh EXAMPLES
.Bd -literal
@@ -153,14 +258,20 @@ cd ~cvs
.Ed
+To extract and patch all sources under `lib'
+.Bd -literal
+cd ~/lib-srcs
+/usr/sbin/ctm -e '^lib' ~ctm/src-cur*
+.Ed
.Sh DIAGNOSTICS
-Numerous messages, hopefully self-explaining. The
+Numerous messages, hopefully self-explanatory. The
.Dq noise level
can be adjusted with the
-.Fl q
-and
+.Fl q ,
.Fl v
+and
+.Fl V
options.
.Sh SEE ALSO
@@ -169,7 +280,7 @@ options.
.Sh HISTORY
-Initial trials ran during the FreeBSD 1.1.5, and many bugs and
+Initial trials were run during the work on FreeBSD 1.1.5, and many bugs and
methods were hashed out.
The
diff --git a/usr.sbin/ctm/ctm/ctm.c b/usr.sbin/ctm/ctm/ctm.c
index 0aff1a9..c0553ed 100644
--- a/usr.sbin/ctm/ctm/ctm.c
+++ b/usr.sbin/ctm/ctm/ctm.c
@@ -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.12 1996/02/05 16:06:46 phk Exp $
+ * $Id: ctm.c,v 1.13 1996/04/29 21:02:28 phk 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 <file> Backup to tar-file.
* -d <int> Debug TBD.
* -m <mail-addr> Email me instead.
* -r <name> Reconstruct file.
@@ -22,16 +21,21 @@
*
* Options we have:
* -b <dir> Base-dir
+ * -B <file> Backup to tar-file.
+ * -t Tar command (default as in TARCMD).
* -c Check it out, don't do anything.
* -F Force
- * -p Less paranoid.
- * -P Paranoid.
* -q Tell us less.
* -T <tmpdir>. Temporary files.
* -u Set all file modification times to the timestamp
* -v Tell us more.
* -V <level> Tell us more level = number of -v
+ * -k Keep files and directories that would have been removed.
+ * -l List actions.
*
+ * Options we don't actually use:
+ * -p Less paranoid.
+ * -P Paranoid.
*/
#define EXTERN /* */
@@ -44,35 +48,82 @@ extern int Proc(char *, unsigned applied);
int
main(int argc, char **argv)
{
- int stat=0;
+ int stat=0, err=0;
int c;
extern int optopt,optind;
extern char * optarg;
unsigned applied = 0;
FILE *statfile;
+ struct CTM_Filter *nfilter = NULL; /* new filter */
u_char * basedir;
basedir = NULL;
Verbose = 1;
Paranoid = 1;
SetTime = 0;
+ KeepIt = 0;
+ ListIt = 0;
+ BackupFile = NULL;
+ TarCmd = TARCMD;
+ LastFilter = FilterList = NULL;
setbuf(stderr,0);
setbuf(stdout,0);
- while((c=getopt(argc,argv,"ab:B:cd:Fm:pPqr:R:T:uV:v")) != -1) {
+ while((c=getopt(argc,argv,"ab:B:cd:e:Fklm:pPqr:R:t:T:uV:vx:")) != -1) {
switch (c) {
case 'b': basedir = optarg; break; /* Base Directory */
+ case 'B': BackupFile = optarg; break;
case 'c': CheckIt++; break; /* Only check it */
+ case 'F': Force = 1; break;
+ case 'k': KeepIt++; break; /* Don't do removes */
+ case 'l': ListIt++; break; /* Only list actions and files */
case 'p': Paranoid--; break; /* Less Paranoid */
case 'P': Paranoid++; break; /* More Paranoid */
case 'q': Verbose--; break; /* Quiet */
- case 'v': Verbose++; break; /* Verbose */
- case 'T': TmpDir = optarg; break;
- case 'F': Force = 1; break;
+ case 't': TarCmd = optarg; break; /* archiver command */
+ case 'T': TmpDir = optarg; break; /* set temporary directory */
case 'u': SetTime++; break; /* Set timestamp on files */
+ case 'v': Verbose++; break; /* Verbose */
case 'V': sscanf(optarg,"%d", &c); /* Verbose */
Verbose += c;
break;
+ case 'e': /* filter expressions */
+ case 'x':
+ if (NULL == (nfilter = Malloc(sizeof(struct CTM_Filter)))) {
+ fprintf(stderr,
+ "Out of memory for expressions: \"%s\"\n",
+ optarg);
+ stat++;
+ break;
+ }
+
+ (void) memset(nfilter, 0, sizeof(struct CTM_Filter));
+
+ if (0 != (err =
+ regcomp(&nfilter->CompiledRegex, optarg, REG_NOSUB))) {
+
+ char errmsg[128];
+
+ regerror(err, &nfilter->CompiledRegex, errmsg,
+ sizeof(errmsg));
+ fprintf(stderr, "Regular expression: \"%s\"\n", errmsg);
+ stat++;
+ break;
+ }
+
+ /* note whether the filter enables or disables on match */
+ nfilter->Action =
+ (('e' == c) ? CTM_FILTER_ENABLE : CTM_FILTER_DISABLE);
+
+ /* link in the expression into the list */
+ nfilter->Next = NULL;
+ if (NULL == FilterList) {
+ LastFilter = FilterList = nfilter; /* init head and tail */
+ } else { /* place at tail */
+ LastFilter->Next = nfilter;
+ LastFilter = nfilter;
+ }
+ break;
case ':':
fprintf(stderr,"Option '%c' requires an argument.\n",optopt);
stat++;
@@ -110,26 +161,37 @@ main(int argc, char **argv)
}
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);
- }
+ if(ListIt)
+ applied = 0;
+ else
+ if((statfile = fopen(Buffer, "r")) == NULL) {
+ if (Verbose > 0)
+ fprintf(stderr, "Warning: %s not found.\n", Buffer);
+ } else {
+ fscanf(statfile, "%*s %u", &applied);
+ fclose(statfile);
+ }
if(!argc)
stat |= Proc("-", applied);
while(argc-- && stat == Exit_Done) {
stat |= Proc(*argv++, applied);
- stat &= ~Exit_Version;
+ stat &= ~(Exit_Version | Exit_NoMatch);
}
if(stat == Exit_Done)
stat = Exit_OK;
- if(Verbose)
+ if(Verbose > 0)
fprintf(stderr,"Exit(%d)\n",stat);
+
+ if (FilterList)
+ for (nfilter = FilterList; nfilter; ) {
+ struct CTM_Filter *tmp = nfilter->Next;
+ Free(nfilter);
+ nfilter = tmp;
+ }
return stat;
}
@@ -176,7 +238,8 @@ Proc(char *filename, unsigned applied)
return Exit_Broke;
}
unlink(fn);
- fprintf(stderr,"Writing tmp-file \"%s\"\n",fn);
+ if (Verbose > 0)
+ fprintf(stderr,"Writing tmp-file \"%s\"\n",fn);
while(EOF != (i=getc(f)))
if(EOF == putc(i,f2)) {
fclose(f2);
@@ -192,6 +255,11 @@ Proc(char *filename, unsigned applied)
if((i=Pass1(f, applied)))
goto exit_and_close;
+ if(ListIt) {
+ i = Exit_Done;
+ goto exit_and_close;
+ }
+
if(!p) {
rewind(f);
} else {
@@ -216,10 +284,25 @@ Proc(char *filename, unsigned applied)
}
if(CheckIt) {
- fprintf(stderr,"All checks out ok.\n");
+ if (Verbose > 0)
+ fprintf(stderr,"All checks out ok.\n");
i = Exit_Done;
goto exit_and_close;
}
+
+ /* backup files if requested */
+ if(BackupFile) {
+
+ i = PassB(f);
+
+ if(!p) {
+ rewind(f);
+ } else {
+ pclose(f);
+ f = popen(p,"r");
+ if(!f) { perror(p); return Exit_Broke; }
+ }
+ }
i=Pass3(f);
@@ -232,6 +315,8 @@ exit_and_close:
if(i)
return i;
- fprintf(stderr,"All done ok\n");
+ if (Verbose > 0)
+ fprintf(stderr,"All done ok\n");
+
return Exit_Done;
}
diff --git a/usr.sbin/ctm/ctm/ctm.h b/usr.sbin/ctm/ctm/ctm.h
index a34a238..93498b5 100644
--- a/usr.sbin/ctm/ctm/ctm.h
+++ b/usr.sbin/ctm/ctm/ctm.h
@@ -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.8 1996/02/05 16:06:47 phk Exp $
+ * $Id: ctm.h,v 1.9 1996/04/29 21:02:29 phk Exp $
*
*/
@@ -22,12 +22,14 @@
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/time.h>
+#include <regex.h>
#define VERSION "2.0"
#define MAXSIZE (1024*1024*10)
#define SUBSUFF ".ctm"
#define TMPSUFF ".ctmtmp"
+#define TARCMD "tar -rf %s -T -"
/* The fields... */
#define CTM_F_MASK 0xff
@@ -51,12 +53,21 @@
#define CTM_Q_MD5_Force 0x0800
struct CTM_Syntax {
- char *Key;
- int *List;
+ char *Key; /* CTM key for operation */
+ int *List; /* List of operations */
};
extern struct CTM_Syntax Syntax[];
+struct CTM_Filter {
+ struct CTM_Filter *Next; /* next filter in the list */
+ int Action; /* enable or disable */
+ regex_t CompiledRegex; /* compiled regex */
+};
+
+#define CTM_FILTER_DISABLE 0
+#define CTM_FILTER_ENABLE 1
+
#define Malloc malloc
#define Free free
#define Delete(foo) if (!foo) ; else {Free(foo); foo = 0; }
@@ -74,6 +85,8 @@ EXTERN u_char *FileName;
EXTERN u_char *TmpDir;
EXTERN u_char *CatPtr;
EXTERN u_char *Buffer;
+EXTERN u_char *BackupFile;
+EXTERN u_char *TarCmd;
/*
* Paranoid -- Just in case they should be after us...
@@ -106,8 +119,12 @@ EXTERN int Verbose;
EXTERN int Exit;
EXTERN int Force;
EXTERN int CheckIt;
+EXTERN int KeepIt;
+EXTERN int ListIt;
EXTERN int SetTime;
EXTERN struct timeval Times[2];
+EXTERN struct CTM_Filter *FilterList;
+EXTERN struct CTM_Filter *LastFilter;
#define Exit_OK 0
#define Exit_Garbage 1
@@ -118,6 +135,7 @@ EXTERN struct timeval Times[2];
#define Exit_Mess 32
#define Exit_Done 64
#define Exit_Version 128
+#define Exit_NoMatch 256
void Fatal_(int ln, char *fn, char *kind);
#define Fatal(foo) Fatal_(__LINE__,__FILE__,foo)
@@ -139,6 +157,7 @@ u_char * Fdata(FILE *fd, int u_chars, MD5_CTX *ctx);
int Pass1(FILE *fd, unsigned applied);
int Pass2(FILE *fd);
+int PassB(FILE *fd);
int Pass3(FILE *fd);
int ctm_edit(u_char *script, int length, char *filein, char *fileout);
diff --git a/usr.sbin/ctm/ctm/ctm_pass1.c b/usr.sbin/ctm/ctm/ctm_pass1.c
index d0bf6c3..563d4d9 100644
--- a/usr.sbin/ctm/ctm/ctm_pass1.c
+++ b/usr.sbin/ctm/ctm/ctm_pass1.c
@@ -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.11 1995/07/12 09:16:08 phk Exp $
+ * $Id: ctm_pass1.c,v 1.12 1996/02/05 16:06:50 phk Exp $
*
*/
@@ -23,9 +23,9 @@ Pass1(FILE *fd, unsigned applied)
u_char *p,*q;
MD5_CTX ctx;
int i,j,sep,cnt;
- u_char *md5=0,*trash=0;
+ u_char *md5=0,*name=0,*trash=0;
struct CTM_Syntax *sp;
- int slashwarn=0;
+ int slashwarn=0, match=0, total_matches=0;
unsigned current;
char md5_1[33];
@@ -55,8 +55,10 @@ Pass1(FILE *fd, unsigned applied)
GETFIELDCOPY(Prefix,'\n'); /* <Prefix> */
sscanf(Nbr, "%u", &current);
+ if (FilterList || ListIt)
+ current = 0; /* ignore if -l or if filters are present */
if(current && current <= applied) {
- if(Verbose)
+ if(Verbose > 0)
fprintf(stderr,"Delta number %u is already applied; ignoring.\n",
current);
return Exit_Version;
@@ -64,8 +66,14 @@ Pass1(FILE *fd, unsigned applied)
for(;;) {
Delete(md5);
+ Delete(name);
Delete(trash);
cnt = -1;
+ /* if a filter list is defined we assume that all pathnames require
+ an action opposite to that requested by the first filter in the
+ list.
+ If no filter is defined, all pathnames are assumed to match. */
+ match = (FilterList ? !(FilterList->Action) : CTM_FILTER_ENABLE);
GETFIELD(p,' '); /* CTM_something */
@@ -92,31 +100,61 @@ Pass1(FILE *fd, unsigned applied)
sep = ' ';
else
sep = '\n';
- if(Verbose > 5)
- fprintf(stderr," %x(%d)",sp->List[i],sep);
+
+ if(Verbose > 5)
+ fprintf(stderr," %x(%d)",sp->List[i],sep);
switch (j & CTM_F_MASK) {
case CTM_F_Name: /* XXX check for garbage and .. */
- GETFIELD(p,sep);
- j = strlen(p);
- if(p[j-1] == '/' && !slashwarn) {
+ GETFIELDCOPY(name,sep);
+ j = strlen(name);
+ if(name[j-1] == '/' && !slashwarn) {
fprintf(stderr,"Warning: contains trailing slash\n");
slashwarn++;
}
- if (p[0] == '/') {
+ if (name[0] == '/') {
Fatal("Absolute paths are illegal.");
return Exit_Mess;
}
+ q = name;
for (;;) {
- if (p[0] == '.' && p[1] == '.')
- if (p[2] == '/' || p[2] == '\0') {
+ if (q[0] == '.' && q[1] == '.')
+ if (q[2] == '/' || q[2] == '\0') {
Fatal("Paths containing '..' are illegal.");
return Exit_Mess;
}
- if ((p = strchr(p, '/')) == NULL)
+ if ((q = strchr(q, '/')) == NULL)
break;
- p++;
+ q++;
+ }
+
+ /* if we have been asked to `keep' files then skip
+ removes; i.e. we don't match these entries at
+ all. */
+ if (KeepIt &&
+ (!strcmp(sp->Key,"DR") || !strcmp(sp->Key,"FR"))) {
+ match = CTM_FILTER_DISABLE;
+ break;
+ }
+
+ /* If filter expression have been defined, match the
+ path name against the expression list. */
+
+ if (FilterList) {
+ struct CTM_Filter *filter;
+
+ for (filter = FilterList; filter;
+ filter = filter->Next) {
+ if (0 == regexec(&filter->CompiledRegex, name,
+ 0, 0, 0))
+ /* if the name matches, adopt the
+ action */
+ match = filter->Action;
+ }
}
+
+ /* Add up the total number of matches */
+ total_matches += match;
break;
case CTM_F_Uid:
GETFIELD(p,sep);
@@ -170,22 +208,22 @@ Pass1(FILE *fd, unsigned applied)
p = MD5Data(trash,cnt,md5_1);
if(md5 && strcmp(md5,p)) {
Fatal("Internal MD5 failed.");
- return 1;
+ return Exit_Garbage;
default:
fprintf(stderr,"List = 0x%x\n",j);
Fatal("List had garbage.");
- return 1;
-
+ return Exit_Garbage;
}
-
- }
}
+ }
if(Verbose > 5)
putc('\n',stderr);
- continue;
+ if(ListIt && match)
+ printf("> %s %s\n", sp->Key, name);
}
Delete(md5);
+ Delete(name);
Delete(trash);
q = MD5End (&ctx,md5_1);
@@ -198,7 +236,7 @@ Pass1(FILE *fd, unsigned applied)
Fatal("MD5 sum doesn't match.");
fprintf(stderr,"\tI have:<%s>\n",q);
fprintf(stderr,"\tShould have been:<%s>\n",p);
- return 1;
+ return Exit_Garbage;
}
if (-1 != getc(fd)) {
if(!Force) {
@@ -206,5 +244,7 @@ Pass1(FILE *fd, unsigned applied)
return 16;
}
}
- return 0;
+ if ((Verbose > 1) && (0 == total_matches))
+ printf("No matches in \"%s\"\n", FileName);
+ return (total_matches ? Exit_OK : Exit_NoMatch);
}
diff --git a/usr.sbin/ctm/ctm/ctm_pass2.c b/usr.sbin/ctm/ctm/ctm_pass2.c
index 9ddd433..3261d8b 100644
--- a/usr.sbin/ctm/ctm/ctm_pass2.c
+++ b/usr.sbin/ctm/ctm/ctm_pass2.c
@@ -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.11 1996/02/05 16:06:52 phk Exp $
+ * $Id: ctm_pass2.c,v 1.12 1996/04/29 21:02:30 phk Exp $
*
*/
@@ -27,7 +27,10 @@ Pass2(FILE *fd)
struct CTM_Syntax *sp;
struct stat st;
int ret = 0;
+ int match = 0;
char md5_1[33];
+ struct CTM_Filter *filter;
+ FILE *ed = NULL;
if(Verbose>3)
printf("Pass2 -- Checking if CTM-patch will apply\n");
@@ -49,6 +52,12 @@ Pass2(FILE *fd)
Delete(md5);
cnt = -1;
+ /* if a filter list was specified, check file name against
+ the filters specified
+ if no filter was given operate on all files. */
+ match = (FilterList ?
+ !(FilterList->Action) : CTM_FILTER_ENABLE);
+
GETFIELD(p,' ');
if (p[0] != 'C' || p[1] != 'T' || p[2] != 'M') WRONG
@@ -70,6 +79,22 @@ Pass2(FILE *fd)
switch (j & CTM_F_MASK) {
case CTM_F_Name:
GETNAMECOPY(name,sep,j,0);
+ /* If `keep' was specified, we won't remove any files,
+ so don't check if the file exists */
+ if (KeepIt &&
+ (!strcmp(sp->Key,"FR") || !strcmp(sp->Key,"DR"))) {
+ match = CTM_FILTER_DISABLE;
+ break;
+ }
+
+ for (filter = FilterList; filter; filter = filter->Next) if (0 == regexec(&filter->CompiledRegex, name,
+ 0, 0, 0)) {
+ match = filter->Action;
+ }
+
+ if (CTM_FILTER_DISABLE == match)
+ break; /* should ignore this file */
+
/* XXX Check DR DM rec's for parent-dir */
if(j & CTM_Q_Name_New) {
/* XXX Check DR FR rec's for item */
@@ -124,7 +149,7 @@ Pass2(FILE *fd)
if(j & CTM_Q_MD5_Before) {
char *tmp;
GETFIELD(p,sep);
- if((st.st_mode & S_IFMT) == S_IFREG &&
+ if(match && (st.st_mode & S_IFMT) == S_IFREG &&
(tmp = MD5File(name,md5_1)) != NULL &&
strcmp(tmp,p)) {
fprintf(stderr," %s: %s md5 mismatch.\n",
@@ -154,6 +179,8 @@ Pass2(FILE *fd)
case CTM_F_Bytes:
if(cnt < 0) WRONG
GETDATA(trash,cnt);
+ if (!match)
+ break;
if(!strcmp(sp->Key,"FN")) {
p = tempnam(TmpDir,"CTMclient");
j = ctm_edit(trash,cnt,name,p);
@@ -174,6 +201,30 @@ Pass2(FILE *fd)
}
unlink(p);
Free(p);
+ } else if (!strcmp(sp->Key,"FE")) {
+ p = tempnam(TmpDir,"CTMclient");
+ ed = popen("ed","w");
+ if (!ed) {
+ WRONG
+ }
+ fprintf(ed,"e %s\n", name);
+ if (cnt != fwrite(trash,1,cnt,ed)) {
+ perror(name);
+ pclose(ed);
+ WRONG
+ }
+ fprintf(ed,"w %s\n",p);
+ if (pclose(ed)) {
+ perror(p);
+ WRONG
+ }
+ if(strcmp(md5,MD5File(p,md5_1))) {
+ fprintf(stderr,"%s %s MD5 didn't come out right\n",
+ sp->Key, name);
+ WRONG
+ }
+ unlink(p);
+ Free(p);
}
break;
diff --git a/usr.sbin/ctm/ctm/ctm_pass3.c b/usr.sbin/ctm/ctm/ctm_pass3.c
index 07d3e6b..2b69c16 100644
--- a/usr.sbin/ctm/ctm/ctm_pass3.c
+++ b/usr.sbin/ctm/ctm/ctm_pass3.c
@@ -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.12 1996/02/05 16:06:53 phk Exp $
+ * $Id: ctm_pass3.c,v 1.13 1996/04/29 21:02:32 phk Exp $
*
*/
@@ -39,8 +39,9 @@ Pass3(FILE *fd)
FILE *ed=0;
struct stat st;
char md5_1[33];
+ int match=0;
struct timeval times[2];
-
+ struct CTM_Filter *filter = NULL;
if(Verbose>3)
printf("Pass3 -- Applying the CTM-patch\n");
MD5Init (&ctx);
@@ -153,7 +154,27 @@ Pass3(FILE *fd)
j = strlen(name)-1;
if(name[j] == '/') name[j] = '\0';
- fprintf(stderr,"> %s %s\n",sp->Key,name);
+ /*
+ * If a filter list is specified, run thru the filter list and
+ * match `name' against filters. If the name matches, set the
+ * required action to that specified in the filter.
+ * The default action if no filterlist is given is to match
+ * everything.
+ */
+
+ match = (FilterList ? !(FilterList->Action) : CTM_FILTER_ENABLE);
+ for (filter = FilterList; filter; filter = filter->Next) {
+ if (0 == regexec(&filter->CompiledRegex, name,
+ 0, 0, 0)) {
+ match = filter->Action;
+ }
+ }
+
+ if (CTM_FILTER_DISABLE == match) /* skip file if disabled */
+ continue;
+
+ if (Verbose > 0)
+ fprintf(stderr,"> %s %s\n",sp->Key,name);
if(!strcmp(sp->Key,"FM") || !strcmp(sp->Key, "FS")) {
i = open(name,O_WRONLY|O_CREAT|O_TRUNC,0666);
if(i < 0) {
@@ -228,7 +249,11 @@ Pass3(FILE *fd)
continue;
}
if(!strcmp(sp->Key,"FR")) {
- if (0 != unlink(name)) {
+ if (KeepIt) {
+ if (Verbose > 1)
+ printf("<%s> not removed\n", name);
+ }
+ else if (0 != unlink(name)) {
fprintf(stderr,"<%s> unlink failed\n",name);
if (!Force)
WRONG
@@ -240,8 +265,14 @@ Pass3(FILE *fd)
* We cannot use rmdir() because we do not get the directories
* in '-depth' order (cvs-cur.0018.gz for examples)
*/
- sprintf(buf,"rm -rf %s",name);
- system(buf);
+ if (KeepIt) {
+ if (Verbose > 1) {
+ printf("<%s> not removed\n", name);
+ }
+ } else {
+ sprintf(buf,"rm -rf %s",name);
+ system(buf);
+ }
continue;
}
WRONG
diff --git a/usr.sbin/ctm/ctm/ctm_passb.c b/usr.sbin/ctm/ctm/ctm_passb.c
new file mode 100644
index 0000000..0fce077
--- /dev/null
+++ b/usr.sbin/ctm/ctm/ctm_passb.c
@@ -0,0 +1,142 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <koshy@india.hp.com> wrote this file. As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return. Joseph Koshy
+ * ----------------------------------------------------------------------------
+ *
+ * $Id$
+ *
+ */
+
+#include "ctm.h"
+#define BADREAD 32
+
+/*---------------------------------------------------------------------------*/
+/* PassB -- Backup modified files.
+ */
+
+int
+PassB(FILE *fd)
+{
+ u_char *p,*q;
+ MD5_CTX ctx;
+ int i,j,sep,cnt;
+ u_char *md5=0,*md5before=0,*trash=0,*name=0,*uid=0,*gid=0,*mode=0;
+ struct CTM_Syntax *sp;
+ FILE *b = 0; /* backup command */
+ u_char buf[BUFSIZ];
+ char md5_1[33];
+ int ret = 0;
+ int match = 0;
+ struct CTM_Filter *filter = NULL;
+
+ if(Verbose>3)
+ printf("PassB -- Backing up files which would be changed.\n");
+
+ MD5Init (&ctx);
+ sprintf(buf, TarCmd, BackupFile);
+ b=popen(buf, "w");
+ if(!b) { perror(buf); return Exit_Garbage; }
+
+ GETFIELD(p,' '); if(strcmp("CTM_BEGIN",p)) WRONG
+ GETFIELD(p,' '); if(strcmp(Version,p)) WRONG
+ GETFIELD(p,' '); if(strcmp(Name,p)) WRONG
+ GETFIELD(p,' '); if(strcmp(Nbr,p)) WRONG
+ GETFIELD(p,' '); if(strcmp(TimeStamp,p)) WRONG
+ GETFIELD(p,'\n'); if(strcmp(Prefix,p)) WRONG
+
+ for(;;) {
+ Delete(md5);
+ Delete(uid);
+ Delete(gid);
+ Delete(mode);
+ Delete(md5before);
+ Delete(trash);
+ Delete(name);
+ cnt = -1;
+
+ GETFIELD(p,' ');
+
+ if (p[0] != 'C' || p[1] != 'T' || p[2] != 'M') WRONG
+
+ if(!strcmp(p+3,"_END"))
+ break;
+
+ for(sp=Syntax;sp->Key;sp++)
+ if(!strcmp(p+3,sp->Key))
+ goto found;
+ WRONG
+ found:
+ for(i=0;(j = sp->List[i]);i++) {
+ if (sp->List[i+1] && (sp->List[i+1] & CTM_F_MASK) != CTM_F_Bytes)
+ sep = ' ';
+ else
+ 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;
+ case CTM_F_MD5:
+ if(j & CTM_Q_MD5_Before)
+ GETFIELDCOPY(md5before,sep);
+ else
+ GETFIELDCOPY(md5,sep);
+ break;
+ case CTM_F_Count: GETBYTECNT(cnt,sep); break;
+ case CTM_F_Bytes: GETDATA(trash,cnt); break;
+ default: WRONG
+ }
+ }
+ /* XXX This should go away. Disallow trailing '/' */
+ j = strlen(name)-1;
+ if(name[j] == '/') name[j] = '\0';
+
+ if (KeepIt &&
+ (!strcmp(sp->Key,"DR") || !strcmp(sp->Key,"FR")))
+ continue;
+
+ /* match the name against the elements of the filter list. The
+ action associated with the last matched filter determines whether
+ this file should be ignored or backed up. */
+ match = (FilterList ? !(FilterList->Action) : CTM_FILTER_ENABLE);
+ for (filter = FilterList; filter; filter = filter->Next) {
+ if (0 == regexec(&filter->CompiledRegex, name, 0, 0, 0))
+ match = filter->Action;
+ }
+
+ if (CTM_FILTER_DISABLE == match)
+ continue;
+
+ if (!strcmp(sp->Key,"FS") || !strcmp(sp->Key,"FN") ||
+ !strcmp(sp->Key,"AS") || !strcmp(sp->Key,"DR") ||
+ !strcmp(sp->Key,"FR")) {
+ /* send name to the archiver for a backup */
+ cnt = strlen(name);
+ if (cnt != fwrite(name,1,cnt,b) || EOF == fputc('\n',b)) {
+ perror(name);
+ pclose(b);
+ WRONG;
+ }
+ }
+ }
+
+ ret = pclose(b);
+
+ Delete(md5);
+ Delete(uid);
+ Delete(gid);
+ Delete(mode);
+ Delete(md5before);
+ Delete(trash);
+ Delete(name);
+
+ q = MD5End (&ctx,md5_1);
+ GETFIELD(p,'\n'); /* <MD5> */
+ if(strcmp(q,p)) WRONG
+ if (-1 != getc(fd)) WRONG
+ return ret;
+}
diff --git a/usr.sbin/ctm/ctm/ctm_syntax.c b/usr.sbin/ctm/ctm/ctm_syntax.c
index 30e2435..014207f 100644
--- a/usr.sbin/ctm/ctm/ctm_syntax.c
+++ b/usr.sbin/ctm/ctm/ctm_syntax.c
@@ -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.5 1995/05/30 03:47:28 rgrimes Exp $
+ * $Id: ctm_syntax.c,v 1.6 1996/02/05 16:06:55 phk Exp $
*
*/
@@ -56,12 +56,12 @@ static int ctmDR[] = /* Directory Remove */
{ Name|Dir, 0 };
struct CTM_Syntax Syntax[] = {
- { "FM", ctmFM },
- { "FS", ctmFS },
- { "FE", ctmFE },
- { "FN", ctmFE },
- { "FR", ctmFR },
- { "AS", ctmAS },
- { "DM", ctmDM },
- { "DR", ctmDR },
- { 0, 0} };
+ { "FM", ctmFM },
+ { "FS", ctmFS },
+ { "FE", ctmFE },
+ { "FN", ctmFE },
+ { "FR", ctmFR },
+ { "AS", ctmAS },
+ { "DM", ctmDM },
+ { "DR", ctmDR },
+ { 0, 0} };
OpenPOWER on IntegriCloud