Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Whats the difference between this lseek, fseek, read, fread?

Tags:

c

I am calling these functions:

unsigned blah[5];
lseek(0, 100, SEEK_CUR);
read(0, blah, sizeof(blah));

and

FILE *fr;
fr = fopen(arg[1], "r");
unsigned blah[5];
fseek(fr, 100, SEEK_CUR);
fread(blah, 1, sizeof(blah), fr);

And I run the first code my running this command:

cat TEXTFILE | ./a.out

I run the second code my running this command:

./a.out TEXTFILE

However, I am getting different results. While the first one seeked properly, so it reads the correct text, the second one is not. I want to use the second format, so what did I do wrong?

like image 670
SuperString Avatar asked Jan 17 '23 18:01

SuperString


1 Answers

With the addition of an open(filename,O_RDONLY); call to the first example, both worked fine for me. I suspect your problem is because of the call lseek(0, 100, SEEK_CUR);, which is asking for a seek on standard input. You cannot always seek on standard in - if you have:

 cat file | ./my_program 

Then standard input is a fifo, and you can't seek. If I do this on my system, seek fails by returning -1, with an error of "Illegal seek". This may be the problem you're having, and you might not notice since you don't check the return value of the seek call in your example.

Note that if you have:

 ./my_program < file

Then standard input is a file, and you may seek. On my system, seek returns 100, and the output is correct.


Here is a program you can use to illustrate the return values:

int main(void){ 

  int fd = 0;
  char blah[5];
  printf("Seek moved to this position: %d\n",lseek(fd, 100, SEEK_CUR));
  perror("Seek said");
  printf("Then read read %d bytes\n",read(fd, blah, sizeof(blah)));
  printf("The bytes read were '%c%c%c%c%c'\n",blah[0],blah[1],blah[2],blah[3],blah[4]); 
}                       

And here are two executions:

 $ ./a.out < text
 Seek moved to this position: 100
 Seek said: Success
 Then read read 5 bytes
 The bytes read were '+++.-'

(Those are the correct bytes from position 100 in that file)

$ cat text | ./a.out 
Seek moved to this position: -1
Seek said: Illegal seek
Then read read 5 bytes
The bytes read were '# def'

(Those bytes are the first 5 bytes of the file)


I also noticed that the standard input version was the one you said was working correctly. If you're having trouble with the FILE * version, I suspect the fopen() call is failing, so make sure you check the return value from fopen(). Of course, you can always do this:

FILE *fr = stdin;  

So that you're reading from standard in. However, as you can't always seek on standard in, I'd recommend always opening a file if you plan to seek.

Note that you can't seek on all devices that you can open files on (though you won't have a problem on most systems), so you should always check that the result of a seek() to make sure it succeeded.

like image 92
Timothy Jones Avatar answered Jan 31 '23 23:01

Timothy Jones