测试用例

This commit is contained in:
2026-08-29 11:39:28 +08:00
parent a0758766c5
commit 8fd65b0de0
19 changed files with 1723 additions and 432 deletions
+210 -1
View File
@@ -3,14 +3,19 @@
#include <windows.h>
#include <io.h> // 提供 _get_osfhandle
#include <direct.h>
#include <dirent.h>
#define C_ACCESS(path) _access(path, 0)
#define C_MAKE_DIR(path) _mkdir(path) // Windows 下创建目录
#define sys_rmdir(path) _rmdir(path)
#define PATH_SEP '\\'
#else
#include <unistd.h> // 提供 fsync
#include <sys/stat.h>
#include <sys/types.h>
#define C_ACCESS(path) access(path, F_OK)
#define C_MAKE_DIR(path) mkdir(path, 0755)
#define sys_rmdir(path) rmdir(path)
#define PATH_SEP '/'
#endif
/* ------------------------------------------------------------------------------------------------------------------ */
@@ -276,4 +281,208 @@ c_err_t c_File_MkDirs(const char* path) {
}
return C_SUCCESS;
}
}
c_err_t c_File_Rmdir(const char* path) {
if (!path || path[0] == '\0') {
return C_ERR_PARAM;
}
// 调用操作系统底层移除目录的 API
int result = sys_rmdir(path);
if (result == 0) {
return C_ERR_OK; // 删除成功
} else {
// 删除失败(可能是由于目录不存在、无权限、或者目录非空)
return C_ERR_FAIL;
}
}
c_err_t c_File_Rmdirs(const char* path) {
if (!path || path[0] == '\0') {
return C_ERR_PARAM;
}
c_err_t status = C_ERR_OK;
#if defined(_WIN32) || defined(_WIN64)
// ==========================================
// Windows 平台的递归删除实现
// ==========================================
char search_path[MAX_PATH];
// Windows 检索目录需要追加 "\\*"
snprintf(search_path, sizeof(search_path), "%s\\*", path);
WIN32_FIND_DATAA find_data;
HANDLE h_find = FindFirstFileA(search_path, &find_data);
if (h_find == INVALID_HANDLE_VALUE) {
// 如果目录根本不存在,或者无法打开,尝试直接当做文件 remove 移除(处理符号链接等边界)
return remove(path) == 0 ? C_ERR_OK : C_ERR_FAIL;
}
do {
// 排除 Windows 的特殊目录 "." 和 ".."
if (strcmp(find_data.cFileName, ".") == 0 || strcmp(find_data.cFileName, "..") == 0) {
continue;
}
// 拼接子项的完整路径
char sub_path[MAX_PATH];
snprintf(sub_path, sizeof(sub_path), "%s\\%s", path, find_data.cFileName);
if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// 如果子项是目录,递归调用
status = c_File_Rmdirs(sub_path);
} else {
// 如果子项是普通文件,取消只读属性(防止因只读导致删除失败),然后将其删除
SetFileAttributesA(sub_path, FILE_ATTRIBUTE_NORMAL);
status = (DeleteFileA(sub_path) != 0) ? C_ERR_OK : C_ERR_FAIL;
}
if (status != C_ERR_OK) {
break;
}
} while (FindNextFileA(h_find, &find_data));
FindClose(h_find);
#else
// ==========================================
// Linux / macOS (POSIX) 平台的递归删除实现
// ==========================================
DIR* dir = opendir(path);
if (!dir) {
// 无法打开作为目录处理,尝试按普通文件物理删除
return remove(path) == 0 ? C_ERR_OK : C_ERR_FAIL;
}
struct dirent* entry;
while ((entry = readdir(dir)) != NULL) {
// 排除 Linux 的特殊目录 "." 和 ".."
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
// 拼接子项的完整路径
char sub_path[1024];
snprintf(sub_path, sizeof(sub_path), "%s/%s", path, entry->d_name);
struct stat statbuf;
if (stat(sub_path, &statbuf) == 0) {
if (S_ISDIR(statbuf.st_mode)) {
// 如果子项是目录,递归调用
status = c_File_Rmdirs(sub_path);
} else {
// 如果子项是文件,执行普通删除
status = (remove(sub_path) == 0) ? C_ERR_OK : C_ERR_FAIL;
}
}
if (status != C_ERR_OK) {
break;
}
}
closedir(dir);
#endif
// ==========================================
// 公共收尾:清空了内部所有子项后,最后删除外层空壳目录
// ==========================================
if (status == C_ERR_OK) {
if (sys_rmdir(path) != 0) {
status = C_ERR_FAIL;
}
}
return status;
}
c_err_t c_File_Delete(const char* fileName) {
if (!fileName || fileName[0] == '\0') {
return C_ERR_PARAM;
}
// 标准 C 库的 remove 能够直接删除文件(在某些平台上也能删除空目录)
int result = remove(fileName);
if (result == 0) {
return C_ERR_OK; // 删除成功
} else {
// 删除失败(文件不存在、或无权限、或文件正被某些操作系统强锁占用)
return C_ERR_FAIL;
}
}
#define COPY_BUFFER_SIZE 4096
c_err_t c_File_Copy(const char* srcPath, const char* destPath) {
if (!srcPath || srcPath[0] == '\0' || !destPath || destPath[0] == '\0') {
return C_ERR_PARAM;
}
FILE* src = fopen(srcPath, "rb");
if (!src) return C_ERR_NOTFOUND;
FILE* dest = fopen(destPath, "wb");
if (!dest) {
fclose(src);
return C_ERR_FAIL;
}
char* buffer = (char*)malloc(COPY_BUFFER_SIZE);
if (!buffer) {
fclose(src);
fclose(dest);
return C_ERR_FAIL;
}
c_err_t status = C_ERR_OK;
size_t bytes_read;
// 循环读写块,避免一次性读入大文件撑爆堆内存
while ((bytes_read = fread(buffer, 1, COPY_BUFFER_SIZE, src)) > 0) {
size_t bytes_written = fwrite(buffer, 1, bytes_read, dest);
if (bytes_written < bytes_read) {
status = C_ERR_FAIL; // 磁盘空间不足或写入错误
break;
}
}
free(buffer);
fclose(src);
fclose(dest);
// 如果中途失败,清理掉生成的不完整目标文件
if (status != C_ERR_OK) {
remove(destPath);
}
return status;
}
c_err_t c_File_Move(const char* oldPath, const char* newPath) {
if (!oldPath || oldPath[0] == '\0' || !newPath || newPath[0] == '\0') {
return C_ERR_PARAM;
}
// 1. 尝试使用操作系统原生的轻量级重命名/移动
if (rename(oldPath, newPath) == 0) {
return C_ERR_OK;
}
// 2. 跨分区保底策略:如果因为跨文件系统挂载点导致 rename 失败,则执行 复制 + 删除
c_err_t copy_err = c_File_Copy(oldPath, newPath);
if (copy_err == C_ERR_OK) {
if (remove(oldPath) == 0) {
return C_ERR_OK;
} else {
// 如果删原文件失败,为了数据安全,把新拷过去的文件也撤销,避免数据状态不一致
remove(newPath);
return C_ERR_FAIL;
}
}
return C_ERR_FAIL;
}