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

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