Unix Programming - lseek + read = ENOENT

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > January 2006 > lseek + read = ENOENT





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author lseek + read = ENOENT
Sam Steingold

2006-01-19, 6:24 pm

I cannot read the last 4-byte word in a file using lseek + read:

/* file "foo" exists and is large enough - say, 4 MB */
int fd = open("foo",O_RDONLY|O_BINARY);
uint32 data;
/* this succeeds and correctly return the size of "foo" minus 4 */
lseek(fd,-sizeof(data),SEEK_END);
/* this returns 0 -- instead of expected 4 -- and sets errno to ENOENT */
read(fd,&data,sizeof(data));

if I run this under gdb and type
lseek(fd,-sizeof(data),SEEK_END);
read(fd,&data,sizeof(data));
several times, eventually read() starts to return 4 and set data to the
value I actually wrote into "foo" last.

I observe this on linux, cygwin and solaris -- what am I doing wrong?

--
Sam Steingold (http://www.podval.org/~sds) running w2k
http://www.camera.org http://www.openvotingconsortium.org http://pmw.org.il
http://ffii.org http://www.jihadwatch.org http://www.memri.org
Vegetarians eat Vegetables, Humanitarians are scary.
Casper H.S. Dik

2006-01-19, 6:24 pm

Sam Steingold <sds@gnu.org> writes:

>I cannot read the last 4-byte word in a file using lseek + read:


>/* file "foo" exists and is large enough - say, 4 MB */
> int fd = open("foo",O_RDONLY|O_BINARY);
> uint32 data;
>/* this succeeds and correctly return the size of "foo" minus 4 */
> lseek(fd,-sizeof(data),SEEK_END);
>/* this returns 0 -- instead of expected 4 -- and sets errno to ENOENT */
> read(fd,&data,sizeof(data));


>if I run this under gdb and type
> lseek(fd,-sizeof(data),SEEK_END);
> read(fd,&data,sizeof(data));
>several times, eventually read() starts to return 4 and set data to the
>value I actually wrote into "foo" last.


>I observe this on linux, cygwin and solaris -- what am I doing wrong?



Run the code under strace/truss and you may be enlightened.

BTW, checking errno when read returns 0 is *wrong*; it gives no
useful information.

Possible clues:

sizeof(data) is unsigned
-sizeof(data) is ?
what's the 2nd argument to lseek in your compilation
environment? (what size is off_t?)
what's the size of size_t?

Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
Pascal Bourguignon

2006-01-19, 6:24 pm

Sam Steingold <sds@gnu.org> writes:

> I cannot read the last 4-byte word in a file using lseek + read:
>
> /* file "foo" exists and is large enough - say, 4 MB */
> int fd = open("foo",O_RDONLY|O_BINARY);
> uint32 data;
> /* this succeeds and correctly return the size of "foo" minus 4 */
> lseek(fd,-sizeof(data),SEEK_END);
> /* this returns 0 -- instead of expected 4 -- and sets errno to ENOENT */
> read(fd,&data,sizeof(data));
>
> if I run this under gdb and type
> lseek(fd,-sizeof(data),SEEK_END);
> read(fd,&data,sizeof(data));
> several times, eventually read() starts to return 4 and set data to the
> value I actually wrote into "foo" last.
>
> I observe this on linux, cygwin and solaris -- what am I doing wrong?


Since you don't say us what uint32 is, or O_BINARY (which is not in
SUSv3 AFAIK), it's hard to say. But the following works perfectly on
Linux 2.6 on ix86:


-*- mode: compilation; default-directory: "/tmp/" -*-
cat last-long.c;make -k last-long CFLAGS=-g ; ls -l /tmp/asfgXDwZ9 ; od -x /tmp/asfgXDwZ9 | tail -3 ; ./last-long /tmp/asfgXDwZ9
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

typedef unsigned long uint32;
const int O_BINARY=0;

int main(int argc,char** argv){
/* file "foo" exists and is large enough - say, 4 MB */
int fd = open(argv[1],O_RDONLY|O_BINARY);
uint32 data;
/* this succeeds and correctly return the size of "foo" minus 4 */
printf("lseek(%d,%d,%d)=%d\n",fd,-sizeof(data),SEEK_END,
lseek(fd,-sizeof(data),SEEK_END));
/* this returns 0 -- instead of expected 4 -- and sets errno to ENOENT */
printf("read(%d,&data,%d)=%d\n",fd,sizeof(data),read(fd,&data,sizeof(data)));
printf("data=%lu\n",data);
return(0);
}


make: `last-long' is up to date.
-rw------- 1 pjb pjb 45473136 2006-01-18 20:54 /tmp/asfgXDwZ9
255356520 f72e 0be6 a903 e425 59c0 00a7 02c0 442c
255356540 09c0 c902 b483 d6d1 2559 925d 0069 0000
255356560
lseek(3,-4,2)=45473132
read(3,&data,4)=4
data=105

Compilation finished at Thu Jan 19 22:36:48

--
__Pascal Bourguignon__ http://www.informatimago.com/

What is this talk of 'release'? Klingons do not make software 'releases'.
Our software 'escapes' leaving a bloody trail of designers and quality
assurance people in it's wake.
Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com