From mark@doorway.homeip.net  Fri Mar  1 03:04:30 2002
Return-Path: <mark@doorway.homeip.net>
Received: from mail012.syd.optusnet.com.au (mail012.syd.optusnet.com.au [203.2.75.172])
	by hub.freebsd.org (Postfix) with ESMTP id 258B237B405
	for <FreeBSD-gnats-submit@freebsd.org>; Fri,  1 Mar 2002 03:04:29 -0800 (PST)
Received: from doorway.homeip.net (c25720.sunsh1.vic.optusnet.com.au [203.164.32.100])
	by mail012.syd.optusnet.com.au (8.11.1/8.11.1) with ESMTP id g21B4QZ00424
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 1 Mar 2002 22:04:27 +1100
Received: (from mark@localhost)
	by doorway.homeip.net (8.11.6/8.11.0) id g21B4Yf80402;
	Fri, 1 Mar 2002 22:04:34 +1100 (EST)
	(envelope-from mark)
Message-Id: <200203011104.g21B4Yf80402@doorway.homeip.net>
Date: Fri, 1 Mar 2002 22:04:34 +1100 (EST)
From: Mark Hannon <markhannon@optushome.com.au>
Reply-To: Mark Hannon <markhannon@optushome.com.au>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: PATCH: pkg_add -r able to save local copy to PKG_SAVEDIR
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         35451
>Category:       bin
>Synopsis:       PATCH: pkg_add -r able to save local copy to PKG_SAVEDIR
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Fri Mar 01 03:10:02 PST 2002
>Closed-Date:    Sun Feb 10 19:22:48 UTC 2008
>Last-Modified:  Sun Feb 10 19:22:48 UTC 2008
>Originator:     Mark Hannon
>Release:        FreeBSD 4.5-RELEASE i386
>Organization:
-
>Environment:
System: FreeBSD tbird.home.lan 4.5-RELEASE FreeBSD 4.5-RELEASE #0: Mon Jan 28 14:31:56 GMT 2002 murray@builder.freebsdmall.com:/usr/src/sys/compile/GENERIC i386
>Description:
	
Included patch adds ability to save a local copy of the downloaded
pkg.tgz file when using the pkg_add -r command.  Pkg.tgz is downloaded
to $PKG_SAVEDIR
>How-To-Repeat:
	
>Fix:

	

Index: pkg_install/add/pkg_add.1
===================================================================
RCS file: /home/ncvs/src/usr.sbin/pkg_install/add/pkg_add.1,v
retrieving revision 1.35.2.10
diff -c -r1.35.2.10 pkg_add.1
*** pkg_install/add/pkg_add.1	2001/12/14 16:48:11	1.35.2.10
--- pkg_install/add/pkg_add.1	2002/02/22 12:23:02
***************
*** 406,411 ****
--- 406,416 ----
  .Pa /usr/tmp
  with sufficient space.
  .Pp
+ If set, the environment variable
+ .Ev PKG_SAVEDIR
+ specifies a directory to which a copy of a remotely fetched package
+ will be saved.
+ .Pp
  The environment variable
  .Ev PACKAGEROOT
  specifies an alternate location for

Index: pkg_install/lib/file.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/pkg_install/lib/file.c,v
retrieving revision 1.40.2.9
diff -c -r1.40.2.9 file.c
*** pkg_install/lib/file.c	2001/10/23 09:16:04	1.40.2.9
--- pkg_install/lib/file.c	2002/02/22 12:23:22
***************
*** 151,156 ****
--- 151,170 ----
      int pfd[2], pstat, r, w;
      char *hint;
      int fd;
+     /*
+      * Additions to handle saving of local copy
+      */
+     int do_copy;	/* Set to 1 if saving local copy */
+     int fd_copy;	/* File Descriptor for local copy */
+     int no_bytes_written;
+     char *contents_name_ptr;
+     char *newline_ptr;
+     char *pkg_name_ptr;
+     char *pkg_savedir;		  
+     char contents_line[8192];
+     char pkg_long_name[FILENAME_MAX];
+     char pkg_short_name[FILENAME_MAX];
+     FILE *contents_file;
  
      rp = NULL;
      /* Special tip that sysinstall left for us */
***************
*** 196,201 ****
--- 210,230 ----
      else
  	strcpy(fname, spec);
  
+     /* 
+      * Check if PKG_SAVEDIR is set, if so then save a copy of the 
+      * package to that directory.
+      */
+     pkg_savedir = getenv("PKG_SAVEDIR");
+     if (pkg_savedir) {
+       /*
+        * Set copy_short_name to $PKG_SAVEDIR/pkg_name.tgz
+        */
+       strcpy(pkg_short_name, pkg_savedir);
+       strcat(pkg_short_name, "/");
+       pkg_name_ptr = strrchr(fname, '/');
+       strcat(pkg_short_name, ++pkg_name_ptr);
+     }
+ 
      if ((ftp = fetchGetURL(fname, Verbose ? "v" : NULL)) == NULL) {
  	printf("Error: FTP Unable to get %s: %s\n",
  	       fname, fetchLastErrString);
***************
*** 227,243 ****
  	execl("/usr/bin/tar", "tar", Verbose ? "-xzvf" : "-xzf", "-", 0);
  	_exit(2);
      }
      close(pfd[0]);
      for (;;) {
! 	if ((r = fread(buf, 1, sizeof buf, ftp)) < 1)
! 	    break;
! 	if ((w = write(pfd[1], buf, r)) != r)
! 	    break;
      }
      if (ferror(ftp))
  	warn("warning: error reading from server");
      fclose(ftp);
      close(pfd[1]);
      if (w == -1)
  	warn("warning: error writing to tar");
      tpid = waitpid(tpid, &pstat, 0);
--- 256,327 ----
  	execl("/usr/bin/tar", "tar", Verbose ? "-xzvf" : "-xzf", "-", 0);
  	_exit(2);
      }
+     
      close(pfd[0]);
+     
+     do_copy = 0;	/* Default = no local copy */
+     if (pkg_savedir) { 	/* If saving local copy then ... */
+       if ( ( 
+ 	    fd_copy = open ( pkg_short_name, 
+ 	      O_WRONLY | O_CREAT | O_EXCL | O_APPEND, 
+ 	      S_IRWXU | S_IRGRP | S_IROTH ) 
+ 	   ) != -1 ){
+ 	do_copy = 1; 	/* make local copy of package tar file */
+       } else {
+ 	fprintf(stderr, "warning: unable to save %s\n", pkg_short_name);
+ 	do_copy = 0; 
+       }
+     }
+ 
      for (;;) {
!       if ((r = fread(buf, 1, sizeof buf, ftp)) < 1)
! 	break;
!       if ((w = write(pfd[1], buf, r)) != r)
! 	break;
!       if ( do_copy && ( (no_bytes_written = write(fd_copy, buf, r) ) != r) )
! 	break;
      }
+ 
      if (ferror(ftp))
  	warn("warning: error reading from server");
      fclose(ftp);
      close(pfd[1]);
+ 
+     /*
+      * In case of a local copy having been made then rename the 
+      * tar file to pkgname-version.tgz if needed.
+      */
+     if ( do_copy == 1 ){
+       if (no_bytes_written == -1)
+ 	warn("warning: error writing %s", pkg_short_name);
+       close(fd_copy);
+       /*
+        * Open the package +CONTENTS file and look for the real pkgname
+        */
+       if ( ( contents_file = fopen(CONTENTS_FNAME, "r") ) != NULL){
+ 	while ( fgets(contents_line, 8192, contents_file) != NULL){
+ 	  /*
+ 	   * Look for @name in line and use to rename package file
+ 	   */
+ 	  if ( ( contents_name_ptr = 
+ 		strstr(contents_line, "@name ") ) != NULL ){
+ 	    contents_name_ptr += 6; /* Move to start of actual name */
+ 	    strcpy(pkg_long_name, pkg_short_name);
+ 	    pkg_name_ptr = strrchr(pkg_long_name, '/');
+ 	    *(++pkg_name_ptr) = '\0'; /* Remove the short base name .... */
+ 	    strcat(pkg_long_name, contents_name_ptr);
+ 	    if ( ( newline_ptr = strrchr(pkg_long_name, '\n') ) != NULL)
+ 	      *(newline_ptr) = '\0'; /* Remove carriage return */ 
+ 	    strcat(pkg_long_name, ".tgz");
+ 	    if ( rename( pkg_short_name, pkg_long_name) == -1)
+ 	      warn("warning: unable to rename %s -> %s", 
+ 		  pkg_short_name, pkg_long_name);
+ 	    break;
+ 	  }
+ 	}
+       }
+     }
+ 
      if (w == -1)
  	warn("warning: error writing to tar");
      tpid = waitpid(tpid, &pstat, 0);
>Release-Note:
>Audit-Trail:

From: "Simon 'corecode' Schubert" <corecode@corecode.ath.cx>
To: Mark Hannon <markhannon@optushome.com.au>
Cc: FreeBSD-gnats-submit@FreeBSD.ORG
Subject: Re: bin/35451: PATCH: pkg_add -r able to save local copy to PKG_SAVEDIR
Date: Fri, 1 Mar 2002 15:13:11 +0100

 --=.:QdE,yE7ZA68NS
 Content-Type: text/plain; charset=ISO-8859-1
 Content-Transfer-Encoding: 8bit
 
 On Fri, 1 Mar 2002 22:04:34 +1100 (EST) Mark Hannon <markhannon@optushome.com.au> wrote:
 
 > +     /* 
 > +      * Check if PKG_SAVEDIR is set, if so then save a copy of the 
 > +      * package to that directory.
 > +      */
 > +     pkg_savedir = getenv("PKG_SAVEDIR");
 > +     if (pkg_savedir) {
 > +       /*
 > +        * Set copy_short_name to $PKG_SAVEDIR/pkg_name.tgz
 > +        */
 > +       strcpy(pkg_short_name, pkg_savedir);
 > +       strcat(pkg_short_name, "/");
 > +       pkg_name_ptr = strrchr(fname, '/');
 > +       strcat(pkg_short_name, ++pkg_name_ptr);
 > +     }
 
 do you really want to rely on the user's input (=env var) being smaller
 than FILENAME_MAX chars? i'd use a strn* function or a snprintf.
 
 [several other strcpys and strcats among the code]
 
 just my  .02
 
 -- 
 /"\   http://corecode.ath.cx/
 \ /
  \     ASCII Ribbon Campaign
 / \  Against HTML Mail and News
 
 --=.:QdE,yE7ZA68NS
 Content-Type: application/pgp-signature
 
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.0.6 (FreeBSD)
 
 iD8DBQE8f4x6r5S+dk6z85oRAiZRAJ9Mt/ogwoQZTOF3DL6cGAU3r+drzQCgnt0k
 TEYBeScxQ/KbYedQi7mk9Rk=
 =hmfV
 -----END PGP SIGNATURE-----
 
 --=.:QdE,yE7ZA68NS--
 

From: Mark Hannon <markhannon@optushome.com.au>
To: freebsd-gnats-submit@FreeBSD.org, markhannon@optushome.com.au
Cc:  
Subject: Re: bin/35451: PATCH: pkg_add -r able to save local copy to PKG_SAVEDIR
Date: Sun, 10 Mar 2002 15:12:08 +1100

 This is a multi-part message in MIME format.
 --------------B4919200D4BC990CD7DFF7DB
 Content-Type: text/plain; charset=us-ascii
 Content-Transfer-Encoding: 7bit
 
 Cleaned up version of the patches, taking into account comments from
 Simon Schubert.
 
 Rgds/mark
 --------------B4919200D4BC990CD7DFF7DB
 Content-Type: text/plain; charset=us-ascii;
  name="pkg_install.2"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline;
  filename="pkg_install.2"
 
 Index: pkg_install/lib/file.c
 ===================================================================
 RCS file: /home/ncvs/src/usr.sbin/pkg_install/lib/file.c,v
 retrieving revision 1.40.2.9
 diff -c -r1.40.2.9 file.c
 *** pkg_install/lib/file.c	2001/10/23 09:16:04	1.40.2.9
 --- pkg_install/lib/file.c	2002/03/10 04:02:03
 ***************
 *** 151,156 ****
 --- 151,160 ----
       int pfd[2], pstat, r, w;
       char *hint;
       int fd;
 +     int do_copy, fd_copy, no_bytes_written;
 +     char *contents_name_ptr, *newline_ptr, *pkg_name_ptr, *pkg_savedir;		  
 +     char contents_line[8192], pkg_long_name[FILENAME_MAX], pkg_short_name[FILENAME_MAX];
 +     FILE *contents_file;
   
       rp = NULL;
       /* Special tip that sysinstall left for us */
 ***************
 *** 196,201 ****
 --- 200,225 ----
       else
   	strcpy(fname, spec);
   
 +     /* 
 +      * Check if PKG_SAVEDIR is set, if so then save a copy of the 
 +      * package to that directory.  During the download process the
 +      * filename is set to package_name.tgz (sans version info).
 +      * Subsequent to installation, when a +CONTENTS file is available,
 +      * the package is renamed to package_name-version.tgz
 +      */
 +     pkg_savedir = getenv("PKG_SAVEDIR");
 +     if (pkg_savedir) { 
 + 	pkg_name_ptr = strrchr(fname, '/');
 + 	if ( ( strlen(pkg_savedir) + strlen(pkg_name_ptr) + 1 ) > 
 + 		sizeof(pkg_short_name) ){
 + 	    fprintf(stderr, "Error: PKG_SAVEDIR/package_name.tgz is too long!\n");
 + 	    return NULL;
 + 	}
 + 	strcpy(pkg_short_name, pkg_savedir);
 + 	strcat(pkg_short_name, "/");
 + 	strcat(pkg_short_name, ++pkg_name_ptr); 
 +     }
 + 
       if ((ftp = fetchGetURL(fname, Verbose ? "v" : NULL)) == NULL) {
   	printf("Error: FTP Unable to get %s: %s\n",
   	       fname, fetchLastErrString);
 ***************
 *** 227,243 ****
   	execl("/usr/bin/tar", "tar", Verbose ? "-xzvf" : "-xzf", "-", 0);
   	_exit(2);
       }
       close(pfd[0]);
       for (;;) {
 ! 	if ((r = fread(buf, 1, sizeof buf, ftp)) < 1)
 ! 	    break;
 ! 	if ((w = write(pfd[1], buf, r)) != r)
 ! 	    break;
       }
       if (ferror(ftp))
   	warn("warning: error reading from server");
       fclose(ftp);
       close(pfd[1]);
       if (w == -1)
   	warn("warning: error writing to tar");
       tpid = waitpid(tpid, &pstat, 0);
 --- 251,329 ----
   	execl("/usr/bin/tar", "tar", Verbose ? "-xzvf" : "-xzf", "-", 0);
   	_exit(2);
       }
 +     
       close(pfd[0]);
 +    
 +     /*
 +      * Check if local copy is being made, if so then create a local file
 +      * to store the download in.
 +      */ 
 +     do_copy = 0;
 +     if (pkg_savedir) {
 + 	if ((fd_copy = open(pkg_short_name, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 
 + 			S_IRWXU|S_IRGRP|S_IROTH)) != -1 ){
 + 	    do_copy = 1;
 + 	} else {
 + 	    fprintf(stderr, "warning: unable to save %s\n", pkg_short_name);
 + 	}
 +     }
 + 
       for (;;) {
 !       if ((r = fread(buf, 1, sizeof buf, ftp)) < 1)
 ! 	break;
 !       if ((w = write(pfd[1], buf, r)) != r)
 ! 	break;
 !       if ( do_copy && ( (no_bytes_written = write(fd_copy, buf, r) ) != r) )
 ! 	break;
       }
 + 
       if (ferror(ftp))
   	warn("warning: error reading from server");
       fclose(ftp);
       close(pfd[1]);
 + 
 +     /*
 +      * In case of a local copy having been made then open the +CONTENTS
 +      * file, obtain the full package and version name and then rename 
 +      * the previously downloaded (shortform) package file.
 +      */
 +     if ( do_copy == 1 ){
 + 	if (no_bytes_written == -1)
 + 	    warn("warning: error writing %s", pkg_short_name);
 + 	close(fd_copy);
 + 	/* Use the short form as basis for the longform package name */
 + 	strcpy(pkg_long_name, pkg_short_name);
 + 	/* Remove the original short form package name */
 + 	pkg_name_ptr = strrchr(pkg_long_name, '/');
 + 	*(++pkg_name_ptr) = '\0';
 + 	/* Open the package +CONTENTS file and look for the real pkgname */
 + 	if ((contents_file = fopen(CONTENTS_FNAME, "r")) != NULL){
 + 	    while (fgets(contents_line, 8192, contents_file) != NULL){
 + 		/* Look for @name in line and use to rename package file */
 + 		if (((contents_name_ptr = strstr(contents_line, "@name ")) != NULL) &&
 + 			(strlen(contents_name_ptr) > 5) &&
 + 			(strlen(pkg_long_name) + strlen(contents_name_ptr) + 4) < 
 + 			sizeof(pkg_long_name)){
 + 		    /* Move to start of the actual package name */
 + 		    contents_name_ptr += 6;
 + 		    if ( ( newline_ptr = strrchr(contents_name_ptr, '\n') ) != NULL)
 + 			*(newline_ptr) = '\0'; /* Remove carriage return */ 
 + 		    /* Add packagename-version.tgz */
 + 		    strcat(pkg_long_name, contents_name_ptr);
 + 		    strcat(pkg_long_name, ".tgz");
 + 		    /* Actually rename file */
 + 		    if (rename(pkg_short_name, pkg_long_name) == -1)
 + 			warn("warning: unable to rename %s -> %s", 
 + 				pkg_short_name, pkg_long_name);
 + 		    break;
 + 		}
 + 	    }
 + 	} else {
 + 	    warn("warning: unable to open +CONTENTS file to rename %s -> %s", 
 + 		    pkg_short_name, pkg_long_name);
 + 	}
 +     }
 + 
       if (w == -1)
   	warn("warning: error writing to tar");
       tpid = waitpid(tpid, &pstat, 0);
 
 --------------B4919200D4BC990CD7DFF7DB--
 

From: "Denis N. Peplin" <info@volginfo.ru>
To: freebsd-gnats-submit@FreeBSD.org, markhannon@optushome.com.au
Cc:  
Subject: Re: bin/35451: PATCH: pkg_add -r able to save local copy to PKG_SAVEDIR
Date: Mon, 21 Oct 2002 12:49:22 +0400

 I wrote my own small patch before looking to 35451.
 This patch is not ready-to-use (but I use it), just a bit simple :)
 And I have one question - why previous patches was not added
 to source tree?
 
 diff -r -u pkg_install.old/lib/file.c pkg_install/lib/file.c
 --- pkg_install.old/lib/file.c	Fri Oct 18 11:34:35 2002
 +++ pkg_install/lib/file.c	Mon Oct 21 10:50:43 2002
 @@ -143,12 +143,15 @@
      char *cp, *rp;
      char fname[FILENAME_MAX];
      char pen[FILENAME_MAX];
 +    char lspec[FILENAME_MAX];
 +    char pspec[FILENAME_MAX];
      char buf[8192];
      FILE *ftp;
      pid_t tpid;
      int pfd[2], pstat, r, w;
      char *hint;
 -    int fd;
 +    int fd, lfd;
 +    char *tok, *ftok;
  
      rp = NULL;
      /* Special tip that sysinstall left for us */
 @@ -227,10 +230,22 @@
  	_exit(2);
      }
      close(pfd[0]);
 +    strcpy(pspec, spec);
 +    strtok(pspec, "/");
 +    while ((tok = strtok(NULL, "/"))) {
 +        ftok = tok;
 +    }
 +    strcpy(lspec, "/tmp/");
 +    strcat(lspec, ftok);
 +    lfd = open(lspec, O_WRONLY | O_CREAT | O_TRUNC, 0644);
 +    if (lfd == FAIL) {
 +        cleanup(0);
 +        errx(2, "%s: unable to open '%s' for for writing", __func__, lspec);
 +    }
      for (;;) {
  	if ((r = fread(buf, 1, sizeof buf, ftp)) < 1)
  	    break;
 -	if ((w = write(pfd[1], buf, r)) != r)
 +	if (write(lfd, buf, r) != r || (w = write(pfd[1], buf, r)) != r)
  	    break;
      }
      if (ferror(ftp))
 
State-Changed-From-To: open->closed 
State-Changed-By: antoine 
State-Changed-When: Sun Feb 10 19:20:23 UTC 2008 
State-Changed-Why:  
Close: a -K option was introduced 2 years ago to pkg_add 
to save downloaded packages in PKGDIR. 
It has been merged to RELENG_5 and RELENG_6. 
Thanks for the report. 

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