简体   繁体   中英

Why system call read() does not work when using user input

It`sa file copying program.

#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdlib.h>

int main()
{
    int fd1,fd2, ndata;
    char data[128];
    char *openname[1], *creatname[1]; 

    write(1, "Write open file name\n", 24); //user input

    read(0, openname, 30 );

    write(1, "Write creat file name\n", 25); //user input

    read(0, creatname,30);

    if((fd1 = open(openname, 0666))<0)
        {
            perror("cannot open the file");
            exit(1);
        }

    if((fd2 = creat(creatname,0666))<0)
        {
            perror("cannot create the file");
            exit(1);
        }

    while((ndata = read(fd1, data, 128))>0)
        {
            if((write(fd2, data, ndata))!=ndata)
                {
                    perror("cannot write the file");
                    exit(1); 
                } 
        }

    close(fd1);
    close(fd2); 

    write(1, "File copy is done.",19);

    return 0;

}

This code ain`t work. This code print the error message:

cannot open the file.

but if i change the code to this :

if((fd1 = open("copy.c", 0666))<0)

and this :

if((fd2 = creat("real.c",0666))<0) 

worked well.

Why this error happend? Please answer.

Your declarations of openname and creatname are incorrect. They should be:

char openname[31], creatname[31];

read() does not add a null terminator to the input, you need to add it. read() returns the number of bytes read. So it should be:

int nread = read(0, openname, sizeof openname -1);
openname[nread-1] = '\0'; // subtract 1 to overwrite the newline

The type of openname and creatname is wrong, and gcc -Wall -g would have warned you. Declare eg char openname[256];

And you should use fgets(openname, sizeof(openname), stdin); to read it.

If you insist on using read , take care of the newline (if any) and add a zero terminating byte.

Learn also to use the gdb debugger.

read is very low level. In this case, it reads 30 bytes, including your enter key and also without a terminating null-byte. So the filename won't be what you think you've entered, it will contain additional garbage (and could even make your program crash due to the missing null-termination). You want to use fgets or readline instead .

In a nutshell, by using read() to input the file names, you are making this unnecessarily hard for yourself: it does not terminate the input with NUL, is not guaranteed to read the number of characters you expect, etc.

My advice would be to stick with scanf() or fgets() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM