/********************************************************************************* * Copyright: (C) 2025 LingYun IoT System Studio * All rights reserved. * * Filename: mycp.c * Description: This file a simple file copy command implement * * Version: 1.0.0(10/15/2025) * Author: Guo Wenxue * ChangeLog: 1, Release initial version on "10/15/2025 11:19:27 AM" * ********************************************************************************/ #include #include #include #include #include #include #include int main(int argc, char *argv[]) { struct stat src_stat; int src_fd = -1; int dst_fd = -1; char buf[512]; ssize_t bytes_read; ssize_t to_read; off_t remaining; int rv = 0; /* 检查输入参数合法性, 此程序需要两个参数: 源文件和目标文件 */ if (argc != 3) { fprintf(stderr, "Usage: %s \n", argv[0]); return 1; } /* 获取源文件的属性信息 */ if (lstat(argv[1], &src_stat) == -1) { fprintf(stderr, "lstat file %s failure: %s\n", argv[1], strerror(errno)); return 2; } /* 此程序只支持普通文件拷贝,不支持文件夹或其它文件 */ if (!S_ISREG(src_stat.st_mode)) { fprintf(stderr, "Error: %s is not a regular file\n", argv[1]); return 2; } /* 打以只读模式打开要拷贝的源文件 */ src_fd = open(argv[1], O_RDONLY); if (src_fd == -1) { fprintf(stderr, "open file %s failure: %s\n", argv[1], strerror(errno)); rv = 3; goto cleanup; } /* 创建要拷贝的目标文件,如果不存在就创建,权限位与源文件一致。如果文件已经存在则截取 */ dst_fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, src_stat.st_mode & 0777); if (dst_fd == -1) { fprintf(stderr, "open file %s failure: %s\n", argv[2], strerror(errno)); rv = 3; goto cleanup; } /* 获取源文件的实际内容大小,并将其所有内容拷贝到目标文件中去 */ remaining = src_stat.st_size; while (remaining > 0) { to_read = remaining > sizeof(buf) ? sizeof(buf) : remaining; bytes_read = read(src_fd, buf, to_read); if (bytes_read == -1) { fprintf(stderr, "read file %s failure: %s\n", argv[1], strerror(errno)); rv = 3; goto cleanup; } if (bytes_read == 0) { fprintf(stderr, "Unexpected end of file\n"); rv = 3; goto cleanup; } if (write(dst_fd, buf, bytes_read) != bytes_read) { fprintf(stderr, "write file %s failure: %s\n", argv[2], strerror(errno)); rv = 3; goto cleanup; } remaining -= bytes_read; } /* 完成后关闭所有打开的文件描述符,如果出错也会goto到这里集中处理 */ cleanup: if(src_fd >= 0) close(src_fd); if(dst_fd >= 0) close(src_fd); /* rv在定义时默认初始化为0表示成功,如果代码中有错误发生则会改变rv值,标识相应的错误原因 */ return rv; }