Subject: Re: lseek() continued! DOH!
To: None <tooleym@douglas.bc.ca>
From: Todd Vierling <tv@NetBSD.ORG>
List: netbsd-help
Date: 02/04/1998 09:34:17
On Wed, 4 Feb 1998 tooleym@douglas.bc.ca wrote:

: > It still sounds like you're treating the offset parameter and return
: > value of lseek() as 32-bit values... they're 64-bit values. When you
: > printf lseek's return value, you have to use a %qd, not %ld or %d. And
: > make sure you #include <unistd.h>

:     pos = 1L;
:     if ((datafile=open("player.records",O_RDWR))>=0) {
: 
:     status=lseek(datafile, (off_t)(-(sizeof(struct record))), SEEK_END);
:     printf("lseeked to %d\n", status);
:     while(pos != -1L) {
:         status=lseek(datafile, (off_t)(-(sizeof(struct record)*pos)), SEEK_END);
:         if (status < 0) break;
:         if ((status=read (datafile, &myrec, sizeof (struct record)))<0) {
:           pos = -1L;
:         } else {
:           printf("status: %d\n", status);
:           printf("name field:%s\n", myrec.name);
:           if (!strncmp(myrec.name,who,strlen(who))) {
:                 printf("found an entry with name: %s\n", myrec.name);
:                 printf("fiddling with entry..\n");
: 		strcpy(myrec.status, "clean");
:                status=lseek(datafile,(off_t)(-( (sizeof(struct record)) * pos),SEEK_END));
:                write (datafile, &myrec, sizeof (record));
:                pos = -1L;
:           } else { pos += 1L; printf("pos:%d\n", pos);}
:         }
:      }
:      close(f);

Let me give you a shot in the dark rewrite.

#include <unistd.h>

/* ... */

  off_t status;
  long pos;

  /* ... */

  pos = 1;
  if ((datafile=open("player.records",O_RDWR))>=0) {
      status=lseek(datafile, (off_t)(-(sizeof(struct record))), SEEK_END);
      printf("lseeked to %d\n", status);
      while(pos != -1) {
        status=lseek(datafile, -((off_t)(sizeof(struct record)*pos)), SEEK_END);
        if (status < 0) break;
        if ((status=read (datafile, &myrec, sizeof(struct record)))<0) {
          pos = -1;
        } else {
          printf("status: %d\n", status);
          printf("name field:%s\n", myrec.name);
          if (!strncmp(myrec.name,who,strlen(who))) {
               printf("found an entry with name: %s\n", myrec.name);
               printf("fiddling with entry..\n");
               strcpy(myrec.status, "clean");
               status=lseek(datafile,-((off_t)(sizeof(struct record) * pos)),SEEK_END));
               write (datafile, &myrec, sizeof(struct record));
                                            /* ^^^^^^^^^^^^^ */
               pos = -1;
          } else { pos += 1; printf("pos:%d\n", pos);}
        }
     }
     close(f);

You'll note four changes:

- status is an off_t (that's the return value of lseek(), though
  conceivably `long' would work if the rest of the code worked ;).
- the removal of `L' from constants assigned to pos (if `pos' is long,
  that's overkill, it's just a cleanup).
- a sizeof(record) is changed to a sizeof(struct record), at the `^^^^^'.
  Perhaps this was a typo, or you `typedef struct record record'?
- casting to off_t is done after all calculations EXCEPT NEGATING is done.
  (From memory:) When you evaluate a sizeof expression, its type is
  `unsigned int'.  Negating it keeps it an `unsigned int', even though you
  negated it properly in 32-bit math.  If you cast first, it becomes off_t
  (`signed long long'), which should work. 

The last change is what I think will fix this code as per the problem you
have.

=====
===== Todd Vierling (Personal tv@pobox.com) =====
== "There's a myth that there is a scarcity of justice to go around, so
== that if we extend justice to 'those people,' it will somehow erode the
== quality of justice everyone else receives."  -- Maria Price