--- a/components/proftpd/Makefile Fri May 15 09:41:56 2015 -0700
+++ b/components/proftpd/Makefile Tue May 19 02:34:35 2015 -0700
@@ -20,7 +20,7 @@
#
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
#
include ../../make-rules/shared-macros.mk
@@ -56,7 +56,7 @@
# instead of 'e'.
IPS_COMPONENT_VERSION= $(COMPONENT_VERSION)
-CONFIGURE_OPTIONS += CFLAGS="$(CFLAGS) -I/usr/include/kerberosv5 -DHAVE_KRB5_H=1 -DKRB5_DLLIMP= -DHAVE__GETGRPSBYMEMBER"
+CONFIGURE_OPTIONS += CFLAGS="$(CFLAGS) -I/usr/include/kerberosv5 -DHAVE_KRB5_H=1 -DKRB5_DLLIMP= -DHAVE__GETGRPSBYMEMBER -D_SOLARIS_DTRACE"
# Force immediate binding because of chroot().
CONFIGURE_OPTIONS += LDFLAGS="-z guidance=nolazyload -z nolazyload -lbsm"
CONFIGURE_OPTIONS += install_user=`id -nu`
@@ -75,7 +75,7 @@
CONFIGURE_OPTIONS += --with-shared=mod_facl:mod_wrap:mod_tls:mod_auth_gss:mod_gss
CONFIGURE_OPTIONS += --enable-buffer-size=16384
-# Copy Solaris modules and GSSAPI modules to proftpd source tree
+# Copy Solaris modules and GSSAPI modules to proftpd source tree.
COMPONENT_PRE_CONFIGURE_ACTION = \
($(CP) mod_solaris_audit.c $(SOURCE_DIR)/contrib ; \
$(CP) mod_solaris_priv.c $(SOURCE_DIR)/contrib ; \
@@ -88,6 +88,10 @@
$(CP) mod_gss.html $(SOURCE_DIR)/doc/contrib ; \
$(CLONEY) $(SOURCE_DIR) $(@D))
+# Build Solaris dtrace object files and copy to proftpd build tree.
+COMPONENT_PRE_BUILD_ACTION = \
+ (cd dtrace && make CP="$(CP)" CC="$(CC)" BD="$(BUILD_DIR)/$(MACH32)")
+
# proftpd configure and build is not ready for run out of the source tree
CONFIGURE_SCRIPT = $(@D)/configure
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/proftpd/dtrace/Makefile Tue May 19 02:34:35 2015 -0700
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+#
+
+all:
+ $(CP) ftp_provider_impl.h $(BD)/modules
+ /usr/sbin/dtrace -xnolibs -C -h -s ftp_provider.d \
+ -o $(BD)/modules/ftp_provider.h
+ $(CC) -c ftp_provider_impl.c -I $(BD)/modules \
+ -o $(BD)/modules/ftp_provider_impl.o
+ /usr/sbin/dtrace -G -32 -xnolibs -C -s ftp_provider.d \
+ -o "$(BD)"/modules/ftp_provider.o \
+ $(BD)/modules/ftp_provider_impl.o
+ echo "modules/ftp_provider_impl.o" >> $(BD)/module-libs.txt
+ echo "modules/ftp_provider.o" >> $(BD)/module-libs.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/proftpd/dtrace/example.d Tue May 19 02:34:35 2015 -0700
@@ -0,0 +1,28 @@
+#!/usr/sbin/dtrace -Zs
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#pragma D option quiet
+#pragma D option switchrate=10hz
+
+dtrace:::BEGIN
+{
+ printf("%-20s %-8s %9s %-5s %-6s %s\n", "CLIENT", "USER", "LAT(us)",
+ "DIR", "BYTES", "PATH");
+}
+
+ftp*:::transfer-start
+{
+ self->start = timestamp;
+}
+
+ftp*:::transfer-done
+/self->start/
+{
+ this->delta = (timestamp - self->start) / 1000;
+ printf("%-20s %-8s %9d %-5s %-6d %s\n", args[0]->ci_remote,
+ args[1]->fti_user, this->delta, args[1]->fti_cmd,
+ args[1]->fti_nbytes, args[1]->fti_pathname);
+ self->start = 0;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/proftpd/dtrace/ftp.d Tue May 19 02:34:35 2015 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#pragma D depends_on library net.d
+
+typedef struct ftpinfo {
+ string fti_user; /* user name */
+ string fti_cmd; /* FTP command */
+ string fti_pathname; /* path of file being operated upon */
+ uint64_t fti_nbytes; /* bytes transferred, if any */
+ int fti_fd; /* fd for transfer, if any */
+} ftpinfo_t;
+
+/*
+ * This structure must match the definition of same in ftp_provider_impl.h.
+ */
+typedef struct ftpproto {
+ uint32_t ftp_user; /* user name */
+ uint32_t ftp_cmd; /* FTP command */
+ uint32_t ftp_pathname; /* path of file being operated upon */
+ uint32_t ftp_raddr; /* remote address, as IPv6 address */
+ uint32_t ftp_fd; /* fd for transfer, if any */
+ uint32_t ftp_pad; /* padding for copyin() */
+ uint64_t ftp_nbytes; /* bytes transferred, if any */
+} ftpproto_t;
+
+#pragma D binding "1.6.1" translator
+translator conninfo_t <ftpproto_t *f> {
+ ci_protocol = "tcp";
+ ci_remote = copyinstr((uintptr_t)
+ *(uint32_t *)copyin((uintptr_t)&f->ftp_raddr, sizeof (uint32_t)));
+ ci_local = "<unknown>";
+};
+
+#pragma D binding "1.6.1" translator
+translator ftpinfo_t <ftpproto_t *f> {
+ fti_user = copyinstr((uintptr_t)
+ *(uint32_t *)copyin((uintptr_t)&f->ftp_user, sizeof (uint32_t)));
+ fti_cmd = copyinstr((uintptr_t)
+ *(uint32_t *)copyin((uintptr_t)&f->ftp_cmd, sizeof (uint32_t)));
+ fti_pathname = copyinstr((uintptr_t)
+ *(uint32_t *)copyin((uintptr_t)&f->ftp_pathname,
+ sizeof (uint32_t)));
+ fti_nbytes =
+ *(uint64_t *)copyin((uintptr_t)&f->ftp_nbytes, sizeof (uint64_t));
+ fti_fd = *(uint32_t *)copyin((uintptr_t)&f->ftp_fd, sizeof (uint32_t));
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/proftpd/dtrace/ftp_provider.d Tue May 19 02:34:35 2015 -0700
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/*
+ * We seem currently unable to depend properly on existing D libraries (like
+ * ftp.d). But the definitions for conninfo_t and ftpinfo_t are stored there
+ * (and have to be, since that's where the real translators live). So we're
+ * forced to define something here to satisfy dtrace(1M), but none of the
+ * definitions or translators here are actually used.
+ */
+typedef struct ftpinfo {
+ int dummy;
+} ftpinfo_t;
+
+typedef struct ftpproto {
+ int dummy;
+} ftpproto_t;
+
+typedef struct conninfo {
+ int dummy;
+} conninfo_t;
+
+translator conninfo_t <ftpproto_t *dp> {
+ dummy = 0;
+};
+
+translator ftpinfo_t <ftpproto_t *dp> {
+ dummy = 0;
+};
+
+provider ftp {
+ probe transfer__start(ftpproto_t *p) :
+ (conninfo_t *p, ftpinfo_t *p);
+ probe transfer__done(ftpproto_t *p) :
+ (conninfo_t *p, ftpinfo_t *p);
+};
+
+#pragma D attributes Evolving/Evolving/ISA provider ftp provider
+#pragma D attributes Private/Private/Unknown provider ftp module
+#pragma D attributes Private/Private/Unknown provider ftp function
+#pragma D attributes Private/Private/ISA provider ftp name
+#pragma D attributes Evolving/Evolving/ISA provider ftp args
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/proftpd/dtrace/ftp_provider_impl.c Tue May 19 02:34:35 2015 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include <sys/int_types.h>
+
+#include "ftp_provider_impl.h"
+#include "ftp_provider.h"
+
+int
+ftp_transfer_start_enabled(void)
+{
+ return (FTP_TRANSFER_START_ENABLED());
+}
+
+int
+ftp_transfer_done_enabled(void)
+{
+ return (FTP_TRANSFER_DONE_ENABLED());
+}
+
+void
+ftp_transfer_start(struct ftpproto *ptr)
+{
+ FTP_TRANSFER_START(ptr);
+}
+
+void
+ftp_transfer_done(struct ftpproto *ptr)
+{
+ FTP_TRANSFER_DONE(ptr);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/proftpd/dtrace/ftp_provider_impl.h Tue May 19 02:34:35 2015 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#ifndef _FTP_PROVIDER_IMPL_H
+#define _FTP_PROVIDER_IMPL_H
+
+/*
+ * This structure must match the definition of same in ftp.d.
+ */
+typedef struct ftpproto {
+ uint32_t ftp_user; /* user name */
+ uint32_t ftp_cmd; /* FTP command */
+ uint32_t ftp_pathname; /* path of file being operated upon */
+ uint32_t ftp_raddr; /* remote address, as IPv6 address */
+ uint32_t ftp_fd; /* fd for transfer, if any */
+ uint32_t ftp_pad; /* padding for copyin() */
+ uint64_t ftp_nbytes; /* bytes transferred, if any */
+} ftpproto_t;
+
+#define FTP_TRANSFER_PROTO(proto, fh, len) \
+do { \
+ bzero((proto), sizeof (struct ftpproto)); \
+ (proto)->ftp_user = (uint32_t)session.user; \
+ (proto)->ftp_cmd = (uint32_t)session.curr_cmd; \
+ (proto)->ftp_pathname = (uint32_t)((fh)->fh_path); \
+ (proto)->ftp_raddr = \
+ (int32_t)pr_netaddr_get_ipstr(session.c->remote_addr); \
+ (proto)->ftp_fd = (uint32_t)((fh)->fh_fd); \
+ (proto)->ftp_nbytes = (len); \
+} while (0)
+
+extern int ftp_transfer_start_enabled(void);
+extern int ftp_transfer_done_enabled(void);
+extern void ftp_transfer_start(struct ftpproto *);
+extern void ftp_transfer_done(struct ftpproto *);
+
+#endif /* _FTP_PROVIDER_IMPL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/proftpd/patches/000.proftpd-manpage.patch Tue May 19 02:34:35 2015 -0700
@@ -0,0 +1,17 @@
+--- a/src/proftpd.8.in
++++ b/src/proftpd.8.in
+@@ -100,10 +100,12 @@ This is enabled by default, if the \fB--enable-ipv6\fP configure option is
+ used.
+ .SH FILES
+ .PD 0
+-.B @SBINDIR@/proftpd
++.B /usr/lib/inet/proftpd
+ .br
+ .B @SYSCONFDIR@/proftpd.conf
+ .br
++.B @SYSCONFDIR@/ftpusers
++.br
+ .B @BINDIR@/ftpwho
+ .br
+ .B @BINDIR@/ftpcount
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/proftpd/patches/001.mod_auth_unix_getgrp.patch Tue May 19 02:34:35 2015 -0700
@@ -0,0 +1,66 @@
+--- old/modules/mod_auth_unix.c Fri May 25 08:31:35 2012
++++ new/modules/mod_auth_unix.c Fri May 25 08:31:35 2012
+@@ -896,6 +896,13 @@
+
+ return gr ? mod_create_data(cmd, (void *) &gr->gr_gid) : PR_DECLINED(cmd);
+ }
++#ifdef HAVE__GETGRPSBYMEMBER
++ extern int _getgroupsbymember
++ (
++ const char* username, gid_t gid_array[],
++ int maxgids, int numgids
++ );
++#endif /* HAVE__GETGRPSBYMEMBER */
+
+ /* cmd->argv[0] = name
+ * cmd->argv[1] = (array_header **) group_ids
+@@ -1065,7 +1072,40 @@
+ }
+
+ free(ptr);
+-#else
++#else /* !HAVE_GETGRSET */
++#ifdef HAVE__GETGRPSBYMEMBER
++ gid_t group_ids[NGROUPS_MAX];
++ int ngroups = NGROUPS_MAX;
++ register unsigned int i;
++
++ pr_trace_msg("auth", 4,
++ "using _getgroupsbymember() to look up group membership");
++
++ memset(group_ids, 0, sizeof(group_ids));
++
++ group_ids[0]=pw->pw_gid;
++ ngroups=
++ _getgroupsbymember(pw->pw_name, group_ids, NGROUPS_MAX, 1);
++
++ if (ngroups < 0) {
++ pr_log_pri(PR_LOG_ERR,
++ "_getgroupsbymember error: %s", strerror(errno));
++ return PR_DECLINED(cmd);
++ }
++
++ for (i = 0; i < ngroups; i++) {
++ gr = my_getgrgid(group_ids[i]);
++ if (gr) {
++ if (gids && pw->pw_gid != gr->gr_gid)
++ *((gid_t *) push_array(gids)) = gr->gr_gid;
++
++ if (groups && pw->pw_gid != gr->gr_gid) {
++ *((char **) push_array(groups)) = pstrdup(session.pool,
++ gr->gr_name);
++ }
++ }
++ }
++#else /* !HAVE__GETGRPSBYMEMBER */
+ char **gr_member = NULL;
+
+ /* This is where things get slow, expensive, and ugly. Loop through
+@@ -1091,6 +1131,7 @@
+ }
+ }
+ }
++#endif /* !HAVE__GETGROUPSBYMEMBER */
+ #endif /* !HAVE_GETGRSET */
+ }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/proftpd/patches/002.proftpd-configuration-html.patch Tue May 19 02:34:35 2015 -0700
@@ -0,0 +1,12 @@
+--- a/doc/Configuration.html
++++ b/doc/Configuration.html
+@@ -10805,7 +10805,7 @@ CLASS="SYNOPSIS"
+ ></DT
+ ><DD
+ ><P
+->IdentLookups on</P
++>IdentLookups off</P
+ ></DD
+ ><DT
+ ><PRE
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/proftpd/patches/003.proftpd-pam.patch Tue May 19 02:34:35 2015 -0700
@@ -0,0 +1,159 @@
+http://bugs.proftpd.org/show_bug.cgi?id=4070
+
+--- proftpd-1.3.3e/include/auth.h Tue Sep 8 22:34:03 2009
++++ proftpd-1.3.3e-pam/include/auth.h Tue May 24 10:37:40 2011
+@@ -59,6 +59,35 @@
+ /* Account has been disabled */
+ #define PR_AUTH_DISABLEDPWD -5
+
++/* Insufficient credentials */
++#define PR_AUTH_CRED_INSUFF -6
++
++/* Unavailable user credentials */
++#define PR_AUTH_CRED_UNAVAIL -7
++
++/* Failure setting user credentials */
++#define PR_AUTH_CRED_ERR -8
++
++/* Unavailable authentication service */
++#define PR_AUTH_UNAVAIL -9
++
++/* Max retries reached */
++#define PR_AUTH_MAXTRIES -10
++
++/* Initialization of authentization failed */
++#define PR_AUTH_INIT_FAIL -11
++
++/* New auth token needed */
++#define PR_AUTH_NEWTOK -12
++
++#define PR_AUTH_OPEN_ERR -15
++#define PR_AUTH_SYMBOL_ERR -16
++#define PR_AUTH_SERVICE_ERR -17
++#define PR_AUTH_SYSTEM_ERR -18
++#define PR_AUTH_BUF_ERR -19
++#define PR_AUTH_CONV_ERR -20
++#define PR_AUTH_PERM_DENIED -21
++
+ void pr_auth_setpwent(pool *);
+ void pr_auth_endpwent(pool *);
+ void pr_auth_setgrent(pool *);
+--- proftpd-1.3.3e/modules/mod_auth.c Mon Feb 21 03:36:38 2011
++++ proftpd-1.3.3e-pam/modules/mod_auth.c Tue May 24 11:32:55 2011
+@@ -898,6 +898,44 @@
+ user);
+ goto auth_failure;
+
++ case PR_AUTH_CRED_INSUFF:
++ pr_log_auth(PR_LOG_NOTICE,
++ "USER %s (Login failed): Insufficient credentials.", origuser);
++ goto auth_failure;
++
++ case PR_AUTH_CRED_UNAVAIL:
++ pr_log_auth(PR_LOG_NOTICE,
++ "USER %s (Login failed): Unavailable credentials.", origuser);
++ goto auth_failure;
++
++
++ case PR_AUTH_CRED_ERR:
++ pr_log_auth(PR_LOG_NOTICE,
++ "USER %s (Login failed): Failure setting user credentials.",
++ origuser);
++ goto auth_failure;
++
++ case PR_AUTH_UNAVAIL:
++ pr_log_auth(PR_LOG_NOTICE,
++ "USER %s (Login failed): Unavailable authentication service.", user);
++ goto auth_failure;
++
++ case PR_AUTH_MAXTRIES:
++ pr_log_auth(PR_LOG_NOTICE,
++ "USER %s (Login failed): Max retries reached.", user);
++ goto auth_failure;
++
++ case PR_AUTH_INIT_FAIL:
++ pr_log_auth(PR_LOG_NOTICE,
++ "USER %s (Login failed): Authentization initialization failed.",
++ origuser);
++ goto auth_failure;
++
++ case PR_AUTH_NEWTOK:
++ pr_log_auth(PR_LOG_NOTICE,
++ "USER %s (Login failed): New authentication token needed.", user);
++ goto auth_failure;
++
+ default:
+ break;
+ };
+--- proftpd-1.3.3e/modules/mod_auth_pam.c Thu Mar 5 06:24:06 2009
++++ proftpd-1.3.3e-pam/modules/mod_auth_pam.c Tue May 24 10:28:58 2011
+@@ -349,6 +349,24 @@
+
+ if (pam_error != PAM_SUCCESS) {
+ switch (pam_error) {
++#ifdef PAM_CRED_INSUFFICIENT
++ case PAM_CRED_INSUFFICIENT:
++ retval = PR_AUTH_CRED_INSUFF;
++ break;
++#endif /* PAM_CRED_INSUFFICIENT */
++
++#ifdef PAM_AUTHINFO_UNAVAIL
++ case PAM_AUTHINFO_UNAVAIL:
++ retval = PR_AUTH_UNAVAIL;
++ break;
++#endif /* PAM_AUTHINFO_UNAVAIL */
++
++#ifdef PAM_MAXTRIES
++ case PAM_MAXTRIES:
++ retval = PR_AUTH_MAXTRIES;
++ break;
++#endif /* PAM_MAXTRIES */
++
+ case PAM_USER_UNKNOWN:
+ retval = PR_AUTH_NOPWD;
+ break;
+@@ -373,6 +391,14 @@
+
+ if (pam_error != PAM_SUCCESS) {
+ switch (pam_error) {
++#ifdef PAM_NEW_AUTHTOK_REQD
++ case PAM_NEW_AUTHTOK_REQD:
++ pr_trace_msg(trace_channel, 8,
++ "account mgmt error: PAM_NEW_AUTH_REQD");
++ retval = PR_AUTH_NEWTOK;
++ break;
++#endif /* PAM_NEW_AUTHTOK_REQD */
++
+ #ifdef PAM_AUTHTOKEN_REQD
+ case PAM_AUTHTOKEN_REQD:
+ pr_trace_msg(trace_channel, 8,
+@@ -417,7 +443,7 @@
+ switch (pam_error) {
+ case PAM_SESSION_ERR:
+ default:
+- retval = PR_AUTH_DISABLEDPWD;
++ retval = PR_AUTH_INIT_FAIL;
+ break;
+ }
+
+@@ -435,6 +461,20 @@
+
+ if (pam_error != PAM_SUCCESS) {
+ switch (pam_error) {
++#ifdef PAM_CRED_UNAVAIL
++ case PAM_CRED_UNAVAIL:
++ pr_trace_msg(trace_channel, 8, "credentials error: PAM_CRED_UNAVAIL");
++ retval = PR_AUTH_CRED_UNAVAIL;
++ break;
++#endif /* PAM_CRED_UNAVAIL */
++
++#ifdef PAM_CRED_ERR
++ case PAM_CRED_ERR:
++ pr_trace_msg(trace_channel, 8, "credentials error: PAM_CRED_ERR");
++ retval = PR_AUTH_CRED_ERR;
++ break;
++#endif /* PAM_CRED_ERR */
++
+ case PAM_CRED_EXPIRED:
+ pr_trace_msg(trace_channel, 8, "credentials error: PAM_CRED_EXPIRED");
+ retval = PR_AUTH_AGEPWD;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/proftpd/patches/004.proftpd-retry.patch Tue May 19 02:34:35 2015 -0700
@@ -0,0 +1,48 @@
+--- a/src/data.c
++++ b/src/data.c
+@@ -337,6 +337,7 @@ static int data_pasv_open(char *reason, off_t size) {
+ static int data_active_open(char *reason, off_t size) {
+ conn_t *c;
+ int bind_port, rev;
++ int retries = 0;
+ pr_netaddr_t *bind_addr;
+ unsigned char *root_revoke = NULL;
+
+@@ -368,7 +369,9 @@ static int data_active_open(char *reason, off_t size) {
+ bind_port = INPORT_ANY;
+ }
+
+- session.d = pr_inet_create_conn(session.pool, -1, bind_addr, bind_port, TRUE);
++ for (;;) {
++ session.d = pr_inet_create_conn(session.pool, -1, bind_addr, bind_port,
++ TRUE);
+
+ /* Default remote address to which to connect for an active transfer,
+ * if the client has not specified a different address via PORT/EPRT,
+@@ -416,6 +419,15 @@ static int data_active_open(char *reason, off_t size) {
+
+ if (pr_inet_connect(session.d->pool, session.d, &session.data_addr,
+ session.data_port) == -1) {
++
++ if (session.d->xerrno == EADDRINUSE && retries < 16) {
++ destroy_pool(session.d->pool);
++ pr_signals_handle();
++ /* Wait up to MSL to avoid TIME_WAIT. */
++ sleep(retries++);
++ continue;
++ }
++
+ pr_log_debug(DEBUG6,
+ "Error connecting to %s#%u for active data transfer: %s",
+ pr_netaddr_get_ipstr(&session.data_addr), session.data_port,
+@@ -427,6 +439,9 @@ static int data_active_open(char *reason, off_t size) {
+ destroy_pool(session.d->pool);
+ session.d = NULL;
+ return -1;
++ } else
++ break;
++
+ }
+
+ c = pr_inet_openrw(session.pool, session.d, NULL, PR_NETIO_STRM_DATA,
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/proftpd/patches/005.proftpd-error_code.patch Tue May 19 02:34:35 2015 -0700
@@ -0,0 +1,466 @@
+diff --git a/include/dirtree.h b/include/dirtree.h
+index 0f41986..fe7b14b 100644
+--- a/include/dirtree.h
++++ b/include/dirtree.h
+@@ -126,6 +126,10 @@ typedef struct cmd_struc {
+ pr_table_t *notes; /* Private data for passing/retaining between handlers */
+
+ int cmd_id; /* Index into commands list, for faster comparisons */
++
++ int error_code; /* Stores errno of failed file transfer
++ * commands. Required for Solaris auditing.
++ */
+ } cmd_rec;
+
+ struct config_struc {
+diff --git a/modules/mod_core.c b/modules/mod_core.c
+index e33ee11..f680748 100644
+--- a/modules/mod_core.c
++++ b/modules/mod_core.c
+@@ -4775,6 +4775,7 @@ MODRET core_rmd(cmd_rec *cmd) {
+ dir = dir_canonical_path(cmd->tmp_pool, dir);
+ if (dir == NULL) {
+ int xerrno = EINVAL;
++ cmd->error_code = EINVAL;
+
+ pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
+
+@@ -4784,6 +4785,7 @@ MODRET core_rmd(cmd_rec *cmd) {
+
+ if (!dir_check_canon(cmd->tmp_pool, cmd, cmd->group, dir, NULL)) {
+ int xerrno = EACCES;
++ cmd->error_code = EACCES;
+
+ pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
+
+@@ -4793,6 +4795,7 @@ MODRET core_rmd(cmd_rec *cmd) {
+
+ if (pr_fsio_rmdir(dir) < 0) {
+ int xerrno = errno;
++ cmd->error_code = errno;
+
+ (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): "
+ "error removing directory '%s': %s", cmd->argv[0], session.user,
+@@ -4849,6 +4852,7 @@ MODRET core_mkd(cmd_rec *cmd) {
+ dir = dir_canonical_path(cmd->tmp_pool, dir);
+ if (dir == NULL) {
+ int xerrno = EINVAL;
++ cmd->error_code = EINVAL;
+
+ pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
+
+@@ -4858,6 +4862,7 @@ MODRET core_mkd(cmd_rec *cmd) {
+
+ if (!dir_check_canon(cmd->tmp_pool, cmd, cmd->group, dir, NULL)) {
+ int xerrno = EACCES;
++ cmd->error_code = EACCES;
+
+ pr_log_debug(DEBUG8, "%s command denied by <Limit> config", cmd->argv[0]);
+ pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
+@@ -4869,6 +4874,7 @@ MODRET core_mkd(cmd_rec *cmd) {
+ if (pr_fsio_smkdir(cmd->tmp_pool, dir, 0777, session.fsuid,
+ session.fsgid) < 0) {
+ int xerrno = errno;
++ cmd->error_code = errno;
+
+ (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): "
+ "error making directory '%s': %s", cmd->argv[0], session.user,
+@@ -4915,6 +4921,7 @@ MODRET core_mdtm(cmd_rec *cmd) {
+ !dir_check(cmd->tmp_pool, cmd, cmd->group, path, NULL) ||
+ pr_fsio_stat(path, &st) == -1) {
+ int xerrno = errno;
++ cmd->error_code = errno;
+
+ pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
+
+@@ -5026,6 +5033,7 @@ MODRET core_dele(cmd_rec *cmd) {
+ path = dir_canonical_path(cmd->tmp_pool, path);
+ if (path == NULL) {
+ int xerrno = ENOENT;
++ cmd->error_code = ENOENT;
+
+ pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
+
+@@ -5035,6 +5043,7 @@ MODRET core_dele(cmd_rec *cmd) {
+
+ if (!dir_check(cmd->tmp_pool, cmd, cmd->group, path, NULL)) {
+ int xerrno = errno;
++ cmd->error_code = errno;
+
+ pr_log_debug(DEBUG7, "deleting '%s' denied by <Limit> configuration", path);
+ pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
+@@ -5051,6 +5060,7 @@ MODRET core_dele(cmd_rec *cmd) {
+ pr_fs_clear_cache();
+ if (pr_fsio_lstat(path, &st) < 0) {
+ int xerrno = errno;
++ cmd->error_code = errno;
+
+ pr_log_debug(DEBUG3, "unable to lstat '%s': %s", path, strerror(xerrno));
+ pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
+@@ -5065,6 +5075,7 @@ MODRET core_dele(cmd_rec *cmd) {
+ */
+ if (S_ISDIR(st.st_mode)) {
+ int xerrno = EISDIR;
++ cmd->error_code = EISDIR;
+
+ (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): "
+ "error deleting '%s': %s", cmd->argv[0], session.user,
+@@ -5081,6 +5092,7 @@ MODRET core_dele(cmd_rec *cmd) {
+
+ if (pr_fsio_unlink(path) < 0) {
+ int xerrno = errno;
++ cmd->error_code = errno;
+
+ (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): "
+ "error deleting '%s': %s", cmd->argv[0], session.user,
+@@ -5165,6 +5177,7 @@ MODRET core_rnto(cmd_rec *cmd) {
+ pr_log_debug(DEBUG6, "AllowOverwrite denied permission for %s", path);
+ pr_response_add_err(R_550, _("%s: Rename permission denied"), cmd->arg);
+ errno = EACCES;
++ cmd->error_code = EACCES;
+ return PR_ERROR(cmd);
+ }
+
+@@ -5172,6 +5185,7 @@ MODRET core_rnto(cmd_rec *cmd) {
+ !dir_check_canon(cmd->tmp_pool, cmd, cmd->group, path, NULL) ||
+ pr_fsio_rename(session.xfer.path, path) == -1) {
+ int xerrno = errno;
++ cmd->error_code = errno;
+
+ if (xerrno != EXDEV) {
+ (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): "
+@@ -5223,6 +5237,7 @@ MODRET core_rnto(cmd_rec *cmd) {
+ */
+ if (pr_fs_copy_file(session.xfer.path, path) < 0) {
+ xerrno = errno;
++ cmd->error_code = errno;
+
+ (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): "
+ "error copying '%s' to '%s': %s", cmd->argv[0], session.user,
+@@ -5238,6 +5253,8 @@ MODRET core_rnto(cmd_rec *cmd) {
+
+ /* Once copied, unlink the original file. */
+ if (pr_fsio_unlink(session.xfer.path) < 0) {
++ cmd->error_code = errno;
++
+ pr_log_debug(DEBUG0, "error unlinking '%s': %s", session.xfer.path,
+ strerror(errno));
+ }
+@@ -5295,6 +5312,7 @@ MODRET core_rnfr(cmd_rec *cmd) {
+ !dir_check(cmd->tmp_pool, cmd, cmd->group, path, NULL) ||
+ !exists(path)) {
+ int xerrno = errno;
++ cmd->error_code = errno;
+
+ pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
+
+diff --git a/modules/mod_xfer.c b/modules/mod_xfer.c
+index bcfb487..41c597e 100644
+--- a/modules/mod_xfer.c
++++ b/modules/mod_xfer.c
+@@ -1190,6 +1190,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) {
+ if (cmd->argc < 2) {
+ pr_response_add_err(R_500, _("'%s' not understood"),
+ pr_cmd_get_displayable_str(cmd, NULL));
++ cmd->error_code = EINVAL;
+ errno = EINVAL;
+ return PR_ERROR(cmd);
+ }
+@@ -1200,6 +1201,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) {
+ if (!path ||
+ !dir_check(cmd->tmp_pool, cmd, cmd->group, path, NULL)) {
+ int xerrno = errno;
++ cmd->error_code = errno;
+
+ pr_log_debug(DEBUG8, "%s %s denied by <Limit> configuration", cmd->argv[0],
+ cmd->arg);
+@@ -1232,6 +1234,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) {
+ if (xfer_check_limit(cmd) < 0) {
+ pr_response_add_err(R_451, _("%s: Too many transfers"), cmd->arg);
+ errno = EPERM;
++ cmd->error_code = EPERM;
+ return PR_ERROR(cmd);
+ }
+
+@@ -1244,6 +1247,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) {
+ pr_log_debug(DEBUG6, "AllowOverwrite denied permission for %s", cmd->arg);
+ pr_response_add_err(R_550, _("%s: Overwrite permission denied"), cmd->arg);
+ errno = EACCES;
++ cmd->error_code = EACCES;
+ return PR_ERROR(cmd);
+ }
+
+@@ -1267,6 +1271,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) {
+
+ /* Deliberately use EISDIR for anything non-file (e.g. directories). */
+ errno = EISDIR;
++ cmd->error_code = EISDIR;
+ return PR_ERROR(cmd);
+ }
+ }
+@@ -1285,6 +1290,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) {
+ session.restart_pos = 0L;
+ session.xfer.xfer_type = STOR_DEFAULT;
+ errno = EPERM;
++ cmd->error_code = EPERM;
+ return PR_ERROR(cmd);
+ }
+
+@@ -1306,6 +1312,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) {
+ /* Otherwise everthing is good */
+ if (pr_table_add(cmd->notes, "mod_xfer.store-path",
+ pstrdup(cmd->pool, path), 0) < 0) {
++ cmd->error_code = errno;
+ if (errno != EEXIST) {
+ pr_log_pri(PR_LOG_NOTICE,
+ "notice: error adding 'mod_xfer.store-path': %s", strerror(errno));
+@@ -1326,6 +1333,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) {
+ pr_response_add_err(R_501,
+ _("REST not compatible with server configuration"));
+ errno = EINVAL;
++ cmd->error_code = EINVAL;
+ return PR_ERROR(cmd);
+ }
+
+@@ -1335,6 +1343,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) {
+ pr_response_add_err(R_550,
+ _("APPE not compatible with server configuration"));
+ errno = EINVAL;
++ cmd->error_code = EINVAL;
+ return PR_ERROR(cmd);
+ }
+
+@@ -1400,6 +1409,7 @@ MODRET xfer_pre_stou(cmd_rec *cmd) {
+ tmpfd = mkstemp(filename);
+ if (tmpfd < 0) {
+ int xerrno = errno;
++ cmd->error_code = errno;
+
+ pr_log_pri(PR_LOG_WARNING, "error: unable to use mkstemp(): %s",
+ strerror(xerrno));
+@@ -1428,6 +1438,7 @@ MODRET xfer_pre_stou(cmd_rec *cmd) {
+ if (!filename ||
+ !dir_check(cmd->tmp_pool, cmd, cmd->group, filename, NULL)) {
+ int xerrno = errno;
++ cmd->error_code = errno;
+
+ /* Do not forget to delete the file created by mkstemp(3) if there is
+ * an error.
+@@ -1461,12 +1472,14 @@ MODRET xfer_pre_stou(cmd_rec *cmd) {
+
+ /* Deliberately use EISDIR for anything non-file (e.g. directories). */
+ errno = EISDIR;
++ cmd->error_code = errno;
+ return PR_ERROR(cmd);
+ }
+
+ /* Otherwise everthing is good */
+ if (pr_table_add(cmd->notes, "mod_xfer.store-path",
+ pstrdup(cmd->pool, filename), 0) < 0) {
++ cmd->error_code = errno;
+ if (errno != EEXIST) {
+ pr_log_pri(PR_LOG_NOTICE,
+ "notice: error adding 'mod_xfer.store-path': %s", strerror(errno));
+@@ -1492,6 +1505,7 @@ MODRET xfer_post_stou(cmd_rec *cmd) {
+ mode_t mode = 0666;
+
+ if (pr_fsio_chmod(cmd->arg, mode) < 0) {
++ cmd->error_code = errno;
+
+ /* Not much to do but log the error. */
+ pr_log_pri(PR_LOG_NOTICE, "error: unable to chmod '%s' to %04o: %s",
+@@ -1510,6 +1524,7 @@ MODRET xfer_pre_appe(cmd_rec *cmd) {
+ if (xfer_check_limit(cmd) < 0) {
+ pr_response_add_err(R_451, _("%s: Too many transfers"), cmd->arg);
+ errno = EPERM;
++ cmd->error_code = EPERM;
+ return PR_ERROR(cmd);
+ }
+
+@@ -1580,6 +1595,7 @@ MODRET xfer_stor(cmd_rec *cmd) {
+
+ if (stor_fh) {
+ if (pr_fsio_lseek(stor_fh, 0, SEEK_END) == (off_t) -1) {
++ cmd->error_code = errno;
+ pr_log_debug(DEBUG4, "unable to seek to end of '%s' for appending: %s",
+ cmd->arg, strerror(errno));
+ (void) pr_fsio_close(stor_fh);
+@@ -1588,6 +1604,7 @@ MODRET xfer_stor(cmd_rec *cmd) {
+
+ } else {
+ ferrno = errno;
++ cmd->error_code = errno;
+
+ (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): "
+ "error opening '%s': %s", cmd->argv[0], session.user,
+@@ -1601,6 +1618,7 @@ MODRET xfer_stor(cmd_rec *cmd) {
+ O_WRONLY|(session.restart_pos ? 0 : O_TRUNC|O_CREAT));
+ if (stor_fh == NULL) {
+ ferrno = errno;
++ cmd->error_code = errno;
+
+ (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): "
+ "error opening '%s': %s", cmd->argv[0], session.user,
+@@ -1614,11 +1632,13 @@ MODRET xfer_stor(cmd_rec *cmd) {
+ int xerrno = 0;
+
+ if (pr_fsio_lseek(stor_fh, session.restart_pos, SEEK_SET) == -1) {
++ cmd->error_code = errno;
+ pr_log_debug(DEBUG4, "unable to seek to position %" PR_LU " of '%s': %s",
+ (pr_off_t) session.restart_pos, cmd->arg, strerror(errno));
+ xerrno = errno;
+
+ } else if (pr_fsio_stat(path, &st) == -1) {
++ cmd->error_code = errno;
+ pr_log_debug(DEBUG4, "unable to stat '%s': %s", cmd->arg,
+ strerror(errno));
+ xerrno = errno;
+@@ -1755,6 +1775,7 @@ MODRET xfer_stor(cmd_rec *cmd) {
+ pr_data_abort(EPERM, FALSE);
+ errno = EPERM;
+ #endif
++ cmd->error_code = errno;
+ return PR_ERROR(cmd);
+ }
+
+@@ -1766,6 +1787,7 @@ MODRET xfer_stor(cmd_rec *cmd) {
+ res = pr_fsio_write(stor_fh, lbuf, len);
+ if (res != len) {
+ int xerrno = EIO;
++ cmd->error_code = errno;
+
+ if (res < 0)
+ xerrno = errno;
+@@ -1795,6 +1817,7 @@ MODRET xfer_stor(cmd_rec *cmd) {
+
+ /* default abort errno, in case session.d et al has already gone away */
+ int xerrno = ECONNABORTED;
++ cmd->error_code = ECONNABORTED;
+
+ stor_abort();
+
+@@ -1814,6 +1837,7 @@ MODRET xfer_stor(cmd_rec *cmd) {
+
+ if (stor_complete() < 0) {
+ int xerrno = errno;
++ cmd->error_code = errno;
+
+ _log_transfer('i', 'i');
+
+@@ -1826,12 +1850,14 @@ MODRET xfer_stor(cmd_rec *cmd) {
+ if (xerrno == EDQUOT) {
+ pr_response_add_err(R_552, "%s: %s", cmd->arg, strerror(xerrno));
+ errno = xerrno;
++ cmd->error_code = errno;
+ return PR_ERROR(cmd);
+ }
+ #elif defined(EFBIG)
+ if (xerrno == EFBIG) {
+ pr_response_add_err(R_552, "%s: %s", cmd->arg, strerror(xerrno));
+ errno = xerrno;
++ cmd->error_code = errno;
+ return PR_ERROR(cmd);
+ }
+ #endif
+@@ -1845,6 +1871,7 @@ MODRET xfer_stor(cmd_rec *cmd) {
+ session.xfer.path_hidden) {
+ if (pr_fsio_rename(session.xfer.path_hidden, session.xfer.path) != 0) {
+ int xerrno = errno;
++ cmd->error_code = errno;
+
+ /* This should only fail on a race condition with a chmod/chown
+ * or if STOR_APPEND is on and the permissions are squirrely.
+@@ -1947,6 +1974,7 @@ MODRET xfer_pre_retr(cmd_rec *cmd) {
+ pr_response_add_err(R_500, _("'%s' not understood"),
+ pr_cmd_get_displayable_str(cmd, NULL));
+ errno = EINVAL;
++ cmd->error_code = EINVAL;
+ return PR_ERROR(cmd);
+ }
+
+@@ -1956,6 +1984,7 @@ MODRET xfer_pre_retr(cmd_rec *cmd) {
+ if (!dir ||
+ !dir_check(cmd->tmp_pool, cmd, cmd->group, dir, NULL)) {
+ int xerrno = errno;
++ cmd->error_code;
+
+ pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
+
+@@ -1978,12 +2007,14 @@ MODRET xfer_pre_retr(cmd_rec *cmd) {
+ if (xfer_check_limit(cmd) < 0) {
+ pr_response_add_err(R_451, _("%s: Too many transfers"), cmd->arg);
+ errno = EPERM;
++ cmd->error_code = EPERM;
+ return PR_ERROR(cmd);
+ }
+
+ fmode = file_mode(dir);
+ if (fmode == 0) {
+ int xerrno = errno;
++ cmd->error_code = errno;
+
+ pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
+
+@@ -2000,6 +2031,7 @@ MODRET xfer_pre_retr(cmd_rec *cmd) {
+
+ /* Deliberately use EISDIR for anything non-file (e.g. directories). */
+ errno = EISDIR;
++ cmd->error_code = EISDIR;
+ return PR_ERROR(cmd);
+ }
+
+@@ -2014,12 +2046,14 @@ MODRET xfer_pre_retr(cmd_rec *cmd) {
+ cmd->arg);
+ session.restart_pos = 0L;
+ errno = EPERM;
++ cmd->error_code = EPERM;
+ return PR_ERROR(cmd);
+ }
+
+ /* Otherwise everthing is good */
+ if (pr_table_add(cmd->notes, "mod_xfer.retr-path",
+ pstrdup(cmd->pool, dir), 0) < 0) {
++ cmd->error_code = errno;
+ if (errno != EEXIST) {
+ pr_log_pri(PR_LOG_NOTICE, "notice: error adding 'mod_xfer.retr-path': %s",
+ strerror(errno));
+@@ -2046,6 +2080,7 @@ MODRET xfer_retr(cmd_rec *cmd) {
+ retr_fh = pr_fsio_open(dir, O_RDONLY);
+ if (retr_fh == NULL) {
+ int xerrno = errno;
++ cmd->error_code = errno;
+
+ (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): "
+ "error opening '%s': %s", cmd->argv[0], session.user,
+@@ -2059,6 +2094,7 @@ MODRET xfer_retr(cmd_rec *cmd) {
+ if (pr_fsio_stat(dir, &st) < 0) {
+ /* Error stat'ing the file. */
+ int xerrno = errno;
++ cmd->error_code = errno;
+ pr_fsio_close(retr_fh);
+ errno = xerrno;
+
+@@ -2083,6 +2119,7 @@ MODRET xfer_retr(cmd_rec *cmd) {
+ if (pr_fsio_lseek(retr_fh, session.restart_pos,
+ SEEK_SET) == (off_t) -1) {
+ int xerrno = errno;
++ cmd->error_code = errno;
+ pr_fsio_close(retr_fh);
+ errno = xerrno;
+ retr_fh = NULL;
+@@ -2143,6 +2180,7 @@ MODRET xfer_retr(cmd_rec *cmd) {
+ retr_abort();
+
+ /* Set errno to EPERM ("Operation not permitted") */
++ cmd->error_code = EPERM;
+ pr_data_abort(EPERM, FALSE);
+ return PR_ERROR(cmd);
+ }
+@@ -2174,6 +2212,7 @@ MODRET xfer_retr(cmd_rec *cmd) {
+ * is preserved; errno itself might be overwritten in retr_abort().
+ */
+ int xerrno = errno;
++ cmd->error_code = errno;
+
+ retr_abort();
+ pr_data_abort(xerrno, FALSE);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/proftpd/patches/006.18845170.patch Tue May 19 02:34:35 2015 -0700
@@ -0,0 +1,20 @@
+http://bugs.proftpd.org/show_bug.cgi?id=4069
+https://github.com/proftpd/proftpd/commit/38cf9e5028cbddee2b0dcba436d60199da1edf80
+
+--- a/modules/mod_ls.c
++++ b/modules/mod_ls.c
+@@ -2755,6 +2755,13 @@ MODRET ls_nlst(cmd_rec *cmd) {
+ parse_list_opts(&list_options, &glob_flags, TRUE);
+ }
+
++ /* If, after parsing out any options, the target string is empty, assume
++ * the current directory (Bug#4069).
++ */
++ if (*target == '\0') {
++ target = pstrdup(cmd->tmp_pool, ".");
++ }
++
+ /* If the target starts with '~' ... */
+ if (*target == '~') {
+ char pb[PR_TUNABLE_PATH_MAX + 1] = {'\0'};
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/proftpd/patches/007.19575647.patch Tue May 19 02:34:35 2015 -0700
@@ -0,0 +1,53 @@
+diff --git a/include/pr-syslog.h b/include/pr-syslog.h
+index 3eea2be..774a3b0 100644
+--- a/include/pr-syslog.h
++++ b/include/pr-syslog.h
+@@ -68,7 +68,7 @@
+ #elif defined(__hpux)
+ # define PR_PATH_LOG "/dev/log.un"
+ #else
+-# define PR_PATH_LOG "/dev/log"
++# define PR_PATH_LOG "/dev/conslog"
+ #endif
+
+ /* Close desriptor used to write to system logger. */
+diff --git a/lib/pr-syslog.c b/lib/pr-syslog.c
+index 3a62956..2b3d747 100644
+--- a/lib/pr-syslog.c
++++ b/lib/pr-syslog.c
+@@ -265,7 +265,7 @@ static void pr_vsyslog(int sockfd, int pri, register const char *fmt,
+ send(sockfd, logbuf, buflen, 0);
+ #else
+
+- /* Prepare the structs for use by putmsg(). As /dev/log is a STREAMS
++ /* Prepare the structs for use by putmsg(). As /dev/conslog is a STREAMS
+ * device on Solaris (and possibly other platforms?), putmsg() is
+ * used so that syslog facility and level are properly honored; write()
+ * does not seem to work as desired.
+@@ -347,22 +347,11 @@ int pr_openlog(const char *ident, int opts, int facility) {
+ }
+ #else
+ sockfd = open(PR_PATH_LOG, O_WRONLY);
+-
+-# ifdef SOLARIS2
+- /* Workaround for a /dev/log bug (SunSolve bug #4817079) on Solaris. */
+- if (sockfd >= 0) {
+- struct strioctl ic;
+-
+- ic.ic_cmd = I_ERRLOG;
+- ic.ic_timout = 0;
+- ic.ic_len = 0;
+- ic.ic_dp = NULL;
+-
+- if (ioctl(sockfd, I_STR, &ic) < 0)
+- fprintf(stderr, "error setting I_ERRLOG on " PR_PATH_LOG ": %s\n",
+- strerror(errno));
++ if (sockfd < 0) {
++ fprintf(stderr, "failed to open %s: %d, %s\n",
++ PR_PATH_LOG, errno, strerror(errno));
++ exit(EXIT_FAILURE);
+ }
+-# endif /* SOLARIS2 */
+ #endif
+
+ return sockfd;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/proftpd/patches/008.19596338.patch Tue May 19 02:34:35 2015 -0700
@@ -0,0 +1,157 @@
+diff --git a/include/glibc-glob.h b/include/glibc-glob.h
+index 422089a..a55899a 100644
+--- a/include/glibc-glob.h
++++ b/include/glibc-glob.h
+@@ -85,6 +85,7 @@ extern "C" {
+ #define GLOB_ABORTED 2 /* Read error. */
+ #define GLOB_NOMATCH 3 /* No matches found. */
+ #define GLOB_NOSYS 4 /* Not implemented. */
++#define GLOB_LIMIT 5 /* MAX_RESULTS limit reached */
+ #ifdef _GNU_SOURCE
+ /* Previous versions of this file defined GLOB_ABEND instead of
+ GLOB_ABORTED. Provide a compatibility definition here. */
+diff --git a/lib/glibc-glob.c b/lib/glibc-glob.c
+index 43b02bc..92c2b94 100644
+--- a/lib/glibc-glob.c
++++ b/lib/glibc-glob.c
+@@ -40,6 +40,15 @@ char *alloca ();
+ #define MAX_RECURSION PR_TUNABLE_GLOBBING_MAX_RECURSION
+ #define MAX_RESULTS PR_TUNABLE_GLOBBING_MAX_MATCHES
+
++unsigned long GlobMaxResults = 0;
++
++static unsigned long get_globmaxresults(void)
++{
++ if (GlobMaxResults > 0)
++ return GlobMaxResults;
++ return MAX_RESULTS;
++}
++
+ /* Enable GNU extensions in glob.h. */
+ #ifndef _GNU_SOURCE
+ # define _GNU_SOURCE 1
+@@ -239,8 +248,6 @@ extern void bcopy ();
+ # define mempcpy(Dest, Src, Len) __mempcpy (Dest, Src, Len)
+ #endif
+
+-static unsigned long nbresults;
+-
+ #ifndef __GNU_LIBRARY__
+ # ifdef __GNUC__
+ __inline
+@@ -1157,7 +1164,6 @@ int
+ glob (const char *pattern, int flags, int (*errfunc) __P((const char *, int)),
+ glob_t *pglob)
+ {
+- nbresults = 0UL;
+ return glob_limited(0U, pattern, flags, errfunc, pglob);
+ }
+
+@@ -1318,6 +1324,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
+ size_t nfound;
+ int meta;
+ int save;
++ int ret_glob_limit = 0;
+
+ meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE));
+ if (meta == 0 && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
+@@ -1428,10 +1435,6 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
+ #endif
+ if (d == NULL)
+ break;
+- if (nbresults > MAX_RESULTS) {
+- break;
+- }
+- nbresults++;
+ if (! REAL_DIR_ENTRY (d))
+ continue;
+
+@@ -1463,6 +1466,14 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
+ new->next = names;
+ names = new;
+ ++nfound;
++
++ if (nfound > get_globmaxresults()) {
++ for (; names != NULL; names = names->next)
++ free(names->name);
++ nfound = 0;
++ ret_glob_limit = 1;
++ break;
++ }
+ }
+ }
+ }
+@@ -1516,6 +1527,9 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
+ }
+ __set_errno (save);
+
++ if (ret_glob_limit)
++ return GLOB_LIMIT;
++
+ return nfound == 0 ? GLOB_NOMATCH : 0;
+
+ memory_error:
+diff --git a/modules/mod_core.c b/modules/mod_core.c
+index e33ee11..1f6da19 100644
+--- a/modules/mod_core.c
++++ b/modules/mod_core.c
+@@ -973,6 +973,26 @@ MODRET set_maxconnrate(cmd_rec *cmd) {
+ return PR_HANDLED(cmd);
+ }
+
++extern unsigned long GlobMaxResults;
++
++MODRET set_globmaxresults(cmd_rec *cmd) {
++ unsigned long max;
++ char *endp;
++
++ CHECK_ARGS(cmd,1);
++ CHECK_CONF(cmd,CONF_ROOT);
++
++ max = strtoul(cmd->argv[1], &endp, 10);
++
++ if ((endp && *endp) || max == 0)
++ CONF_ERROR(cmd, "argument must be greater than 0");
++
++ pr_log_debug(DEBUG1, "setting GlobMaxResults to %lu", max);
++
++ GlobMaxResults = max;
++ return PR_HANDLED(cmd);
++}
++
+ MODRET set_timeoutidle(cmd_rec *cmd) {
+ int timeout = -1;
+ config_rec *c = NULL;
+@@ -6108,6 +6128,7 @@ static conftable core_conftab[] = {
+ { "DisplayConnect", set_displayconnect, NULL },
+ { "DisplayQuit", set_displayquit, NULL },
+ { "From", add_from, NULL },
++ { "GlobMaxResults", set_globmaxresults, NULL },
+ { "Group", set_group, NULL },
+ { "GroupOwner", add_groupowner, NULL },
+ { "HideFiles", set_hidefiles, NULL },
+diff --git a/modules/mod_ls.c b/modules/mod_ls.c
+index 5b95d2b..e8bbb74 100644
+--- a/modules/mod_ls.c
++++ b/modules/mod_ls.c
+@@ -2015,6 +2015,8 @@ static int dolist(cmd_rec *cmd, const char *opt, int clearflags) {
+ pr_response_add(R_226, _("Read error during globbing of %s"),
+ pr_fs_encode_path(cmd->tmp_pool, arg));
+
++ } else if (a == GLOB_LIMIT) {
++ pr_response_add(R_226, _("Too many files"));
+ } else if (a != GLOB_NOMATCH) {
+ pr_response_add(R_226, _("Unknown error during globbing of %s"),
+ pr_fs_encode_path(cmd->tmp_pool, arg));
+@@ -2837,7 +2839,10 @@ MODRET ls_nlst(cmd_rec *cmd) {
+ return PR_HANDLED(cmd);
+ }
+
+- pr_response_add_err(R_450, _("No files found"));
++ if (res == GLOB_LIMIT)
++ pr_response_add_err(R_451, _("Too many files"));
++ else
++ pr_response_add_err(R_450, _("No files found"));
+ return PR_ERROR(cmd);
+ }
+ }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/proftpd/patches/009.19668629.patch Tue May 19 02:34:35 2015 -0700
@@ -0,0 +1,18 @@
+http://bugs.proftpd.org/show_bug.cgi?id=4109
+https://github.com/proftpd/proftpd/commit/0b8afb267eb6fd6acf98595a8c2812cd27ac11a0
+
+diff --git a/src/inet.c b/src/inet.c
+index f5602e0..d0a0631 100644
+--- a/src/inet.c
++++ b/src/inet.c
+@@ -770,8 +770,9 @@ int pr_inet_set_proto_opts(pool *p, conn_t *c, int mss, int nodelay,
+ if (pr_netaddr_use_ipv6()) {
+ /* Only set TCLASS flags on IPv6 sockets; IPv4 sockets use TOS. */
+ if (pr_netaddr_get_family(c->local_addr) == AF_INET6) {
++ int level = ipv6_proto;
+ if (c->listen_fd != -1) {
+- if (setsockopt(c->listen_fd, ip_level, IPV6_TCLASS, (void *) &tos,
++ if (setsockopt(c->listen_fd, level, IPV6_TCLASS, (void *) &tos,
+ sizeof(tos)) < 0) {
+ pr_log_pri(PR_LOG_NOTICE, "error setting listen fd IPV6_TCLASS: %s",
+ strerror(errno));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/proftpd/patches/010.20393612.patch Tue May 19 02:34:35 2015 -0700
@@ -0,0 +1,15 @@
+http://bugs.proftpd.org/show_bug.cgi?id=4132
+
+diff --git a/src/log.c b/src/log.c
+index 4b83413..c83b8ee 100644
+--- a/src/log.c
++++ b/src/log.c
+@@ -36,7 +36,7 @@
+ static int syslog_open = FALSE;
+ static int syslog_discard = FALSE;
+ static int logstderr = TRUE;
+-static int debug_level = DEBUG0; /* Default is no debug logging */
++static int debug_level = DEBUG0 - 1; /* Default is no debug logging */
+ static int facility = LOG_DAEMON;
+ static int set_facility = -1;
+ static char systemlog_fn[PR_TUNABLE_PATH_MAX] = {'\0'};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/proftpd/patches/011.19693019-proftpd-slow_ls.patch Tue May 19 02:34:35 2015 -0700
@@ -0,0 +1,103 @@
+The fix was developed in-house and submitted upstream. The upstream bug
+is:
+
+http://bugs.proftpd.org/show_bug.cgi?id=4157
+
+diff --git a/modules/mod_core.c b/modules/mod_core.c
+--- a/modules/mod_core.c
++++ b/modules/mod_core.c
+@@ -40,6 +40,7 @@
+ /* From src/main.c */
+ extern unsigned long max_connects;
+ extern unsigned int max_connect_interval;
++extern unsigned char tracing_enabled;
+
+ /* From modules/mod_site.c */
+ extern modret_t *site_dispatch(cmd_rec*);
+@@ -1381,6 +1382,8 @@
+ int per_session = FALSE;
+ unsigned int idx = 1;
+
++ tracing_enabled = TRUE;
++
+ if (cmd->argc-1 < 1)
+ CONF_ERROR(cmd, "wrong number of parameters");
+ CHECK_CONF(cmd, CONF_ROOT);
+diff --git a/modules/mod_ls.c b/modules/mod_ls.c
+--- a/modules/mod_ls.c
++++ b/modules/mod_ls.c
+@@ -307,10 +307,12 @@
+
+ static int sendline(int flags, char *fmt, ...) {
+ va_list msg;
+- char buf[PR_TUNABLE_BUFFER_SIZE+1] = {'\0'};
++ char buf[PR_TUNABLE_BUFFER_SIZE+1];
+ int res = 0;
+ size_t buflen, listbuflen;
+
++ (void) memset(buf, '\0', sizeof(buf));
++
+ if (listbuf == NULL) {
+ listbufsz = pr_config_get_server_xfer_bufsz(PR_NETIO_IO_WR);
+ listbuf = listbuf_ptr = pcalloc(session.pool, listbufsz);
+diff --git a/src/fsio.c b/src/fsio.c
+--- a/src/fsio.c
++++ b/src/fsio.c
+@@ -556,10 +556,12 @@
+ static int cache_stat(pr_fs_t *fs, const char *path, struct stat *sbuf,
+ unsigned int op) {
+ int res = -1;
+- char pathbuf[PR_TUNABLE_PATH_MAX + 1] = {'\0'};
++ char pathbuf[PR_TUNABLE_PATH_MAX + 1];
+ int (*mystat)(pr_fs_t *, const char *, struct stat *) = NULL;
+ size_t pathlen;
+
++ (void) memset(pathbuf, '\0', sizeof(pathbuf));
++
+ /* Sanity checks */
+ if (fs == NULL) {
+ errno = EINVAL;
+@@ -641,8 +643,8 @@
+ * during the hit.
+ */
+ static pr_fs_t *lookup_dir_fs(const char *path, int op) {
+- char buf[PR_TUNABLE_PATH_MAX + 1] = {'\0'};
+- char tmp_path[PR_TUNABLE_PATH_MAX + 1] = {'\0'};
++ char buf[PR_TUNABLE_PATH_MAX + 1];
++ char tmp_path[PR_TUNABLE_PATH_MAX + 1];
+ pr_fs_t *fs = NULL;
+ int exact = FALSE;
+ size_t tmp_pathlen = 0;
+@@ -651,6 +653,9 @@
+ pr_fs_match_t *fsm = NULL;
+ #endif /* PR_FS_MATCH */
+
++ (void) memset(buf, '\0', sizeof(buf));
++ (void) memset(tmp_path, '\0', sizeof(tmp_path));
++
+ sstrncpy(buf, path, sizeof(buf));
+
+ /* Check if the given path is an absolute path. Since there may be
+diff --git a/src/trace.c b/src/trace.c
+--- a/src/trace.c
++++ b/src/trace.c
+@@ -32,6 +32,8 @@
+
+ #ifdef PR_USE_TRACE
+
++unsigned char tracing_enabled = FALSE;
++
+ static int trace_logfd = -1;
+ static unsigned long trace_opts = PR_TRACE_OPT_DEFAULT;
+ static pool *trace_pool = NULL;
+@@ -473,6 +475,10 @@
+ int res;
+ va_list msg;
+
++ /* Optimization: do not run tracing code unless explicitly enabled. */
++ if (tracing_enabled == FALSE)
++ return 0;
++
+ va_start(msg, fmt);
+ res = pr_trace_vmsg(channel, level, fmt, msg);
+ va_end(msg);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/proftpd/patches/012.20553228-dtrace-provider.patch Tue May 19 02:34:35 2015 -0700
@@ -0,0 +1,66 @@
+http://bugs.proftpd.org/show_bug.cgi?id=4162
+
+--- a/modules/mod_xfer.c 2015-02-03 20:54:22.857151750 -0800
++++ b/modules/mod_xfer.c 2015-02-03 21:10:36.020000070 -0800
+@@ -31,6 +31,9 @@
+
+ #include "conf.h"
+ #include "privs.h"
++#ifdef _SOLARIS_DTRACE
++#include "ftp_provider_impl.h"
++#endif
+
+ #ifdef HAVE_SYS_SENDFILE_H
+ # include <sys/sendfile.h>
+@@ -1784,7 +1787,24 @@
+ * be doing short writes, and we ideally should be more resilient/graceful
+ * in the face of such things.
+ */
++#ifdef _SOLARIS_DTRACE
++ if (ftp_transfer_start_enabled()) {
++ ftpproto_t proto;
++ FTP_TRANSFER_PROTO(&proto, stor_fh, 0);
++ ftp_transfer_start(&proto);
++ }
++#endif
++
+ res = pr_fsio_write(stor_fh, lbuf, len);
++
++#ifdef _SOLARIS_DTRACE
++ if (ftp_transfer_done_enabled() && res == len) {
++ ftpproto_t proto;
++ FTP_TRANSFER_PROTO(&proto, stor_fh, res);
++ ftp_transfer_done(&proto);
++ }
++#endif
++
+ if (res != len) {
+ int xerrno = EIO;
+ cmd->error_code = errno;
+@@ -2203,7 +2223,24 @@
+ if (XFER_ABORTED)
+ break;
+
++#ifdef _SOLARIS_DTRACE
++ if (ftp_transfer_start_enabled()) {
++ ftpproto_t proto;
++ FTP_TRANSFER_PROTO(&proto, retr_fh, 0);
++ ftp_transfer_start(&proto);
++ }
++#endif
++
+ len = transmit_data(nbytes_sent, &curr_pos, lbuf, bufsz);
++
++#ifdef _SOLARIS_DTRACE
++ if (ftp_transfer_done_enabled() && len > 0) {
++ ftpproto_t proto;
++ FTP_TRANSFER_PROTO(&proto, retr_fh, len);
++ ftp_transfer_done(&proto);
++ }
++#endif
++
+ if (len == 0)
+ break;
+
+
+
--- a/components/proftpd/patches/18845170.patch Fri May 15 09:41:56 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-http://bugs.proftpd.org/show_bug.cgi?id=4069
-https://github.com/proftpd/proftpd/commit/38cf9e5028cbddee2b0dcba436d60199da1edf80
-
---- a/modules/mod_ls.c
-+++ b/modules/mod_ls.c
-@@ -2755,6 +2755,13 @@ MODRET ls_nlst(cmd_rec *cmd) {
- parse_list_opts(&list_options, &glob_flags, TRUE);
- }
-
-+ /* If, after parsing out any options, the target string is empty, assume
-+ * the current directory (Bug#4069).
-+ */
-+ if (*target == '\0') {
-+ target = pstrdup(cmd->tmp_pool, ".");
-+ }
-+
- /* If the target starts with '~' ... */
- if (*target == '~') {
- char pb[PR_TUNABLE_PATH_MAX + 1] = {'\0'};
-
--- a/components/proftpd/patches/19575647.patch Fri May 15 09:41:56 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-diff --git a/include/pr-syslog.h b/include/pr-syslog.h
-index 3eea2be..774a3b0 100644
---- a/include/pr-syslog.h
-+++ b/include/pr-syslog.h
-@@ -68,7 +68,7 @@
- #elif defined(__hpux)
- # define PR_PATH_LOG "/dev/log.un"
- #else
--# define PR_PATH_LOG "/dev/log"
-+# define PR_PATH_LOG "/dev/conslog"
- #endif
-
- /* Close desriptor used to write to system logger. */
-diff --git a/lib/pr-syslog.c b/lib/pr-syslog.c
-index 3a62956..2b3d747 100644
---- a/lib/pr-syslog.c
-+++ b/lib/pr-syslog.c
-@@ -265,7 +265,7 @@ static void pr_vsyslog(int sockfd, int pri, register const char *fmt,
- send(sockfd, logbuf, buflen, 0);
- #else
-
-- /* Prepare the structs for use by putmsg(). As /dev/log is a STREAMS
-+ /* Prepare the structs for use by putmsg(). As /dev/conslog is a STREAMS
- * device on Solaris (and possibly other platforms?), putmsg() is
- * used so that syslog facility and level are properly honored; write()
- * does not seem to work as desired.
-@@ -347,22 +347,11 @@ int pr_openlog(const char *ident, int opts, int facility) {
- }
- #else
- sockfd = open(PR_PATH_LOG, O_WRONLY);
--
--# ifdef SOLARIS2
-- /* Workaround for a /dev/log bug (SunSolve bug #4817079) on Solaris. */
-- if (sockfd >= 0) {
-- struct strioctl ic;
--
-- ic.ic_cmd = I_ERRLOG;
-- ic.ic_timout = 0;
-- ic.ic_len = 0;
-- ic.ic_dp = NULL;
--
-- if (ioctl(sockfd, I_STR, &ic) < 0)
-- fprintf(stderr, "error setting I_ERRLOG on " PR_PATH_LOG ": %s\n",
-- strerror(errno));
-+ if (sockfd < 0) {
-+ fprintf(stderr, "failed to open %s: %d, %s\n",
-+ PR_PATH_LOG, errno, strerror(errno));
-+ exit(EXIT_FAILURE);
- }
--# endif /* SOLARIS2 */
- #endif
-
- return sockfd;
--- a/components/proftpd/patches/19596338.patch Fri May 15 09:41:56 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,157 +0,0 @@
-diff --git a/include/glibc-glob.h b/include/glibc-glob.h
-index 422089a..a55899a 100644
---- a/include/glibc-glob.h
-+++ b/include/glibc-glob.h
-@@ -85,6 +85,7 @@ extern "C" {
- #define GLOB_ABORTED 2 /* Read error. */
- #define GLOB_NOMATCH 3 /* No matches found. */
- #define GLOB_NOSYS 4 /* Not implemented. */
-+#define GLOB_LIMIT 5 /* MAX_RESULTS limit reached */
- #ifdef _GNU_SOURCE
- /* Previous versions of this file defined GLOB_ABEND instead of
- GLOB_ABORTED. Provide a compatibility definition here. */
-diff --git a/lib/glibc-glob.c b/lib/glibc-glob.c
-index 43b02bc..92c2b94 100644
---- a/lib/glibc-glob.c
-+++ b/lib/glibc-glob.c
-@@ -40,6 +40,15 @@ char *alloca ();
- #define MAX_RECURSION PR_TUNABLE_GLOBBING_MAX_RECURSION
- #define MAX_RESULTS PR_TUNABLE_GLOBBING_MAX_MATCHES
-
-+unsigned long GlobMaxResults = 0;
-+
-+static unsigned long get_globmaxresults(void)
-+{
-+ if (GlobMaxResults > 0)
-+ return GlobMaxResults;
-+ return MAX_RESULTS;
-+}
-+
- /* Enable GNU extensions in glob.h. */
- #ifndef _GNU_SOURCE
- # define _GNU_SOURCE 1
-@@ -239,8 +248,6 @@ extern void bcopy ();
- # define mempcpy(Dest, Src, Len) __mempcpy (Dest, Src, Len)
- #endif
-
--static unsigned long nbresults;
--
- #ifndef __GNU_LIBRARY__
- # ifdef __GNUC__
- __inline
-@@ -1157,7 +1164,6 @@ int
- glob (const char *pattern, int flags, int (*errfunc) __P((const char *, int)),
- glob_t *pglob)
- {
-- nbresults = 0UL;
- return glob_limited(0U, pattern, flags, errfunc, pglob);
- }
-
-@@ -1318,6 +1324,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
- size_t nfound;
- int meta;
- int save;
-+ int ret_glob_limit = 0;
-
- meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE));
- if (meta == 0 && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
-@@ -1428,10 +1435,6 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
- #endif
- if (d == NULL)
- break;
-- if (nbresults > MAX_RESULTS) {
-- break;
-- }
-- nbresults++;
- if (! REAL_DIR_ENTRY (d))
- continue;
-
-@@ -1463,6 +1466,14 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
- new->next = names;
- names = new;
- ++nfound;
-+
-+ if (nfound > get_globmaxresults()) {
-+ for (; names != NULL; names = names->next)
-+ free(names->name);
-+ nfound = 0;
-+ ret_glob_limit = 1;
-+ break;
-+ }
- }
- }
- }
-@@ -1516,6 +1527,9 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
- }
- __set_errno (save);
-
-+ if (ret_glob_limit)
-+ return GLOB_LIMIT;
-+
- return nfound == 0 ? GLOB_NOMATCH : 0;
-
- memory_error:
-diff --git a/modules/mod_core.c b/modules/mod_core.c
-index e33ee11..1f6da19 100644
---- a/modules/mod_core.c
-+++ b/modules/mod_core.c
-@@ -973,6 +973,26 @@ MODRET set_maxconnrate(cmd_rec *cmd) {
- return PR_HANDLED(cmd);
- }
-
-+extern unsigned long GlobMaxResults;
-+
-+MODRET set_globmaxresults(cmd_rec *cmd) {
-+ unsigned long max;
-+ char *endp;
-+
-+ CHECK_ARGS(cmd,1);
-+ CHECK_CONF(cmd,CONF_ROOT);
-+
-+ max = strtoul(cmd->argv[1], &endp, 10);
-+
-+ if ((endp && *endp) || max == 0)
-+ CONF_ERROR(cmd, "argument must be greater than 0");
-+
-+ pr_log_debug(DEBUG1, "setting GlobMaxResults to %lu", max);
-+
-+ GlobMaxResults = max;
-+ return PR_HANDLED(cmd);
-+}
-+
- MODRET set_timeoutidle(cmd_rec *cmd) {
- int timeout = -1;
- config_rec *c = NULL;
-@@ -6108,6 +6128,7 @@ static conftable core_conftab[] = {
- { "DisplayConnect", set_displayconnect, NULL },
- { "DisplayQuit", set_displayquit, NULL },
- { "From", add_from, NULL },
-+ { "GlobMaxResults", set_globmaxresults, NULL },
- { "Group", set_group, NULL },
- { "GroupOwner", add_groupowner, NULL },
- { "HideFiles", set_hidefiles, NULL },
-diff --git a/modules/mod_ls.c b/modules/mod_ls.c
-index 5b95d2b..e8bbb74 100644
---- a/modules/mod_ls.c
-+++ b/modules/mod_ls.c
-@@ -2015,6 +2015,8 @@ static int dolist(cmd_rec *cmd, const char *opt, int clearflags) {
- pr_response_add(R_226, _("Read error during globbing of %s"),
- pr_fs_encode_path(cmd->tmp_pool, arg));
-
-+ } else if (a == GLOB_LIMIT) {
-+ pr_response_add(R_226, _("Too many files"));
- } else if (a != GLOB_NOMATCH) {
- pr_response_add(R_226, _("Unknown error during globbing of %s"),
- pr_fs_encode_path(cmd->tmp_pool, arg));
-@@ -2837,7 +2839,10 @@ MODRET ls_nlst(cmd_rec *cmd) {
- return PR_HANDLED(cmd);
- }
-
-- pr_response_add_err(R_450, _("No files found"));
-+ if (res == GLOB_LIMIT)
-+ pr_response_add_err(R_451, _("Too many files"));
-+ else
-+ pr_response_add_err(R_450, _("No files found"));
- return PR_ERROR(cmd);
- }
- }
--- a/components/proftpd/patches/19668629.patch Fri May 15 09:41:56 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-http://bugs.proftpd.org/show_bug.cgi?id=4109
-https://github.com/proftpd/proftpd/commit/0b8afb267eb6fd6acf98595a8c2812cd27ac11a0
-
-diff --git a/src/inet.c b/src/inet.c
-index f5602e0..d0a0631 100644
---- a/src/inet.c
-+++ b/src/inet.c
-@@ -770,8 +770,9 @@ int pr_inet_set_proto_opts(pool *p, conn_t *c, int mss, int nodelay,
- if (pr_netaddr_use_ipv6()) {
- /* Only set TCLASS flags on IPv6 sockets; IPv4 sockets use TOS. */
- if (pr_netaddr_get_family(c->local_addr) == AF_INET6) {
-+ int level = ipv6_proto;
- if (c->listen_fd != -1) {
-- if (setsockopt(c->listen_fd, ip_level, IPV6_TCLASS, (void *) &tos,
-+ if (setsockopt(c->listen_fd, level, IPV6_TCLASS, (void *) &tos,
- sizeof(tos)) < 0) {
- pr_log_pri(PR_LOG_NOTICE, "error setting listen fd IPV6_TCLASS: %s",
- strerror(errno));
--- a/components/proftpd/patches/20393612.patch Fri May 15 09:41:56 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-http://bugs.proftpd.org/show_bug.cgi?id=4132
-
-diff --git a/src/log.c b/src/log.c
-index 4b83413..c83b8ee 100644
---- a/src/log.c
-+++ b/src/log.c
-@@ -36,7 +36,7 @@
- static int syslog_open = FALSE;
- static int syslog_discard = FALSE;
- static int logstderr = TRUE;
--static int debug_level = DEBUG0; /* Default is no debug logging */
-+static int debug_level = DEBUG0 - 1; /* Default is no debug logging */
- static int facility = LOG_DAEMON;
- static int set_facility = -1;
- static char systemlog_fn[PR_TUNABLE_PATH_MAX] = {'\0'};
--- a/components/proftpd/patches/mod_auth_unix_getgrp.patch Fri May 15 09:41:56 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
---- old/modules/mod_auth_unix.c Fri May 25 08:31:35 2012
-+++ new/modules/mod_auth_unix.c Fri May 25 08:31:35 2012
-@@ -896,6 +896,13 @@
-
- return gr ? mod_create_data(cmd, (void *) &gr->gr_gid) : PR_DECLINED(cmd);
- }
-+#ifdef HAVE__GETGRPSBYMEMBER
-+ extern int _getgroupsbymember
-+ (
-+ const char* username, gid_t gid_array[],
-+ int maxgids, int numgids
-+ );
-+#endif /* HAVE__GETGRPSBYMEMBER */
-
- /* cmd->argv[0] = name
- * cmd->argv[1] = (array_header **) group_ids
-@@ -1065,7 +1072,40 @@
- }
-
- free(ptr);
--#else
-+#else /* !HAVE_GETGRSET */
-+#ifdef HAVE__GETGRPSBYMEMBER
-+ gid_t group_ids[NGROUPS_MAX];
-+ int ngroups = NGROUPS_MAX;
-+ register unsigned int i;
-+
-+ pr_trace_msg("auth", 4,
-+ "using _getgroupsbymember() to look up group membership");
-+
-+ memset(group_ids, 0, sizeof(group_ids));
-+
-+ group_ids[0]=pw->pw_gid;
-+ ngroups=
-+ _getgroupsbymember(pw->pw_name, group_ids, NGROUPS_MAX, 1);
-+
-+ if (ngroups < 0) {
-+ pr_log_pri(PR_LOG_ERR,
-+ "_getgroupsbymember error: %s", strerror(errno));
-+ return PR_DECLINED(cmd);
-+ }
-+
-+ for (i = 0; i < ngroups; i++) {
-+ gr = my_getgrgid(group_ids[i]);
-+ if (gr) {
-+ if (gids && pw->pw_gid != gr->gr_gid)
-+ *((gid_t *) push_array(gids)) = gr->gr_gid;
-+
-+ if (groups && pw->pw_gid != gr->gr_gid) {
-+ *((char **) push_array(groups)) = pstrdup(session.pool,
-+ gr->gr_name);
-+ }
-+ }
-+ }
-+#else /* !HAVE__GETGRPSBYMEMBER */
- char **gr_member = NULL;
-
- /* This is where things get slow, expensive, and ugly. Loop through
-@@ -1091,6 +1131,7 @@
- }
- }
- }
-+#endif /* !HAVE__GETGROUPSBYMEMBER */
- #endif /* !HAVE_GETGRSET */
- }
-
--- a/components/proftpd/patches/proftpd-configuration-html.patch Fri May 15 09:41:56 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
---- a/doc/Configuration.html
-+++ b/doc/Configuration.html
-@@ -10805,7 +10805,7 @@ CLASS="SYNOPSIS"
- ></DT
- ><DD
- ><P
-->IdentLookups on</P
-+>IdentLookups off</P
- ></DD
- ><DT
- ><PRE
-
--- a/components/proftpd/patches/proftpd-error_code.patch Fri May 15 09:41:56 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,466 +0,0 @@
-diff --git a/include/dirtree.h b/include/dirtree.h
-index 0f41986..fe7b14b 100644
---- a/include/dirtree.h
-+++ b/include/dirtree.h
-@@ -126,6 +126,10 @@ typedef struct cmd_struc {
- pr_table_t *notes; /* Private data for passing/retaining between handlers */
-
- int cmd_id; /* Index into commands list, for faster comparisons */
-+
-+ int error_code; /* Stores errno of failed file transfer
-+ * commands. Required for Solaris auditing.
-+ */
- } cmd_rec;
-
- struct config_struc {
-diff --git a/modules/mod_core.c b/modules/mod_core.c
-index e33ee11..f680748 100644
---- a/modules/mod_core.c
-+++ b/modules/mod_core.c
-@@ -4775,6 +4775,7 @@ MODRET core_rmd(cmd_rec *cmd) {
- dir = dir_canonical_path(cmd->tmp_pool, dir);
- if (dir == NULL) {
- int xerrno = EINVAL;
-+ cmd->error_code = EINVAL;
-
- pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
-
-@@ -4784,6 +4785,7 @@ MODRET core_rmd(cmd_rec *cmd) {
-
- if (!dir_check_canon(cmd->tmp_pool, cmd, cmd->group, dir, NULL)) {
- int xerrno = EACCES;
-+ cmd->error_code = EACCES;
-
- pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
-
-@@ -4793,6 +4795,7 @@ MODRET core_rmd(cmd_rec *cmd) {
-
- if (pr_fsio_rmdir(dir) < 0) {
- int xerrno = errno;
-+ cmd->error_code = errno;
-
- (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): "
- "error removing directory '%s': %s", cmd->argv[0], session.user,
-@@ -4849,6 +4852,7 @@ MODRET core_mkd(cmd_rec *cmd) {
- dir = dir_canonical_path(cmd->tmp_pool, dir);
- if (dir == NULL) {
- int xerrno = EINVAL;
-+ cmd->error_code = EINVAL;
-
- pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
-
-@@ -4858,6 +4862,7 @@ MODRET core_mkd(cmd_rec *cmd) {
-
- if (!dir_check_canon(cmd->tmp_pool, cmd, cmd->group, dir, NULL)) {
- int xerrno = EACCES;
-+ cmd->error_code = EACCES;
-
- pr_log_debug(DEBUG8, "%s command denied by <Limit> config", cmd->argv[0]);
- pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
-@@ -4869,6 +4874,7 @@ MODRET core_mkd(cmd_rec *cmd) {
- if (pr_fsio_smkdir(cmd->tmp_pool, dir, 0777, session.fsuid,
- session.fsgid) < 0) {
- int xerrno = errno;
-+ cmd->error_code = errno;
-
- (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): "
- "error making directory '%s': %s", cmd->argv[0], session.user,
-@@ -4915,6 +4921,7 @@ MODRET core_mdtm(cmd_rec *cmd) {
- !dir_check(cmd->tmp_pool, cmd, cmd->group, path, NULL) ||
- pr_fsio_stat(path, &st) == -1) {
- int xerrno = errno;
-+ cmd->error_code = errno;
-
- pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
-
-@@ -5026,6 +5033,7 @@ MODRET core_dele(cmd_rec *cmd) {
- path = dir_canonical_path(cmd->tmp_pool, path);
- if (path == NULL) {
- int xerrno = ENOENT;
-+ cmd->error_code = ENOENT;
-
- pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
-
-@@ -5035,6 +5043,7 @@ MODRET core_dele(cmd_rec *cmd) {
-
- if (!dir_check(cmd->tmp_pool, cmd, cmd->group, path, NULL)) {
- int xerrno = errno;
-+ cmd->error_code = errno;
-
- pr_log_debug(DEBUG7, "deleting '%s' denied by <Limit> configuration", path);
- pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
-@@ -5051,6 +5060,7 @@ MODRET core_dele(cmd_rec *cmd) {
- pr_fs_clear_cache();
- if (pr_fsio_lstat(path, &st) < 0) {
- int xerrno = errno;
-+ cmd->error_code = errno;
-
- pr_log_debug(DEBUG3, "unable to lstat '%s': %s", path, strerror(xerrno));
- pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
-@@ -5065,6 +5075,7 @@ MODRET core_dele(cmd_rec *cmd) {
- */
- if (S_ISDIR(st.st_mode)) {
- int xerrno = EISDIR;
-+ cmd->error_code = EISDIR;
-
- (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): "
- "error deleting '%s': %s", cmd->argv[0], session.user,
-@@ -5081,6 +5092,7 @@ MODRET core_dele(cmd_rec *cmd) {
-
- if (pr_fsio_unlink(path) < 0) {
- int xerrno = errno;
-+ cmd->error_code = errno;
-
- (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): "
- "error deleting '%s': %s", cmd->argv[0], session.user,
-@@ -5165,6 +5177,7 @@ MODRET core_rnto(cmd_rec *cmd) {
- pr_log_debug(DEBUG6, "AllowOverwrite denied permission for %s", path);
- pr_response_add_err(R_550, _("%s: Rename permission denied"), cmd->arg);
- errno = EACCES;
-+ cmd->error_code = EACCES;
- return PR_ERROR(cmd);
- }
-
-@@ -5172,6 +5185,7 @@ MODRET core_rnto(cmd_rec *cmd) {
- !dir_check_canon(cmd->tmp_pool, cmd, cmd->group, path, NULL) ||
- pr_fsio_rename(session.xfer.path, path) == -1) {
- int xerrno = errno;
-+ cmd->error_code = errno;
-
- if (xerrno != EXDEV) {
- (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): "
-@@ -5223,6 +5237,7 @@ MODRET core_rnto(cmd_rec *cmd) {
- */
- if (pr_fs_copy_file(session.xfer.path, path) < 0) {
- xerrno = errno;
-+ cmd->error_code = errno;
-
- (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): "
- "error copying '%s' to '%s': %s", cmd->argv[0], session.user,
-@@ -5238,6 +5253,8 @@ MODRET core_rnto(cmd_rec *cmd) {
-
- /* Once copied, unlink the original file. */
- if (pr_fsio_unlink(session.xfer.path) < 0) {
-+ cmd->error_code = errno;
-+
- pr_log_debug(DEBUG0, "error unlinking '%s': %s", session.xfer.path,
- strerror(errno));
- }
-@@ -5295,6 +5312,7 @@ MODRET core_rnfr(cmd_rec *cmd) {
- !dir_check(cmd->tmp_pool, cmd, cmd->group, path, NULL) ||
- !exists(path)) {
- int xerrno = errno;
-+ cmd->error_code = errno;
-
- pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
-
-diff --git a/modules/mod_xfer.c b/modules/mod_xfer.c
-index bcfb487..41c597e 100644
---- a/modules/mod_xfer.c
-+++ b/modules/mod_xfer.c
-@@ -1190,6 +1190,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) {
- if (cmd->argc < 2) {
- pr_response_add_err(R_500, _("'%s' not understood"),
- pr_cmd_get_displayable_str(cmd, NULL));
-+ cmd->error_code = EINVAL;
- errno = EINVAL;
- return PR_ERROR(cmd);
- }
-@@ -1200,6 +1201,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) {
- if (!path ||
- !dir_check(cmd->tmp_pool, cmd, cmd->group, path, NULL)) {
- int xerrno = errno;
-+ cmd->error_code = errno;
-
- pr_log_debug(DEBUG8, "%s %s denied by <Limit> configuration", cmd->argv[0],
- cmd->arg);
-@@ -1232,6 +1234,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) {
- if (xfer_check_limit(cmd) < 0) {
- pr_response_add_err(R_451, _("%s: Too many transfers"), cmd->arg);
- errno = EPERM;
-+ cmd->error_code = EPERM;
- return PR_ERROR(cmd);
- }
-
-@@ -1244,6 +1247,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) {
- pr_log_debug(DEBUG6, "AllowOverwrite denied permission for %s", cmd->arg);
- pr_response_add_err(R_550, _("%s: Overwrite permission denied"), cmd->arg);
- errno = EACCES;
-+ cmd->error_code = EACCES;
- return PR_ERROR(cmd);
- }
-
-@@ -1267,6 +1271,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) {
-
- /* Deliberately use EISDIR for anything non-file (e.g. directories). */
- errno = EISDIR;
-+ cmd->error_code = EISDIR;
- return PR_ERROR(cmd);
- }
- }
-@@ -1285,6 +1290,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) {
- session.restart_pos = 0L;
- session.xfer.xfer_type = STOR_DEFAULT;
- errno = EPERM;
-+ cmd->error_code = EPERM;
- return PR_ERROR(cmd);
- }
-
-@@ -1306,6 +1312,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) {
- /* Otherwise everthing is good */
- if (pr_table_add(cmd->notes, "mod_xfer.store-path",
- pstrdup(cmd->pool, path), 0) < 0) {
-+ cmd->error_code = errno;
- if (errno != EEXIST) {
- pr_log_pri(PR_LOG_NOTICE,
- "notice: error adding 'mod_xfer.store-path': %s", strerror(errno));
-@@ -1326,6 +1333,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) {
- pr_response_add_err(R_501,
- _("REST not compatible with server configuration"));
- errno = EINVAL;
-+ cmd->error_code = EINVAL;
- return PR_ERROR(cmd);
- }
-
-@@ -1335,6 +1343,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) {
- pr_response_add_err(R_550,
- _("APPE not compatible with server configuration"));
- errno = EINVAL;
-+ cmd->error_code = EINVAL;
- return PR_ERROR(cmd);
- }
-
-@@ -1400,6 +1409,7 @@ MODRET xfer_pre_stou(cmd_rec *cmd) {
- tmpfd = mkstemp(filename);
- if (tmpfd < 0) {
- int xerrno = errno;
-+ cmd->error_code = errno;
-
- pr_log_pri(PR_LOG_WARNING, "error: unable to use mkstemp(): %s",
- strerror(xerrno));
-@@ -1428,6 +1438,7 @@ MODRET xfer_pre_stou(cmd_rec *cmd) {
- if (!filename ||
- !dir_check(cmd->tmp_pool, cmd, cmd->group, filename, NULL)) {
- int xerrno = errno;
-+ cmd->error_code = errno;
-
- /* Do not forget to delete the file created by mkstemp(3) if there is
- * an error.
-@@ -1461,12 +1472,14 @@ MODRET xfer_pre_stou(cmd_rec *cmd) {
-
- /* Deliberately use EISDIR for anything non-file (e.g. directories). */
- errno = EISDIR;
-+ cmd->error_code = errno;
- return PR_ERROR(cmd);
- }
-
- /* Otherwise everthing is good */
- if (pr_table_add(cmd->notes, "mod_xfer.store-path",
- pstrdup(cmd->pool, filename), 0) < 0) {
-+ cmd->error_code = errno;
- if (errno != EEXIST) {
- pr_log_pri(PR_LOG_NOTICE,
- "notice: error adding 'mod_xfer.store-path': %s", strerror(errno));
-@@ -1492,6 +1505,7 @@ MODRET xfer_post_stou(cmd_rec *cmd) {
- mode_t mode = 0666;
-
- if (pr_fsio_chmod(cmd->arg, mode) < 0) {
-+ cmd->error_code = errno;
-
- /* Not much to do but log the error. */
- pr_log_pri(PR_LOG_NOTICE, "error: unable to chmod '%s' to %04o: %s",
-@@ -1510,6 +1524,7 @@ MODRET xfer_pre_appe(cmd_rec *cmd) {
- if (xfer_check_limit(cmd) < 0) {
- pr_response_add_err(R_451, _("%s: Too many transfers"), cmd->arg);
- errno = EPERM;
-+ cmd->error_code = EPERM;
- return PR_ERROR(cmd);
- }
-
-@@ -1580,6 +1595,7 @@ MODRET xfer_stor(cmd_rec *cmd) {
-
- if (stor_fh) {
- if (pr_fsio_lseek(stor_fh, 0, SEEK_END) == (off_t) -1) {
-+ cmd->error_code = errno;
- pr_log_debug(DEBUG4, "unable to seek to end of '%s' for appending: %s",
- cmd->arg, strerror(errno));
- (void) pr_fsio_close(stor_fh);
-@@ -1588,6 +1604,7 @@ MODRET xfer_stor(cmd_rec *cmd) {
-
- } else {
- ferrno = errno;
-+ cmd->error_code = errno;
-
- (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): "
- "error opening '%s': %s", cmd->argv[0], session.user,
-@@ -1601,6 +1618,7 @@ MODRET xfer_stor(cmd_rec *cmd) {
- O_WRONLY|(session.restart_pos ? 0 : O_TRUNC|O_CREAT));
- if (stor_fh == NULL) {
- ferrno = errno;
-+ cmd->error_code = errno;
-
- (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): "
- "error opening '%s': %s", cmd->argv[0], session.user,
-@@ -1614,11 +1632,13 @@ MODRET xfer_stor(cmd_rec *cmd) {
- int xerrno = 0;
-
- if (pr_fsio_lseek(stor_fh, session.restart_pos, SEEK_SET) == -1) {
-+ cmd->error_code = errno;
- pr_log_debug(DEBUG4, "unable to seek to position %" PR_LU " of '%s': %s",
- (pr_off_t) session.restart_pos, cmd->arg, strerror(errno));
- xerrno = errno;
-
- } else if (pr_fsio_stat(path, &st) == -1) {
-+ cmd->error_code = errno;
- pr_log_debug(DEBUG4, "unable to stat '%s': %s", cmd->arg,
- strerror(errno));
- xerrno = errno;
-@@ -1755,6 +1775,7 @@ MODRET xfer_stor(cmd_rec *cmd) {
- pr_data_abort(EPERM, FALSE);
- errno = EPERM;
- #endif
-+ cmd->error_code = errno;
- return PR_ERROR(cmd);
- }
-
-@@ -1766,6 +1787,7 @@ MODRET xfer_stor(cmd_rec *cmd) {
- res = pr_fsio_write(stor_fh, lbuf, len);
- if (res != len) {
- int xerrno = EIO;
-+ cmd->error_code = errno;
-
- if (res < 0)
- xerrno = errno;
-@@ -1795,6 +1817,7 @@ MODRET xfer_stor(cmd_rec *cmd) {
-
- /* default abort errno, in case session.d et al has already gone away */
- int xerrno = ECONNABORTED;
-+ cmd->error_code = ECONNABORTED;
-
- stor_abort();
-
-@@ -1814,6 +1837,7 @@ MODRET xfer_stor(cmd_rec *cmd) {
-
- if (stor_complete() < 0) {
- int xerrno = errno;
-+ cmd->error_code = errno;
-
- _log_transfer('i', 'i');
-
-@@ -1826,12 +1850,14 @@ MODRET xfer_stor(cmd_rec *cmd) {
- if (xerrno == EDQUOT) {
- pr_response_add_err(R_552, "%s: %s", cmd->arg, strerror(xerrno));
- errno = xerrno;
-+ cmd->error_code = errno;
- return PR_ERROR(cmd);
- }
- #elif defined(EFBIG)
- if (xerrno == EFBIG) {
- pr_response_add_err(R_552, "%s: %s", cmd->arg, strerror(xerrno));
- errno = xerrno;
-+ cmd->error_code = errno;
- return PR_ERROR(cmd);
- }
- #endif
-@@ -1845,6 +1871,7 @@ MODRET xfer_stor(cmd_rec *cmd) {
- session.xfer.path_hidden) {
- if (pr_fsio_rename(session.xfer.path_hidden, session.xfer.path) != 0) {
- int xerrno = errno;
-+ cmd->error_code = errno;
-
- /* This should only fail on a race condition with a chmod/chown
- * or if STOR_APPEND is on and the permissions are squirrely.
-@@ -1947,6 +1974,7 @@ MODRET xfer_pre_retr(cmd_rec *cmd) {
- pr_response_add_err(R_500, _("'%s' not understood"),
- pr_cmd_get_displayable_str(cmd, NULL));
- errno = EINVAL;
-+ cmd->error_code = EINVAL;
- return PR_ERROR(cmd);
- }
-
-@@ -1956,6 +1984,7 @@ MODRET xfer_pre_retr(cmd_rec *cmd) {
- if (!dir ||
- !dir_check(cmd->tmp_pool, cmd, cmd->group, dir, NULL)) {
- int xerrno = errno;
-+ cmd->error_code;
-
- pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
-
-@@ -1978,12 +2007,14 @@ MODRET xfer_pre_retr(cmd_rec *cmd) {
- if (xfer_check_limit(cmd) < 0) {
- pr_response_add_err(R_451, _("%s: Too many transfers"), cmd->arg);
- errno = EPERM;
-+ cmd->error_code = EPERM;
- return PR_ERROR(cmd);
- }
-
- fmode = file_mode(dir);
- if (fmode == 0) {
- int xerrno = errno;
-+ cmd->error_code = errno;
-
- pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno));
-
-@@ -2000,6 +2031,7 @@ MODRET xfer_pre_retr(cmd_rec *cmd) {
-
- /* Deliberately use EISDIR for anything non-file (e.g. directories). */
- errno = EISDIR;
-+ cmd->error_code = EISDIR;
- return PR_ERROR(cmd);
- }
-
-@@ -2014,12 +2046,14 @@ MODRET xfer_pre_retr(cmd_rec *cmd) {
- cmd->arg);
- session.restart_pos = 0L;
- errno = EPERM;
-+ cmd->error_code = EPERM;
- return PR_ERROR(cmd);
- }
-
- /* Otherwise everthing is good */
- if (pr_table_add(cmd->notes, "mod_xfer.retr-path",
- pstrdup(cmd->pool, dir), 0) < 0) {
-+ cmd->error_code = errno;
- if (errno != EEXIST) {
- pr_log_pri(PR_LOG_NOTICE, "notice: error adding 'mod_xfer.retr-path': %s",
- strerror(errno));
-@@ -2046,6 +2080,7 @@ MODRET xfer_retr(cmd_rec *cmd) {
- retr_fh = pr_fsio_open(dir, O_RDONLY);
- if (retr_fh == NULL) {
- int xerrno = errno;
-+ cmd->error_code = errno;
-
- (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): "
- "error opening '%s': %s", cmd->argv[0], session.user,
-@@ -2059,6 +2094,7 @@ MODRET xfer_retr(cmd_rec *cmd) {
- if (pr_fsio_stat(dir, &st) < 0) {
- /* Error stat'ing the file. */
- int xerrno = errno;
-+ cmd->error_code = errno;
- pr_fsio_close(retr_fh);
- errno = xerrno;
-
-@@ -2083,6 +2119,7 @@ MODRET xfer_retr(cmd_rec *cmd) {
- if (pr_fsio_lseek(retr_fh, session.restart_pos,
- SEEK_SET) == (off_t) -1) {
- int xerrno = errno;
-+ cmd->error_code = errno;
- pr_fsio_close(retr_fh);
- errno = xerrno;
- retr_fh = NULL;
-@@ -2143,6 +2180,7 @@ MODRET xfer_retr(cmd_rec *cmd) {
- retr_abort();
-
- /* Set errno to EPERM ("Operation not permitted") */
-+ cmd->error_code = EPERM;
- pr_data_abort(EPERM, FALSE);
- return PR_ERROR(cmd);
- }
-@@ -2174,6 +2212,7 @@ MODRET xfer_retr(cmd_rec *cmd) {
- * is preserved; errno itself might be overwritten in retr_abort().
- */
- int xerrno = errno;
-+ cmd->error_code = errno;
-
- retr_abort();
- pr_data_abort(xerrno, FALSE);
--- a/components/proftpd/patches/proftpd-manpage.patch Fri May 15 09:41:56 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
---- a/src/proftpd.8.in
-+++ b/src/proftpd.8.in
-@@ -100,10 +100,12 @@ This is enabled by default, if the \fB--enable-ipv6\fP configure option is
- used.
- .SH FILES
- .PD 0
--.B @SBINDIR@/proftpd
-+.B /usr/lib/inet/proftpd
- .br
- .B @SYSCONFDIR@/proftpd.conf
- .br
-+.B @SYSCONFDIR@/ftpusers
-+.br
- .B @BINDIR@/ftpwho
- .br
- .B @BINDIR@/ftpcount
-
--- a/components/proftpd/patches/proftpd-pam.patch Fri May 15 09:41:56 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,159 +0,0 @@
-http://bugs.proftpd.org/show_bug.cgi?id=4070
-
---- proftpd-1.3.3e/include/auth.h Tue Sep 8 22:34:03 2009
-+++ proftpd-1.3.3e-pam/include/auth.h Tue May 24 10:37:40 2011
-@@ -59,6 +59,35 @@
- /* Account has been disabled */
- #define PR_AUTH_DISABLEDPWD -5
-
-+/* Insufficient credentials */
-+#define PR_AUTH_CRED_INSUFF -6
-+
-+/* Unavailable user credentials */
-+#define PR_AUTH_CRED_UNAVAIL -7
-+
-+/* Failure setting user credentials */
-+#define PR_AUTH_CRED_ERR -8
-+
-+/* Unavailable authentication service */
-+#define PR_AUTH_UNAVAIL -9
-+
-+/* Max retries reached */
-+#define PR_AUTH_MAXTRIES -10
-+
-+/* Initialization of authentization failed */
-+#define PR_AUTH_INIT_FAIL -11
-+
-+/* New auth token needed */
-+#define PR_AUTH_NEWTOK -12
-+
-+#define PR_AUTH_OPEN_ERR -15
-+#define PR_AUTH_SYMBOL_ERR -16
-+#define PR_AUTH_SERVICE_ERR -17
-+#define PR_AUTH_SYSTEM_ERR -18
-+#define PR_AUTH_BUF_ERR -19
-+#define PR_AUTH_CONV_ERR -20
-+#define PR_AUTH_PERM_DENIED -21
-+
- void pr_auth_setpwent(pool *);
- void pr_auth_endpwent(pool *);
- void pr_auth_setgrent(pool *);
---- proftpd-1.3.3e/modules/mod_auth.c Mon Feb 21 03:36:38 2011
-+++ proftpd-1.3.3e-pam/modules/mod_auth.c Tue May 24 11:32:55 2011
-@@ -898,6 +898,44 @@
- user);
- goto auth_failure;
-
-+ case PR_AUTH_CRED_INSUFF:
-+ pr_log_auth(PR_LOG_NOTICE,
-+ "USER %s (Login failed): Insufficient credentials.", origuser);
-+ goto auth_failure;
-+
-+ case PR_AUTH_CRED_UNAVAIL:
-+ pr_log_auth(PR_LOG_NOTICE,
-+ "USER %s (Login failed): Unavailable credentials.", origuser);
-+ goto auth_failure;
-+
-+
-+ case PR_AUTH_CRED_ERR:
-+ pr_log_auth(PR_LOG_NOTICE,
-+ "USER %s (Login failed): Failure setting user credentials.",
-+ origuser);
-+ goto auth_failure;
-+
-+ case PR_AUTH_UNAVAIL:
-+ pr_log_auth(PR_LOG_NOTICE,
-+ "USER %s (Login failed): Unavailable authentication service.", user);
-+ goto auth_failure;
-+
-+ case PR_AUTH_MAXTRIES:
-+ pr_log_auth(PR_LOG_NOTICE,
-+ "USER %s (Login failed): Max retries reached.", user);
-+ goto auth_failure;
-+
-+ case PR_AUTH_INIT_FAIL:
-+ pr_log_auth(PR_LOG_NOTICE,
-+ "USER %s (Login failed): Authentization initialization failed.",
-+ origuser);
-+ goto auth_failure;
-+
-+ case PR_AUTH_NEWTOK:
-+ pr_log_auth(PR_LOG_NOTICE,
-+ "USER %s (Login failed): New authentication token needed.", user);
-+ goto auth_failure;
-+
- default:
- break;
- };
---- proftpd-1.3.3e/modules/mod_auth_pam.c Thu Mar 5 06:24:06 2009
-+++ proftpd-1.3.3e-pam/modules/mod_auth_pam.c Tue May 24 10:28:58 2011
-@@ -349,6 +349,24 @@
-
- if (pam_error != PAM_SUCCESS) {
- switch (pam_error) {
-+#ifdef PAM_CRED_INSUFFICIENT
-+ case PAM_CRED_INSUFFICIENT:
-+ retval = PR_AUTH_CRED_INSUFF;
-+ break;
-+#endif /* PAM_CRED_INSUFFICIENT */
-+
-+#ifdef PAM_AUTHINFO_UNAVAIL
-+ case PAM_AUTHINFO_UNAVAIL:
-+ retval = PR_AUTH_UNAVAIL;
-+ break;
-+#endif /* PAM_AUTHINFO_UNAVAIL */
-+
-+#ifdef PAM_MAXTRIES
-+ case PAM_MAXTRIES:
-+ retval = PR_AUTH_MAXTRIES;
-+ break;
-+#endif /* PAM_MAXTRIES */
-+
- case PAM_USER_UNKNOWN:
- retval = PR_AUTH_NOPWD;
- break;
-@@ -373,6 +391,14 @@
-
- if (pam_error != PAM_SUCCESS) {
- switch (pam_error) {
-+#ifdef PAM_NEW_AUTHTOK_REQD
-+ case PAM_NEW_AUTHTOK_REQD:
-+ pr_trace_msg(trace_channel, 8,
-+ "account mgmt error: PAM_NEW_AUTH_REQD");
-+ retval = PR_AUTH_NEWTOK;
-+ break;
-+#endif /* PAM_NEW_AUTHTOK_REQD */
-+
- #ifdef PAM_AUTHTOKEN_REQD
- case PAM_AUTHTOKEN_REQD:
- pr_trace_msg(trace_channel, 8,
-@@ -417,7 +443,7 @@
- switch (pam_error) {
- case PAM_SESSION_ERR:
- default:
-- retval = PR_AUTH_DISABLEDPWD;
-+ retval = PR_AUTH_INIT_FAIL;
- break;
- }
-
-@@ -435,6 +461,20 @@
-
- if (pam_error != PAM_SUCCESS) {
- switch (pam_error) {
-+#ifdef PAM_CRED_UNAVAIL
-+ case PAM_CRED_UNAVAIL:
-+ pr_trace_msg(trace_channel, 8, "credentials error: PAM_CRED_UNAVAIL");
-+ retval = PR_AUTH_CRED_UNAVAIL;
-+ break;
-+#endif /* PAM_CRED_UNAVAIL */
-+
-+#ifdef PAM_CRED_ERR
-+ case PAM_CRED_ERR:
-+ pr_trace_msg(trace_channel, 8, "credentials error: PAM_CRED_ERR");
-+ retval = PR_AUTH_CRED_ERR;
-+ break;
-+#endif /* PAM_CRED_ERR */
-+
- case PAM_CRED_EXPIRED:
- pr_trace_msg(trace_channel, 8, "credentials error: PAM_CRED_EXPIRED");
- retval = PR_AUTH_AGEPWD;
--- a/components/proftpd/patches/proftpd-retry.patch Fri May 15 09:41:56 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
---- a/src/data.c
-+++ b/src/data.c
-@@ -337,6 +337,7 @@ static int data_pasv_open(char *reason, off_t size) {
- static int data_active_open(char *reason, off_t size) {
- conn_t *c;
- int bind_port, rev;
-+ int retries = 0;
- pr_netaddr_t *bind_addr;
- unsigned char *root_revoke = NULL;
-
-@@ -368,7 +369,9 @@ static int data_active_open(char *reason, off_t size) {
- bind_port = INPORT_ANY;
- }
-
-- session.d = pr_inet_create_conn(session.pool, -1, bind_addr, bind_port, TRUE);
-+ for (;;) {
-+ session.d = pr_inet_create_conn(session.pool, -1, bind_addr, bind_port,
-+ TRUE);
-
- /* Default remote address to which to connect for an active transfer,
- * if the client has not specified a different address via PORT/EPRT,
-@@ -416,6 +419,15 @@ static int data_active_open(char *reason, off_t size) {
-
- if (pr_inet_connect(session.d->pool, session.d, &session.data_addr,
- session.data_port) == -1) {
-+
-+ if (session.d->xerrno == EADDRINUSE && retries < 16) {
-+ destroy_pool(session.d->pool);
-+ pr_signals_handle();
-+ /* Wait up to MSL to avoid TIME_WAIT. */
-+ sleep(retries++);
-+ continue;
-+ }
-+
- pr_log_debug(DEBUG6,
- "Error connecting to %s#%u for active data transfer: %s",
- pr_netaddr_get_ipstr(&session.data_addr), session.data_port,
-@@ -427,6 +439,9 @@ static int data_active_open(char *reason, off_t size) {
- destroy_pool(session.d->pool);
- session.d = NULL;
- return -1;
-+ } else
-+ break;
-+
- }
-
- c = pr_inet_openrw(session.pool, session.d, NULL, PR_NETIO_STRM_DATA,
-
--- a/components/proftpd/patches/proftpd-slow_ls.patch Fri May 15 09:41:56 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-The fix was developed in-house and submitted upstream. The upstream bug
-is:
-
-http://bugs.proftpd.org/show_bug.cgi?id=4157
-
-diff --git a/modules/mod_core.c b/modules/mod_core.c
---- a/modules/mod_core.c
-+++ b/modules/mod_core.c
-@@ -40,6 +40,7 @@
- /* From src/main.c */
- extern unsigned long max_connects;
- extern unsigned int max_connect_interval;
-+extern unsigned char tracing_enabled;
-
- /* From modules/mod_site.c */
- extern modret_t *site_dispatch(cmd_rec*);
-@@ -1381,6 +1382,8 @@
- int per_session = FALSE;
- unsigned int idx = 1;
-
-+ tracing_enabled = TRUE;
-+
- if (cmd->argc-1 < 1)
- CONF_ERROR(cmd, "wrong number of parameters");
- CHECK_CONF(cmd, CONF_ROOT);
-diff --git a/modules/mod_ls.c b/modules/mod_ls.c
---- a/modules/mod_ls.c
-+++ b/modules/mod_ls.c
-@@ -307,10 +307,12 @@
-
- static int sendline(int flags, char *fmt, ...) {
- va_list msg;
-- char buf[PR_TUNABLE_BUFFER_SIZE+1] = {'\0'};
-+ char buf[PR_TUNABLE_BUFFER_SIZE+1];
- int res = 0;
- size_t buflen, listbuflen;
-
-+ (void) memset(buf, '\0', sizeof(buf));
-+
- if (listbuf == NULL) {
- listbufsz = pr_config_get_server_xfer_bufsz(PR_NETIO_IO_WR);
- listbuf = listbuf_ptr = pcalloc(session.pool, listbufsz);
-diff --git a/src/fsio.c b/src/fsio.c
---- a/src/fsio.c
-+++ b/src/fsio.c
-@@ -556,10 +556,12 @@
- static int cache_stat(pr_fs_t *fs, const char *path, struct stat *sbuf,
- unsigned int op) {
- int res = -1;
-- char pathbuf[PR_TUNABLE_PATH_MAX + 1] = {'\0'};
-+ char pathbuf[PR_TUNABLE_PATH_MAX + 1];
- int (*mystat)(pr_fs_t *, const char *, struct stat *) = NULL;
- size_t pathlen;
-
-+ (void) memset(pathbuf, '\0', sizeof(pathbuf));
-+
- /* Sanity checks */
- if (fs == NULL) {
- errno = EINVAL;
-@@ -641,8 +643,8 @@
- * during the hit.
- */
- static pr_fs_t *lookup_dir_fs(const char *path, int op) {
-- char buf[PR_TUNABLE_PATH_MAX + 1] = {'\0'};
-- char tmp_path[PR_TUNABLE_PATH_MAX + 1] = {'\0'};
-+ char buf[PR_TUNABLE_PATH_MAX + 1];
-+ char tmp_path[PR_TUNABLE_PATH_MAX + 1];
- pr_fs_t *fs = NULL;
- int exact = FALSE;
- size_t tmp_pathlen = 0;
-@@ -651,6 +653,9 @@
- pr_fs_match_t *fsm = NULL;
- #endif /* PR_FS_MATCH */
-
-+ (void) memset(buf, '\0', sizeof(buf));
-+ (void) memset(tmp_path, '\0', sizeof(tmp_path));
-+
- sstrncpy(buf, path, sizeof(buf));
-
- /* Check if the given path is an absolute path. Since there may be
-diff --git a/src/trace.c b/src/trace.c
---- a/src/trace.c
-+++ b/src/trace.c
-@@ -32,6 +32,8 @@
-
- #ifdef PR_USE_TRACE
-
-+unsigned char tracing_enabled = FALSE;
-+
- static int trace_logfd = -1;
- static unsigned long trace_opts = PR_TRACE_OPT_DEFAULT;
- static pool *trace_pool = NULL;
-@@ -473,6 +475,10 @@
- int res;
- va_list msg;
-
-+ /* Optimization: do not run tracing code unless explicitly enabled. */
-+ if (tracing_enabled == FALSE)
-+ return 0;
-+
- va_start(msg, fmt);
- res = pr_trace_vmsg(channel, level, fmt, msg);
- va_end(msg);
--- a/components/proftpd/proftpd.p5m Fri May 15 09:41:56 2015 -0700
+++ b/components/proftpd/proftpd.p5m Tue May 19 02:34:35 2015 -0700
@@ -18,82 +18,46 @@
#
# CDDL HEADER END
#
-# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
#
# PSARC/2011/088
<transform file path=usr.*/man/.+ -> default mangler.man.stability uncommitted>
set name=pkg.fmri \
value=pkg:/service/network/ftp@$(IPS_COMPONENT_VERSION),$(BUILD_VERSION)
+set name=pkg.summary value="FTP Server and Utilities"
set name=pkg.human-version value=$(HUMAN_VERSION)
-set name=pkg.summary value="FTP Server and Utilities"
-set name=info.classification value="org.opensolaris.category.2008:System/Core"
+set name=info.classification value=org.opensolaris.category.2008:System/Core
set name=info.source-url value=$(COMPONENT_ARCHIVE_URL)
set name=info.upstream-url value=$(COMPONENT_PROJECT_URL)
-set name=org.opensolaris.arc-caseid \
- value=PSARC/2011/088
+set name=org.opensolaris.arc-caseid value=PSARC/2011/088
set name=org.opensolaris.consolidation value=$(CONSOLIDATION)
-
-dir path=etc
-dir path=etc/security
-dir path=etc/security/auth_attr.d
-dir path=etc/security/prof_attr.d
-dir path=lib
-dir path=lib/svc
-dir path=lib/svc/manifest
-dir path=lib/svc/manifest/network
-dir path=lib/svc/method
-dir path=usr
-dir path=usr/bin
-dir path=usr/include
-dir path=usr/include/proftpd
-dir path=usr/lib
-dir path=usr/lib/help
-dir path=usr/lib/help/auths
-dir path=usr/lib/help/auths/locale
-dir path=usr/lib/help/auths/locale/C
-dir path=usr/lib/inet
-dir path=usr/lib/pkgconfig
-dir path=usr/lib/proftpd
-dir path=usr/sbin
-dir path=usr/share
-dir path=usr/share/doc
-dir path=usr/share/doc/proftpd
-dir path=usr/share/doc/proftpd/modules
-dir path=usr/share/locale
-dir path=usr/share/locale/bg_BG
-dir path=usr/share/locale/bg_BG/LC_MESSAGES
-dir path=usr/share/locale/en_US
-dir path=usr/share/locale/en_US/LC_MESSAGES
-dir path=usr/share/locale/fr
-dir path=usr/share/locale/fr/LC_MESSAGES
-dir path=usr/share/locale/it
-dir path=usr/share/locale/it/LC_MESSAGES
-dir path=usr/share/locale/ja
-dir path=usr/share/locale/ja/LC_MESSAGES
-dir path=usr/share/locale/ko
-dir path=usr/share/locale/ko/LC_MESSAGES
-dir path=usr/share/locale/ru
-dir path=usr/share/locale/ru/LC_MESSAGES
-dir path=usr/share/locale/zh_CN
-dir path=usr/share/locale/zh_CN/LC_MESSAGES
-dir path=usr/share/locale/zh_TW
-dir path=usr/share/locale/zh_TW/LC_MESSAGES
-dir path=usr/share/man
-dir path=usr/share/man/man1
-dir path=usr/share/man/man4
-dir path=usr/share/man/man5
-dir path=usr/share/man/man8
+dir path=etc
file proftpd.conf path=etc/proftpd.conf mode=0644 preserve=true
-file auth_service-network-ftpd path=etc/security/auth_attr.d/service-network-ftpd
-file prof_service-network-ftpd path=etc/security/prof_attr.d/service-network-ftpd
+dir path=etc/security
+dir path=etc/security/auth_attr.d
+file auth_service-network-ftpd \
+ path=etc/security/auth_attr.d/service-network-ftpd
+dir path=etc/security/prof_attr.d
+file prof_service-network-ftpd \
+ path=etc/security/prof_attr.d/service-network-ftpd
+dir path=lib
+dir path=lib/svc
+dir path=lib/svc/manifest
+dir path=lib/svc/manifest/network
file ftp.xml path=lib/svc/manifest/network/ftp.xml
+dir path=lib/svc/method
file svc-ftp path=lib/svc/method/svc-ftp
+dir path=usr
+dir path=usr/bin
file path=usr/bin/ftpcount
file path=usr/bin/ftpdctl
file path=usr/bin/ftptop
file path=usr/bin/ftpwho
file path=usr/bin/prxs
+file dtrace/example.d path=usr/demo/dtrace/ftp.d
+dir path=usr/include
+dir path=usr/include/proftpd
file path=usr/include/proftpd/auth.h
file path=usr/include/proftpd/bindings.h
file path=usr/include/proftpd/buildstamp.h
@@ -151,65 +115,106 @@
file path=usr/include/proftpd/var.h
file path=usr/include/proftpd/version.h
file path=usr/include/proftpd/xferlog.h
+dir path=usr/lib
+file dtrace/ftp.d path=usr/lib/dtrace/ftp.d
+dir path=usr/lib/help
+dir path=usr/lib/help/auths
+dir path=usr/lib/help/auths/locale
+dir path=usr/lib/help/auths/locale/C
file ManageFTP.html path=usr/lib/help/auths/locale/C/ManageFTP.html
+dir path=usr/lib/inet
file usr/sbin/proftpd path=usr/lib/inet/proftpd
+dir path=usr/lib/pkgconfig
file path=usr/lib/pkgconfig/proftpd.pc
+dir path=usr/lib/proftpd
file path=usr/lib/proftpd/mod_auth_gss.so
file path=usr/lib/proftpd/mod_facl.so
file path=usr/lib/proftpd/mod_gss.so
file path=usr/lib/proftpd/mod_tls.so
file path=usr/lib/proftpd/mod_wrap.so
+dir path=usr/sbin
file ftprestart.sh path=usr/sbin/ftprestart
file path=usr/sbin/ftpscrub
file path=usr/sbin/ftpshut
-file proftpd_migration.txt path=usr/share/doc/proftpd/proftpd_migration.txt
+dir path=usr/share
+dir path=usr/share/doc
+dir path=usr/share/doc/proftpd
file doc/Configuration.html path=usr/share/doc/proftpd/Configuration.html
-file doc/modules/mod_auth_file.html path=usr/share/doc/proftpd/modules/mod_auth_file.html
-file doc/modules/mod_auth_pam.html path=usr/share/doc/proftpd/modules/mod_auth_pam.html
-file doc/modules/mod_ctrls.html path=usr/share/doc/proftpd/modules/mod_ctrls.html
-file doc/modules/mod_delay.html path=usr/share/doc/proftpd/modules/mod_delay.html
+dir path=usr/share/doc/proftpd/modules
+file doc/modules/mod_auth_file.html \
+ path=usr/share/doc/proftpd/modules/mod_auth_file.html
+file doc/modules/mod_auth_pam.html \
+ path=usr/share/doc/proftpd/modules/mod_auth_pam.html
+file doc/modules/mod_ctrls.html \
+ path=usr/share/doc/proftpd/modules/mod_ctrls.html
+file doc/modules/mod_delay.html \
+ path=usr/share/doc/proftpd/modules/mod_delay.html
file doc/modules/mod_dso.html path=usr/share/doc/proftpd/modules/mod_dso.html
file doc/modules/mod_facl.html path=usr/share/doc/proftpd/modules/mod_facl.html
-file doc/modules/mod_facts.html path=usr/share/doc/proftpd/modules/mod_facts.html
-file doc/modules/mod_ident.html path=usr/share/doc/proftpd/modules/mod_ident.html
+file doc/modules/mod_facts.html \
+ path=usr/share/doc/proftpd/modules/mod_facts.html
+file doc/contrib/mod_gss.html path=usr/share/doc/proftpd/modules/mod_gss.html
+file doc/modules/mod_ident.html \
+ path=usr/share/doc/proftpd/modules/mod_ident.html
file doc/modules/mod_lang.html path=usr/share/doc/proftpd/modules/mod_lang.html
-file doc/contrib/mod_gss.html path=usr/share/doc/proftpd/modules/mod_gss.html
file doc/contrib/mod_tls.html path=usr/share/doc/proftpd/modules/mod_tls.html
file doc/contrib/mod_wrap.html path=usr/share/doc/proftpd/modules/mod_wrap.html
+file proftpd_migration.txt path=usr/share/doc/proftpd/proftpd_migration.txt
+dir path=usr/share/locale
+dir path=usr/share/locale/bg_BG
+dir path=usr/share/locale/bg_BG/LC_MESSAGES
file path=usr/share/locale/bg_BG/LC_MESSAGES/proftpd.mo
+dir path=usr/share/locale/en_US
+dir path=usr/share/locale/en_US/LC_MESSAGES
file path=usr/share/locale/en_US/LC_MESSAGES/proftpd.mo
-file usr/share/locale/fr_FR/LC_MESSAGES/proftpd.mo path=usr/share/locale/fr/LC_MESSAGES/proftpd.mo
-file usr/share/locale/it_IT/LC_MESSAGES/proftpd.mo path=usr/share/locale/it/LC_MESSAGES/proftpd.mo
-file usr/share/locale/ja_JP/LC_MESSAGES/proftpd.mo path=usr/share/locale/ja/LC_MESSAGES/proftpd.mo
-file usr/share/locale/ko_KR/LC_MESSAGES/proftpd.mo path=usr/share/locale/ko/LC_MESSAGES/proftpd.mo
-file usr/share/locale/ru_RU/LC_MESSAGES/proftpd.mo path=usr/share/locale/ru/LC_MESSAGES/proftpd.mo
+dir path=usr/share/locale/fr
+dir path=usr/share/locale/fr/LC_MESSAGES
+file usr/share/locale/fr_FR/LC_MESSAGES/proftpd.mo \
+ path=usr/share/locale/fr/LC_MESSAGES/proftpd.mo
+dir path=usr/share/locale/it
+dir path=usr/share/locale/it/LC_MESSAGES
+file usr/share/locale/it_IT/LC_MESSAGES/proftpd.mo \
+ path=usr/share/locale/it/LC_MESSAGES/proftpd.mo
+dir path=usr/share/locale/ja
+dir path=usr/share/locale/ja/LC_MESSAGES
+file usr/share/locale/ja_JP/LC_MESSAGES/proftpd.mo \
+ path=usr/share/locale/ja/LC_MESSAGES/proftpd.mo
+dir path=usr/share/locale/ko
+dir path=usr/share/locale/ko/LC_MESSAGES
+file usr/share/locale/ko_KR/LC_MESSAGES/proftpd.mo \
+ path=usr/share/locale/ko/LC_MESSAGES/proftpd.mo
+dir path=usr/share/locale/ru
+dir path=usr/share/locale/ru/LC_MESSAGES
+file usr/share/locale/ru_RU/LC_MESSAGES/proftpd.mo \
+ path=usr/share/locale/ru/LC_MESSAGES/proftpd.mo
+dir path=usr/share/locale/zh_CN
+dir path=usr/share/locale/zh_CN/LC_MESSAGES
file path=usr/share/locale/zh_CN/LC_MESSAGES/proftpd.mo
+dir path=usr/share/locale/zh_TW
+dir path=usr/share/locale/zh_TW/LC_MESSAGES
file path=usr/share/locale/zh_TW/LC_MESSAGES/proftpd.mo
+dir path=usr/share/man
+dir path=usr/share/man/man1
file path=usr/share/man/man1/ftpcount.1
file path=usr/share/man/man1/ftptop.1
file path=usr/share/man/man1/ftpwho.1
+dir path=usr/share/man/man4
+dir path=usr/share/man/man5
file path=usr/share/man/man5/proftpd.conf.5
file path=usr/share/man/man5/xferlog.5
+dir path=usr/share/man/man8
file path=usr/share/man/man8/ftpdctl.8
file path=usr/share/man/man8/ftpscrub.8
file path=usr/share/man/man8/ftpshut.8
file path=usr/share/man/man8/proftpd.8
-
-group groupname="ftp" gid=21
-
-legacy pkg=SUNWftpu \
- name="FTP Server, (Usr)" \
- desc="FTP Server and Utilities"
-
+group groupname=ftp gid=21
+user username=ftp ftpuser=false gcos-field="FTPD Reserved UID" group=ftp uid=21
+legacy pkg=SUNWftpu desc="FTP Server and Utilities" name="FTP Server, (Usr)"
license proftpd.license license="GPLv2 (mod_gss)" \
com.oracle.info.description="the ProFPTD GSS Engine" \
- com.oracle.info.name=mod_gss \
- com.oracle.info.tpno=13480 \
+ com.oracle.info.name=mod_gss com.oracle.info.tpno=13480 \
com.oracle.info.version=1.3.6
license proftpd.license license="GPLv2 (proftpd)" \
com.oracle.info.description="the ProFTPD server and utilities" \
- com.oracle.info.name=proftpd \
- com.oracle.info.tpno=17783 \
+ com.oracle.info.name=proftpd com.oracle.info.tpno=17783 \
com.oracle.info.version=1.3.5
-
-user ftpuser=false gcos-field="FTPD Reserved UID" username="ftp" uid=21 group="ftp"