自己实现的tee命令

操作系统
Published

May 8, 2018

题目

 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)也会没有用。