From stephen@wilberforce.math.missouri.edu  Wed Aug 10 22:39:41 2011
Return-Path: <stephen@wilberforce.math.missouri.edu>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 2D7A5106564A
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 10 Aug 2011 22:39:41 +0000 (UTC)
	(envelope-from stephen@wilberforce.math.missouri.edu)
Received: from wilberforce.math.missouri.edu (wilberforce.math.missouri.edu [128.206.184.213])
	by mx1.freebsd.org (Postfix) with ESMTP id D2D488FC19
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 10 Aug 2011 22:39:39 +0000 (UTC)
Received: from wilberforce.math.missouri.edu (localhost [127.0.0.1])
	by wilberforce.math.missouri.edu (8.14.4/8.14.4) with ESMTP id p7AMdd7b033364
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 10 Aug 2011 17:39:39 -0500 (CDT)
	(envelope-from stephen@wilberforce.math.missouri.edu)
Received: (from stephen@localhost)
	by wilberforce.math.missouri.edu (8.14.4/8.14.4/Submit) id p7AMdcCn033363;
	Wed, 10 Aug 2011 17:39:39 -0500 (CDT)
	(envelope-from stephen)
Message-Id: <201108102239.p7AMdcCn033363@wilberforce.math.missouri.edu>
Date: Wed, 10 Aug 2011 17:39:39 -0500 (CDT)
From: Stephen Montgomery-Smith <stephen@freebsd.org>
Reply-To: Stephen Montgomery-Smith <stephen@freebsd.org>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: ctm does not work with bzip2 or xz compressed files.
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         159665
>Category:       bin
>Synopsis:       [patch] ctm(1) does not work with bzip2 or xz compressed files.
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          analyzed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Wed Aug 10 22:40:07 UTC 2011
>Closed-Date:    
>Last-Modified:  Wed Jul 03 01:34:42 UTC 2013
>Originator:     Stephen Montgomery-Smith
>Release:        FreeBSD 8.2-STABLE amd64
>Organization:
>Environment:
System: FreeBSD wilberforce 8.2-STABLE FreeBSD 8.2-STABLE #0: Sat May 28 09:40:58 CDT 2011 stephen@laptop5.gateway.2wire.net:/usr/obj/usr/src/sys/GENERIC amd64


	
>Description:
	
I run the CTM creation computers.  I would like to allow ctm to decompress bzip2'ed files and xz'ed files, as well as gzip'ed files.
>How-To-Repeat:
	
>Fix:

Apply this patch to src/usr.sbin/ctm/ctm/.

Since xz isn't part of early versions of FreeBSD (e.g. FreeBSD 7.x), I have added a comment to the man page, and a helpful error message to ctm.c.


diff -u ctm.1.orig ctm.1
--- ctm.1.orig  2011-08-10 17:04:53.000000000 -0500
+++ ctm.1       2011-08-10 17:06:01.000000000 -0500
@@ -52,8 +52,11 @@
 You can pass a CTM delta on stdin, or you can give the
 filename as an argument.
 If you do the latter, you make life a lot
-easier for your self, since the program can accept gzip'ed files and
+easier for your self, since the program can accept gzip'ed,
+bzip2'ed, or xz'ed files and
 since it will not have to make a temporary copy of your file.
+(If you pass it an xz'ed file, and xz is not part of your base system,
+you will have to install xz from the ports.)
 You can
 specify multiple deltas at one time, they will be processed one at a
 time.
diff -u ctm.c.orig ctm.c
--- ctm.c.orig	2011-08-10 17:15:30.000000000 -0500
+++ ctm.c	2011-08-10 17:19:23.000000000 -0500
@@ -211,6 +211,22 @@
 	strcat(p,filename);
 	f = popen(p,"r");
 	if(!f) { warn("%s", p); return Exit_Garbage; }
+    } else if(p && !strcmp(p,".bz2")) {
+	p = alloca(20 + strlen(filename));
+	strcpy(p,"bzcat < ");
+	strcat(p,filename);
+	f = popen(p,"r");
+	if(!f) { warn("%s", p); return Exit_Garbage; }
+    } else if(p && !strcmp(p,".xz")) {
+	if (system("which -s xz") != 0) {
+	    fprintf(stderr, "xz is not installed.  You can install it from ports.\n");
+	    return Exit_Garbage;
+	}
+	p = alloca(20 + strlen(filename));
+	strcpy(p,"xz -dc < ");
+	strcat(p,filename);
+	f = popen(p,"r");
+	if(!f) { warn("%s", p); return Exit_Garbage; }
     } else {
 	p = 0;
 	f = fopen(filename,"r");

>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->analyzed 
State-Changed-By: rik 
State-Changed-When: Wed Jan 18 13:41:29 UTC 2012 
State-Changed-Why:  
I'll take care of it. 


Responsible-Changed-From-To: freebsd-bugs->rik 
Responsible-Changed-By: rik 
Responsible-Changed-When: Wed Jan 18 13:41:29 UTC 2012 
Responsible-Changed-Why:  
I'll take care of it. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=159665 

From: Emil Cazamir <emil.cazamir@arabesque.ro>
To: bug-followup@FreeBSD.org, stephen@freebsd.org
Cc:  
Subject: Re: bin/159665: [patch] ctm(1) does not work with bzip2 or xz compressed
 files.
Date: Wed, 18 Jan 2012 17:29:10 +0200

 I have a comment about the message displayed to the user.
 
 'which -s' won't find an executable file if $PATH does not include it's location:
 
 [root@x] ~# echo $PATH
 /sbin:/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/sbin:/usr/local/bin:/root/bin
 [root@x] ~# mkdir ~/xbin
 [root@x] ~# touch ~/xbin/sample_executable
 [root@x] ~# chmod +x /xbin/sample_executable
 [root@x] ~# rehash
 [root@x] ~/xbin# which sample_executable
 sample_executable: Command not found.
 <add ~/xbin to $PATH>
 [root@x] ~/xbin# echo $PATH
 /sbin:/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/sbin:/usr/local/bin:/root/bin:/root/xbin
 [root@x] ~/xbin# which sample_executable
 /root/xbin/sample_executable
 
 I suggest adjusting the text for letting the user know xz is not in the search 
 path or installed, instead of simply telling 'is not installed', which may not 
 be true.
 
 -- 
 Best regards,
 
 Emil Cazamir
 
 --------------------------------------------------------------------------
 Acest e-mail este confidential si poate contine informatii protejate prin
 lege. Daca nu sunteti destinatarul de drept al mesajului, nu sunteti
 autorizat sa cititi, imprimati, salvati, procesati sau sa divulgati acest
 mesaj. Daca ati primit mesajul dintr-o eroare, va rugam sa informati
 expeditorul cat mai curand posibil si sa stergeti acest e-mail, documentele
 atasate si orice copii ale mesajului. Va multumim!
 
 This e-mail is confidential and may also contain privileged information.
 If you are not the intended recipient, you are not authorised to read, print,
 save, process or disclose this message. If you have received this message by
 mistake, please inform the sender immediately and delete this e-mail, its
 attachments and any copies. Thank you!

From: Stephen Montgomery-Smith <stephen@missouri.edu>
To: bug-followup@FreeBSD.org, stephen@FreeBSD.org
Cc:  
Subject: Re: bin/159665: [patch] ctm(1) does not work with bzip2 or xz compressed
 files.
Date: Sun, 16 Dec 2012 21:59:18 -0600

 This is a multi-part message in MIME format.
 --------------010804090006070209000003
 Content-Type: text/plain; charset=ISO-8859-1
 Content-Transfer-Encoding: 7bit
 
 I didn't see the previous follow up until today.  That's why my reply is
 11 months late.
 
 So I made a mild modification to the error message if xz is not
 installed.  If you don't like my mild modification, use whatever else
 you would like to use, as long as it says the same thing.
 
 But I also added a large number of other changes so that ctm can handle
 the new ctm-svn-cur deltas.
 
 You will also find this patch at
 ftp://ftp.freebsd.org/pub/FreeBSD/CTM/svn-cur (you might have to wait
 an hour or so after this email is sent until this patch appears on that
 ftp site).
 
 --------------010804090006070209000003
 Content-Type: text/plain; charset=UTF-8;
  name="patch-for-ctm-v07"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
  filename="patch-for-ctm-v07"
 
 diff -ur /usr/src/usr.sbin/ctm/ctm/ctm.1 ctm/ctm.1
 --- /usr/src/usr.sbin/ctm/ctm/ctm.1	2010-04-24 17:19:38.000000000 -0500
 +++ ctm/ctm.1	2011-12-24 16:38:07.000000000 -0600
 @@ -52,8 +52,11 @@
  You can pass a CTM delta on stdin, or you can give the
  filename as an argument.
  If you do the latter, you make life a lot
 -easier for your self, since the program can accept gzip'ed files and
 +easier for your self, since the program can accept gzip'ed,
 +bzip2'ed, or xz'ed files and
  since it will not have to make a temporary copy of your file.
 +(If you pass it an xz'ed file, and xz is not part of your base system,
 +you will have to install xz from the ports.)
  You can
  specify multiple deltas at one time, they will be processed one at a
  time.
 diff -ur /usr/src/usr.sbin/ctm/ctm/ctm.c ctm/ctm.c
 --- /usr/src/usr.sbin/ctm/ctm/ctm.c	2010-04-24 17:19:38.000000000 -0500
 +++ ctm/ctm.c	2012-12-16 21:39:50.000000000 -0600
 @@ -211,6 +211,22 @@
  	strcat(p,filename);
  	f = popen(p,"r");
  	if(!f) { warn("%s", p); return Exit_Garbage; }
 +    } else if(p && !strcmp(p,".bz2")) {
 +	p = alloca(20 + strlen(filename));
 +	strcpy(p,"bzcat < ");
 +	strcat(p,filename);
 +	f = popen(p,"r");
 +	if(!f) { warn("%s", p); return Exit_Garbage; }
 +    } else if(p && !strcmp(p,".xz")) {
 +	if (system("which -s xz") != 0) {
 +	    fprintf(stderr, "xz is not found in $PATH.  You can install it from ports, or adjust $PATH.\n");
 +	    return Exit_Garbage;
 +	}
 +	p = alloca(20 + strlen(filename));
 +	strcpy(p,"xz -dc < ");
 +	strcat(p,filename);
 +	f = popen(p,"r");
 +	if(!f) { warn("%s", p); return Exit_Garbage; }
      } else {
  	p = 0;
  	f = fopen(filename,"r");
 diff -ur /usr/src/usr.sbin/ctm/ctm/ctm.h ctm/ctm.h
 --- /usr/src/usr.sbin/ctm/ctm/ctm.h	2010-04-24 17:19:38.000000000 -0500
 +++ ctm/ctm.h	2012-09-08 22:55:17.000000000 -0500
 @@ -24,6 +24,7 @@
  #include <sys/stat.h>
  #include <sys/file.h>
  #include <sys/time.h>
 +#include <stdint.h>
  
  #define VERSION "2.0"
  
 @@ -40,6 +41,8 @@
  #define CTM_F_MD5		0x05
  #define CTM_F_Count		0x06
  #define CTM_F_Bytes		0x07
 +#define CTM_F_Release		0x08
 +#define CTM_F_Forward		0x09
  
  /* The qualifiers... */
  #define CTM_Q_MASK		0xff00
 @@ -47,10 +50,13 @@
  #define CTM_Q_Name_Dir		0x0200
  #define CTM_Q_Name_New		0x0400
  #define CTM_Q_Name_Subst	0x0800
 +#define CTM_Q_Name_Svnbase	0x1000
  #define CTM_Q_MD5_After		0x0100
  #define CTM_Q_MD5_Before	0x0200
  #define CTM_Q_MD5_Chunk		0x0400
  #define CTM_Q_MD5_Force		0x0800
 +#define CTM_Q_Forward_Tar	0x0100
 +#define CTM_Q_Forward_SVN	0x0200
  
  struct CTM_Syntax {
      char	*Key;		/* CTM key for operation */
 @@ -145,14 +151,16 @@
  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);
 +intmax_t Fbytecnt(FILE *fd, MD5_CTX *ctx, u_char term);
  
  u_char * Fdata(FILE *fd, int u_chars, MD5_CTX *ctx);
 +int Fforward(FILE *fd, intmax_t u_chars, MD5_CTX *ctx, FILE *fd_to);
  
  #define GETFIELD(p,q) if(!((p)=Ffield(fd,&ctx,(q)))) return BADREAD
  #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 GETFORWARD(p,q) if(!Fforward(fd,(p),&ctx,q)) 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);
 diff -ur /usr/src/usr.sbin/ctm/ctm/ctm_input.c ctm/ctm_input.c
 --- /usr/src/usr.sbin/ctm/ctm/ctm_input.c	2010-04-24 17:19:38.000000000 -0500
 +++ ctm/ctm_input.c	2011-12-24 16:38:07.000000000 -0600
 @@ -61,11 +61,11 @@
      return buf;
  }
  
 -int
 +intmax_t
  Fbytecnt(FILE *fd, MD5_CTX *ctx, u_char term)
  {
      u_char *p,*q;
 -    int u_chars=0;
 +    intmax_t u_chars=0;
  
      p = Ffield(fd,ctx,term);
      if(!p) return -1;
 @@ -100,6 +100,42 @@
      return p;
  }
  
 +int Fforward(FILE *fd, intmax_t u_chars, MD5_CTX *ctx, FILE *fd_to)
 +{
 +    u_char buf[BUFSIZ];
 +    intmax_t amount_read = 0;
 +    int amount_to_read;
 +
 +    while (amount_read < u_chars) {
 +	if (u_chars - amount_read >= BUFSIZ)
 +	    amount_to_read = BUFSIZ;
 +	else
 +	    amount_to_read = u_chars - amount_read;
 +	if(amount_to_read != fread(buf, 1, amount_to_read, fd)) {
 +	    Fatal("Truncated patch.");
 +	    return 0;
 +	}
 +	MD5Update(ctx,buf,amount_to_read);
 +	if (fd_to != NULL) {
 +	    if (amount_to_read != fwrite(buf, 1, amount_to_read, fd_to)) {
 +		Fatal("Write error.");
 +		return 0;
 +	    }
 +	}
 +	amount_read += amount_to_read;
 +    }
 +
 +    if(getc(fd) != '\n') {
 +	if(Verbose > 3)
 +	    printf("FileData wasn't followed by a newline.\n");
 +        Fatal("Corrupt patch.");
 +	return 0;
 +    }
 +    MD5Update(ctx,"\n",1);
 +    return 1;
 +}
 +
 +
  /*---------------------------------------------------------------------------*/
  /* 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) 
 diff -ur /usr/src/usr.sbin/ctm/ctm/ctm_pass1.c ctm/ctm_pass1.c
 --- /usr/src/usr.sbin/ctm/ctm/ctm_pass1.c	2010-04-24 17:19:38.000000000 -0500
 +++ ctm/ctm_pass1.c	2011-12-24 16:38:07.000000000 -0600
 @@ -22,7 +22,8 @@
  {
      u_char *p,*q;
      MD5_CTX ctx;
 -    int i,j,sep,cnt;
 +    int i,j,sep;
 +    intmax_t cnt, rel;
      u_char *md5=0,*name=0,*trash=0;
      struct CTM_Syntax *sp;
      int slashwarn=0, match=0, total_matches=0;
 @@ -96,7 +97,7 @@
  	if(Verbose > 5)
  	    fprintf(stderr,"%s ",sp->Key);
  	for(i=0;(j = sp->List[i]);i++) {
 -	    if (sp->List[i+1] && (sp->List[i+1] & CTM_F_MASK) != CTM_F_Bytes)
 +	    if (sp->List[i+1] && (sp->List[i+1] & CTM_F_MASK) != CTM_F_Bytes && (sp->List[i+1] & CTM_F_MASK) != CTM_F_Forward)
  		sep = ' ';
  	    else
  		sep = '\n';
 @@ -209,6 +210,17 @@
  		    if(md5 && strcmp(md5,p)) {
  			Fatal("Internal MD5 failed.");
  			return Exit_Garbage;
 +		case CTM_F_Release:
 +		    GETBYTECNT(rel,sep);
 +		    break;
 +		case CTM_F_Forward:
 +		    if(cnt < 0) WRONG
 +		    if ((j & CTM_Q_MASK) == CTM_Q_Forward_SVN && system("which -s svnadmin") != 0) {
 +			fprintf(stderr, "subversion is not installed.  You can install it from ports.\n");
 +			return Exit_Garbage;
 +		    }
 +		    GETFORWARD(cnt,NULL);
 +		    break;
  		default:
  			fprintf(stderr,"List = 0x%x\n",j);
  			Fatal("List had garbage.");
 diff -ur /usr/src/usr.sbin/ctm/ctm/ctm_pass2.c ctm/ctm_pass2.c
 --- /usr/src/usr.sbin/ctm/ctm/ctm_pass2.c	2010-04-24 17:19:38.000000000 -0500
 +++ ctm/ctm_pass2.c	2012-12-15 22:06:06.000000000 -0600
 @@ -22,7 +22,11 @@
  {
      u_char *p,*q,*md5=0;
      MD5_CTX ctx;
 -    int i,j,sep,cnt,fdesc;
 +    int i,j,sep,fdesc;
 +    intmax_t cnt, rel;
 +    int rel2;
 +    FILE *current;
 +    char *current_file_name = NULL;
      u_char *trash=0,*name=0;
      struct CTM_Syntax *sp;
      struct stat st;
 @@ -30,7 +34,7 @@
      int match = 0;
      char md5_1[33];
      struct CTM_Filter *filter;
 -    FILE *ed = NULL;
 +    FILE *ed = NULL, *fd_to = NULL;
      static char *template = NULL;
  
      if(Verbose>3)
 @@ -72,7 +76,7 @@
  	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)
 +	    if (sp->List[i+1] && (sp->List[i+1] & CTM_F_MASK) != CTM_F_Bytes && (sp->List[i+1] & CTM_F_MASK) != CTM_F_Forward)
  		sep = ' ';
  	    else
  		sep = '\n';
 @@ -128,6 +132,22 @@
  				sp->Key,name);
  			    ret |= Exit_NotOK;
  			}
 +			if (j & CTM_Q_Name_Svnbase) {
 +			    current_file_name = alloca(strlen(name)+128);
 +			    strcpy(current_file_name,name);
 +			    strcat(current_file_name,"/db/current");
 +	 		    current = fopen(current_file_name,"r");
 +			    if (current==NULL) {
 +				fprintf(stderr,"Cannot open %s\n",current_file_name);
 +				WRONG
 +			    }
 +			    if (fscanf(current,"%d",&rel2) != 1) {
 +				fprintf(stderr,"Cannot find release number in %s\n",current_file_name);
 +				fclose(current);
 +				WRONG
 +			    }
 +			    fclose(current);
 +			}
  			break;
  		    }
  		    if (j & CTM_Q_Name_File) {
 @@ -284,6 +304,42 @@
  		    }
  
  		    break;
 +		case CTM_F_Release:
 +		    GETBYTECNT(rel,sep);
 +		    if(Verbose > 3)
 +			printf("Expecting release number %jd\n",rel);
 +		    if(Verbose > 3)
 +			printf("Actual release number %d\n",rel2);
 +		    if (rel != rel2) {
 +			fprintf(stderr,"Release number mismatch: found %d, need %jd\n",rel2,rel);
 +			WRONG
 +		    }
 +		    break;
 +		case CTM_F_Forward:
 +		    if ((j & CTM_Q_MASK) == CTM_Q_Forward_SVN) {
 +			if(Verbose>3)
 +			    printf("This is a svn dump file and there is no certainty that it will apply cleanly.\n");
 +			GETFORWARD(cnt,NULL);
 +		    }
 +		    else if ((j & CTM_Q_MASK) == CTM_Q_Forward_Tar) {
 +			if(Verbose>3) {
 +			    printf("This is a tar file and there is no certainty that it will apply cleanly even if it passes the following test.\n");
 +			    fd_to = popen("tar tvf -","w");
 +			} else
 +			    fd_to = popen("tar tf - >/dev/null 2>&1","w");
 +			if (fd_to == NULL) {
 +			    fprintf(stderr,"Cannot forward\n");
 +			    WRONG
 +			}
 +			GETFORWARD(cnt,fd_to);
 +			if (pclose(fd_to)) {
 +			    fprintf(stderr,"Tar failed to close properly\n");
 +			    WRONG
 +			} else
 +			    if (Verbose > 3)
 +				printf("Tar file test was good\n");
 +		    }
 +		    break;
  		default: WRONG
  	    }
          }
 diff -ur /usr/src/usr.sbin/ctm/ctm/ctm_pass3.c ctm/ctm_pass3.c
 --- /usr/src/usr.sbin/ctm/ctm/ctm_pass3.c	2010-04-24 17:19:38.000000000 -0500
 +++ ctm/ctm_pass3.c	2012-12-16 15:12:57.000000000 -0600
 @@ -33,10 +33,12 @@
  {
      u_char *p,*q,buf[BUFSIZ];
      MD5_CTX ctx;
 -    int i,j,sep,cnt;
 +    int i,j,sep;
 +    intmax_t cnt,rel;
 +    char *svn_command = NULL;
      u_char *md5=0,*md5before=0,*trash=0,*name=0,*uid=0,*gid=0,*mode=0;
      struct CTM_Syntax *sp;
 -    FILE *ed=0;
 +    FILE *ed=0, *fd_to;
      struct stat st;
      char md5_1[33];
      int match=0;
 @@ -129,7 +131,7 @@
  	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)
 +	    if (sp->List[i+1] && (sp->List[i+1] & CTM_F_MASK) != CTM_F_Bytes && (sp->List[i+1] & CTM_F_MASK) != CTM_F_Forward)
  		sep = ' ';
  	    else
  		sep = '\n';
 @@ -147,53 +149,98 @@
  		    break;
  		case CTM_F_Count: GETBYTECNT(cnt,sep); break;
  		case CTM_F_Bytes: GETDATA(trash,cnt); break;
 +		case CTM_F_Release: GETBYTECNT(rel,sep); break;
 +		case CTM_F_Forward:
 +		    if ((j & CTM_Q_MASK) == CTM_Q_Forward_Tar) {
 +			if (Verbose > 0)
 +			    fd_to = popen("tar xvf -","w");
 +			else
 +			    fd_to = popen("tar xvf - >/dev/null 2>&1","w");
 +		    } else if ((j & CTM_Q_MASK) == CTM_Q_Forward_SVN) {
 +			svn_command = alloca(strlen(name)+128);
 +			if (Verbose > 0)
 +			    snprintf(svn_command,strlen(name)+127,"svnadmin load %s\n", name);
 +			else
 +			    snprintf(svn_command,strlen(name)+127,"svnadmin load %s > /dev/null 2>&1\n", name);
 +			fd_to = popen(svn_command,"w");
 +		    } else WRONG
 +		    if (fd_to == NULL) {
 +			fprintf(stderr,"Cannot forward\n");
 +			WRONG
 +		    }
 +	    	    if (Verbose > 0) {
 +			if (!strcmp(sp->Key,"TR"))
 +			    fprintf(stderr,"> %s\n",sp->Key);
 +			else
 +	 		    fprintf(stderr,"> %s %s\n",sp->Key,name);
 +		    }
 +		    GETFORWARD(cnt,fd_to);
 +		    if (pclose(fd_to)) {
 +			if ((j & CTM_Q_MASK) == CTM_Q_Forward_Tar)
 +			    fprintf(stderr,"Tar failed to close properly\n");
 +			else if ((j & CTM_Q_MASK) == CTM_Q_Forward_SVN)
 +			    fprintf(stderr,"Svnadmin failed to close properly\n");
 +			WRONG
 +		    }
 +		    if ((j & CTM_Q_MASK) == CTM_Q_Forward_SVN) {
 +			snprintf(svn_command,strlen(name)+127,"svnadmin pack %s\n", name);
 +			if (system(svn_command)) {
 +			    fprintf(stderr,"\"%s\" didn't work.", svn_command);
 +			    WRONG
 +			}
 +		    }
 +		    break;
  		default: WRONG
  		}
  	    }
 -	/* XXX This should go away.  Disallow trailing '/' */
 -	j = strlen(name)-1;
 -	if(name[j] == '/') name[j] = '\0';
 -
 -	/*
 -	 * 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 (name) {
 +	    /* XXX This should go away.  Disallow trailing '/' */
 +	    j = strlen(name)-1;
 +	    if(name[j] == '/') name[j] = '\0';
 +
 +	    /*
 +	     * 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 (CTM_FILTER_DISABLE == match) /* skip file if disabled */
 +		    continue;
  
 -	if (Verbose > 0)
 +	    if (Verbose > 0 && strcmp(sp->Key,"SV") && strcmp(sp->Key,"TR"))
  		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) {
 -		warn("%s", name);
 -		WRONG
 -	    }
 -	    if(cnt != write(i,trash,cnt)) {
 -		warn("%s", name);
 -		WRONG
 -	    }
 -	    close(i);
 -	    if(strcmp(md5,MD5File(name,md5_1))) {
 -		fprintf(stderr,"  %s %s MD5 didn't come out right\n",
 -		   sp->Key,name);
 -		WRONG
 +	    if(!strcmp(sp->Key,"FM") || !strcmp(sp->Key, "FS")) {
 +		i = open(name,O_WRONLY|O_CREAT|O_TRUNC,0666);
 +		if(i < 0) {
 +		    warn("%s", name);
 +		    WRONG
 +		}
 +		if(cnt != write(i,trash,cnt)) {
 +		    warn("%s", name);
 +		    WRONG
 +		}
 +		close(i);
 +		if(strcmp(md5,MD5File(name,md5_1))) {
 +		    fprintf(stderr,"  %s %s MD5 didn't come out right\n",
 +		       sp->Key,name);
 +		    WRONG
 +		}
 +		if (settime(name,times)) WRONG
 +		continue;
  	    }
 -	    if (settime(name,times)) WRONG
 -	    continue;
  	}
 +
  	if(!strcmp(sp->Key,"FE")) {
  	    ed = popen("ed","w");
  	    if(!ed) {
 @@ -276,6 +323,8 @@
  	    }
  	    continue;
  	}
 +	if(!strcmp(sp->Key,"TR") || !strcmp(sp->Key,"SV"))
 +	    continue;
  	WRONG
      }
  
 diff -ur /usr/src/usr.sbin/ctm/ctm/ctm_syntax.c ctm/ctm_syntax.c
 --- /usr/src/usr.sbin/ctm/ctm/ctm_syntax.c	2010-04-24 17:19:38.000000000 -0500
 +++ ctm/ctm_syntax.c	2012-09-09 08:42:32.000000000 -0500
 @@ -20,16 +20,21 @@
  #define MD5	CTM_F_MD5
  #define Count	CTM_F_Count
  #define Bytes	CTM_F_Bytes
 +#define Release	CTM_F_Release
 +#define Forward	CTM_F_Forward
  
  /* The qualifiers... */
  #define File	CTM_Q_Name_File
  #define Dir	CTM_Q_Name_Dir
 +#define Svnbase	CTM_Q_Name_Svnbase
  #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
 +#define Tar	CTM_Q_Forward_Tar
 +#define SVN	CTM_Q_Forward_SVN
  
  static int ctmFM[] = /* File Make */
      { Name|File|New|Subst, Uid, Gid, Mode,
 @@ -55,6 +60,12 @@
  static int ctmDR[] = /* Directory Remove */
      { Name|Dir, 0 };
  
 +static int ctmTR[] = /* Forward to tar */
 +    { Count, Forward|Tar, 0 };
 +
 +static int ctmSV[] = /* Forward to svnadmin load */
 +    { Name|Dir|Svnbase, Release, Count, Forward|SVN, 0 };
 +
  struct CTM_Syntax Syntax[] = {
      { "FM",  	ctmFM },
      { "FS",  	ctmFS },
 @@ -64,4 +75,6 @@
      { "AS", 	ctmAS },
      { "DM",  	ctmDM },
      { "DR",  	ctmDR },
 +    { "TR",  	ctmTR },
 +    { "SV",  	ctmSV },
      { 0,    	0} };
 
 --------------010804090006070209000003--

From: Stephen Montgomery-Smith <stephen@missouri.edu>
To: bug-followup@FreeBSD.org, stephen@FreeBSD.org
Cc:  
Subject: Re: bin/159665: [patch] ctm(1) does not work with bzip2 or xz compressed
 files.
Date: Sun, 16 Dec 2012 22:32:39 -0600

 Oops - I forgot to modify the error message if subversion isn't in the
 path.  But something similar to when xz isn't found will do just fine.
 
 
State-Changed-From-To: analyzed->analyzed 
State-Changed-By: linimon 
State-Changed-When: Wed Jul 3 00:50:32 UTC 2013 
State-Changed-Why:  
commit bit has been taken in for safekeeping. 


Responsible-Changed-From-To: rik->freebsd-bugs 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Wed Jul 3 00:50:32 UTC 2013 
Responsible-Changed-Why:  

http://www.freebsd.org/cgi/query-pr.cgi?pr=159665 
>Unformatted:
