题目

 tee命令是从标准输入中读取数据,直至文件结尾,随后将数据写入标准输出和命令行参数所指定的文件。请使用I/O系统调用实现tee命令。并实现-a选项。

代码


#include <ctype.h>
#include "tlpi_hdr.h"
#include <stdbool.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
char ch;
bool append = FALSE;
char buf[1024] = {0};
char end = EOF;
int outfilefd, ret;
ssize_t len;
/* 读取选项 */
while ((ch = getopt(argc, argv, "a")) != -1)
{
switch (ch)
{
case 'a':
// printf("option append\n");
append = TRUE; //在文件后面追加数据
break;
default:
usageErr(" [-a] filename\n");
break;
}
}
if (append && argc == 3) //追加模式且有操作文件
{
/* !!!!!使用了O_APPEND和O_TRUNC时,默认还是从头开始,并且使用lseek也没有用处 */
outfilefd = open(argv[2], O_RDWR | O_CREAT | O_APPEND , S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); //读写输出文件
if (outfilefd == -1)
errExit("open faild\n");
while (1)
{
len = read(STDIN_FILENO, buf, 1024);
if (len != -1)
{
if (len == 0)
{
close(outfilefd);
exit(EXIT_SUCCESS);
}
write(STDOUT_FILENO, buf,len);
write(outfilefd, buf, len);

memset(buf, 0, 1024);
}
}
}
if (append && argc == 2) //追加模式但无操作文件
{
while (1)
{
len = read(STDIN_FILENO, buf, 1024);
if (len != -1)
{
if (len == 0)
{
exit(EXIT_SUCCESS);
}
write(STDOUT_FILENO, buf, len);
memset(buf, 0, 1024);
}
}
}
if (!append && argc == 2) //非追加模式且有操作文件
{
outfilefd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); //读写输出文件
if (outfilefd == -1)
errExit("open file\n");
while (1)
{
len = read(STDIN_FILENO, buf, 1024);
if (len != -1)
{
if (len == 0)
{
close(outfilefd);
exit(EXIT_SUCCESS);
}
write(STDOUT_FILENO, buf, len);
write(outfilefd, buf, len);
memset(buf, 0, 1024);
}
}
}
if (!append && argc == 1) //非追加模式 无操作文件
{
while (1)
{
len = read(STDIN_FILENO, buf, 1024);
if (len != -1)
{
if (len == 0)
{
exit(EXIT_SUCCESS);
}
write(STDOUT_FILENO, buf, len);
memset(buf, 0, 1024);
}
}
}
exit(EXIT_SUCCESS);
}

总结


  • 打开文件的句柄不能弄错。  我之前的出错代码如下:

    ret = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); //读写输出文件
    if (ret == -1)
    errExit("open file\n");
    .
    .
    .
    .
    .
    write(outfilefd, buf, len);

    习惯性的用ret来表示返回值,但是这里的返回值是文件句柄。

  • O_APPEND和O_TRUNC不能一起使用  至少在当你想在追加的时候不能使用,当使用这截断打开,此时不仅追加没用用,lseek(fd,0,SEEK_END)也会没有用。