diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..638b9b9 --- /dev/null +++ b/.clang-format @@ -0,0 +1,39 @@ +AccessModifierOffset: -4 +AlignAfterOpenBracket: DontAlign +AllowShortBlocksOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +BasedOnStyle: LLVM +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterStruct: false + AfterUnion: false + BeforeCatch: true + BeforeElse: true + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true +BreakBeforeBraces: Custom +ColumnLimit: 0 +Cpp11BracedListStyle: false +FixNamespaceComments: false +IndentCaseLabels: false +IndentPPDirectives: None +IndentWidth: 4 +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: All +PointerAlignment: Right +SortIncludes: false +SortUsingDeclarations: false +SpaceAfterCStyleCast: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +TabWidth: 4 +UseTab: true diff --git a/2/pack_v1.c b/2/pack_v1.c new file mode 100644 index 0000000..1d036d0 --- /dev/null +++ b/2/pack_v1.c @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include +#include +#include + +int main() { + DIR *dir; + struct dirent *entry; + int pack_fd, file_fd; + char buffer[4096]; + ssize_t bytes_read; + + // 打开当前目录 + dir = opendir("."); + if (dir == NULL) { + perror("无法打开当前目录"); + return 1; + } + + // 创建打包文件 + pack_fd = open("a.pack", O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (pack_fd == -1) { + perror("无法创建打包文件"); + closedir(dir); + return 1; + } + + // 遍历目录中的所有文件 + while ((entry = readdir(dir)) != NULL) { + // 忽略目录项和a.pack文件本身 + if (entry->d_type == DT_DIR || strcmp(entry->d_name, "a.pack") == 0) { + continue; + } + + printf("正在打包: %s\n", entry->d_name); + + // 写入文件名长度 + int name_len = strlen(entry->d_name); + write(pack_fd, &name_len, sizeof(int)); + + // 写入文件名 + write(pack_fd, entry->d_name, name_len); + + // 打开源文件 + file_fd = open(entry->d_name, O_RDONLY); + if (file_fd == -1) { + perror("无法打开源文件"); + continue; + } + + // 获取文件大小 + struct stat st; + fstat(file_fd, &st); + int file_size = st.st_size; + + // 写入文件大小 + write(pack_fd, &file_size, sizeof(int)); + + // 写入文件数据 + while ((bytes_read = read(file_fd, buffer, sizeof(buffer))) > 0) { + write(pack_fd, buffer, bytes_read); + } + + close(file_fd); + } + + close(pack_fd); + closedir(dir); + + printf("打包完成,所有文件已打包到 a.pack\n"); + return 0; +} diff --git a/2/pack_v2.c b/2/pack_v2.c new file mode 100644 index 0000000..88abfdb --- /dev/null +++ b/2/pack_v2.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) { + DIR *dir; + struct dirent *entry; + int pack_fd, file_fd; + char buffer[4096]; + ssize_t bytes_read; + char filepath[PATH_MAX]; + + // 检查命令行参数 + if (argc != 2) { + fprintf(stderr, "用法: %s <目录名>\n", argv[0]); + return 1; + } + + // 打开指定目录 + dir = opendir(argv[1]); + if (dir == NULL) { + perror("无法打开指定目录"); + return 1; + } + + // 创建打包文件 + pack_fd = open("a.pack", O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (pack_fd == -1) { + perror("无法创建打包文件"); + closedir(dir); + return 1; + } + + // 遍历目录中的所有文件 + while ((entry = readdir(dir)) != NULL) { + struct stat st; + + // 跳过 . 和 .. 目录 + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { + continue; + } + + // 构建完整的文件路径 + snprintf(filepath, PATH_MAX, "%s/%s", argv[1], entry->d_name); + + // 获取文件状态 + if (stat(filepath, &st) == -1) { + perror("获取文件状态失败"); + continue; + } + + // 只处理普通文件 + if (!S_ISREG(st.st_mode)) { + continue; + } + + printf("正在打包: %s\n", entry->d_name); + + // 写入文件名长度 + int name_len = strlen(entry->d_name); + write(pack_fd, &name_len, sizeof(int)); + + // 写入文件名 + write(pack_fd, entry->d_name, name_len); + + // 打开源文件 + file_fd = open(filepath, O_RDONLY); + if (file_fd == -1) { + perror("无法打开源文件"); + continue; + } + + // 写入文件大小 + int file_size = st.st_size; + write(pack_fd, &file_size, sizeof(int)); + + // 写入文件数据 + while ((bytes_read = read(file_fd, buffer, sizeof(buffer))) > 0) { + write(pack_fd, buffer, bytes_read); + } + + close(file_fd); + } + + close(pack_fd); + closedir(dir); + + printf("打包完成,所有文件已打包到 a.pack\n"); + return 0; +} diff --git a/2/unpack_v1.c b/2/unpack_v1.c new file mode 100644 index 0000000..5470eca --- /dev/null +++ b/2/unpack_v1.c @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include + +int main() { + int pack_fd, file_fd; + char buffer[4096]; + ssize_t bytes_read; + + // 打开打包文件 + pack_fd = open("a.pack", O_RDONLY); + if (pack_fd == -1) { + perror("无法打开打包文件"); + return 1; + } + + // 读取并解包文件 + while (1) { + int name_len, file_size; + + // 读取文件名长度 + if (read(pack_fd, &name_len, sizeof(int)) <= 0) { + // 到达文件末尾或出错 + break; + } + + // 读取文件名 + char *filename = (char *)malloc(name_len + 1); + if (filename == NULL) { + perror("内存分配失败"); + close(pack_fd); + return 1; + } + + read(pack_fd, filename, name_len); + filename[name_len] = '\0'; // 添加字符串结束符 + + // 读取文件大小 + read(pack_fd, &file_size, sizeof(int)); + + printf("正在解包: %s (%d 字节)\n", filename, file_size); + + // 创建目标文件 + file_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (file_fd == -1) { + perror("无法创建目标文件"); + free(filename); + continue; + } + + // 拷贝文件数据 + int remaining = file_size; + while (remaining > 0) { + int to_read = (remaining < sizeof(buffer)) ? remaining : sizeof(buffer); + bytes_read = read(pack_fd, buffer, to_read); + if (bytes_read <= 0) { + perror("读取文件数据失败"); + break; + } + + write(file_fd, buffer, bytes_read); + remaining -= bytes_read; + } + + close(file_fd); + free(filename); + } + + close(pack_fd); + printf("解包完成\n"); + return 0; +} diff --git a/2/unpack_v2.c b/2/unpack_v2.c new file mode 100644 index 0000000..edc0c99 --- /dev/null +++ b/2/unpack_v2.c @@ -0,0 +1,152 @@ +#include +#include +#include +#include +#include +#include + +// 列出打包文件中的内容,不解包 +void list_pack_contents(const char *packfile) { + int pack_fd; + + pack_fd = open(packfile, O_RDONLY); + if (pack_fd == -1) { + perror("无法打开打包文件"); + exit(1); + } + + printf("%-30s %s\n", "文件名", "文件大小 (字节)"); + printf("%-30s %s\n", "------------------------------", "---------------"); + + while (1) { + int name_len, file_size; + + // 读取文件名长度 + if (read(pack_fd, &name_len, sizeof(int)) <= 0) { + break; // 到达文件末尾或出错 + } + + // 读取文件名 + char *filename = (char *)malloc(name_len + 1); + if (filename == NULL) { + perror("内存分配失败"); + close(pack_fd); + exit(1); + } + + read(pack_fd, filename, name_len); + filename[name_len] = '\0'; // 添加字符串结束符 + + // 读取文件大小 + read(pack_fd, &file_size, sizeof(int)); + + // 打印文件信息 + printf("%-30s %d\n", filename, file_size); + + // 跳过文件数据 + lseek(pack_fd, file_size, SEEK_CUR); + + free(filename); + } + + close(pack_fd); +} + +// 解包文件 +void extract_pack(const char *packfile) { + int pack_fd, file_fd; + char buffer[4096]; + ssize_t bytes_read; + + // 打开打包文件 + pack_fd = open(packfile, O_RDONLY); + if (pack_fd == -1) { + perror("无法打开打包文件"); + exit(1); + } + + // 读取并解包文件 + while (1) { + int name_len, file_size; + + // 读取文件名长度 + if (read(pack_fd, &name_len, sizeof(int)) <= 0) { + break; // 到达文件末尾或出错 + } + + // 读取文件名 + char *filename = (char *)malloc(name_len + 1); + if (filename == NULL) { + perror("内存分配失败"); + close(pack_fd); + exit(1); + } + + read(pack_fd, filename, name_len); + filename[name_len] = '\0'; // 添加字符串结束符 + + // 读取文件大小 + read(pack_fd, &file_size, sizeof(int)); + + printf("正在解包: %s (%d 字节)\n", filename, file_size); + + // 创建目标文件 + file_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (file_fd == -1) { + perror("无法创建目标文件"); + free(filename); + continue; + } + + // 拷贝文件数据 + int remaining = file_size; + while (remaining > 0) { + int to_read = (remaining < sizeof(buffer)) ? remaining : sizeof(buffer); + bytes_read = read(pack_fd, buffer, to_read); + if (bytes_read <= 0) { + perror("读取文件数据失败"); + break; + } + + write(file_fd, buffer, bytes_read); + remaining -= bytes_read; + } + + close(file_fd); + free(filename); + } + + close(pack_fd); + printf("解包完成\n"); +} + +int main(int argc, char *argv[]) { + bool list_only = false; + char *packfile = NULL; + + // 解析命令行参数 + if (argc == 2) { + // 普通解包模式 + packfile = argv[1]; + } + else if (argc == 3 && strcmp(argv[1], "-l") == 0) { + // 列表模式 + list_only = true; + packfile = argv[2]; + } + else { + fprintf(stderr, "用法:\n"); + fprintf(stderr, " %s <打包文件> - 解包文件\n", argv[0]); + fprintf(stderr, " %s -l <打包文件> - 列出打包文件内容\n", argv[0]); + return 1; + } + + if (list_only) { + list_pack_contents(packfile); + } + else { + extract_pack(packfile); + } + + return 0; +}