From root@scry.dstc.edu.au  Mon Jul 15 22:37:27 1996
Received: from trapdoor.dstc.edu.au (root@trapdoor.dstc.edu.au [130.102.176.12])
          by freefall.freebsd.org (8.7.5/8.7.3) with ESMTP id WAA06197
          for <FreeBSD-gnats-submit@freebsd.org>; Mon, 15 Jul 1996 22:37:25 -0700 (PDT)
Received: from scry.dstc.edu.au (scry.dstc.edu.au [130.102.176.222]) by trapdoor.dstc.edu.au (8.6.9/8.6.12) with ESMTP id PAA21138 for <FreeBSD-gnats-submit@freebsd.org>; Tue, 16 Jul 1996 15:37:21 +1000
Received: (from root@localhost) by scry.dstc.edu.au (8.6.12/8.6.12) id PAA19753; Tue, 16 Jul 1996 15:37:25 +1000
Message-Id: <199607160537.PAA19753@scry.dstc.edu.au>
Date: Tue, 16 Jul 1996 15:37:25 +1000
From: Charlie Root <root@scry.dstc.edu.au>
Reply-To: leonard@dstc.edu.au
To: FreeBSD-gnats-submit@freebsd.org
Subject: libftpio: some problems with ftpGet() fixed
X-Send-Pr-Version: 3.2

>Number:         1388
>Category:       misc
>Synopsis:       libftpio: some problems with ftpGet() fixed
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    jkh
>State:          closed
>Quarter:
>Keywords:
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Jul 15 22:40:01 PDT 1996
>Closed-Date:    Mon Oct 14 12:16:32 PDT 1996
>Last-Modified:  Mon Oct 14 12:18:26 PDT 1996
>Originator:     David Leonard
>Release:        FreeBSD 2.2-CURRENT i386
>Organization:
DSTC, +61 7 3365 4310
>Environment:

FreeBSD scry.dstc.edu.au 2.2-CURRENT FreeBSD 2.2-CURRENT #0: Mon Jul 15 16:35:40 EST 1996     d@scry.dstc.edu.au:/u2/src/sys/compile/SCRY  i386

sup'd and compiled yesterday

>Description:

	Some FTP servers automatically tar.gz their directories. 

	The ftpio library will get such a tarfile like this:
		RETR /path/to/the/directory.tar.gz
	and when you uncompress/extract it, you end up with the directory
		./path/to/the/directory
	instead of
		./directory
	as you would normally(?) want.

	Anyway - its just a suggestion.

>How-To-Repeat:

	pkg_add ftp://freebsd.dstc.edu.au/freebsd/FreeBSD-current/ports/sysutils/top.tar.gz
	(i know this isn't a package, and that packages are already .tgz, 
	 but it is an example)

>Fix:
	The following patches:
	   * add an ftpPWDir() function that returns the current directory
	   * make sure that ftpGet() attempts to PWD then CWD to the
	     directory containing the file before it RETRs it. When the RETR
	     is done, it CWDs back to where it was. If the CWD/PWD fails, it
	     does the RETR as it always had. (semantics of Get aren't changed
	     wrt the current directory)

*** lib/libftpio/ftpio.c.orig	Tue Jul 16 14:26:53 1996
--- lib/libftpio/ftpio.c	Tue Jul 16 15:35:22 1996
***************
*** 82,87 ****
--- 82,91 ----
   */
  #define fcookie(fp)	((fp)->_cookie)
  
+ /* you thought that was evil? */
+ /* this is the last line read with get_a_line/get_a_number */
+ static char last_line_buf[BUFSIZ];
+ 
  /* Placeholder in case we want to do any pre-init stuff at some point */ 
  int
  networkInit()
***************
*** 158,163 ****
--- 162,191 ----
      return SUCCESS;
  }
  
+ int 
+ ftpPWDir(FILE *fp, char*dirp)
+ {
+     int i;
+     FTP_t ftp = fcookie(fp);
+     char *buffer = last_line_buf;
+ 
+     i = cmd( ftp, "PWD" );
+     if (i < 0) return i;
+ 
+     /* match the line `257 "..." ...' */
+     if (buffer[0] == '2' && buffer[4] == '\"' )
+     {
+ 	char *end = strchr( &buffer[5], '\"' );
+ 	if (end) 
+ 	{
+ 		*end = '\0';
+ 		strcpy( dirp, buffer+5 );
+ 		return SUCCESS;
+ 	}
+     }
+     return FAILURE;
+ }
+ 
  int
  ftpErrno(FILE *fp)
  {
***************
*** 217,232 ****
  FILE *
  ftpGet(FILE *fp, char *file, int *seekto)
  {
!     FILE *fp2;
      FTP_t ftp = fcookie(fp);
  
      check_passive(fp);
      if (ftpBinary(fp) != SUCCESS)
  	return NULL;
  
!     if (ftp_file_op(ftp, "RETR", file, &fp2, "r", seekto) == SUCCESS)
! 	return fp2;
!     return NULL;
  }
  
  /* Returns a standard FILE pointer type representing an open control connection */
--- 245,286 ----
  FILE *
  ftpGet(FILE *fp, char *file, int *seekto)
  {
!     FILE *fp2 = NULL;
      FTP_t ftp = fcookie(fp);
+     char *dir, *filename;
+     char saved_wd[ BUFSIZ ];
  
      check_passive(fp);
      if (ftpBinary(fp) != SUCCESS)
  	return NULL;
  
!     dir = strdup(file);
!     filename = strrchr( dir, '/' );
!     if (filename != NULL) 
! 	*filename++ = '\0';
! 
!     if (
! 	filename!=NULL 
! 	&& 
! 	*dir != '\0'
! 	&& 
! 	ftpPWDir( fp, saved_wd ) == SUCCESS
! 	&&
! 	ftpChdir( fp, dir ) == SUCCESS 
!     )
!     {
!       if (ftp_file_op(ftp, "RETR", filename, &fp2, "r", seekto) != SUCCESS)
! 	fp2 = NULL;
!       ftpChdir( fp, saved_wd );
!     }
!     else
!     {
!       if (ftp_file_op(ftp, "RETR", file, &fp2, "r", seekto) != SUCCESS)
! 	fp2 = NULL;
!     }
! 
!     free(dir);
!     return fp2;
  }
  
  /* Returns a standard FILE pointer type representing an open control connection */
***************
*** 434,445 ****
      return SUCCESS;
  }
  
  static __inline char *
  get_a_line(FTP_t ftp)
  {
-     static char buf[BUFSIZ];
      int i,j;
  
      /* Set the timer */
      FtpTimedOut = FALSE;
      signal(SIGALRM, ftp_timeout);
--- 488,501 ----
      return SUCCESS;
  }
  
+ 
  static __inline char *
  get_a_line(FTP_t ftp)
  {
      int i,j;
  
+     char *buf = last_line_buf;
+ 
      /* Set the timer */
      FtpTimedOut = FALSE;
      signal(SIGALRM, ftp_timeout);
***************
*** 537,544 ****
      va_start(ap, fmt);
      (void)vsnprintf(p, sizeof p, fmt, ap);
      va_end(ap);
- 
- fprintf(stderr,"cmd( %s )\n",p);
  
      if (ftp->con_state != isopen)
  	return botch("cmd", "open");
--- 593,598 ----
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->jkh 
Responsible-Changed-By: wosch 
Responsible-Changed-When: Wed Sep 25 16:59:53 PDT 1996 
Responsible-Changed-Why:  
State-Changed-From-To: open->closed 
State-Changed-By: jkh 
State-Changed-When: Mon Oct 14 12:16:32 PDT 1996 
State-Changed-Why:  
Uhm.  I'm not sure that I can see how this is any kind of problem: 

Here's an example: 

jkh@time-> fetch ftp://ftp.freebsd.org/pub/FreeBSD/ports-current/shells.tar.gz 
Receiving shells.tar.gz: 9 Kbytes 
9949 bytes transfered in 1.3 seconds  (7.37 K/s) 
jkh@time-> tar tvzf shells.tar.gz  
drwxr-xr-x root/523          0 Jul 30 02:17 1996 shells/ 
drwxr-xr-x root/523          0 Aug 28 14:19 1996 shells/bash/ 
drwxr-xr-x root/523          0 Aug 28 14:19 1996 shells/bash/files/ 
-rw-r--r-- root/523         60 Aug 28 14:19 1996 shells/bash/files/md5 
... 

The behavior seems exactly right to me? 
>Unformatted:
