[proftpd-mod-counter] 01/01: Finalize for release.
Hilmar Preuße
hilmar-guest at moszumanska.debian.org
Fri Mar 16 21:13:57 GMT 2018
This is an automated email from the git hooks/post-receive script.
hilmar-guest pushed a commit to branch master
in repository proftpd-mod-counter.
commit c29e8d6e871e88c382e022f13615f55b235f9ef4
Author: Hilmar Preuße <hille42 at web.de>
Date: Fri Mar 16 22:13:28 2018 +0100
Finalize for release.
---
README.md | 14 +
debian/changelog | 6 +-
debian/compat | 2 +-
debian/control | 6 +-
debian/proftpd-mod-counter.docs | 2 +
debian/rules | 2 +-
mod_counter.c | 140 +++--
mod_counter.html | 11 +-
t/lib/ProFTPD/Tests/Modules/mod_counter.pm | 945 ++++++++++++++++++++---------
9 files changed, 785 insertions(+), 343 deletions(-)
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..58a1c06
--- /dev/null
+++ b/README.md
@@ -0,0 +1,14 @@
+proftpd-mod_counter
+===================
+
+Status
+------
+[![Build Status](https://travis-ci.org/Castaglia/proftpd-mod_counter.svg?branch=master)](https://travis-ci.org/Castaglia/proftpd-mod_counter)
+[![License](https://img.shields.io/badge/license-GPL-brightgreen.svg)](https://img.shields.io/badge/license-GPL-brightgreen.svg)
+
+Synopsis
+--------
+The `mod_counter` module for ProFTPD provides limits on the number
+of concurrent uploads/downloads for files.
+
+For further module documentation, see [mod_counter.html](https://htmlpreview.github.io/?https://github.com/Castaglia/proftpd-mod_counter/blob/master/mod_counter.html).
diff --git a/debian/changelog b/debian/changelog
index 788a989..558be70 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,5 +1,7 @@
-proftpd-mod-counter (0.5-1) UNRELEASED; urgency=low
+proftpd-mod-counter (0.6.1-1) UNRELEASED; urgency=low
+
+ [ Hilmar Preuße ]
* Initial release. (Closes: #653438)
- -- Mahyuddin Susanto <udienz at ubuntu.com> Wed, 28 Dec 2011 17:09:19 +0700
+ -- Francesco Paolo Lovergine <frankie at debian.org> Fri, 16 Mar 2018 22:08:51 +0100
diff --git a/debian/compat b/debian/compat
index 7f8f011..ec63514 100644
--- a/debian/compat
+++ b/debian/compat
@@ -1 +1 @@
-7
+9
diff --git a/debian/control b/debian/control
index a7ae0a9..22f395b 100644
--- a/debian/control
+++ b/debian/control
@@ -1,13 +1,13 @@
Source: proftpd-mod-counter
Section: net
-Priority: extra
+Priority: optional
Maintainer: ProFTPD Maintainance Team <pkg-proftpd-maintainers at lists.alioth.debian.org>
Uploaders: Mahyuddin Susanto <udienz at ubuntu.com>,
Francesco Paolo Lovergine <frankie at debian.org>
Build-Depends: autotools-dev,
- debhelper (>= 7.0.50~),
+ debhelper (>= 9~),
proftpd-dev (>= 1.3.4~rc3-2~)
-Standards-Version: 3.9.2
+Standards-Version: 4.1.3
Homepage: http://www.castaglia.org/proftpd/modules/mod_counter.html
Vcs-Git: git://git.debian.org/pkg-proftpd/proftpd-mod-counter.git
Vcs-Browser: http://git.debian.org/?p=pkg-proftpd/proftpd-mod-counter.git
diff --git a/debian/proftpd-mod-counter.docs b/debian/proftpd-mod-counter.docs
new file mode 100644
index 0000000..8d1524b
--- /dev/null
+++ b/debian/proftpd-mod-counter.docs
@@ -0,0 +1,2 @@
+mod_counter.html
+README.md
\ No newline at end of file
diff --git a/debian/rules b/debian/rules
index 5ca4db4..f05b002 100755
--- a/debian/rules
+++ b/debian/rules
@@ -5,7 +5,7 @@ MODULE_NAME=mod_counter
DEBNAME=proftpd-mod-counter
%:
- dh $@
+ dh $@ --without python-support
override_dh_auto_build:
DESTDIR=$(CURDIR)/debian/$(DEBNAME) prxs -c $(MODULE_NAME).c
diff --git a/mod_counter.c b/mod_counter.c
index 0788a5c..82051fc 100644
--- a/mod_counter.c
+++ b/mod_counter.c
@@ -1,7 +1,6 @@
/*
* ProFTPD: mod_counter -- a module for using counters to enforce per-file usage
- *
- * Copyright (c) 2004-2010 TJ Saunders
+ * Copyright (c) 2004-2017 TJ Saunders
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,8 +23,6 @@
*
* This is mod_counter, contrib software for proftpd 1.2.10rc1 and above.
* For more information contact TJ Saunders <tj at castaglia.org>.
- *
- * $Id: mod_counter.c,v 1.6 2010/02/06 02:05:01 tj Exp tj $
*/
#include "conf.h"
@@ -35,7 +32,7 @@
#include <sys/ipc.h>
#include <sys/sem.h>
-#define MOD_COUNTER_VERSION "mod_counter/0.5"
+#define MOD_COUNTER_VERSION "mod_counter/0.6.1"
#if PROFTPD_VERSION_NUMBER < 0x0001030201
# error "ProFTPD 1.3.2rc1 or later required"
@@ -63,6 +60,7 @@ struct counter_fh {
static pool *counter_pool = NULL;
static xaset_t *counter_fhs = NULL;
+static const char *counter_chroot_path = NULL;
static const char *counter_curr_path = NULL;
static int counter_curr_semid = -1;
static int counter_engine = FALSE;
@@ -74,7 +72,9 @@ static int counter_pending = 0;
#define COUNTER_HAVE_READER 0x01
#define COUNTER_HAVE_WRITER 0x02
-#if (defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)) || defined(DARWIN9)
+#if (defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)) || \
+ defined(DARWIN9) || defined(DARWIN10) || defined(DARWIN11) || \
+ defined(DARWIN12) || defined(DARWIN13) || defined(DARWIN14)
#else
union semun {
int val;
@@ -328,6 +328,8 @@ static int counter_file_write(pr_fh_t *fh, array_header *ids) {
for (i = 0; i < ids->nelts; i++) {
char buf[32];
+ pr_signals_handle();
+
/* Skip any negative IDs. This small hack allows for IDs to be
* effectively removed from the list.
*/
@@ -366,27 +368,38 @@ static int counter_file_write(pr_fh_t *fh, array_header *ids) {
return 0;
}
+static char *counter_abs_path(pool *p, const char *path, int interpolate) {
+ const char *chroot_path;
+ char *abs_path;
+
+ chroot_path = session.chroot_path;
+ if (counter_chroot_path != NULL) {
+ session.chroot_path = counter_chroot_path;
+ }
+
+ abs_path = dir_abs_path(p, path, interpolate);
+ session.chroot_path = chroot_path;
+
+ return abs_path;
+}
+
static pr_fh_t *counter_get_fh(pool *p, const char *path) {
struct counter_fh *iter, *cfh = NULL;
const char *abs_path;
- size_t pathlen;
/* Find the CounterFile handle to use for the given path, if any. */
-
if (counter_fhs == NULL) {
errno = ENOENT;
return NULL;
}
if (session.chroot_path) {
- abs_path = dir_abs_path(p, path, FALSE);
+ abs_path = counter_abs_path(p, path, FALSE);
} else {
abs_path = path;
}
- pathlen = strlen(abs_path);
-
/* In order to handle globs, we do two passes. On the first pass,
* we look for the closest-matching glob area. On the second pass,
* we look for any closest-matching non-glob area. This means that
@@ -395,6 +408,7 @@ static pr_fh_t *counter_get_fh(pool *p, const char *path) {
for (iter = (struct counter_fh *) counter_fhs->xas_list; iter;
iter = iter->next) {
+ pr_signals_handle();
if (!iter->isglob) {
continue;
@@ -619,12 +633,15 @@ MODRET set_counterengine(cmd_rec *cmd) {
/* usage: CounterFile path */
MODRET set_counterfile(cmd_rec *cmd) {
config_rec *c;
+ const char *path;
CHECK_ARGS(cmd, 1);
CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL|CONF_ANON|CONF_DIR);
- if (*cmd->argv[1] != '/')
+ path = cmd->argv[1];
+ if (*path != '/') {
CONF_ERROR(cmd, "must be an absolute path");
+ }
/* In theory, we could open a filehandle on the configured path right
* here, and fail if the file couldn't be created/opened. Then we
@@ -637,7 +654,7 @@ MODRET set_counterfile(cmd_rec *cmd) {
* where we know vhost to which the client connected.
*/
- c = add_config_param_str(cmd->argv[0], 1, cmd->argv[1]);
+ c = add_config_param_str(cmd->argv[0], 1, path);
c->flags |= CF_MERGEDOWN;
return PR_HANDLED(cmd);
@@ -648,8 +665,9 @@ MODRET set_counterlog(cmd_rec *cmd) {
CHECK_ARGS(cmd, 1);
CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
- if (pr_fs_valid_path(cmd->argv[1]) < 0)
+ if (pr_fs_valid_path(cmd->argv[1]) < 0) {
CONF_ERROR(cmd, "must be an absolute path");
+ }
add_config_param_str(cmd->argv[0], 1, cmd->argv[1]);
return PR_HANDLED(cmd);
@@ -692,25 +710,33 @@ MODRET counter_retr(cmd_rec *cmd) {
config_rec *c;
int res;
pr_fh_t *fh;
+ const char *path;
- if (!counter_engine)
+ if (counter_engine == FALSE) {
return PR_DECLINED(cmd);
+ }
c = find_config(CURRENT_CONF, CONF_PARAM, "CounterMaxReaders", FALSE);
counter_max_readers = c ? *((int *) c->argv[0]) : COUNTER_DEFAULT_MAX_READERS;
- if (counter_max_readers == 0)
+ if (counter_max_readers == 0) {
return PR_DECLINED(cmd);
+ }
- counter_curr_path = pr_table_get(cmd->notes, "mod_xfer.retr-path", NULL);
- if (counter_curr_path == NULL) {
+ path = pr_table_get(cmd->notes, "mod_xfer.retr-path", NULL);
+ if (path == NULL) {
return PR_DECLINED(cmd);
}
+ /* Note that for purposes of our semaphores, we need to use the absolute
+ * path.
+ */
+ counter_curr_path = counter_abs_path(cmd->tmp_pool, path, FALSE);
+
fh = counter_get_fh(cmd->tmp_pool, counter_curr_path);
if (fh == NULL) {
(void) pr_log_writefile(counter_logfd, MOD_COUNTER_VERSION,
- "%s: no CounterFile found for path '%s'", cmd->argv[0],
+ "%s: no CounterFile found for path '%s'", (char *) cmd->argv[0],
counter_curr_path);
/* No CounterFile configured/available for this path. */
@@ -736,7 +762,7 @@ MODRET counter_retr(cmd_rec *cmd) {
* The download should be failed.
*/
(void) pr_log_writefile(counter_logfd, MOD_COUNTER_VERSION,
- "%s: max number of readers (%d) reached for '%s'", cmd->argv[0],
+ "%s: max number of readers (%d) reached for '%s'", (char *) cmd->argv[0],
counter_max_readers, counter_curr_path);
pr_response_add_err(R_450, _("%s: File busy"), cmd->arg);
return PR_ERROR(cmd);
@@ -744,8 +770,8 @@ MODRET counter_retr(cmd_rec *cmd) {
counter_pending |= COUNTER_HAVE_READER;
(void) pr_log_writefile(counter_logfd, MOD_COUNTER_VERSION,
- "%s: added reader counter for '%s' (semaphore ID %d)", cmd->argv[0],
- counter_curr_path, counter_curr_semid);
+ "%s: added reader counter for '%s' (semaphore ID %d)",
+ (char *) cmd->argv[0], counter_curr_path, counter_curr_semid);
return PR_DECLINED(cmd);
}
@@ -783,7 +809,7 @@ MODRET counter_alter(cmd_rec *cmd) {
fh = counter_get_fh(cmd->tmp_pool, counter_curr_path);
if (fh == NULL) {
(void) pr_log_writefile(counter_logfd, MOD_COUNTER_VERSION,
- "%s: no CounterFile found for path '%s'", cmd->argv[0],
+ "%s: no CounterFile found for path '%s'", (char *) cmd->argv[0],
counter_curr_path);
/* No CounterFile configured/available for this path. */
@@ -809,7 +835,7 @@ MODRET counter_alter(cmd_rec *cmd) {
* The upload should be failed.
*/
(void) pr_log_writefile(counter_logfd, MOD_COUNTER_VERSION,
- "%s: max number of writers (%d) reached for '%s'", cmd->argv[0],
+ "%s: max number of writers (%d) reached for '%s'", (char *) cmd->argv[0],
counter_max_writers, counter_curr_path);
pr_response_add_err(R_450, _("%s: File busy"), cmd->arg);
return PR_ERROR(cmd);
@@ -817,8 +843,8 @@ MODRET counter_alter(cmd_rec *cmd) {
counter_pending |= COUNTER_HAVE_WRITER;
(void) pr_log_writefile(counter_logfd, MOD_COUNTER_VERSION,
- "%s: added writer counter for '%s' (semaphore ID %d)", cmd->argv[0],
- counter_curr_path, counter_curr_semid);
+ "%s: added writer counter for '%s' (semaphore ID %d)",
+ (char *) cmd->argv[0], counter_curr_path, counter_curr_semid);
return PR_DECLINED(cmd);
}
@@ -827,24 +853,33 @@ MODRET counter_stor(cmd_rec *cmd) {
config_rec *c;
int res;
pr_fh_t *fh;
+ const char *path;
- if (!counter_engine)
+ if (counter_engine == FALSE) {
return PR_DECLINED(cmd);
+ }
c = find_config(CURRENT_CONF, CONF_PARAM, "CounterMaxWriters", FALSE);
counter_max_writers = c ? *((int *) c->argv[0]) : COUNTER_DEFAULT_MAX_WRITERS;
- if (counter_max_writers == 0)
+ if (counter_max_writers == 0) {
return PR_DECLINED(cmd);
+ }
- counter_curr_path = pr_table_get(cmd->notes, "mod_xfer.store-path", NULL);
- if (!counter_curr_path)
+ path = pr_table_get(cmd->notes, "mod_xfer.store-path", NULL);
+ if (path == NULL) {
return PR_DECLINED(cmd);
+ }
+
+ /* Note that for purposes of our semaphores, we need to use the absolute
+ * path.
+ */
+ counter_curr_path = counter_abs_path(cmd->tmp_pool, path, FALSE);
fh = counter_get_fh(cmd->tmp_pool, counter_curr_path);
if (fh == NULL) {
(void) pr_log_writefile(counter_logfd, MOD_COUNTER_VERSION,
- "%s: no CounterFile found for path '%s'", cmd->argv[0],
+ "%s: no CounterFile found for path '%s'", (char *) cmd->argv[0],
counter_curr_path);
/* No CounterFile configured/available for this path. */
@@ -870,7 +905,7 @@ MODRET counter_stor(cmd_rec *cmd) {
* The upload should be failed.
*/
(void) pr_log_writefile(counter_logfd, MOD_COUNTER_VERSION,
- "%s: max number of writers (%d) reached for '%s'", cmd->argv[0],
+ "%s: max number of writers (%d) reached for '%s'", (char *) cmd->argv[0],
counter_max_writers, counter_curr_path);
pr_response_add_err(R_450, _("%s: File busy"), cmd->arg);
return PR_ERROR(cmd);
@@ -878,8 +913,8 @@ MODRET counter_stor(cmd_rec *cmd) {
counter_pending |= COUNTER_HAVE_WRITER;
(void) pr_log_writefile(counter_logfd, MOD_COUNTER_VERSION,
- "%s: added writer counter for '%s' (semaphore ID %d)", cmd->argv[0],
- counter_curr_path, counter_curr_semid);
+ "%s: added writer counter for '%s' (semaphore ID %d)",
+ (char *) cmd->argv[0], counter_curr_path, counter_curr_semid);
return PR_DECLINED(cmd);
}
@@ -896,7 +931,7 @@ MODRET counter_reader_done(cmd_rec *cmd) {
fh = counter_get_fh(cmd->tmp_pool, counter_curr_path);
if (fh == NULL) {
(void) pr_log_writefile(counter_logfd, MOD_COUNTER_VERSION,
- "%s: no CounterFile found for path '%s'", cmd->argv[0],
+ "%s: no CounterFile found for path '%s'", (char *) cmd->argv[0],
counter_curr_path);
/* No CounterFile configured/available for this path. */
@@ -943,7 +978,7 @@ MODRET counter_writer_done(cmd_rec *cmd) {
fh = counter_get_fh(cmd->tmp_pool, counter_curr_path);
if (fh == NULL) {
(void) pr_log_writefile(counter_logfd, MOD_COUNTER_VERSION,
- "%s: no CounterFile found for path '%s'", cmd->argv[0],
+ "%s: no CounterFile found for path '%s'", (char *) cmd->argv[0],
counter_curr_path);
/* No CounterFile configured/available for this path. */
@@ -993,11 +1028,16 @@ static void counter_mod_unload_ev(const void *event_data, void *user_data) {
}
#endif
+static void counter_chroot_ev(const void *event_data, void *user_data) {
+ counter_chroot_path = pstrdup(counter_pool, event_data);
+}
+
static void counter_exit_ev(const void *event_data, void *user_data) {
pr_fh_t *fh;
- if (!counter_engine)
+ if (counter_engine == FALSE) {
return;
+ }
if (counter_curr_semid != -1 &&
(counter_pending & COUNTER_HAVE_READER)) {
@@ -1049,15 +1089,16 @@ static int counter_sess_init(void) {
config_rec *c;
c = find_config(main_server->conf, CONF_PARAM, "CounterEngine", FALSE);
- if (c &&
- *((unsigned int *) c->argv[0]) == TRUE)
- counter_engine = TRUE;
+ if (c != NULL) {
+ counter_engine = *((unsigned int *) c->argv[0]);
+ }
- if (!counter_engine)
+ if (counter_engine == FALSE) {
return 0;
+ }
c = find_config(main_server->conf, CONF_PARAM, "CounterLog", FALSE);
- if (c) {
+ if (c != NULL) {
const char *path = c->argv[0];
if (strcasecmp(path, "none") != 0) {
@@ -1082,8 +1123,8 @@ static int counter_sess_init(void) {
* of a chroot.
*/
c = find_config(main_server->conf, CONF_PARAM, "CounterFile", TRUE);
- while (c) {
- int xerrno;
+ while (c != NULL) {
+ int xerrno = 0;
const char *area = NULL, *path;
pr_fh_t *fh;
struct counter_fh *cfh;
@@ -1114,7 +1155,7 @@ static int counter_sess_init(void) {
PRIVS_ROOT
fh = pr_fsio_open(path, O_RDWR|O_CREAT);
- xerrno = xerrno;
+ xerrno = errno;
PRIVS_RELINQUISH
if (fh == NULL) {
@@ -1125,7 +1166,7 @@ static int counter_sess_init(void) {
if (counter_fhs != NULL) {
for (cfh = (struct counter_fh *) counter_fhs->xas_list; cfh;
cfh = cfh->next) {
- pr_fsio_close(cfh->fh);
+ (void) pr_fsio_close(cfh->fh);
}
}
@@ -1171,6 +1212,13 @@ static int counter_sess_init(void) {
pr_event_register(&counter_module, "core.exit", counter_exit_ev, NULL);
+ /* If mod_vroot is present, we need to do a little more magic to counter
+ * the mod_vroot magic.
+ */
+ if (pr_module_exists("mod_vroot.c") == TRUE) {
+ pr_event_register(&counter_module, "core.chroot", counter_chroot_ev, NULL);
+ }
+
return 0;
}
diff --git a/mod_counter.html b/mod_counter.html
index 8197163..c49432c 100644
--- a/mod_counter.html
+++ b/mod_counter.html
@@ -1,6 +1,3 @@
-<!-- $Id: mod_case.html,v 1.4 2004/01/23 20:56:12 tj Exp tj $ -->
-<!-- $Source: /home/tj/proftpd/modules/doc/RCS/mod_case.html,v $ -->
-
<html>
<head>
<title>ProFTPD module mod_counter</title>
@@ -210,13 +207,8 @@ can be downloading a given file at the same time, you would use the
<p>
<hr><br>
-Author: <i>$Author: tj $</i><br>
-Last Updated: <i>$Date: 2004/01/23 20:56:12 $</i><br>
-
-<br><hr>
-
<font size=2><b><i>
-© Copyright 2004-2010 TJ Saunders<br>
+© Copyright 2004-2017 TJ Saunders<br>
All Rights Reserved<br>
</i></b></font>
@@ -224,4 +216,3 @@ Last Updated: <i>$Date: 2004/01/23 20:56:12 $</i><br>
</body>
</html>
-
diff --git a/t/lib/ProFTPD/Tests/Modules/mod_counter.pm b/t/lib/ProFTPD/Tests/Modules/mod_counter.pm
index 26aba91..270bf33 100644
--- a/t/lib/ProFTPD/Tests/Modules/mod_counter.pm
+++ b/t/lib/ProFTPD/Tests/Modules/mod_counter.pm
@@ -1,7 +1,7 @@
package ProFTPD::Tests::Modules::mod_counter;
use lib qw(t/lib);
-use base qw(Test::Unit::TestCase ProFTPD::TestSuite::Child);
+use base qw(ProFTPD::TestSuite::Child);
use strict;
use File::Copy;
@@ -112,6 +112,26 @@ my $TESTS = {
test_class => [qw(forking)],
},
+ counter_vroot_retr_max_readers_exceeded => {
+ order => ++$order,
+ test_class => [qw(forking mod_vroot)],
+ },
+
+ counter_vroot_retr_max_readers_exceeded_in_subdir => {
+ order => ++$order,
+ test_class => [qw(forking mod_vroot)],
+ },
+
+ counter_vroot_stor_max_writers_exceeded => {
+ order => ++$order,
+ test_class => [qw(forking mod_vroot)],
+ },
+
+ counter_vroot_stor_max_writers_exceeded_in_subdir => {
+ order => ++$order,
+ test_class => [qw(forking mod_vroot)],
+ },
+
};
sub new {
@@ -122,82 +142,29 @@ sub list_tests {
return testsuite_get_runnable_tests($TESTS);
}
-sub set_up {
- my $self = shift;
- $self->{tmpdir} = testsuite_get_tmp_dir();
-
- # Create temporary scratch dir
- eval { mkpath($self->{tmpdir}) };
- if ($@) {
- my $abs_path = File::Spec->rel2abs($self->{tmpdir});
- die("Can't create dir $abs_path: $@");
- }
-}
-
-sub tear_down {
- my $self = shift;
-
- # Remove temporary scratch dir
- if ($self->{tmpdir}) {
- eval { rmtree($self->{tmpdir}) };
- }
-
- undef $self;
-}
-
sub counter_retr_max_readers_exceeded {
my $self = shift;
my $tmpdir = $self->{tmpdir};
+ my $setup = test_setup($tmpdir, 'counter');
- my $config_file = "$tmpdir/counter.conf";
- my $pid_file = File::Spec->rel2abs("$tmpdir/counter.pid");
- my $scoreboard_file = File::Spec->rel2abs("$tmpdir/counter.scoreboard");
-
- my $log_file = File::Spec->rel2abs('tests.log');
-
- my $auth_user_file = File::Spec->rel2abs("$tmpdir/counter.passwd");
- my $auth_group_file = File::Spec->rel2abs("$tmpdir/counter.group");
-
- my $user = 'proftpd';
- my $passwd = 'test';
- my $home_dir = File::Spec->rel2abs($tmpdir);
- my $uid = 500;
- my $gid = 500;
-
- # Make sure that, if we're running as root, that the home directory has
- # permissions/privs set for the account we create
- if ($< == 0) {
- unless (chmod(0755, $home_dir)) {
- die("Can't set perms on $home_dir to 0755: $!");
- }
-
- unless (chown($uid, $gid, $home_dir)) {
- die("Can't set owner of $home_dir to $uid/$gid: $!");
- }
- }
-
- auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
- '/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
-
my $counter_file = File::Spec->rel2abs("$tmpdir/counter.tab");
-
my $test_file = 'counter.conf';
my $config = {
- PidFile => $pid_file,
- ScoreboardFile => $scoreboard_file,
- SystemLog => $log_file,
+ PidFile => $setup->{pid_file},
+ ScoreboardFile => $setup->{scoreboard_file},
+ SystemLog => $setup->{log_file},
+ TraceLog => $setup->{log_file},
+ Trace => 'counter:20',
- AuthUserFile => $auth_user_file,
- AuthGroupFile => $auth_group_file,
+ AuthUserFile => $setup->{auth_user_file},
+ AuthGroupFile => $setup->{auth_group_file},
IfModules => {
'mod_counter.c' => {
CounterEngine => 'on',
- CounterLog => $log_file,
+ CounterLog => $setup->{log_file},
CounterFile => $counter_file,
- CounterMaxReaders => 1,
},
'mod_delay.c' => {
@@ -206,7 +173,22 @@ sub counter_retr_max_readers_exceeded {
},
};
- my ($port, $config_user, $config_group) = config_write($config_file, $config);
+ my ($port, $config_user, $config_group) = config_write($setup->{config_file},
+ $config);
+
+ if (open(my $fh, ">> $setup->{config_file}")) {
+ print $fh <<EOC;
+<Directory /test.d>
+ CounterMaxReaders 1
+</Directory>
+EOC
+ unless (close($fh)) {
+ die("Can't write $setup->{config_file}: $!");
+ }
+
+ } else {
+ die("Can't open $setup->{config_file}: $!");
+ }
# Open pipes, for use between the parent and child processes. Specifically,
# the child will indicate when it's done with its test by writing a message
@@ -223,11 +205,11 @@ sub counter_retr_max_readers_exceeded {
defined(my $pid = fork()) or die("Can't fork: $!");
if ($pid) {
eval {
- my $client1 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
- $client1->login($user, $passwd);
+ my $client1 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port, 0, 1);
+ $client1->login($setup->{user}, $setup->{passwd});
- my $client2 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
- $client2->login($user, $passwd);
+ my $client2 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port, 0, 1);
+ $client2->login($setup->{user}, $setup->{passwd});
my $conn = $client1->retr_raw($test_file);
unless ($conn) {
@@ -235,47 +217,35 @@ sub counter_retr_max_readers_exceeded {
$client1->response_msg());
}
- my ($resp_code, $resp_msg);
- my $expected;
-
# Now, before we close this data connection, try to open another
# data connection for the same file.
my $conn2 = $client2->retr_raw($test_file);
if ($conn2) {
die("RETR $test_file succeeded unexpectedly");
+ }
- } else {
- $resp_code = $client2->response_code();
- $resp_msg = $client2->response_msg();
+ my $resp_code = $client2->response_code();
+ my $resp_msg = $client2->response_msg();
- $expected = 450;
- $self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
+ my $expected = 450;
+ $self->assert($expected == $resp_code,
+ "Expected response code $expected, got $resp_code");
- $expected = "$test_file: File busy";
- $self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
- }
+ $expected = "$test_file: File busy";
+ $self->assert($expected eq $resp_msg,
+ "Expected response message '$expected', got '$resp_msg'");
my $buf;
$conn->read($buf, 8192);
- $conn->close();
+ eval { $conn->close() };
$resp_code = $client1->response_code();
$resp_msg = $client1->response_msg();
-
- $expected = 226;
- $self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
-
- $expected = "Transfer complete";
- $self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ $self->assert_transfer_ok($resp_code, $resp_msg);
$client2->quit();
$client1->quit();
};
-
if ($@) {
$ex = $@;
}
@@ -284,7 +254,7 @@ sub counter_retr_max_readers_exceeded {
$wfh->flush();
} else {
- eval { server_wait($config_file, $rfh) };
+ eval { server_wait($setup->{config_file}, $rfh) };
if ($@) {
warn($@);
exit 1;
@@ -294,15 +264,10 @@ sub counter_retr_max_readers_exceeded {
}
# Stop server
- server_stop($pid_file);
-
+ server_stop($setup->{pid_file});
$self->assert_child_ok($pid);
- if ($ex) {
- die($ex);
- }
-
- unlink($log_file);
+ test_cleanup($setup->{log_file}, $ex);
}
sub counter_stor_max_writers_exceeded {
@@ -411,27 +376,20 @@ sub counter_stor_max_writers_exceeded {
$expected = 450;
$self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
+ "Expected response code $expected, got $resp_code");
$expected = "$test_file: File busy";
$self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ "Expected response message '$expected', got '$resp_msg'");
}
my $buf = "Hello, World!\n";
$conn->write($buf, length($buf));
- $conn->close();
+ eval { $conn->close() };
$resp_code = $client1->response_code();
$resp_msg = $client1->response_msg();
-
- $expected = 226;
- $self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
-
- $expected = "Transfer complete";
- $self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ $self->assert_transfer_ok($resp_code, $resp_msg);
$client2->quit();
$client1->quit();
@@ -573,27 +531,20 @@ sub counter_appe_max_writers_exceeded {
$expected = 450;
$self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
+ "Expected response code $expected, got $resp_code");
$expected = "$test_file: File busy";
$self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ "Expected response message '$expected', got '$resp_msg'");
}
my $buf = "Hello, World!\n";
$conn->write($buf, length($buf));
- $conn->close();
+ eval { $conn->close() };
$resp_code = $client1->response_code();
$resp_msg = $client1->response_msg();
-
- $expected = 226;
- $self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
-
- $expected = "Transfer complete";
- $self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ $self->assert_transfer_ok($resp_code, $resp_msg);
$client2->quit();
$client1->quit();
@@ -734,32 +685,24 @@ sub counter_dele_max_writers_exceeded {
$expected = 450;
$self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
+ "Expected response code $expected, got $resp_code");
$expected = "$test_file: File busy";
$self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ "Expected response message '$expected', got '$resp_msg'");
}
my $buf = "Hello, World!\n";
$conn->write($buf, length($buf));
- $conn->close();
+ eval { $conn->close() };
$resp_code = $client1->response_code();
$resp_msg = $client1->response_msg();
-
- $expected = 226;
- $self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
-
- $expected = "Transfer complete";
- $self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ $self->assert_transfer_ok($resp_code, $resp_msg);
$client2->quit();
$client1->quit();
};
-
if ($@) {
$ex = $@;
}
@@ -895,32 +838,24 @@ sub counter_rnfr_max_writers_exceeded {
$expected = 450;
$self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
+ "Expected response code $expected, got $resp_code");
$expected = "$test_file: File busy";
$self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ "Expected response message '$expected', got '$resp_msg'");
}
my $buf = "Hello, World!\n";
$conn->write($buf, length($buf));
- $conn->close();
+ eval { $conn->close() };
$resp_code = $client1->response_code();
$resp_msg = $client1->response_msg();
-
- $expected = 226;
- $self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
-
- $expected = "Transfer complete";
- $self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ $self->assert_transfer_ok($resp_code, $resp_msg);
$client2->quit();
$client1->quit();
};
-
if ($@) {
$ex = $@;
}
@@ -1067,32 +1002,24 @@ sub counter_rnto_max_writers_exceeded {
$expected = 450;
$self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
+ "Expected response code $expected, got $resp_code");
$expected = "$test_file: File busy";
$self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ "Expected response message '$expected', got '$resp_msg'");
}
my $buf = "Hello, World!\n";
$conn->write($buf, length($buf));
- $conn->close();
+ eval { $conn->close() };
$resp_code = $client1->response_code();
$resp_msg = $client1->response_msg();
-
- $expected = 226;
- $self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
-
- $expected = "Transfer complete";
- $self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ $self->assert_transfer_ok($resp_code, $resp_msg);
$client2->quit();
$client1->quit();
};
-
if ($@) {
$ex = $@;
}
@@ -1253,32 +1180,24 @@ EOC
$expected = 450;
$self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
+ "Expected response code $expected, got $resp_code");
$expected = "$test_file: File busy";
$self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ "Expected response message '$expected', got '$resp_msg'");
}
my $buf;
$conn->read($buf, 8192);
- $conn->close();
+ eval { $conn->close() };
$resp_code = $client1->response_code();
$resp_msg = $client1->response_msg();
-
- $expected = 226;
- $self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
-
- $expected = "Transfer complete";
- $self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ $self->assert_transfer_ok($resp_code, $resp_msg);
$client2->quit();
$client1->quit();
};
-
if ($@) {
$ex = $@;
}
@@ -1440,32 +1359,24 @@ EOC
$expected = 450;
$self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
+ "Expected response code $expected, got $resp_code");
$expected = "$test_file: File busy";
$self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ "Expected response message '$expected', got '$resp_msg'");
}
my $buf;
$conn->read($buf, 8192);
- $conn->close();
+ eval { $conn->close() };
$resp_code = $client1->response_code();
$resp_msg = $client1->response_msg();
-
- $expected = 226;
- $self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
-
- $expected = "Transfer complete";
- $self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ $self->assert_transfer_ok($resp_code, $resp_msg);
$client2->quit();
$client1->quit();
};
-
if ($@) {
$ex = $@;
}
@@ -1632,32 +1543,24 @@ EOC
$expected = 450;
$self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
+ "Expected response code $expected, got $resp_code");
$expected = "$test_file: File busy";
$self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ "Expected response message '$expected', got '$resp_msg'");
}
my $buf;
$conn->read($buf, 8192);
- $conn->close();
+ eval { $conn->close() };
$resp_code = $client1->response_code();
$resp_msg = $client1->response_msg();
-
- $expected = 226;
- $self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
-
- $expected = "Transfer complete";
- $self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ $self->assert_transfer_ok($resp_code, $resp_msg);
$client2->quit();
$client1->quit();
};
-
if ($@) {
$ex = $@;
}
@@ -3196,62 +3099,44 @@ sub counter_closest_matching_file_using_anon_subdir {
sub counter_closest_matching_file_using_globs {
my $self = shift;
my $tmpdir = $self->{tmpdir};
+ my $setup = test_setup($tmpdir, 'counter');
- my $config_file = "$tmpdir/counter.conf";
- my $pid_file = File::Spec->rel2abs("$tmpdir/counter.pid");
- my $scoreboard_file = File::Spec->rel2abs("$tmpdir/counter.scoreboard");
-
- my $log_file = File::Spec->rel2abs('tests.log');
-
- my $auth_user_file = File::Spec->rel2abs("$tmpdir/counter.passwd");
- my $auth_group_file = File::Spec->rel2abs("$tmpdir/counter.group");
-
- my $user = 'proftpd';
- my $passwd = 'test';
- my $home_dir = File::Spec->rel2abs($tmpdir);
- my $uid = 500;
- my $gid = 500;
-
- my $sub_dir = File::Spec->rel2abs("$home_dir/foo");
+ my $sub_dir = File::Spec->rel2abs("$tmpdir/foo");
mkpath($sub_dir);
- my $sub_sub_dir = File::Spec->rel2abs("$home_dir/foo/bar");
+ my $sub_sub_dir = File::Spec->rel2abs("$tmpdir/foo/bar");
mkpath($sub_sub_dir);
- # Make sure that, if we're running as root, that the home directory has
- # permissions/privs set for the account we create
if ($< == 0) {
- unless (chmod(0755, $home_dir, $sub_dir, $sub_sub_dir)) {
- die("Can't set perms on $home_dir to 0755: $!");
+ unless (chmod(0755, $sub_dir, $sub_sub_dir)) {
+ die("Can't set perms on $sub_dir to 0755: $!");
}
- unless (chown($uid, $gid, $home_dir, $sub_dir, $sub_sub_dir)) {
- die("Can't set owner of $home_dir to $uid/$gid: $!");
+ unless (chown($setup->{uid}, $setup->{gid}, $sub_dir, $sub_sub_dir)) {
+ die("Can't set owner of $sub_dir to $setup->{uid}/$setup->{gid}: $!");
}
}
- auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
- '/bin/bash');
- auth_group_write($auth_group_file, 'ftpd', $gid, $user);
-
- my $toplevel_tab = File::Spec->rel2abs("$home_dir/counter.tab");
+ my $toplevel_tab = File::Spec->rel2abs("$tmpdir/counter.tab");
my $subdir_tab = File::Spec->rel2abs("$sub_dir/counter.tab");
my $subsubdir_tab = File::Spec->rel2abs("$sub_sub_dir/counter.tab");
my $test_file = 'counter.conf';
my $config = {
- PidFile => $pid_file,
- ScoreboardFile => $scoreboard_file,
- SystemLog => $log_file,
+ PidFile => $setup->{pid_file},
+ ScoreboardFile => $setup->{scoreboard_file},
+ SystemLog => $setup->{log_file},
+ TraceLog => $setup->{log_file},
+ Trace => 'counter:20',
- AuthUserFile => $auth_user_file,
- AuthGroupFile => $auth_group_file,
+ AuthUserFile => $setup->{auth_user_file},
+ AuthGroupFile => $setup->{auth_group_file},
IfModules => {
'mod_counter.c' => {
CounterEngine => 'on',
- CounterLog => $log_file,
+ CounterLog => $setup->{log_file},
CounterMaxReaders => 1,
},
@@ -3261,9 +3146,10 @@ sub counter_closest_matching_file_using_globs {
},
};
- my ($port, $config_user, $config_group) = config_write($config_file, $config);
+ my ($port, $config_user, $config_group) = config_write($setup->{config_file},
+ $config);
- if (open(my $fh, ">> $config_file")) {
+ if (open(my $fh, ">> $setup->{config_file}")) {
print $fh <<EOC;
<Directory $sub_dir/*/>
CounterFile $subsubdir_tab
@@ -3271,15 +3157,15 @@ sub counter_closest_matching_file_using_globs {
EOC
unless (close($fh)) {
- die("Can't write $config_file: $!");
+ die("Can't write $setup->{config_file}: $!");
}
} else {
- die("Can't open $config_file: $!");
+ die("Can't open $setup->{config_file}: $!");
}
- unless (copy($config_file, "$sub_sub_dir/counter.conf")) {
- die("Can't copy $config_file to '$sub_sub_dir/counter.conf': $!");
+ unless (copy($setup->{config_file}, "$sub_sub_dir/counter.conf")) {
+ die("Can't copy $setup->{config_file} to '$sub_sub_dir/counter.conf': $!");
}
# Open pipes, for use between the parent and child processes. Specifically,
@@ -3297,12 +3183,12 @@ EOC
defined(my $pid = fork()) or die("Can't fork: $!");
if ($pid) {
eval {
- my $client1 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
- $client1->login($user, $passwd);
+ my $client1 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port, 0, 1);
+ $client1->login($setup->{user}, $setup->{passwd});
$client1->cwd("foo/bar");
- my $client2 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
- $client2->login($user, $passwd);
+ my $client2 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port, 0, 1);
+ $client2->login($setup->{user}, $setup->{passwd});
$client2->cwd("foo/bar");
my $conn = $client1->retr_raw($test_file);
@@ -3311,47 +3197,35 @@ EOC
$client1->response_msg());
}
- my ($resp_code, $resp_msg);
- my $expected;
-
# Now, before we close this data connection, try to open another
# data connection for the same file.
my $conn2 = $client2->retr_raw($test_file);
if ($conn2) {
die("RETR $test_file succeeded unexpectedly");
+ }
- } else {
- $resp_code = $client2->response_code();
- $resp_msg = $client2->response_msg();
+ my $resp_code = $client2->response_code();
+ my $resp_msg = $client2->response_msg();
- $expected = 450;
- $self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
+ my $expected = 450;
+ $self->assert($expected == $resp_code,
+ "Expected response code $expected, got $resp_code");
- $expected = "$test_file: File busy";
- $self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
- }
+ $expected = "$test_file: File busy";
+ $self->assert($expected eq $resp_msg,
+ "Expected response message '$expected', got '$resp_msg'");
my $buf;
$conn->read($buf, 8192);
- $conn->close();
+ eval { $conn->close() };
$resp_code = $client1->response_code();
$resp_msg = $client1->response_msg();
-
- $expected = 226;
- $self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
-
- $expected = "Transfer complete";
- $self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ $self->assert_transfer_ok($resp_code, $resp_msg);
$client2->quit();
$client1->quit();
};
-
if ($@) {
$ex = $@;
}
@@ -3360,7 +3234,7 @@ EOC
$wfh->flush();
} else {
- eval { server_wait($config_file, $rfh) };
+ eval { server_wait($setup->{config_file}, $rfh) };
if ($@) {
warn($@);
exit 1;
@@ -3370,15 +3244,10 @@ EOC
}
# Stop server
- server_stop($pid_file);
-
+ server_stop($setup->{pid_file});
$self->assert_child_ok($pid);
- if ($ex) {
- die($ex);
- }
-
- unlink($log_file);
+ test_cleanup($setup->{log_file}, $ex);
}
sub counter_closest_matching_file_using_globs_and_exact {
@@ -3517,32 +3386,24 @@ EOC
$expected = 450;
$self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
+ "Expected response code $expected, got $resp_code");
$expected = "$test_file: File busy";
$self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ "Expected response message '$expected', got '$resp_msg'");
}
my $buf;
$conn->read($buf, 8192);
- $conn->close();
+ eval { $conn->close() };
$resp_code = $client1->response_code();
$resp_msg = $client1->response_msg();
-
- $expected = 226;
- $self->assert($expected == $resp_code,
- test_msg("Expected $expected, got $resp_code"));
-
- $expected = "Transfer complete";
- $self->assert($expected eq $resp_msg,
- test_msg("Expected '$expected', got '$resp_msg'"));
+ $self->assert_transfer_ok($resp_code, $resp_msg);
$client2->quit();
$client1->quit();
};
-
if ($@) {
$ex = $@;
}
@@ -3572,4 +3433,528 @@ EOC
unlink($log_file);
}
+sub counter_vroot_retr_max_readers_exceeded {
+ my $self = shift;
+ my $tmpdir = $self->{tmpdir};
+ my $setup = test_setup($tmpdir, 'counter');
+
+ my $counter_file = File::Spec->rel2abs("$tmpdir/counter.tab");
+
+ my $test_file = File::Spec->rel2abs("$tmpdir/test.dat");
+ if (open(my $fh, "> $test_file")) {
+ print $fh "Hello, World!\n";
+ unless (close($fh)) {
+ die("Can't write $test_file: $!");
+ }
+
+ } else {
+ die("Can't open $test_file: $!");
+ }
+
+ my $config = {
+ PidFile => $setup->{pid_file},
+ ScoreboardFile => $setup->{scoreboard_file},
+ SystemLog => $setup->{log_file},
+ TraceLog => $setup->{log_file},
+ Trace => 'counter:20 vroot:20 vroot.fsio:20',
+
+ AuthUserFile => $setup->{auth_user_file},
+ AuthGroupFile => $setup->{auth_group_file},
+ AllowOverwrite => 'on',
+ DefaultRoot => '~',
+
+ IfModules => {
+ 'mod_counter.c' => {
+ CounterEngine => 'on',
+ CounterLog => $setup->{log_file},
+ CounterFile => $counter_file,
+ CounterMaxReaders => 1,
+ },
+
+ 'mod_delay.c' => {
+ DelayEngine => 'off',
+ },
+
+ 'mod_vroot.c' => {
+ VRootEngine => 'on',
+ },
+ },
+ };
+
+ my ($port, $config_user, $config_group) = config_write($setup->{config_file},
+ $config);
+
+ # Open pipes, for use between the parent and child processes. Specifically,
+ # the child will indicate when it's done with its test by writing a message
+ # to the parent.
+ my ($rfh, $wfh);
+ unless (pipe($rfh, $wfh)) {
+ die("Can't open pipe: $!");
+ }
+
+ my $ex;
+
+ # Fork child
+ $self->handle_sigchld();
+ defined(my $pid = fork()) or die("Can't fork: $!");
+ if ($pid) {
+ eval {
+ my $client1 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port, 0, 1);
+ $client1->login($setup->{user}, $setup->{passwd});
+
+ my $client2 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port, 0, 1);
+ $client2->login($setup->{user}, $setup->{passwd});
+
+ my $conn = $client1->retr_raw('test.dat');
+ unless ($conn) {
+ die("Failed to RETR test.d: " . $client1->response_code() . " " .
+ $client1->response_msg());
+ }
+
+ # Now, before we close this data connection, try to open another
+ # data connection for the same file.
+ my $conn2 = $client2->retr_raw('test.dat');
+ if ($conn2) {
+ die("RETR test.dat succeeded unexpectedly");
+ }
+
+ my $resp_code = $client2->response_code();
+ my $resp_msg = $client2->response_msg();
+
+ my $expected = 450;
+ $self->assert($expected == $resp_code,
+ "Expected response code $expected, got $resp_code");
+
+ $expected = "test.dat: File busy";
+ $self->assert($expected eq $resp_msg,
+ "Expected response message '$expected', got '$resp_msg'");
+
+ my $buf;
+ $conn->read($buf, 8192, 15);
+ eval { $conn->close() };
+
+ $resp_code = $client1->response_code();
+ $resp_msg = $client1->response_msg();
+ $self->assert_transfer_ok($resp_code, $resp_msg);
+
+ $client2->quit();
+ $client1->quit();
+ };
+ if ($@) {
+ $ex = $@;
+ }
+
+ $wfh->print("done\n");
+ $wfh->flush();
+
+ } else {
+ eval { server_wait($setup->{config_file}, $rfh) };
+ if ($@) {
+ warn($@);
+ exit 1;
+ }
+
+ exit 0;
+ }
+
+ # Stop server
+ server_stop($setup->{pid_file});
+ $self->assert_child_ok($pid);
+
+ test_cleanup($setup->{log_file}, $ex);
+}
+
+sub counter_vroot_retr_max_readers_exceeded_in_subdir {
+ my $self = shift;
+ my $tmpdir = $self->{tmpdir};
+ my $setup = test_setup($tmpdir, 'counter');
+
+ my $counter_file = File::Spec->rel2abs("$tmpdir/counter.tab");
+
+ my $sub_dir = File::Spec->rel2abs("$tmpdir/test.d");
+ mkpath($sub_dir);
+
+ my $test_file = File::Spec->rel2abs("$sub_dir/test.dat");
+ if (open(my $fh, "> $test_file")) {
+ print $fh "Hello, World!\n";
+ unless (close($fh)) {
+ die("Can't write $test_file: $!");
+ }
+
+ } else {
+ die("Can't open $test_file: $!");
+ }
+
+ my $config = {
+ PidFile => $setup->{pid_file},
+ ScoreboardFile => $setup->{scoreboard_file},
+ SystemLog => $setup->{log_file},
+ TraceLog => $setup->{log_file},
+ Trace => 'counter:20 vroot:20 vroot.fsio:20',
+
+ AuthUserFile => $setup->{auth_user_file},
+ AuthGroupFile => $setup->{auth_group_file},
+ AllowOverwrite => 'on',
+ DefaultRoot => '~',
+
+ IfModules => {
+ 'mod_counter.c' => {
+ CounterEngine => 'on',
+ CounterLog => $setup->{log_file},
+ CounterFile => $counter_file,
+ CounterMaxReaders => 1,
+ },
+
+ 'mod_delay.c' => {
+ DelayEngine => 'off',
+ },
+
+ 'mod_vroot.c' => {
+ VRootEngine => 'on',
+ },
+ },
+ };
+
+ my ($port, $config_user, $config_group) = config_write($setup->{config_file},
+ $config);
+
+ # Open pipes, for use between the parent and child processes. Specifically,
+ # the child will indicate when it's done with its test by writing a message
+ # to the parent.
+ my ($rfh, $wfh);
+ unless (pipe($rfh, $wfh)) {
+ die("Can't open pipe: $!");
+ }
+
+ my $ex;
+
+ # Fork child
+ $self->handle_sigchld();
+ defined(my $pid = fork()) or die("Can't fork: $!");
+ if ($pid) {
+ eval {
+ my $client1 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port, 0, 1);
+ $client1->login($setup->{user}, $setup->{passwd});
+
+ my $client2 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port, 0, 1);
+ $client2->login($setup->{user}, $setup->{passwd});
+
+ my $conn = $client1->retr_raw('test.d/test.dat');
+ unless ($conn) {
+ die("Failed to RETR test.d/test.d: " . $client1->response_code() . " " .
+ $client1->response_msg());
+ }
+
+ # Now, before we close this data connection, try to open another
+ # data connection for the same file.
+ my $conn2 = $client2->retr_raw('test.d/test.dat');
+ if ($conn2) {
+ die("RETR test.d/test.dat succeeded unexpectedly");
+ }
+
+ my $resp_code = $client2->response_code();
+ my $resp_msg = $client2->response_msg();
+
+ my $expected = 450;
+ $self->assert($expected == $resp_code,
+ "Expected response code $expected, got $resp_code");
+
+ $expected = "test.d/test.dat: File busy";
+ $self->assert($expected eq $resp_msg,
+ "Expected response message '$expected', got '$resp_msg'");
+
+ my $buf;
+ $conn->read($buf, 8192, 15);
+ eval { $conn->close() };
+
+ $resp_code = $client1->response_code();
+ $resp_msg = $client1->response_msg();
+ $self->assert_transfer_ok($resp_code, $resp_msg);
+
+ $client2->quit();
+ $client1->quit();
+ };
+ if ($@) {
+ $ex = $@;
+ }
+
+ $wfh->print("done\n");
+ $wfh->flush();
+
+ } else {
+ eval { server_wait($setup->{config_file}, $rfh) };
+ if ($@) {
+ warn($@);
+ exit 1;
+ }
+
+ exit 0;
+ }
+
+ # Stop server
+ server_stop($setup->{pid_file});
+ $self->assert_child_ok($pid);
+
+ test_cleanup($setup->{log_file}, $ex);
+}
+
+sub counter_vroot_stor_max_writers_exceeded {
+ my $self = shift;
+ my $tmpdir = $self->{tmpdir};
+ my $setup = test_setup($tmpdir, 'counter');
+
+ my $counter_file = File::Spec->rel2abs("$tmpdir/counter.tab");
+ my $test_file = 'test.dat';
+
+ my $config = {
+ PidFile => $setup->{pid_file},
+ ScoreboardFile => $setup->{scoreboard_file},
+ SystemLog => $setup->{log_file},
+ TraceLog => $setup->{log_file},
+ Trace => 'counter:20 vroot:20 vroot.fsio:20',
+
+ AuthUserFile => $setup->{auth_user_file},
+ AuthGroupFile => $setup->{auth_group_file},
+ AllowOverwrite => 'on',
+ DefaultRoot => '~',
+
+ IfModules => {
+ 'mod_counter.c' => {
+ CounterEngine => 'on',
+ CounterLog => $setup->{log_file},
+ CounterFile => $counter_file,
+ CounterMaxWriters => 1,
+ },
+
+ 'mod_delay.c' => {
+ DelayEngine => 'off',
+ },
+
+ 'mod_vroot.c' => {
+ VRootEngine => 'on',
+ },
+ },
+ };
+
+ my ($port, $config_user, $config_group) = config_write($setup->{config_file},
+ $config);
+
+ # Open pipes, for use between the parent and child processes. Specifically,
+ # the child will indicate when it's done with its test by writing a message
+ # to the parent.
+ my ($rfh, $wfh);
+ unless (pipe($rfh, $wfh)) {
+ die("Can't open pipe: $!");
+ }
+
+ my $ex;
+
+ # Fork child
+ $self->handle_sigchld();
+ defined(my $pid = fork()) or die("Can't fork: $!");
+ if ($pid) {
+ eval {
+ my $client1 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port, 0, 1);
+ $client1->login($setup->{user}, $setup->{passwd});
+
+ my $client2 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port, 0, 1);
+ $client2->login($setup->{user}, $setup->{passwd});
+
+ my $conn = $client1->stor_raw($test_file);
+ unless ($conn) {
+ die("Failed to STOR: " . $client1->response_code() . " " .
+ $client1->response_msg());
+ }
+
+ # Now, before we close this data connection, try to open another
+ # data connection for the same file.
+ my $conn2 = $client2->stor_raw($test_file);
+ if ($conn2) {
+ die("STOR $test_file succeeded unexpectedly");
+ }
+
+ my $resp_code = $client2->response_code();
+ my $resp_msg = $client2->response_msg();
+
+ my $expected = 450;
+ $self->assert($expected == $resp_code,
+ "Expected response code $expected, got $resp_code");
+
+ $expected = "$test_file: File busy";
+ $self->assert($expected eq $resp_msg,
+ "Expected response message '$expected', got '$resp_msg'");
+
+ my $buf = 'Hello, World!\n';
+ $conn->write($buf, length($buf));
+ eval { $conn->close() };
+
+ $resp_code = $client1->response_code();
+ $resp_msg = $client1->response_msg();
+ $self->assert_transfer_ok($resp_code, $resp_msg);
+
+ $client2->quit();
+ $client1->quit();
+ };
+ if ($@) {
+ $ex = $@;
+ }
+
+ $wfh->print("done\n");
+ $wfh->flush();
+
+ } else {
+ eval { server_wait($setup->{config_file}, $rfh) };
+ if ($@) {
+ warn($@);
+ exit 1;
+ }
+
+ exit 0;
+ }
+
+ # Stop server
+ server_stop($setup->{pid_file});
+ $self->assert_child_ok($pid);
+
+ test_cleanup($setup->{log_file}, $ex);
+}
+
+sub counter_vroot_stor_max_writers_exceeded_in_subdir {
+ my $self = shift;
+ my $tmpdir = $self->{tmpdir};
+ my $setup = test_setup($tmpdir, 'counter');
+
+ my $counter_file = File::Spec->rel2abs("$tmpdir/counter.tab");
+
+ my $sub_dir = File::Spec->rel2abs("$tmpdir/test.d");
+ mkpath($sub_dir);
+
+ my $test_file = 'test.d/test.dat';
+
+ my $config = {
+ PidFile => $setup->{pid_file},
+ ScoreboardFile => $setup->{scoreboard_file},
+ SystemLog => $setup->{log_file},
+ TraceLog => $setup->{log_file},
+ Trace => 'counter:20 vroot:20 vroot.fsio:20',
+
+ AuthUserFile => $setup->{auth_user_file},
+ AuthGroupFile => $setup->{auth_group_file},
+ AllowOverwrite => 'on',
+ DefaultRoot => '~',
+
+ IfModules => {
+ 'mod_counter.c' => {
+ CounterEngine => 'on',
+ CounterLog => $setup->{log_file},
+ CounterFile => $counter_file,
+ },
+
+ 'mod_delay.c' => {
+ DelayEngine => 'off',
+ },
+
+ 'mod_vroot.c' => {
+ VRootEngine => 'on',
+ },
+ },
+ };
+
+ my ($port, $config_user, $config_group) = config_write($setup->{config_file},
+ $config);
+
+ if (open(my $fh, ">> $setup->{config_file}")) {
+ print $fh <<EOC;
+<Directory /test.d/>
+ CounterMaxWriters 1
+</Directory>
+EOC
+ unless (close($fh)) {
+ die("Can't write $setup->{config_file}: $!");
+ }
+
+ } else {
+ die("Can't open $setup->{config_file}: $!");
+ }
+
+ # Open pipes, for use between the parent and child processes. Specifically,
+ # the child will indicate when it's done with its test by writing a message
+ # to the parent.
+ my ($rfh, $wfh);
+ unless (pipe($rfh, $wfh)) {
+ die("Can't open pipe: $!");
+ }
+
+ my $ex;
+
+ # Fork child
+ $self->handle_sigchld();
+ defined(my $pid = fork()) or die("Can't fork: $!");
+ if ($pid) {
+ eval {
+ my $client1 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port, 0, 1);
+ $client1->login($setup->{user}, $setup->{passwd});
+
+ my $client2 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port, 0, 1);
+ $client2->login($setup->{user}, $setup->{passwd});
+
+ my $conn = $client1->stor_raw($test_file);
+ unless ($conn) {
+ die("Failed to STOR: " . $client1->response_code() . " " .
+ $client1->response_msg());
+ }
+
+ # Now, before we close this data connection, try to open another
+ # data connection for the same file.
+ my $conn2 = $client2->stor_raw($test_file);
+ if ($conn2) {
+ die("STOR $test_file succeeded unexpectedly");
+ }
+
+ my $resp_code = $client2->response_code();
+ my $resp_msg = $client2->response_msg();
+
+ my $expected = 450;
+ $self->assert($expected == $resp_code,
+ "Expected response code $expected, got $resp_code");
+
+ $expected = "$test_file: File busy";
+ $self->assert($expected eq $resp_msg,
+ "Expected response message '$expected', got '$resp_msg'");
+
+ my $buf = "Hello, World!\n";
+ $conn->write($buf, length($buf), 15);
+ eval { $conn->close() };
+
+ $resp_code = $client1->response_code();
+ $resp_msg = $client1->response_msg();
+ $self->assert_transfer_ok($resp_code, $resp_msg);
+
+ $client2->quit();
+ $client1->quit();
+ };
+ if ($@) {
+ $ex = $@;
+ }
+
+ $wfh->print("done\n");
+ $wfh->flush();
+
+ } else {
+ eval { server_wait($setup->{config_file}, $rfh) };
+ if ($@) {
+ warn($@);
+ exit 1;
+ }
+
+ exit 0;
+ }
+
+ # Stop server
+ server_stop($setup->{pid_file});
+ $self->assert_child_ok($pid);
+
+ test_cleanup($setup->{log_file}, $ex);
+}
+
1;
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-proftpd/proftpd-mod-counter.git
More information about the Pkg-proftpd-maintainers
mailing list