DaemonForums  

Go Back   DaemonForums > Miscellaneous > Programming

Programming C, bash, Python, Perl, PHP, Java, you name it.

 
 
Thread Tools Display Modes
Prev Previous Post   Next Post Next
  #1   (View Single Post)  
Old 13th April 2009
IdOp's Avatar
IdOp IdOp is offline
Too dumb for a smartphone
 
Join Date: May 2008
Location: twisting on the daemon's fork(2)
Posts: 566
Thanked 14 Times in 13 Posts
Default fseek() and read() problem

I was working on an audio program on the weekend and had some weird results on BSD. Tracking it down, it seems to be related to fseek() and read(). It occurs on both

* NetBSD 4.0.1 -release i386

* OpenBSD 4.4 -release i386

What happens is this: An input file consists of a whole number of frames (frame=2352 bytes). I fseek() a whole number of frames into the file, and then try to read() the rest of the file frame-by-frame. I noticed the wrong number of frames get read, and the last read() doesn't read a whole frame (too few bytes are read). From the read(2) man page:

Quote:
The system guarantees to read the number of bytes requested if the descriptor references a normal file that has that many bytes left before the end-of-file, but in no other case.
After tracking down the problem a bit, here's a simple demo that reproduces it. First, make an input file:

$ dd if=/dev/zero of=infile bs=2352 count=9

You can vary the count to see what happens. Check the file size:

Code:
$ ls -l infile
-rw-r--r--  1 xxx  users  21168 Apr 13 10:17 infile
Then grab this file trd.c:

Code:
#include <stdio.h>
#include <unistd.h>

int
main( int argc, char* argv[] )
{
    ssize_t     nr;
    char        buf[2352];      /*  = 1 frame */
    int         ifd, j;
    FILE        *ifp;

    ifp = fopen( "infile", "rb" );
    ifd = fileno( ifp );

    printf( "where = %ld\n", ftell( ifp ) );

    if( fseek( ifp, 2352, SEEK_SET ) )    /* seek 1 frame in */
        return 1;

    printf( "where = %ld\n", ftell( ifp ) );

    for( j=1; (nr = read( ifd, (void*)buf, 2352 )) != -1; j++ ) {

        printf( "%d:  nr = %d\n", j, nr );
        if( nr==0 ) break;

    }
    fclose( ifp );
    return 0;
}
and compile it

$ gcc -Wall -o trd trd.c

and run it. E.g., with a count of 9:

Code:
$ trd
where = 0
where = 2352
1:  nr = 2352
2:  nr = 2352
3:  nr = 80
4:  nr = 0
So it's reading 2-and-a-partial frames, when it should read 8. I hope it's just me doing something dumb (as usual), but I can't see what it is. Any help or comments appreciated!
Reply With Quote
 

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
How do you read an IRIX cd using EFS ablecode NetBSD General 9 26th May 2010 07:54 PM
I've read the installation guide...but! wubrgamer FreeBSD General 5 20th September 2008 02:37 PM
when and by what is .profile read? kasse FreeBSD General 8 11th September 2008 08:46 AM
/etc/rc.* files isn't read properly? mathias OpenBSD General 4 1st June 2008 06:35 PM
Filesystem read errors Foon FreeBSD General 0 10th May 2008 07:27 AM


All times are GMT. The time now is 06:14 AM.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content copyright © 2007-2010, the authors
Daemon image copyright ©1988, Marshall Kirk McKusick