Blame SOURCES/vsftpd-2.2.2-nfs-fail.patch

ac8676
diff --git a/ftpcodes.h b/ftpcodes.h
ac8676
index 995788a..22c3c9b 100644
ac8676
--- a/ftpcodes.h
ac8676
+++ b/ftpcodes.h
ac8676
@@ -73,6 +73,7 @@
ac8676
 #define FTP_NOHANDLEPROT      536
ac8676
 #define FTP_FILEFAIL          550
ac8676
 #define FTP_NOPERM            550
ac8676
+#define FTP_DISKQUOTA         552
ac8676
 #define FTP_UPLOADFAIL        553
ac8676
 
ac8676
 #endif /* VSF_FTPCODES_H */
ac8676
diff --git a/postlogin.c b/postlogin.c
ac8676
index e1f080f..ffe0f38 100644
ac8676
--- a/postlogin.c
ac8676
+++ b/postlogin.c
ac8676
@@ -28,6 +28,8 @@
ac8676
 #include "vsftpver.h"
ac8676
 #include "opts.h"
ac8676
 
ac8676
+#include <errno.h>
ac8676
+
ac8676
 /* Private local functions */
ac8676
 static void handle_pwd(struct vsf_session* p_sess);
ac8676
 static void handle_cwd(struct vsf_session* p_sess);
ac8676
@@ -996,8 +998,10 @@ handle_upload_common(struct vsf_session* p_sess, int is_append, int is_unique)
ac8676
   struct vsf_transfer_ret trans_ret;
ac8676
   int new_file_fd;
ac8676
   int remote_fd;
ac8676
+  int close_errno;
ac8676
   int success = 0;
ac8676
   int created = 0;
ac8676
+  int closed = 0;
ac8676
   int do_truncate = 0;
ac8676
   filesize_t offset = p_sess->restart_pos;
ac8676
   p_sess->restart_pos = 0;
ac8676
@@ -1110,6 +1114,18 @@ handle_upload_common(struct vsf_session* p_sess, int is_append, int is_unique)
ac8676
     trans_ret = vsf_ftpdataio_transfer_file(p_sess, remote_fd,
ac8676
                                             new_file_fd, 1, 0);
ac8676
   }
ac8676
+
ac8676
+  /* Need to check close operation here because some errors
ac8676
+   * like EIO, EDQUOT, ENOSPC can be detected only on close
ac8676
+   * when using NFS
ac8676
+   */
ac8676
+  close_errno = vsf_sysutil_close_errno(new_file_fd);
ac8676
+  closed = 1;
ac8676
+  if (close_errno != 0)
ac8676
+  {
ac8676
+    trans_ret.retval = -1;
ac8676
+  }
ac8676
+
ac8676
   if (vsf_ftpdataio_dispose_transfer_fd(p_sess) != 1 && trans_ret.retval == 0)
ac8676
   {
ac8676
     trans_ret.retval = -2;
ac8676
@@ -1122,7 +1138,16 @@ handle_upload_common(struct vsf_session* p_sess, int is_append, int is_unique)
ac8676
   }
ac8676
   if (trans_ret.retval == -1)
ac8676
   {
ac8676
-    vsf_cmdio_write(p_sess, FTP_BADSENDFILE, "Failure writing to local file.");
ac8676
+    /* Disk quota exceeded */
ac8676
+    if (close_errno == EDQUOT)
ac8676
+    {
ac8676
+      vsf_cmdio_write(p_sess, FTP_DISKQUOTA, "Disk quota exceeded.");
ac8676
+    }
ac8676
+    /* any other local error */
ac8676
+    else
ac8676
+    {
ac8676
+      vsf_cmdio_write(p_sess, FTP_BADSENDFILE, "Failure writing to local file.");
ac8676
+    }
ac8676
   }
ac8676
   else if (trans_ret.retval == -2)
ac8676
   {
ac8676
@@ -1144,7 +1169,10 @@ port_pasv_cleanup_out:
ac8676
   {
ac8676
     str_unlink(p_filename);
ac8676
   }
ac8676
-  vsf_sysutil_close(new_file_fd);
ac8676
+  if (!closed)
ac8676
+  {
ac8676
+    vsf_sysutil_close(new_file_fd);
ac8676
+  }
ac8676
 }
ac8676
 
ac8676
 static void
ac8676
diff --git a/sysutil.c b/sysutil.c
ac8676
index 01a726d..2c3659b 100644
ac8676
--- a/sysutil.c
ac8676
+++ b/sysutil.c
ac8676
@@ -1271,6 +1271,27 @@ vsf_sysutil_close(int fd)
ac8676
 }
ac8676
 
ac8676
 int
ac8676
+vsf_sysutil_close_errno(int fd)
ac8676
+{
ac8676
+  while (1)
ac8676
+  {
ac8676
+    int retval = close(fd);
ac8676
+    if (retval != 0)
ac8676
+    {
ac8676
+      if (errno == EINTR)
ac8676
+      {
ac8676
+        vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0);
ac8676
+        continue;
ac8676
+      }
ac8676
+      else {
ac8676
+        return errno;
ac8676
+      }
ac8676
+    }
ac8676
+    return 0;
ac8676
+  }
ac8676
+}
ac8676
+
ac8676
+int
ac8676
 vsf_sysutil_close_failok(int fd)
ac8676
 {
ac8676
   return close(fd);
ac8676
diff --git a/sysutil.h b/sysutil.h
ac8676
index 92fb7a9..c9ca9e4 100644
ac8676
--- a/sysutil.h
ac8676
+++ b/sysutil.h
ac8676
@@ -92,6 +92,7 @@ int vsf_sysutil_create_append_file(const char* p_filename);
ac8676
 int vsf_sysutil_create_or_open_file(const char* p_filename, unsigned int mode);
ac8676
 void vsf_sysutil_dupfd2(int old_fd, int new_fd);
ac8676
 void vsf_sysutil_close(int fd);
ac8676
+int vsf_sysutil_close_errno(int fd);
ac8676
 int vsf_sysutil_close_failok(int fd);
ac8676
 int vsf_sysutil_unlink(const char* p_dead);
ac8676
 int vsf_sysutil_write_access(const char* p_filename);