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