-1

I'm looking for the equivalent of Microsoft's _filelength in Linux. I tried this, but it's incorrect.

long _filelength(char *f)
{
    struct stat st;
    stat(f, &st);
    return st.st_size;
}

if((hfile = fopen("data.arp","rb"))!=NULL)
    fsize = _filelength(fileno(hfile));

How do I get the file length in C on Linux?

jww
  • 97,681
  • 90
  • 411
  • 885
  • 1
    What makes you think that it is incorrect? It does not compile! – Basile Starynkevitch May 01 '18 at 15:25
  • I think `fsize = _filelength(fileno(hfile));` --> `fsize = _filelength(hfile);` – Achal May 01 '18 at 15:28
  • 2
    Possible duplicate of [How do you determine the size of a file in C?](https://stackoverflow.com/q/8236/608639), [How can I get a file's size in C?](https://stackoverflow.com/q/238603/608639), [Proper way to get file size in C](https://stackoverflow.com/q/35390912/608639), [How to get a file length in c?](https://stackoverflow.com/q/1669676/608639), etc. – jww May 02 '18 at 02:04

4 Answers4

2

I'm looking for the equivalent of _filelength in linux.

That is a very wrong approach and shows a wrong mindset. There is no exact equivalent of Windows' _filelength on Linux. Linux is not Windows and Windows is not Linux. Each operating system has its own API and its own vision of files (On Linux, they are inodes, see inode(7) and also this answer...), processes etc.... Linux is mostly POSIX compliant, so study POSIX and read some book on Linux system programming, perhaps the old ALP or something newer. Don't expect (and don't even try) to find an equivalent of every Windows or WinAPI function on Linux. See intro(2), syscalls(2), intro(3).

Read more carefully stat(2). It takes a string (some file path), not a file descriptor (like fstat does) as the one given by fileno(3). It can fail (and you need to understand why, probably using errno(3), which is never negative).

BTW, identifiers with a name starting with _ are reserved.

Perhaps you might try:

long filelength(const char*filpath) { // don't use that. Learn POSIX API
   struct stat st;
   if (stat(filpath, &st)) /*failure*/
      return -1; // when file does not exist or is not accessible
   return (long) st.st_size;
}

but in practice you'll better use stat directly in your program (and check errno(3) on failure, not just simply returning -1 like I did above), and you probably should use the other metadata returned by stat in it.

Linux (and Unix) also have sparse files, hard links, device files, symbolic links, anonymous files (e.g. still opened inodes, but no more present in the file system), fifo(7)-s, unix(7) sockets, etc.... You probably need to handle them (but they don't have an exact equivalent on Windows).

Read also Operating Systems: Three Easy Pieces

You might use multi-platform frameworks like Poco or Boost or Qt. They are trying to provide some common abstraction above several operating systems (but some details still matter and are difficult to hide or to abstract; for example a file path is not the same on Windows and on Linux. See path_resolution(7)...)

You should compile with all warnings and debug info (so gcc -Wall -Wextra -g with GCC). Then use the gdb debugger. You might also use strace(1) to understand the system calls done by your program.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • Yes. Did you check `errno` ? As I try to explain, you have the wrong approach. Change your mindset to be Linux friendly. Don't think in WinAPI terms. Learn the POSIX API, it is not the same! – Basile Starynkevitch May 01 '18 at 15:47
  • I definitely agree with learning the Linux APIs. I'm not sure I agree with using them though. If you're writing code that works on Windows and Linux, you might well want a portability layer, and you might decide your portability layer looks a lot more like winapi than Linux. – Sam Hartman May 01 '18 at 15:57
  • `errno` is never -1. You've got something wrong. Show some [MCVE] in your question. – Basile Starynkevitch May 01 '18 at 16:04
  • 1
    Wonderful introduction. – Matthias Jul 06 '21 at 07:28
0
FILE *fp = fopen("filename", "rb");
fseek(fp, 0, SEEK_END);
int lengthOfFile = ftell(fp);
fclose(fp);
0

Maybe you can try with this.

size_t _filelength(int filedes)
{
    off_t pos = lseek(filedes, 0, SEEK_CUR);
    if (pos != (off_t)-1)
    {
        off_t size = lseek(filedes, 0, SEEK_END);
        lseek(filedes, pos, SEEK_SET);
        return (size_t)size;
    }
    return (off_t)-1;
}
-1

You have to seek through the file.

fseek(file, 0L, SEEK_END);

Then get the current position:

fileSize = ftell(file);

Then to reset the position back to the beginning use:

rewind(file);
Jimenemex
  • 3,104
  • 3
  • 24
  • 56
  • That's not strictly-compliant C. It's [undefined behavior to seek to the end of a binary stream](https://port70.net/~nsz/c/c11/n1570.html#note268), and you [can't use `ftell()` to get the size of a text stream in bytes](https://port70.net/~nsz/c/c11/n1570.html#7.21.9.4p2) – Andrew Henle May 02 '18 at 09:26