Berkeley CSUA MOTD:Entry 13830
Berkeley CSUA MOTD
 
WIKI | FAQ | Tech FAQ
http://csua.com/feed/
2025/05/25 [General] UID:1000 Activity:popular
5/25    

1998/3/18-20 [Computer/SW/OS/FreeBSD, Computer/SW/Languages, Computer/SW/Languages/Perl] UID:13830 Activity:moderate
3/18    Has anyone (else) encountered a bug where after using lseek with
        a negative offset read stops working on that fd, even though a
        valid off_t was returned?  In particular, I have a file with two
        binary unsigned longs at the end, and when I do an lseek(fd,
        -2*sizeof(unsigned long), SEEK_END); the reads then fail. -mel
        \_ Use PERL.
        \_ Did you try seeking to the beginning to the file, then a forward
           seek to where you want to read as a work-around?
           \_ The file is full of longs and I had wanted to read the two
              longs at the end of it.  The workaround I found was:

              end_offset = lseek(fd, 0, SEEK_END);
              lseek(fd, end_offset-2*sizeof(long), SEEK_SET);

              which is ugly but it works.  Throw in a few error checks
              on the return codes and it should work for you too. -mel
                \_ mel you ugly squint, get off the motd
        \_ And now, the right answer: You are specifying a seek relative to
           SEEK_END... Such a seek is implicitly in the negative direction,
           since it's impossible to seek past the end of the file.  The minus
           sign in front of the 2 is unnecessary.  So you should be doing:
           lseek(fd, 2*sizeof(unsigned long), SEEK_END);
           I tried looking for an example of this in K&R, but in each instance
           where SEEK_END is used, they demonstrate with an offset of 0, which
           is not too instructive.  WHY HAST THOU FORSAKEN ME, K&R? I TOOK
           THY WORD AS GOSPEL ONLY TO FIND A HALF-TRUTH LYING IN WAIT TO SNARE
           THE UNWARY! -mogul (hey, it's 3:15am, fuck off!)
           \_ Not quite.  A seek from SEEK_END is not implcitly negative;
              just like SEEK_CUR and SEEK_SET, positive offsets go forwards
              and negative offsets go backwards (see lseek(2)).  The problem
              with your code (and it's not really your fault) is that sizeof
              returns a size_t, which (on freebsd) is an unsigned int; when
              you multiply that by -2, you get another unsigned int (K&R 2.0,
              p. 198); and the unsigned int (0xfffffff8) then gets promoted
              to a signed long long (0x00000000fffffff8).

              This is not what you want.  The Right Way to fix it would be
              for freebsd to make size_t an unsigned long long, but that
              would break a lot of stuff and probably won't happen soon; in
              the meantime, you can cast the return value of sizeof to a
              signed int and your code will work.    --mconst