习题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开始,和内存一样的设计。