Skip to content

Commit

Permalink
Merge pull request #313 from proftpd/copy-cpto-quota-bug4262
Browse files Browse the repository at this point in the history
Bug#4262: SITE CPTO returns 250 even when the copy operation fails due to the user's quota being exceeded
  • Loading branch information
Castaglia committed Aug 2, 2016
2 parents 1353911 + 3d6929d commit 99136a2
Show file tree
Hide file tree
Showing 3 changed files with 283 additions and 11 deletions.
38 changes: 36 additions & 2 deletions contrib/mod_copy.c
Expand Up @@ -28,7 +28,7 @@

#include "conf.h"

#define MOD_COPY_VERSION "mod_copy/0.5"
#define MOD_COPY_VERSION "mod_copy/0.6"

/* Make sure the version of proftpd is as necessary. */
#if PROFTPD_VERSION_NUMBER < 0x0001030401
Expand Down Expand Up @@ -268,10 +268,17 @@ static int copy_dir(pool *p, const char *src_dir, const char *dst_dir) {

} else {
if (pr_fs_copy_file(src_path, dst_path) < 0) {
int xerrno = errno;

pr_log_debug(DEBUG7, MOD_COPY_VERSION
": error copying file '%s' to '%s': %s", src_path, dst_path,
strerror(xerrno));

pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
pr_response_clear(&resp_err_list);

errno = xerrno;
res = -1;
break;

Expand Down Expand Up @@ -768,8 +775,35 @@ MODRET copy_cpto(cmd_rec *cmd) {

if (copy_paths(cmd->tmp_pool, from, to) < 0) {
int xerrno = errno;
const char *resp_code = R_550;

pr_log_debug(DEBUG7, MOD_COPY_VERSION
": error copying '%s' to '%s': %s", from, to, strerror(xerrno));

/* Check errno for EDQOUT (or the most appropriate alternative).
* (I hate the fact that FTP has a special response code just for
* this, and that clients actually expect it. Special cases are
* stupid.)
*/
switch (xerrno) {
#if defined(EDQUOT)
case EDQUOT:
#endif /* EDQUOT */
#if defined(EFBIG)
case EFBIG:
#endif /* EFBIG */
#if defined(ENOSPC)
case ENOSPC:
#endif /* ENOSPC */
resp_code = R_552;
break;

default:
resp_code = R_550;
break;
}

pr_response_add_err(R_550, "%s: %s", (char *) cmd->argv[1],
pr_response_add_err(resp_code, "%s: %s", (char *) cmd->argv[1],
strerror(xerrno));

pr_cmd_set_errno(cmd, xerrno);
Expand Down
45 changes: 38 additions & 7 deletions contrib/mod_quotatab.c
Expand Up @@ -1392,13 +1392,17 @@ int quotatab_write(quota_tally_t *tally,
/* FSIO handlers
*/

static off_t copied_bytes = 0;

static int quotatab_fsio_write(pr_fh_t *fh, int fd, const char *buf,
size_t bufsz) {
int res;
off_t total_bytes;

res = write(fd, buf, bufsz);
if (res < 0)
if (res < 0) {
return res;
}

if (have_quota_update == 0) {
return res;
Expand All @@ -1415,8 +1419,22 @@ static int quotatab_fsio_write(pr_fh_t *fh, int fd, const char *buf,
* simultaneous connections.
*/

/* If the client is copying a file (versus uploading a file), then we need
* to track the "total bytes" differently.
*/
if (session.curr_cmd_id == PR_CMD_SITE_ID &&
(session.curr_cmd_rec->argc >= 2 &&
(strncasecmp(session.curr_cmd_rec->argv[1], "CPTO", 5) == 0 ||
strncasecmp(session.curr_cmd_rec->argv[1], "COPY", 5) == 0))) {
copied_bytes += res;
total_bytes = copied_bytes;

} else {
total_bytes = session.xfer.total_bytes;
}

if (sess_limit.bytes_in_avail > 0.0 &&
sess_tally.bytes_in_used + session.xfer.total_bytes > sess_limit.bytes_in_avail) {
sess_tally.bytes_in_used + total_bytes > sess_limit.bytes_in_avail) {
int xerrno;
char *errstr = NULL;

Expand All @@ -1428,7 +1446,7 @@ static int quotatab_fsio_write(pr_fh_t *fh, int fd, const char *buf,
}

if (sess_limit.bytes_xfer_avail > 0.0 &&
sess_tally.bytes_xfer_used + session.xfer.total_bytes > sess_limit.bytes_xfer_avail) {
sess_tally.bytes_xfer_used + total_bytes > sess_limit.bytes_xfer_avail) {
int xerrno;
char *errstr = NULL;

Expand Down Expand Up @@ -2135,6 +2153,7 @@ MODRET quotatab_post_appe_err(cmd_rec *cmd) {
MODRET quotatab_pre_copy(cmd_rec *cmd) {
struct stat st;

copied_bytes = 0;
have_aborted_transfer = FALSE;
have_err_response = FALSE;

Expand Down Expand Up @@ -2248,6 +2267,7 @@ MODRET quotatab_pre_copy(cmd_rec *cmd) {
}
}

have_quota_update = QUOTA_HAVE_WRITE_UPDATE;
return PR_DECLINED(cmd);
}

Expand All @@ -2256,13 +2276,18 @@ MODRET quotatab_post_copy(cmd_rec *cmd) {
off_t copy_bytes = 0;
int dst_truncated = FALSE;

copied_bytes = 0;

/* Sanity check */
if (!use_quotas)
if (!use_quotas) {
have_quota_update = 0;
return PR_DECLINED(cmd);
}

if (quotatab_ignore_path(cmd->tmp_pool, cmd->argv[2])) {
quotatab_log("%s: path '%s' matched QuotaExcludeFilter '%s', ignoring",
(char *) cmd->argv[0], (char *) cmd->argv[2], quota_exclude_filter);
have_quota_update = 0;
return PR_DECLINED(cmd);
}

Expand Down Expand Up @@ -2421,19 +2446,25 @@ MODRET quotatab_post_copy(cmd_rec *cmd) {
/* Clear the cached bytes/files. */
quotatab_disk_nbytes = 0;
quotatab_disk_nfiles = 0;


have_quota_update = 0;
return PR_DECLINED(cmd);
}

MODRET quotatab_post_copy_err(cmd_rec *cmd) {
copied_bytes = 0;

/* Sanity check */
if (!use_quotas)
if (!use_quotas) {
have_quota_update = 0;
return PR_DECLINED(cmd);
}

/* Clear the cached bytes/files. */
quotatab_disk_nbytes = 0;
quotatab_disk_nfiles = 0;


have_quota_update = 0;
return PR_DECLINED(cmd);
}

Expand Down

0 comments on commit 99136a2

Please sign in to comment.