习题1:实现 部分tee,实现 -a 追加选项
#include <stdio.h> #include <readline/readline.h> #include <readline/history.h> #include "tlpi_hdr.h" #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #define MAX_READ 1024 int readLine(int fd, char *buf, int size) { int count = 0, nbytes; char *ptr; ptr = buf; while (count < size) { nbytes = read(fd, ptr, 1); if (nbytes == -1) errExit("read"); if (nbytes == 0) break; if (*ptr == '\n') break; ptr++; count++; } return count; } int main(int argc, char **argv) { int opt, flags, fd, nbytes; char buf[MAX_READ + 1], *file; if (argc > 3) { usageErr("%s [-a] <file>\n", argv[0]); } opt = getopt(argc, argv , "a:"); if (opt == ':' || opt == '?') usageErr("%s [-a] <file>\n", argv[0]); switch(opt) { case 'a': flags = O_APPEND | O_WRONLY | O_CREAT; file = optarg; break; default: flags = O_WRONLY | O_TRUNC | O_CREAT; file = argv[1]; break; } if (file == NULL) fd = STDOUT_FILENO; else fd = open(file, flags, 0644); while (1) { if (fd == -1) errExit("open"); nbytes = readLine(STDIN_FILENO, buf, MAX_READ); buf[nbytes] = '\0'; if (write(fd, buf, nbytes) == -1) errExit("write"); if (write(fd, "\n", 1) == -1) errExit("write"); } close(fd); exit(EXIT_SUCCESS); }
总结:练习了 getopt,并纠正一个错误认识——close后,数据才会写入文件,实际上write后,数据已经写入驱动的缓存中,即数据是否写入文件与close无关,close只是释放文件描述符资源,由于文件描述符为有限资源,所以需要及时释放。
习题2:实现cp 命令,能复制空洞文件
#include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include "tlpi_hdr.h" int main(int argc, char **argv) { int src_fd, des_fd, src_size, i, nbytes; struct stat src_st; char ch; if (argc != 3) usageErr("%s <source file> <des file>\n", argv[0]); src_fd = open(argv[1], O_RDONLY); if (src_fd == -1) errExit("open src"); des_fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644); if (des_fd == -1) errExit("open des"); if (stat(argv[1], &src_st) == -1) errExit("stat src"); src_size = src_st.st_size; for (i = 0; i < src_size; i++) { lseek(src_fd, i, SEEK_SET); lseek(des_fd, i, SEEK_SET); nbytes = read(src_fd, &ch, sizeof(ch)); if (nbytes == -1) errExit("read src"); if (nbytes == 0) continue; nbytes = write(des_fd, &ch, sizeof(ch)); if (nbytes == -1) errExit("write des"); } exit(EXIT_SUCCESS); }
总结:练习了下lseek的使用,直观感受是和写内存一样,另外文件偏移量是从0开始,和内存一样的设计。