tags:

views:

369

answers:

5

lseek() is supposed to return the position of the file descriptor.

The documentation says:

Upon successful completion, lseek() returns the resulting offset location as measured in bytes from the beginning of the file. Otherwise, a value of -1 is returned and errno is set to indicate the error.

Trouble is, not even this works:

#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
printf("size off_t: %i\n", sizeof(off_t));

off_t pos;
pos = lseek(file, (off_t)0, SEEK_CUR);
printf("pos: %lli\n", pos);

// same result for SEEK_SET and SEEK_END
pos = lseek(file, (off_t)2352, SEEK_CUR);
printf("pos: %lli\n", pos);

This gives me:

size off_t: 8
pos: 0
pos: 0

Why is this? Is there an alternative to find the current offset, using the raw I/O functions? (read, open, lseek, …)

Edit 1:

I tried to make the example simpler.

A: 

You might want to change the test to:

if ( (pos = lseek(file, (off_t)i, SEEK_CUR)) != -1 ) {

You are probably hitting a -1 somewhere, but you're testing for 0 here.

Mike
He is printing pos unless pos is 0. Thus, he would be informed if pos == -1 (and would hopefully tell us). I don't think that is the issue though.
strager
thx for the edit strager :) been using VB.NET too much lately
Mike
A: 

I'm not sure I understand your question, but here are a few thoughts which might help.

  • Offset 0 is valid; it means you are at the beginning of the file
  • Depending on your platform, off_t may well be limited to 32 bits unsigned.
  • Are you intending to seek relative to your current position?

-- MarkusQ

MarkusQ
A: 

What kind of file is it? Is it a pipe by any chance? Because if it's anything but a regular file, chances are it doesn't support seeking:

The behavior of lseek() on devices which are incapable of seeking is implementation-defined. The value of the file offset associated with such a device is undefined.

Adam Rosenfield
I tried it with different files. /dev/disk1, /dev/rdisk1 and /path/to/a/normal/file (any of those should be seek-able)
Georg
I'd fstat() the file and check S_ISREG(stat.st_mode) just to be sure.
Randy Proctor
+1  A: 

Something else is up, probably something silly. I tried your code, as here:

#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>

int main(int argc, char *argv[]){
    off_t pos;
    int file ;
    if((file = open("/Users/chasrmartin/.bash_history",O_RDONLY)) == -1){
        perror(argv[0]);
        exit(1);
    }
    printf("size off_t: %i\n", sizeof(off_t));

    pos = lseek(file, (off_t)0, SEEK_CUR);
    printf("pos: %lli\n", pos);

    // same result for SEEK_SET and SEEK_END
    pos = lseek(file, (off_t)2352, SEEK_CUR);
    printf("pos: %lli\n", pos);

    exit(0);
}

and get this result:

bash $ gcc foo.c
bash $ ./a.out
size off_t: 8
pos: 0
pos: 2352

(Just to be definite, this is on Mac OS/X 10.5.6 on Intel.)

Update.

Or maybe it's not silly. I just tried it on a PPC G5, and get the results you do.

Update 2

Okay, here's the result on a PPC:

$ gcc foo.c
$ ./a.out
size off_t: 8
pos: 0
pos: 0
Charlie Martin
The exact same code (with gs instead of chasrmartin) doesn't work for me. (OSX 10.5.6) What's your system?
Georg
See the update. Works on intel, doesn't work on PPC. WTF?
Charlie Martin
Keen on writing a bug report? I'm not really, but I think I'll do it anyway.
Georg
Sure looks like it to me. Doesn't make sense, though --- there are a *zillion* things that won't work if lseek(2) doesn't work.
Charlie Martin
I'll try next the support for long files, maybe this is only for normal files.
Georg
+5  A: 

Try adding #include <unistd.h> to the top.

See: http://forums.macosxhints.com/archive/index.php/t-35508.html

Basically, since you didn't #include <unistd.h>, the compiler is "guessing" that lseek() returns an int.

Probably an int is 4-bytes long, and since PPC is "big-endian" byte order, you're getting the "top" 4 bytes, which are all zero.

Include unistd.h lets the compiler realize that lseek() is returning an off_t, so you don't lose half the bytes.

Wow, thanks! Have you've got any idea why the compiler doesn't show a warning? With malloc it does it every time.
Georg
Actually, adding -Wall does the trick.
Georg