C - Wrong read after lseek with define expression

135 views Asked by At

I have a binary file from which I need to read timestamps. In particular, I'm trying to read the last record. Every record is 24 bytes long, the timestamp is in the first 8 bytes. Here's the code I wrote:

#define IDX_RS_LEN (unsigned int)(sizeof(unsigned long) * 3)

int main(int argc, char** argv)
{
   int fd;
   unsigned long rGmte;
   char filename[256];
   int offset;

   fd = open(filename, O_RDONLY);
   if (fd != -1) {
      offset = lseek(fd, -IDX_RS_LEN, SEEK_END);
      read(fd, &rGmte, sizeof(unsigned long));
      printf("offset:%d\trGmte: %lu\n", offset, rGmte);
   } else {
      printf("Error opening file\n");
   }
   close(fd);

   return 0;
}

But this gives me the following output:

offset:117384 rGmte: 0

Which is wrong. If I replace the expression in the define with the fixed value 24 I get the right output:

offset:117384 rGmte: 1606314900

Please also note that offset is the same in both cases, but the value read is different. Any idea?

1

There are 1 answers

0
David Ranieri On BEST ANSWER

You are using a wrong type to set the position / offset in lseek, you should use an off_t(signed long) not an unsigned int.

Take a look to What happens when I assign a negative value to an unsigned int?

The offset set to lseek should be -24:

printf("Output: %ld\n", -(signed long)(sizeof(unsigned long) * 3));
Output: -24

but you are setting

printf("Output: %ld\n", -(unsigned int)(sizeof(unsigned long) * 3));
Output: 4294967272

Switch from

#define IDX_RS_LEN (unsigned int)(sizeof(unsigned long) * 3)

int main(int argc, char** argv)
{
   int fd;
   unsigned long rGmte;
   char filename[256];
   int offset;

   fd = open(filename, O_RDONLY);
   if (fd != -1) {
      offset = lseek(fd, -IDX_RS_LEN, SEEK_END);

to

#define IDX_RS_LEN (sizeof(unsigned long) * 3)

int main(int argc, char** argv)
{
   int fd;
   unsigned long rGmte;
   char filename[256];
   off_t offset = IDX_RS_LEN;

   fd = open(filename, O_RDONLY);
   if (fd != -1) {
      offset = lseek(fd, -offset, SEEK_END);

and it should work: https://godbolt.org/z/hEG4xx