These patches add support to ftpd for tarring (and optionally gzipping) down directories on the fly. If a client requests a file ending in .tar or .tgz, and there is no file by that name, but there is a directory with the same name except for the .tar or .tgz ending, ftpd will tar (and optionally gzip) that directory on the fly and send the tarball. Note that if you're offering anonymous FTP or use chroots, you will need to place a copy of tar (and optionally gzip) in /usr/bin inside each chroot space. DES -- Dag-Erling Smorgrav - des@freebsd.org Index: include/paths.h =================================================================== RCS file: /home/ncvs/src/include/paths.h,v retrieving revision 1.9 diff -u -r1.9 paths.h --- include/paths.h 1999/01/11 09:07:41 1.9 +++ include/paths.h 2000/07/20 11:48:05 @@ -59,6 +59,7 @@ #define _PATH_NOLOGIN "/var/run/nologin" #define _PATH_SENDMAIL "/usr/sbin/sendmail" #define _PATH_SHELLS "/etc/shells" +#define _PATH_TAR "/usr/bin/tar" #define _PATH_TTY "/dev/tty" #define _PATH_UNIX "don't use _PATH_UNIX" #define _PATH_VI "/usr/bin/vi" Index: libexec/ftpd/ftpd.c =================================================================== RCS file: /home/ncvs/src/libexec/ftpd/ftpd.c,v retrieving revision 1.64 diff -u -r1.64 ftpd.c --- libexec/ftpd/ftpd.c 2000/06/26 05:36:09 1.64 +++ libexec/ftpd/ftpd.c 2000/07/20 11:46:30 @@ -139,6 +139,7 @@ int anon_only = 0; /* Only anonymous ftp allowed */ int guest; int dochroot; +int have_tar; int stats; int statfd = -1; int type; @@ -1302,6 +1303,9 @@ goto bad; } + /* Check the availability of tar */ + have_tar = (access(_PATH_TAR, X_OK) == 0); + /* * Display a login message, if it exists. * N.B. reply(230,) must follow the message. @@ -1379,15 +1383,34 @@ retrieve(cmd, name) char *cmd, *name; { + char dir[MAXPATHLEN]; FILE *fin, *dout; struct stat st; int (*closefunc) __P((FILE *)); time_t start; + size_t len; if (cmd == 0) { fin = fopen(name, "r"), closefunc = fclose; st.st_size = 0; - } else { + } + if (cmd == 0 && fin == NULL && errno == ENOENT && have_tar) { + len = strlen(name) - 4; + if (len > 0 && len < MAXPATHLEN && + (strcmp(name + len, ".tar") == 0 || + strcmp(name + len, ".tgz") == 0)) { + strncpy(dir, name, len); + dir[len] = 0; + if (stat(dir, &st) != -1 && S_ISDIR(st.st_mode)) { + if (name[len + 3] == 'z') + cmd = _PATH_TAR " -zcf - %s"; + else + cmd = _PATH_TAR " -cf - %s"; + name = dir; + } + } + } + if (cmd != 0) { char line[BUFSIZ]; (void) snprintf(line, sizeof(line), cmd, name), name = line; Index: libexec/ftpd/popen.c =================================================================== RCS file: /home/ncvs/src/libexec/ftpd/popen.c,v retrieving revision 1.18 diff -u -r1.18 popen.c --- libexec/ftpd/popen.c 2000/01/27 09:28:21 1.18 +++ libexec/ftpd/popen.c 2000/07/20 11:46:30 @@ -132,7 +132,6 @@ dup2(pdes[1], STDOUT_FILENO); (void)close(pdes[1]); } - dup2(STDOUT_FILENO, STDERR_FILENO); /* stderr too! */ (void)close(pdes[0]); } else { if (pdes[0] != STDIN_FILENO) {