2

I tried to use the system call lseek() to get back the beginning of a file or reach the end of the file.

The exact code I used is:

int location = lseek(fd, 0, SEEK_SET) //get back to the beginning
int location = lseek(fd, 0, SEEK_END) //reach to the end

However, after the file location has been reset, whenever I tried to use read(), the return value of read() is always set to -1, which means something was wrong. Furthermore, the errno message I got was Bad file descriptor. Does anyone know what should I do?

PS: I tried to close and reopen the file to help me get back to the beginning of the file and it worked. But I have no ideas on how should I get to the end of the file and read the entire file in the reverse order without using lseek().

Plus: a reproducible example would be:

#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>

int main(void)
{
    int fd;
    char buffer[1000];

    fd = creat("newFile", 0777);

    memset(buffer, 'a', 500);
    write(fd, buffer, 500); // fill up

    int location = lseek(fd, 0, SEEK_SET); //get back to the beginning

    int read_bytes = read(fd, buffer, 500);
    // this should return the bytes it reads but it actually returns -1
    printf("%d\n", read_bytes);
    return 0;
}
S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
Fred
  • 111
  • 1
  • 6

2 Answers2

5

The creat function does not allow you to read from the file. It only allows you to write to it.

From creat(2):

creat()
A call to creat() is equivalent to calling open() with flags equal to O_CREAT|O_WRONLY|O_TRUNC.

The important part here is O_WRONLY. That means "write only".

If you want to open the file (and create it) for reading and writing, then you can use open like so:

int fd = open("newFile", O_CREAT|O_RDWR|O_TRUNC, 0777);

The important part here is O_RDWR. That means "read and write".
If you want to have open give an error if the file already exists, add the O_EXCL flag; this causes -1 to be returned and errno to be set to EEXIST if the file already exists when you try to create it.

S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
  • 1
    So after I created a file and wrote something into it, I should use open() before I can use read()? But I thought the second parameter, which I specified to be 0777, already gives me the right to read, write and execute. – Fred Sep 02 '19 at 22:55
  • 1
    @Fred You can open it for reading and writing in the first place by using `open()` and the correct flags – Ctx Sep 02 '19 at 22:55
  • 1
    @Fred Those are just the permissions on the file. You still have to `open` the file with the adequate permissions. – S.S. Anne Sep 02 '19 at 22:59
0

The following proposed code:

  1. cleanly compiles
  2. properly declares the variable types
  3. properly creates the file
  4. properly includes the needed header files
  5. properly checks for error indications from C library functions (and properly handles any error)

And now, the proposed code:

#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <string.h>
#include <unistd.h>

int main(void)
{
    int fd;
    char buffer[1000];

    // fd = creat("newFile", 0777);
    fd = open("newFile", O_CREAT|O_RDWR|O_TRUNC, 0777);
    if( fd < 0 )
    {
        perror( "open failed" );
        exit( EXIT_FAILURE );
    }

    memset(buffer, 'a', 500);
    write(fd, buffer, 500); // fill up

    off_t location = lseek(fd, 0, SEEK_SET); //get back to the beginning

    printf( "%ld\n", location );

    ssize_t read_bytes = read(fd, buffer, 500);

    if( read_bytes < 0 )
    {
        perror( "read failed" );
        exit( EXIT_FAILURE );
    }


    // this should return the bytes it reads but it actually returns -1
    printf("%ld\n", read_bytes);

    return 0;
}

A run of the program results in:

0
500

Suggest reading/understanding the MAN pages for any C library functions your code uses

S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
user3629249
  • 16,402
  • 1
  • 16
  • 17