# HG changeset patch
# User Tomas Klacko IdentLookups on
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, + diff -r acff78288302 -r 1b7dd68f6aa9 components/proftpd/patches/005.proftpd-error_code.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/proftpd/patches/005.proftpd-error_code.patch Wed Mar 11 03:50:20 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 byconfig", 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 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 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); diff -r acff78288302 -r 1b7dd68f6aa9 components/proftpd/patches/006.18845170.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/proftpd/patches/006.18845170.patch Wed Mar 11 03:50:20 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'}; + diff -r acff78288302 -r 1b7dd68f6aa9 components/proftpd/patches/007.19575647.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/proftpd/patches/007.19575647.patch Wed Mar 11 03:50:20 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; diff -r acff78288302 -r 1b7dd68f6aa9 components/proftpd/patches/008.19596338.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/proftpd/patches/008.19596338.patch Wed Mar 11 03:50:20 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); + } + } diff -r acff78288302 -r 1b7dd68f6aa9 components/proftpd/patches/009.19668629.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/proftpd/patches/009.19668629.patch Wed Mar 11 03:50:20 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)); diff -r acff78288302 -r 1b7dd68f6aa9 components/proftpd/patches/010.20393612.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/proftpd/patches/010.20393612.patch Wed Mar 11 03:50:20 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'}; diff -r acff78288302 -r 1b7dd68f6aa9 components/proftpd/patches/011.19693019-proftpd-slow_ls.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/proftpd/patches/011.19693019-proftpd-slow_ls.patch Wed Mar 11 03:50:20 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); diff -r acff78288302 -r 1b7dd68f6aa9 components/proftpd/patches/012.20553228-dtrace-provider.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/proftpd/patches/012.20553228-dtrace-provider.patch Wed Mar 11 03:50:20 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 +@@ -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; + + + diff -r acff78288302 -r 1b7dd68f6aa9 components/proftpd/patches/18845170.patch --- a/components/proftpd/patches/18845170.patch Tue Mar 10 11:12:15 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'}; - diff -r acff78288302 -r 1b7dd68f6aa9 components/proftpd/patches/19575647.patch --- a/components/proftpd/patches/19575647.patch Tue Mar 10 11:12:15 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; diff -r acff78288302 -r 1b7dd68f6aa9 components/proftpd/patches/19596338.patch --- a/components/proftpd/patches/19596338.patch Tue Mar 10 11:12:15 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); - } - } diff -r acff78288302 -r 1b7dd68f6aa9 components/proftpd/patches/19668629.patch --- a/components/proftpd/patches/19668629.patch Tue Mar 10 11:12:15 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)); diff -r acff78288302 -r 1b7dd68f6aa9 components/proftpd/patches/20393612.patch --- a/components/proftpd/patches/20393612.patch Tue Mar 10 11:12:15 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'}; diff -r acff78288302 -r 1b7dd68f6aa9 components/proftpd/patches/mod_auth_unix_getgrp.patch --- a/components/proftpd/patches/mod_auth_unix_getgrp.patch Tue Mar 10 11:12:15 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 */ - } - diff -r acff78288302 -r 1b7dd68f6aa9 components/proftpd/patches/proftpd-configuration-html.patch --- a/components/proftpd/patches/proftpd-configuration-html.patch Tue Mar 10 11:12:15 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" - >
IdentLookups on
IdentLookups offtmp_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 byconfig", 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 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 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); diff -r acff78288302 -r 1b7dd68f6aa9 components/proftpd/patches/proftpd-manpage.patch --- a/components/proftpd/patches/proftpd-manpage.patch Tue Mar 10 11:12:15 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 - diff -r acff78288302 -r 1b7dd68f6aa9 components/proftpd/patches/proftpd-pam.patch --- a/components/proftpd/patches/proftpd-pam.patch Tue Mar 10 11:12:15 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; diff -r acff78288302 -r 1b7dd68f6aa9 components/proftpd/patches/proftpd-retry.patch --- a/components/proftpd/patches/proftpd-retry.patch Tue Mar 10 11:12:15 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, - diff -r acff78288302 -r 1b7dd68f6aa9 components/proftpd/patches/proftpd-slow_ls.patch --- a/components/proftpd/patches/proftpd-slow_ls.patch Tue Mar 10 11:12:15 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); diff -r acff78288302 -r 1b7dd68f6aa9 components/proftpd/proftpd.p5m --- a/components/proftpd/proftpd.p5m Tue Mar 10 11:12:15 2015 -0700 +++ b/components/proftpd/proftpd.p5m Wed Mar 11 03:50:20 2015 -0700 @@ -49,6 +49,7 @@ 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 file path=usr/include/proftpd/auth.h file path=usr/include/proftpd/bindings.h file path=usr/include/proftpd/buildstamp.h @@ -106,6 +107,7 @@ file path=usr/include/proftpd/var.h file path=usr/include/proftpd/version.h file path=usr/include/proftpd/xferlog.h +file dtrace/ftp.d path=usr/lib/dtrace/ftp.d file ManageFTP.html path=usr/lib/help/auths/locale/C/ManageFTP.html file usr/sbin/proftpd path=usr/lib/inet/proftpd file path=usr/lib/pkgconfig/proftpd.pc