Blame SOURCES/0032-Propagate-errors-from-nfs-with-quota-to-client.patch

bd689f
From aa9cb48373018502ef99a57aad70b69c0c75ff65 Mon Sep 17 00:00:00 2001
bd689f
From: Martin Sehnoutka <msehnout@redhat.com>
bd689f
Date: Thu, 17 Nov 2016 13:29:59 +0100
bd689f
Subject: [PATCH 32/59] Propagate errors from nfs with quota to client.
bd689f
bd689f
vsftpd now checks for errors when closing newly uploaded file and
bd689f
forward errors to the client (e.g. when file system quota was
bd689f
exceeded)
bd689f
---
bd689f
 ftpcodes.h  |  1 +
bd689f
 postlogin.c | 32 ++++++++++++++++++++++++++++++--
bd689f
 sysutil.c   | 21 +++++++++++++++++++++
bd689f
 sysutil.h   |  1 +
bd689f
 4 files changed, 53 insertions(+), 2 deletions(-)
bd689f
bd689f
diff --git a/ftpcodes.h b/ftpcodes.h
bd689f
index 54dfae7..97801f3 100644
bd689f
--- a/ftpcodes.h
bd689f
+++ b/ftpcodes.h
bd689f
@@ -74,6 +74,7 @@
bd689f
 #define FTP_NOHANDLEPROT      536
bd689f
 #define FTP_FILEFAIL          550
bd689f
 #define FTP_NOPERM            550
bd689f
+#define FTP_DISKQUOTA         552
bd689f
 #define FTP_UPLOADFAIL        553
bd689f
 
bd689f
 #endif /* VSF_FTPCODES_H */
bd689f
diff --git a/postlogin.c b/postlogin.c
bd689f
index e473c34..8363c9c 100644
bd689f
--- a/postlogin.c
bd689f
+++ b/postlogin.c
bd689f
@@ -28,6 +28,8 @@
bd689f
 #include "vsftpver.h"
bd689f
 #include "opts.h"
bd689f
 
bd689f
+#include <errno.h>
bd689f
+
bd689f
 /* Private local functions */
bd689f
 static void handle_pwd(struct vsf_session* p_sess);
bd689f
 static void handle_cwd(struct vsf_session* p_sess);
bd689f
@@ -1035,8 +1037,10 @@ handle_upload_common(struct vsf_session* p_sess, int is_append, int is_unique)
bd689f
   struct vsf_transfer_ret trans_ret;
bd689f
   int new_file_fd;
bd689f
   int remote_fd;
bd689f
+  int close_errno;
bd689f
   int success = 0;
bd689f
   int created = 0;
bd689f
+  int closed = 0;
bd689f
   int do_truncate = 0;
bd689f
   filesize_t offset = p_sess->restart_pos;
bd689f
   p_sess->restart_pos = 0;
bd689f
@@ -1149,6 +1153,18 @@ handle_upload_common(struct vsf_session* p_sess, int is_append, int is_unique)
bd689f
     trans_ret = vsf_ftpdataio_transfer_file(p_sess, remote_fd,
bd689f
                                             new_file_fd, 1, 0);
bd689f
   }
bd689f
+
bd689f
+  /* Need to check close operation here because some errors
bd689f
+   * like EIO, EDQUOT, ENOSPC can be detected only on close
bd689f
+   * when using NFS
bd689f
+   */
bd689f
+  close_errno = vsf_sysutil_close_errno(new_file_fd);
bd689f
+  closed = 1;
bd689f
+  if (close_errno != 0)
bd689f
+  {
bd689f
+    trans_ret.retval = -1;
bd689f
+  }
bd689f
+
bd689f
   if (vsf_ftpdataio_dispose_transfer_fd(p_sess) != 1 && trans_ret.retval == 0)
bd689f
   {
bd689f
     trans_ret.retval = -2;
bd689f
@@ -1161,7 +1177,16 @@ handle_upload_common(struct vsf_session* p_sess, int is_append, int is_unique)
bd689f
   }
bd689f
   if (trans_ret.retval == -1)
bd689f
   {
bd689f
-    vsf_cmdio_write(p_sess, FTP_BADSENDFILE, "Failure writing to local file.");
bd689f
+    /* Disk quota exceeded */
bd689f
+    if (close_errno == EDQUOT)
bd689f
+    {
bd689f
+      vsf_cmdio_write(p_sess, FTP_DISKQUOTA, "Disk quota exceeded.");
bd689f
+    }
bd689f
+    /* any other local error */
bd689f
+    else
bd689f
+    {
bd689f
+      vsf_cmdio_write(p_sess, FTP_BADSENDFILE, "Failure writing to local file.");
bd689f
+    }
bd689f
   }
bd689f
   else if (trans_ret.retval == -2)
bd689f
   {
bd689f
@@ -1183,7 +1208,10 @@ port_pasv_cleanup_out:
bd689f
   {
bd689f
     str_unlink(p_filename);
bd689f
   }
bd689f
-  vsf_sysutil_close(new_file_fd);
bd689f
+  if (!closed)
bd689f
+  {
bd689f
+    vsf_sysutil_close(new_file_fd);
bd689f
+  }
bd689f
 }
bd689f
 
bd689f
 static void
bd689f
diff --git a/sysutil.c b/sysutil.c
bd689f
index 42bcdf8..1c0422e 100644
bd689f
--- a/sysutil.c
bd689f
+++ b/sysutil.c
bd689f
@@ -1268,6 +1268,27 @@ vsf_sysutil_close(int fd)
bd689f
   }
bd689f
 }
bd689f
 
bd689f
+int
bd689f
+vsf_sysutil_close_errno(int fd)
bd689f
+{
bd689f
+  while (1)
bd689f
+  {
bd689f
+    int retval = close(fd);
bd689f
+    if (retval != 0)
bd689f
+    {
bd689f
+      if (errno == EINTR)
bd689f
+      {
bd689f
+        vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0);
bd689f
+        continue;
bd689f
+      }
bd689f
+      else {
bd689f
+        return errno;
bd689f
+      }
bd689f
+    }
bd689f
+    return 0;
bd689f
+  }
bd689f
+}
bd689f
+
bd689f
 int
bd689f
 vsf_sysutil_close_failok(int fd)
bd689f
 {
bd689f
diff --git a/sysutil.h b/sysutil.h
bd689f
index 2886bbc..be727f5 100644
bd689f
--- a/sysutil.h
bd689f
+++ b/sysutil.h
bd689f
@@ -92,6 +92,7 @@ int vsf_sysutil_create_or_open_file_append(const char* p_filename,
bd689f
 int vsf_sysutil_create_or_open_file(const char* p_filename, unsigned int mode);
bd689f
 void vsf_sysutil_dupfd2(int old_fd, int new_fd);
bd689f
 void vsf_sysutil_close(int fd);
bd689f
+int vsf_sysutil_close_errno(int fd);
bd689f
 int vsf_sysutil_close_failok(int fd);
bd689f
 int vsf_sysutil_unlink(const char* p_dead);
bd689f
 int vsf_sysutil_write_access(const char* p_filename);
bd689f
-- 
bd689f
2.14.4
bd689f