From 4cbe3984b6fa33571c35705bd9199c9248128fa0 Mon Sep 17 00:00:00 2001 From: liujinchang Date: Fri, 30 Oct 2026 03:19:53 +0800 Subject: [PATCH] fix: correct error prompt on disk-full transfer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Root cause: writeBlock() returns false on disk-full but caller writeAndCreateFile() never sets _device_not_enough, so handleJobStatus() omits "::not enough" suffix and frontend shows generic "file read/write error" instead of "insufficient storage" 2. Fix: add errno check for ENOSPC/EFBIG in writeBlock() overloads, pass result via output parameter; writeAndCreateFile() sets _device_not_enough accordingly; fix first overload to return false on write failure; fix sendToRemote() IO_ERROR path to check not_enough flag from FileTransResponse instead of unconditionally setting _device_not_enough 3. Impact: disk-full during file transfer now correctly shows "insufficient storage" on both sender and receiver; other I/O errors remain showing "file read/write error" Log: Fix incorrect error prompt when storage space is insufficient during file transfer Influence: 1. Test file transfer when receiver disk is full 2. Test file transfer with normal available space 3. Test file transfer with permission-denied write path fix: 修复传输过程中磁盘空间不足时错误提示不正确的问题 1. 根因:writeBlock() 在磁盘空间不足时返回 false,但调用方 writeAndCreateFile() 未设置 _device_not_enough 标志, handleJobStatus() 因此不含 "::not enough" 后缀,前端回退 显示"文件读写异常"而非"储存空间不足" 2. 方案:在 writeBlock() 重载中增加 errno 检查 ENOSPC/EFBIG, 通过输出参数传递空间不足信号;writeAndCreateFile() 据此设置 _device_not_enough;修复第一重载写入失败仍返回 true 的缺陷; 修复 sendToRemote() IO_ERROR 路径改为检查 FileTransResponse 中的 not_enough 标志,避免非磁盘满场景误报 3. 影响:磁盘空间不足时正确显示"储存空间不足",其他 I/O 错误 仍显示"文件读写异常" Log: 修复文件传输过程中储存空间不足时提示错误的问题 Influence: 1. 测试接收端磁盘空间不足时的文件传输 2. 测试正常可用空间下的文件传输 3. 测试权限不足等非空间类写入错误时的提示 Bug: https://pms.uniontech.com/bug-view-261917.html PMS: BUG-261917 --- src/common/commonstruct.h | 3 +++ src/plugins/daemon/core/service/fsadapter.cpp | 17 +++++++++++++---- src/plugins/daemon/core/service/fsadapter.h | 6 +++--- .../daemon/core/service/job/transferjob.cpp | 9 ++++++--- src/plugins/daemon/core/service/jobmanager.cpp | 2 ++ 5 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/common/commonstruct.h b/src/common/commonstruct.h index 32a5bd9c2..7f3f09caf 100644 --- a/src/common/commonstruct.h +++ b/src/common/commonstruct.h @@ -225,11 +225,13 @@ struct FileTransResponse { int32 id { -1 }; fastring name; int32 result { -1 }; + bool not_enough { false }; void from_json(const co::Json& _x_) { id = (int32)_x_.get("id").as_int64(); name = _x_.get("name").as_c_str(); result = (int32)_x_.get("result").as_int64(); + not_enough = _x_.get("not_enough").as_bool(); } co::Json as_json() const { @@ -237,6 +239,7 @@ struct FileTransResponse { _x_.add_member("id", id); _x_.add_member("name", name); _x_.add_member("result", result); + _x_.add_member("not_enough", not_enough); return _x_; } }; diff --git a/src/plugins/daemon/core/service/fsadapter.cpp b/src/plugins/daemon/core/service/fsadapter.cpp index 1d1090427..16ba84166 100644 --- a/src/plugins/daemon/core/service/fsadapter.cpp +++ b/src/plugins/daemon/core/service/fsadapter.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2023-2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: GPL-3.0-or-later @@ -11,6 +11,8 @@ #include "co/log.h" #include "co/path.h" +#include + //using namespace deamon_core; FSAdapter::FSAdapter(QObject *parent) @@ -81,7 +83,7 @@ bool FSAdapter::newFileByFullPath(const char *fullpath, bool isdir) return fs::exists(fullpath); } -bool FSAdapter::writeBlock(const char *name, int64 seek_len, const char *data, size_t size) +bool FSAdapter::writeBlock(const char *name, int64 seek_len, const char *data, size_t size, bool *not_enough) { fs::file fx(name, 'm'); if (!fx.exists()) { @@ -89,12 +91,16 @@ bool FSAdapter::writeBlock(const char *name, int64 seek_len, const char *data, s return false; } + bool write = true; size_t wirted_size = 0; size_t rem_size = size; fx.seek(seek_len); do { size_t wsize = fx.write(data, rem_size); if (wsize <= 0) { + write = false; + if (not_enough && (errno == ENOSPC || errno == EFBIG)) + *not_enough = true; ELOG << "fx write done: " << rem_size << " => " << wsize; break; } @@ -103,11 +109,12 @@ bool FSAdapter::writeBlock(const char *name, int64 seek_len, const char *data, s } while (wirted_size < size); fx.close(); - return true; + return write; } bool FSAdapter::writeBlock(const char *name, int64 seek_len, - const char *data, size_t size, const int flags, fs::file **fx) + const char *data, size_t size, const int flags, fs::file **fx, + bool *not_enough) { if (flags & JobTransFileOp::FIlE_CREATE) { if ((*fx) != nullptr) { @@ -143,6 +150,8 @@ bool FSAdapter::writeBlock(const char *name, int64 seek_len, size_t wsize = (*fx)->write(data, rem_size); if (wsize <= 0) { write = false; + if (not_enough && (errno == ENOSPC || errno == EFBIG)) + *not_enough = true; ELOG << "fx write done: " << rem_size << " => " << wsize; break; } diff --git a/src/plugins/daemon/core/service/fsadapter.h b/src/plugins/daemon/core/service/fsadapter.h index 5dcfff520..b6c3285c0 100644 --- a/src/plugins/daemon/core/service/fsadapter.h +++ b/src/plugins/daemon/core/service/fsadapter.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2023-2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: GPL-3.0-or-later @@ -21,9 +21,9 @@ class FSAdapter : public QObject static int getFileEntry(const char *path, FileEntry **entry); static bool newFile(const char *path, bool isdir); static bool newFileByFullPath(const char *fullpath, bool isdir); - static bool writeBlock(const char *name, int64 seek_len, const char *data, size_t size); + static bool writeBlock(const char *name, int64 seek_len, const char *data, size_t size, bool *not_enough = nullptr); static bool writeBlock(const char *name, int64 seek_len, const char *data, size_t size, - const int flags, fs::file **fx); + const int flags, fs::file **fx, bool *not_enough = nullptr); static bool reacquirePath(fastring filepath, fastring *newpath); signals: diff --git a/src/plugins/daemon/core/service/job/transferjob.cpp b/src/plugins/daemon/core/service/job/transferjob.cpp index d075147a8..d241d38fc 100644 --- a/src/plugins/daemon/core/service/job/transferjob.cpp +++ b/src/plugins/daemon/core/service/job/transferjob.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2023-2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: GPL-3.0-or-later @@ -706,13 +706,16 @@ bool TransferJob::writeAndCreateFile(const QSharedPointer block, co // << " flags !!! " << block->flags; int count = 3; bool good = false; + bool not_enough = false; do { - good = FSAdapter::writeBlock(fullpath.c_str(), offset, buffer.c_str(), len, block->flags, &fx); + good = FSAdapter::writeBlock(fullpath.c_str(), offset, buffer.c_str(), len, block->flags, &fx, ¬_enough); count--; } while(!good && count > 0); if (!good) { + if (not_enough) + _device_not_enough = true; ELOG << "file : " << fullpath << " write BLOCK error"; } else { if (len == 0 && block->flags & JobTransFileOp::FIlE_CREATE) { @@ -754,7 +757,7 @@ bool TransferJob::sendToRemote(const QSharedPointer block) transres.from_json(resJson); if (transres.result == IO_ERROR) { DLOG << "remote return: IO_ERROR!"; - _device_not_enough = block->flags & JobTransFileOp::FILE_COUNTED; + _device_not_enough = transres.not_enough; return false; } } else { diff --git a/src/plugins/daemon/core/service/jobmanager.cpp b/src/plugins/daemon/core/service/jobmanager.cpp index f446eea0b..185677306 100644 --- a/src/plugins/daemon/core/service/jobmanager.cpp +++ b/src/plugins/daemon/core/service/jobmanager.cpp @@ -170,6 +170,8 @@ bool JobManager::handleFSData(const co::Json &info, fastring buf, FileTransRespo if (!job.isNull()) { job->pushQueque(datablock); if (datablock->flags & JobTransFileOp::FILE_COUNTED && job->freeBytes() < datablock->data_size) { + if (reply) + reply->not_enough = true; return false; } else if (datablock->flags & JobTransFileOp::FIlE_DIR_CREATE || datablock->flags & JobTransFileOp::FIlE_CREATE) { co::sleep(10);