22. mkdir - 创建目录 链接到标题
函数介绍 链接到标题
mkdir
系统调用用于创建新的目录。可以指定目录的访问权限,新创建的目录权限会受到进程的umask值影响。
函数原型 链接到标题
#include <sys/stat.h>
#include <sys/types.h>
int mkdir(const char *pathname, mode_t mode);
功能 链接到标题
创建指定路径名的新目录。
参数 链接到标题
const char *pathname
: 要创建的目录路径名mode_t mode
: 目录的访问权限(如0755)
返回值 链接到标题
- 成功时返回0
- 失败时返回-1,并设置errno:
EACCES
: 权限不足EDQUOT
: 磁盘配额超限EEXIST
: 目录已存在EINVAL
: 参数无效ELOOP
: 符号链接循环EMLINK
: 链接数超限ENAMETOOLONG
: 路径名过长ENOENT
: 父目录不存在ENOSPC
: 磁盘空间不足ENOTDIR
: 路径前缀不是目录EROFS
: 文件系统只读
相似函数 链接到标题
mkdirat()
: 相对路径版本umask()
: 设置文件权限掩码
示例代码 链接到标题
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <limits.h>
#include <time.h>
int main() {
char buffer[PATH_MAX];
mode_t old_umask;
printf("=== Mkdir函数示例 ===\n");
// 示例1: 基本的目录创建操作
printf("\n示例1: 基本的目录创建操作\n");
// 创建简单的目录
const char *simple_dir = "test_mkdir_simple";
if (mkdir(simple_dir, 0755) == -1) {
if (errno == EEXIST) {
printf("目录 %s 已存在\n", simple_dir);
} else {
perror("创建简单目录失败");
}
} else {
printf("成功创建目录: %s (权限 0755)\n", simple_dir);
// 验证目录创建
if (access(simple_dir, F_OK) == 0) {
printf("目录存在验证成功\n");
// 获取目录信息
struct stat dir_stat;
if (stat(simple_dir, &dir_stat) == 0) {
printf("目录信息:\n");
printf(" inode: %ld\n", dir_stat.st_ino);
printf(" 大小: %ld 字节\n", dir_stat.st_size);
printf(" 权限: %o\n", dir_stat.st_mode & 0777);
printf(" 创建时间: %s", ctime(&dir_stat.st_ctime));
}
}
}
// 示例2: 不同权限的目录创建
printf("\n示例2: 不同权限的目录创建\n");
// 保存当前umask
old_umask = umask(0);
printf("当前umask: %03o\n", old_umask);
// 恢复umask
umask(old_umask);
struct {
const char *name;
mode_t mode;
const char *description;
} dirs[] = {
{"dir_rwx_rwx_rwx", 0777, "完全权限"},
{"dir_rwx_r_x___", 0750, "所有者完全权限,组用户读执行"},
{"dir_rwx_______", 0700, "仅所有者有权限"},
{"dir_r_x_r_x_r_x", 0555, "只读执行权限"}
};
for (int i = 0; i < 4; i++) {
// 添加唯一标识避免重名
char unique_name[100];
snprintf(unique_name, sizeof(unique_name), "%s_%d", dirs[i].name, (int)time(NULL) % 1000);
if (mkdir(unique_name, dirs[i].mode) == -1) {
if (errno == EEXIST) {
printf("目录 %s 已存在\n", unique_name);
} else {
perror("创建目录失败");
}
} else {
printf("创建目录: %s (权限 %03o - %s)\n",
unique_name, dirs[i].mode, dirs[i].description);
// 验证实际权限(考虑umask)
struct stat stat_buf;
if (stat(unique_name, &stat_buf) == 0) {
mode_t actual_mode = stat_buf.st_mode & 0777;
printf(" 实际权限: %03o\n", actual_mode);
}
// 清理测试目录
rmdir(unique_name);
}
}
// 示例3: 多级目录创建
printf("\n示例3: 多级目录创建\n");
// 创建深层目录结构
const char *deep_path = "level1/level2/level3";
printf("创建深层目录: %s\n", deep_path);
// 需要逐级创建
if (mkdir("level1", 0755) == -1 && errno != EEXIST) {
perror("创建level1失败");
} else {
printf("创建目录: level1\n");
if (mkdir("level1/level2", 0755) == -1 && errno != EEXIST) {
perror("创建level1/level2失败");
} else {
printf("创建目录: level1/level2\n");
if (mkdir("level1/level2/level3", 0755) == -1 && errno != EEXIST) {
perror("创建level1/level2/level3失败");
} else {
printf("创建目录: level1/level2/level3\n");
// 验证目录结构
if (access(deep_path, F_OK) == 0) {
printf("深层目录创建验证成功\n");
}
}
}
}
// 示例4: 错误处理演示
printf("\n示例4: 错误处理演示\n");
// 尝试创建已存在的目录
if (mkdir(simple_dir, 0755) == -1) {
if (errno == EEXIST) {
printf("创建已存在目录: %s\n", strerror(errno));
}
}
// 尝试创建嵌套目录(父目录不存在)
if (mkdir("nonexistent_parent/child", 0755) == -1) {
if (errno == ENOENT) {
printf("创建父目录不存在的目录: %s\n", strerror(errno));
}
}
// 尝试在只读文件系统创建目录
if (mkdir("/proc/test_dir", 0755) == -1) {
if (errno == EROFS || errno == EACCES) {
printf("在只读文件系统创建目录: %s\n", strerror(errno));
}
}
// 尝试使用过长的路径名
char long_path[PATH_MAX + 100];
memset(long_path, 'a', sizeof(long_path) - 1);
long_path[sizeof(long_path) - 1] = '\0';
if (mkdir(long_path, 0755) == -1) {
if (errno == ENAMETOOLONG) {
printf("使用过长路径名: %s\n", strerror(errno));
}
}
// 示例5: 实际应用场景
printf("\n示例5: 实际应用场景\n");
// 场景1: 应用程序数据目录创建
printf("场景1: 应用程序数据目录创建\n");
const char *app_dirs[] = {
".myapp",
".myapp/config",
".myapp/data",
".myapp/logs",
".myapp/cache"
};
printf("创建应用程序目录结构:\n");
for (int i = 0; i < 5; i++) {
mode_t mode = (i == 0) ? 0700 : 0755; // 主目录更严格的权限
if (mkdir(app_dirs[i], mode) == -1) {
if (errno == EEXIST) {
printf(" 目录已存在: %s\n", app_dirs[i]);
} else {
printf(" 创建 %s 失败: %s\n", app_dirs[i], strerror(errno));
}
} else {
printf(" 创建目录: %s (权限 %03o)\n", app_dirs[i], mode);
}
}
// 场景2: 临时目录创建
printf("场景2: 临时目录创建\n");
char temp_dir_template[] = "/tmp/mkdir_test_XXXXXX";
char *temp_dir = mkdtemp(temp_dir_template);
if (temp_dir == NULL) {
perror("创建临时目录失败");
} else {
printf("创建临时目录: %s\n", temp_dir);
// 在临时目录中创建子目录
char subdir[PATH_MAX];
snprintf(subdir, sizeof(subdir), "%s/subdir", temp_dir);
if (mkdir(subdir, 0755) == -1) {
perror("创建临时子目录失败");
} else {
printf("在临时目录中创建子目录: %s\n", subdir);
}
// 清理临时目录
rmdir(subdir);
rmdir(temp_dir);
}
// 场景3: 日志目录管理
printf("场景3: 日志目录管理\n");
time_t now = time(NULL);
struct tm *local_time = localtime(&now);
char log_dir[100];
snprintf(log_dir, sizeof(log_dir), "logs_%04d%02d%02d",
local_time->tm_year + 1900,
local_time->tm_mon + 1,
local_time->tm_mday);
if (mkdir(log_dir, 0755) == -1) {
if (errno == EEXIST) {
printf("日志目录已存在: %s\n", log_dir);
} else {
perror("创建日志目录失败");
}
} else {
printf("创建日志目录: %s\n", log_dir);
// 创建按小时分类的子目录
for (int hour = 0; hour < 24; hour += 6) {
char hour_dir[150];
snprintf(hour_dir, sizeof(hour_dir), "%s/hour_%02d", log_dir, hour);
if (mkdir(hour_dir, 0755) == -1 && errno != EEXIST) {
printf("创建小时目录 %s 失败: %s\n", hour_dir, strerror(errno));
} else {
printf(" 创建小时目录: %s\n", hour_dir);
}
}
}
// 示例6: 权限和umask交互
printf("\n示例6: 权限和umask交互\n");
// 保存并设置不同的umask值进行测试
mode_t original_umask = umask(0);
printf("原始umask: %03o\n", original_umask);
struct {
mode_t umask_val;
mode_t dir_mode;
const char *desc;
} umask_tests[] = {
{0000, 0755, "umask 0000"},
{0022, 0755, "umask 0022"},
{0077, 0755, "umask 0077"},
{0027, 0750, "umask 0027"}
};
for (int i = 0; i < 4; i++) {
// 设置umask
umask(umask_tests[i].umask_val);
printf("设置umask为 %03o\n", umask_tests[i].umask_val);
// 创建测试目录
char test_dir[50];
snprintf(test_dir, sizeof(test_dir), "umask_test_%d", i);
if (mkdir(test_dir, umask_tests[i].dir_mode) == -1 && errno != EEXIST) {
perror("创建测试目录失败");
} else {
// 检查实际权限
struct stat stat_buf;
if (stat(test_dir, &stat_buf) == 0) {
mode_t actual_mode = stat_buf.st_mode & 0777;
mode_t expected_mode = umask_tests[i].dir_mode & ~(umask_tests[i].umask_val);
printf(" 请求权限: %03o, umask: %03o, 实际权限: %03o, 期望权限: %03o\n",
umask_tests[i].dir_mode, umask_tests[i].umask_val,
actual_mode, expected_mode);
}
// 清理
rmdir(test_dir);
}
}
// 恢复原始umask
umask(original_umask);
// 示例7: 目录创建性能测试
printf("\n示例7: 目录创建性能测试\n");
const int iterations = 1000;
char perf_dir_base[] = "perf_test_XXXXXX";
char perf_dir[100];
// 创建基准目录
if (mkdtemp(perf_dir_base) != NULL) {
printf("在 %s 中进行性能测试\n", perf_dir_base);
clock_t start = clock();
for (int i = 0; i < iterations; i++) {
snprintf(perf_dir, sizeof(perf_dir), "%s/dir_%d", perf_dir_base, i);
if (mkdir(perf_dir, 0755) == -1 && errno != EEXIST) {
printf("创建目录失败: %s\n", strerror(errno));
break;
}
}
clock_t creation_time = clock() - start;
// 删除目录
start = clock();
for (int i = 0; i < iterations; i++) {
snprintf(perf_dir, sizeof(perf_dir), "%s/dir_%d", perf_dir_base, i);
rmdir(perf_dir);
}
clock_t deletion_time = clock() - start;
printf("%d次目录创建耗时: %f 秒\n",
iterations, ((double)creation_time) / CLOCKS_PER_SEC);
printf("%d次目录删除耗时: %f 秒\n",
iterations, ((double)deletion_time) / CLOCKS_PER_SEC);
printf("平均每次操作耗时: %f 毫秒\n",
(((double)creation_time) / CLOCKS_PER_SEC * 1000) / iterations);
// 清理基准目录
rmdir(perf_dir_base);
}
// 示例8: 安全考虑
printf("\n示例8: 安全考虑\n");
// 场景: 安全的临时目录创建
printf("安全的临时目录创建:\n");
char secure_temp[] = "/tmp/secure_app_XXXXXX";
char *secure_dir = mkdtemp(secure_temp);
if (secure_dir == NULL) {
perror("创建安全临时目录失败");
} else {
printf("创建安全临时目录: %s\n", secure_dir);
printf("特点: 唯一名称,避免竞态条件\n");
// 设置严格的权限
if (chmod(secure_dir, 0700) == -1) {
perror("设置严格权限失败");
} else {
printf("设置目录权限为 0700 (仅所有者可访问)\n");
}
// 清理
rmdir(secure_dir);
}
// 示例9: 符号链接处理
printf("\n示例9: 符号链接处理\n");
// 创建测试目录
if (mkdir("symlink_test_dir", 0755) == -1 && errno != EEXIST) {
perror("创建符号链接测试目录失败");
} else {
printf("创建符号链接测试目录\n");
// 创建符号链接
if (symlink("symlink_test_dir", "symlink_to_dir") == -1 && errno != EEXIST) {
perror("创建符号链接失败");
} else {
printf("创建符号链接: symlink_to_dir -> symlink_test_dir\n");
// 尝试在符号链接上创建目录(会失败)
if (mkdir("symlink_to_dir/subdir", 0755) == -1) {
printf("通过符号链接创建子目录失败: %s\n", strerror(errno));
printf("说明: 不能通过符号链接创建子目录\n");
}
// 清理
unlink("symlink_to_dir");
}
rmdir("symlink_test_dir");
}
// 清理测试资源
printf("\n清理测试资源...\n");
// 删除基本测试目录
if (access(simple_dir, F_OK) == 0) {
if (rmdir(simple_dir) == -1) {
printf("删除目录 %s 失败: %s\n", simple_dir, strerror(errno));
} else {
printf("删除目录: %s\n", simple_dir);
}
}
// 删除深层目录结构
if (access("level1/level2/level3", F_OK) == 0) {
rmdir("level1/level2/level3");
rmdir("level1/level2");
rmdir("level1");
printf("删除深层目录结构\n");
}
// 删除应用程序目录
for (int i = 4; i >= 0; i--) {
if (access(app_dirs[i], F_OK) == 0) {
rmdir(app_dirs[i]);
}
}
printf("删除应用程序目录结构\n");
// 删除日志目录
char hour_dir[150];
for (int hour = 18; hour >= 0; hour -= 6) {
snprintf(hour_dir, sizeof(hour_dir), "%s/hour_%02d", log_dir, hour);
if (access(hour_dir, F_OK) == 0) {
rmdir(hour_dir);
}
}
if (access(log_dir, F_OK) == 0) {
rmdir(log_dir);
printf("删除日志目录\n");
}
return 0;
}
23. rmdir - 删除空目录 链接到标题
函数介绍 链接到标题
rmdir
系统调用用于删除空目录。只能删除没有任何文件或子目录的目录,如果目录非空则操作失败。
函数原型 链接到标题
#include <unistd.h>
int rmdir(const char *pathname);
功能 链接到标题
删除指定路径名的空目录。
参数 链接到标题
const char *pathname
: 要删除的目录路径名
返回值 链接到标题
- 成功时返回0
- 失败时返回-1,并设置errno:
EBUSY
: 目录正在被使用EACCES
: 权限不足EINVAL
: 参数无效ELOOP
: 符号链接循环ENAMETOOLONG
: 路径名过长ENOENT
: 目录不存在ENOTDIR
: 路径不是目录ENOTEMPTY
: 目录非空EPERM
: 操作不被允许EROFS
: 文件系统只读
相似函数 链接到标题
unlink()
: 删除文件remove()
: 删除文件或空目录rmdirat()
: 相对路径版本
示例代码 链接到标题
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <limits.h>
#include <dirent.h>
int main() {
printf("=== Rmdir函数示例 ===\n");
// 示例1: 基本的空目录删除操作
printf("\n示例1: 基本的空目录删除操作\n");
// 创建测试目录
const char *test_dir = "test_rmdir_empty";
if (mkdir(test_dir, 0755) == -1) {
if (errno == EEXIST) {
printf("测试目录已存在\n");
} else {
perror("创建测试目录失败");
exit(EXIT_FAILURE);
}
} else {
printf("创建测试目录: %s\n", test_dir);
}
// 验证目录存在
if (access(test_dir, F_OK) == 0) {
printf("目录存在验证成功\n");
}
// 删除空目录
if (rmdir(test_dir) == -1) {
perror("删除空目录失败");
} else {
printf("成功删除空目录: %s\n", test_dir);
// 验证目录已删除
if (access(test_dir, F_OK) != 0) {
printf("目录删除验证成功\n");
}
}
// 示例2: 非空目录删除(应该失败)
printf("\n示例2: 非空目录删除(应该失败)\n");
// 创建带文件的目录
const char *non_empty_dir = "test_rmdir_nonempty";
if (mkdir(non_empty_dir, 0755) == -1 && errno != EEXIST) {
perror("创建非空测试目录失败");
} else {
printf("创建非空测试目录: %s\n", non_empty_dir);
// 在目录中创建文件
char file_path[PATH_MAX];
snprintf(file_path, sizeof(file_path), "%s/test_file.txt", non_empty_dir);
int fd = open(file_path, O_CREAT | O_WRONLY, 0644);
if (fd != -1) {
const char *content = "Test content for non-empty directory";
write(fd, content, strlen(content));
close(fd);
printf("在目录中创建文件: test_file.txt\n");
}
// 尝试删除非空目录
if (rmdir(non_empty_dir) == -1) {
if (errno == ENOTEMPTY) {
printf("删除非空目录失败(预期): %s\n", strerror(errno));
} else {
printf("删除非空目录失败(其他错误): %s\n", strerror(errno));
}
} else {
printf("意外成功删除非空目录\n");
}
// 清理:先删除文件,再删除目录
unlink(file_path);
if (rmdir(non_empty_dir) == -1) {
perror("清理非空目录失败");
} else {
printf("成功清理非空目录\n");
}
}
// 示例3: 多级目录删除
printf("\n示例3: 多级目录删除\n");
// 创建多级目录结构
const char *level1 = "rmdir_level1";
const char *level2 = "rmdir_level1/level2";
const char *level3 = "rmdir_level1/level2/level3";
if (mkdir(level1, 0755) == -1 && errno != EEXIST) {
perror("创建level1失败");
} else {
printf("创建目录: %s\n", level1);
if (mkdir(level2, 0755) == -1 && errno != EEXIST) {
perror("创建level2失败");
} else {
printf("创建目录: %s\n", level2);
if (mkdir(level3, 0755) == -1 && errno != EEXIST) {
perror("创建level3失败");
} else {
printf("创建目录: %s\n", level3);
}
}
}
// 删除目录(必须从最深层开始)
printf("删除多级目录(从最深层开始):\n");
if (rmdir(level3) == -1) {
perror("删除level3失败");
} else {
printf("成功删除: %s\n", level3);
}
if (rmdir(level2) == -1) {
perror("删除level2失败");
} else {
printf("成功删除: %s\n", level2);
}
if (rmdir(level1) == -1) {
perror("删除level1失败");
} else {
printf("成功删除: %s\n", level1);
}
// 示例4: 特殊目录删除
printf("\n示例4: 特殊目录删除\n");
// 尝试删除当前目录(应该失败)
if (rmdir(".") == -1) {
printf("删除当前目录.: %s\n", strerror(errno));
}
// 尝试删除上级目录(应该失败)
if (rmdir("..") == -1) {
printf("删除上级目录..: %s\n", strerror(errno));
}
// 示例5: 错误处理演示
printf("\n示例5: 错误处理演示\n");
// 尝试删除不存在的目录
if (rmdir("nonexistent_directory") == -1) {
if (errno == ENOENT) {
printf("删除不存在的目录: %s\n", strerror(errno));
}
}
// 尝试删除文件而非目录
const char *regular_file = "regular_file_for_rmdir_test.txt";
int fd = open(regular_file, O_CREAT | O_WRONLY, 0644);
if (fd != -1) {
write(fd, "test", 4);
close(fd);
if (rmdir(regular_file) == -1) {
if (errno == ENOTDIR) {
printf("删除文件而非目录: %s\n", strerror(errno));
}
}
unlink(regular_file);
}
// 尝试删除只读文件系统上的目录
if (rmdir("/proc") == -1) {
if (errno == EROFS || errno == EACCES || errno == EBUSY) {
printf("删除系统目录/proc: %s\n", strerror(errno));
}
}
// 尝试使用过长的路径名
char long_path[PATH_MAX + 100];
memset(long_path, 'a', sizeof(long_path) - 1);
long_path[sizeof(long_path) - 1] = '\0';
if (rmdir(long_path) == -1) {
if (errno == ENAMETOOLONG) {
printf("使用过长路径名: %s\n", strerror(errno));
}
}
// 示例6: 实际应用场景
printf("\n示例6: 实际应用场景\n");
// 场景1: 临时目录清理
printf("场景1: 临时目录清理\n");
char temp_dir_template[] = "/tmp/rmdir_test_XXXXXX";
char *temp_dir = mkdtemp(temp_dir_template);
if (temp_dir != NULL) {
printf("创建临时目录: %s\n", temp_dir);
// 在临时目录中创建工作
char work_file[PATH_MAX];
snprintf(work_file, sizeof(work_file), "%s/work_file.txt", temp_dir);
fd = open(work_file, O_CREAT | O_WRONLY, 0644);
if (fd != -1) {
const char *work_content = "Temporary work file content";
write(fd, work_content, strlen(work_content));
close(fd);
printf("创建临时工作文件\n");
}
// 工作完成后清理
unlink(work_file); // 先删除文件
if (rmdir(temp_dir) == -1) {
perror("清理临时目录失败");
} else {
printf("成功清理临时目录\n");
}
}
// 场景2: 应用程序缓存清理
printf("场景2: 应用程序缓存清理\n");
const char *cache_base = ".app_cache";
// 创建缓存目录结构
if (mkdir(cache_base, 0755) == -1 && errno != EEXIST) {
perror("创建缓存基础目录失败");
} else {
printf("创建缓存基础目录: %s\n", cache_base);
// 创建多个缓存子目录
const char *cache_dirs[] = {"session", "temp", "downloads"};
for (int i = 0; i < 3; i++) {
char cache_subdir[100];
snprintf(cache_subdir, sizeof(cache_subdir), "%s/%s", cache_base, cache_dirs[i]);
if (mkdir(cache_subdir, 0755) == -1 && errno != EEXIST) {
printf("创建缓存子目录 %s 失败: %s\n", cache_subdir, strerror(errno));
} else {
printf("创建缓存子目录: %s\n", cache_subdir);
}
}
// 模拟清理过程
printf("清理缓存目录:\n");
for (int i = 2; i >= 0; i--) {
char cache_subdir[100];
snprintf(cache_subdir, sizeof(cache_subdir), "%s/%s", cache_base, cache_dirs[i]);
if (rmdir(cache_subdir) == -1) {
printf("删除缓存子目录 %s 失败: %s\n", cache_subdir, strerror(errno));
} else {
printf("成功删除缓存子目录: %s\n", cache_subdir);
}
}
// 删除基础缓存目录
if (rmdir(cache_base) == -1) {
perror("删除基础缓存目录失败");
} else {
printf("成功删除基础缓存目录\n");
}
}
// 场景3: 日志轮转清理
printf("场景3: 日志轮转清理\n");
const char *log_dir = "old_logs";
if (mkdir(log_dir, 0755) == -1 && errno != EEXIST) {
perror("创建日志目录失败");
} else {
printf("创建日志目录: %s\n", log_dir);
// 创建一些旧日志文件(简化为在目录中创建标记)
char log_marker[100];
snprintf(log_marker, sizeof(log_marker), "%s/.old", log_dir);
fd = open(log_marker, O_CREAT | O_WRONLY, 0644);
if (fd != -1) {
close(fd);
printf("创建日志标记文件\n");
}
// 当需要清理时
printf("清理旧日志目录:\n");
unlink(log_marker); // 先删除文件
if (rmdir(log_dir) == -1) {
printf("删除日志目录失败: %s\n", strerror(errno));
} else {
printf("成功删除日志目录\n");
}
}
// 示例7: 递归删除辅助函数
printf("\n示例7: 递归删除辅助函数\n");
// 创建用于测试的复杂目录结构
const char *complex_dir = "complex_rmdir_test";
if (mkdir(complex_dir, 0755) == -1 && errno != EEXIST) {
perror("创建复杂测试目录失败");
} else {
printf("创建复杂测试目录: %s\n", complex_dir);
// 创建子目录和文件
mkdir("complex_rmdir_test/sub1", 0755);
mkdir("complex_rmdir_test/sub2", 0755);
mkdir("complex_rmdir_test/sub1/subsub1", 0755);
// 创建文件
int test_fd = open("complex_rmdir_test/file1.txt", O_CREAT | O_WRONLY, 0644);
if (test_fd != -1) close(test_fd);
test_fd = open("complex_rmdir_test/sub1/file2.txt", O_CREAT | O_WRONLY, 0644);
if (test_fd != -1) close(test_fd);
test_fd = open("complex_rmdir_test/sub1/subsub1/file3.txt", O_CREAT | O_WRONLY, 0644);
if (test_fd != -1) close(test_fd);
printf("创建了复杂的目录结构用于演示\n");
printf("注意: rmdir只能删除空目录,递归删除需要编程实现\n");
}
// 示例8: 权限相关错误
printf("\n示例8: 权限相关错误\n");
// 创建测试目录
const char *permission_test_dir = "permission_test_dir";
if (mkdir(permission_test_dir, 0755) == -1 && errno != EEXIST) {
perror("创建权限测试目录失败");
} else {
printf("创建权限测试目录: %s\n", permission_test_dir);
// 尝试在没有权限的情况下删除(需要特殊设置)
printf("权限相关错误通常包括:\n");
printf(" EACCES: 权限不足\n");
printf(" EPERM: 操作不被允许\n");
printf(" EBUSY: 目录正在被使用\n");
// 清理
if (rmdir(permission_test_dir) == -1) {
perror("删除权限测试目录失败");
} else {
printf("成功删除权限测试目录\n");
}
}
// 示例9: 性能考虑
printf("\n示例9: 性能考虑\n");
// 创建大量空目录进行删除测试
const int dir_count = 100;
char perf_test_base[] = "rmdir_perf_test_XXXXXX";
char *perf_dir = mkdtemp(perf_test_base);
if (perf_dir != NULL) {
printf("在 %s 中进行性能测试\n", perf_dir);
// 创建测试目录
for (int i = 0; i < dir_count; i++) {
char test_dir[PATH_MAX];
snprintf(test_dir, sizeof(test_dir), "%s/test_dir_%d", perf_dir, i);
mkdir(test_dir, 0755);
}
printf("创建了 %d 个测试目录\n", dir_count);
// 删除目录并计时
clock_t start = clock();
for (int i = 0; i < dir_count; i++) {
char test_dir[PATH_MAX];
snprintf(test_dir, sizeof(test_dir), "%s/test_dir_%d", perf_dir, i);
if (rmdir(test_dir) == -1) {
printf("删除目录 %s 失败: %s\n", test_dir, strerror(errno));
}
}
clock_t delete_time = clock() - start;
printf("删除 %d 个空目录耗时: %f 秒\n",
dir_count, ((double)delete_time) / CLOCKS_PER_SEC);
printf("平均每次删除耗时: %f 毫秒\n",
(((double)delete_time) / CLOCKS_PER_SEC * 1000) / dir_count);
// 清理基准目录
rmdir(perf_dir);
}
// 示例10: 与符号链接的交互
printf("\n示例10: 与符号链接的交互\n");
// 创建测试目录
if (mkdir("symlink_rmdir_test", 0755) == -1 && errno != EEXIST) {
perror("创建符号链接测试目录失败");
} else {
printf("创建符号链接测试目录\n");
// 创建指向目录的符号链接
if (symlink("symlink_rmdir_test", "symlink_to_rmdir_test") == -1 && errno != EEXIST) {
perror("创建符号链接失败");
} else {
printf("创建符号链接: symlink_to_rmdir_test -> symlink_rmdir_test\n");
// 尝试删除符号链接(会删除符号链接本身,而不是目标目录)
if (rmdir("symlink_to_rmdir_test") == -1) {
printf("删除符号链接失败: %s\n", strerror(errno));
} else {
printf("成功删除符号链接(不是目标目录)\n");
}
}
// 清理原目录
if (rmdir("symlink_rmdir_test") == -1) {
perror("删除原目录失败");
} else {
printf("成功删除原目录\n");
}
}
return 0;
}