LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 09-21-2010, 01:18 PM   #1
kvm1983
Member
 
Registered: Jul 2009
Posts: 47

Rep: Reputation: 1
lseek failing for filesize 4GB


Hello all,
I am trying to lseek into a file till offset 4GB (4294967296 bytes).
Code:
off64_t FILESIZE = 4294967296;
result = lseek64(fd, FILESIZE-1, SEEK_SET);
Please note that fd is a valid file descriptor, I have made sure that the file open call is successful.

Heres what I observe:
1. If FILESIZE < 4GB, lseek works.
2. If FILESIZE = 4GB, lseek fails with errno 29 (ESPIPE), which states that fd is associated with a pipe, socket, or FIFO.
3. If FILESIZE > 4GB, lseek works again.

So I am confused why lseek fails when FILESIZE is exactly 4GB. I am running this program on a dual core 64 bit Opteron machine running OpenSuse. Any pointers into this error are greatly appreciated.

Heres the complete program:
Code:
#include <stdio.h>
#include <stdlib.h>
#define _LARGEFILE64_SOURCE 1
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <string.h>
#include <errno.h>

#define FILEPATH "/tmp/km_mmap.txt"

off64_t FILESIZE = 4294967296; //2147483648;

int main(int argc, char *argv[])
{
    int fd; 
    int result;

    fd = open64(FILEPATH, O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
    if (fd == -1) {
        perror("Error opening file for writing");
        exit(EXIT_FAILURE);
    }   

    result = lseek64(fd, (off64_t)(FILESIZE-1), SEEK_SET);
    if (result == -1) {
        close(fd);
        perror("Error calling lseek() to 'stretch' the file");
        fprintf(stdout, "errno: %d\n", errno);
        exit(EXIT_FAILURE);
    }   
    
    return 0;
}
- Kshitij

Last edited by kvm1983; 09-21-2010 at 03:45 PM.
 
Old 09-22-2010, 03:27 AM   #2
paulsm4
LQ Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
Try adding "LLU" or "LL" suffix to your integer literal.

EXAMPLE:
Code:
off64_t FILESIZE = 4294967296LLU;
'Hope that helps
 
Old 09-22-2010, 11:31 AM   #3
kvm1983
Member
 
Registered: Jul 2009
Posts: 47

Original Poster
Rep: Reputation: 1
Nopes, that didnt work. I tried LU, LLU, U. None of these solved it

- Kshitij
 
Old 09-22-2010, 12:09 PM   #4
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by kvm1983 View Post
Nopes, that didnt work. I tried LU, LLU, U. None of these solved it

- Kshitij
Did you try to print FILESIZE to make sure the compiler correctly understood your intent ?
 
Old 09-22-2010, 12:15 PM   #5
kvm1983
Member
 
Registered: Jul 2009
Posts: 47

Original Poster
Rep: Reputation: 1
yes, i printf filesize and it correctly prints the value 4294967296.

- Kshitij
 
Old 09-22-2010, 12:37 PM   #6
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by kvm1983 View Post
yes, i printf filesize and it correctly prints the value 4294967296.

- Kshitij
For no good reason try to modify your code this way:

Code:
off64_t offset = (off64_t)FILESIZE - (off64_t)1;
fprintf(stderr, "offset=%llu\n", (unsigned long long)offset);
result = lseek64(fd, offset, SEEK_SET);
 
Old 09-22-2010, 12:52 PM   #7
kvm1983
Member
 
Registered: Jul 2009
Posts: 47

Original Poster
Rep: Reputation: 1
Well that didnt work either. Now it prints the offset correctly as 4294967295, but the program still crashes with errno=29 (ESPIPE).

- Kshitij
 
Old 09-22-2010, 01:20 PM   #8
paulsm4
LQ Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
Hi -

Several suggestions:
1. Make sure nothing in any of your expressions casts the value down to a 32-bit int (that's what I was suggesting with "LL"; that's what Sergei Steshenko was suggestiong with "off64_t offset = (off64_t)FILESIZE - (off64_t)1").

2. Lose the "open64()" and substitute "open()" with "O_LARGEFILE".

3. Read this man page on "lseek64()" and see if any of the "gotcha's" mentioned in it might be applicable to your system:

http://linux.die.net/man/3/lseek64
 
Old 09-22-2010, 02:17 PM   #9
kvm1983
Member
 
Registered: Jul 2009
Posts: 47

Original Poster
Rep: Reputation: 1
Ok, got it.
This is the culprit:
Code:
result = lseek64(fd, offset, SEEK_SET);
Like an idiot, I declared result as an int, instead of off64_t. Note that lseek returns the offset at which the file pointer was positioned, hence the program fails.

What I noticed was that
For filesize 4294967298 (4GB + 2), the program did not crash, but the result was being set to 2.
For filesize 4294967295 (4GB - 2), the result was being set to -1.
It crashed when filesize was exactly 4GB.

Since the int could hold a maximum value of 2147483647, any value over it was making the result a -ve number.

Thanks a lot for all your help.

- Kshitij
 
  


Reply



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 Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
sysfs bin file lseek problem gtopmiller Linux - General 1 04-10-2007 04:35 PM
How do I access an address bigger than a long int with lseek? son_t Programming 8 01-22-2007 09:04 AM
problem with lseek crash88 Programming 2 07-08-2006 07:54 PM
eth1 failing on boot, IEEE firewire card driver failing, help jackuss_169 Linux - Laptop and Netbook 5 03-05-2005 07:34 AM
LILO install failing, Boot failing, but Installation fine. sramelyk Slackware 9 08-23-2003 02:37 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 01:44 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration