cposixlow-levellow-level-io

C Low level I/O : Why does it hang in the while loop?


I'm studying low-level I/O in C for the first time and I'm trying to write a program that prints a file backwards, but it seems that this while loop doesn't work. Why does it happen?

#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define BUFFSIZE 4096

int main(){
    int n;
    int buf[BUFFSIZE];
    off_t currpos;

    int fd;
    if((fd = open("fileprova", O_RDWR)) < 0)
        perror("open error");

    if(lseek(fd, -1, SEEK_END) == -1)
        perror("seek error");

    while((n = read(fd, buf, 1)) > 0){
        if(write(STDOUT_FILENO, buf, n) != n)
            perror("write error");

        if(lseek(fd, -1, SEEK_CUR) == -1)
            perror("seek error");

        currpos = lseek(fd, 0, SEEK_CUR);
        printf("Current pos: %ld\n", currpos);
    }

    if(n < 0)
        perror("read error");

    return 0;

}

Solution

  • The call read(fd, buf, 1), if successful, will read one byte of data and then move the file pointer forward by one byte! The call lseek(fd, -1, SEEK_CUR) will then move the file pointer backward by one byte!

    Net result: your while loop will continue to read the same byte forever!

    Solution: Inside your while loop use the following to set the file pointer to read the previous byte: lseek(fd, -2, SEEK_CUR) - and break out of the loop when that call returns -1.