6

I am using this piece of code

long filesize (const char * filename)
{
    ifstream file (filename, ios::in|ios::binary);
    file.seekg (0, ios::end);
    return file.tellg();
}

in order to return the size of file in bytes. However i file without read permission results in returning -1. Is there any way using c++ or c to return size of the file and directories , that works even on file without read permission? I was looking for a while but fail to find solid solution.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Dingo
  • 331
  • 2
  • 3
  • 10
  • 4
    since C++ doesn't have a concept for access permissions, there's no OS independent solution to this – BeyelerStudios Jun 06 '16 at 19:30
  • 1
    @BeyelerStudios [Filesystem handling is coming](http://en.cppreference.com/w/cpp/filesystem) – NathanOliver Jun 06 '16 at 19:33
  • 1
    You might use the POSIX-function stat (but you need reed permission on the directory) –  Jun 06 '16 at 19:35
  • 1
    This will be platform dependent. I believe that even the coming `` defers to the underlying `OS` for its errors. – Galik Jun 06 '16 at 19:43
  • Might want to look at http://www.boost.org/doc/libs/1_39_0/libs/filesystem/doc/index.htm, but I have no idea if that offers this kind of functionality. It *is* OS-dependent, so the question is what will abstract it for you. –  Jun 06 '16 at 19:52
  • If you can't read a file knowing its size is of limited usefulness. (Even knowing the size if you can read it can be problematic, since the size might change before you read it.) I'm not suggesting your question is invalid. – Keith Thompson Jun 06 '16 at 20:18
  • @KeithThompson: This functionality is common in file browsers. Nothing out of the ordinary. – IInspectable Jun 06 '16 at 21:27
  • @IInspectable: Sure, the information is available. I'm just suggesting that it may not be particularly useful and warning against relying on it. – Keith Thompson Jun 06 '16 at 22:46
  • @KeithThompson: I find it very useful to see file sizes, even for files I do not have read access, because I might decide to sudo/UAC over, and use them in just a minute. – IInspectable Jun 06 '16 at 22:53

3 Answers3

3

The current c++ standard library does not offer the possibility to inquire the size of a file from the file system.

In the future, when c++17 is released, the c++ standard library will have have an API for basic file system operations. Using that API, this should not require read permission to the file (but you do need permission on all parent directories in the path, of course) although, I don't think that the standard provides any guarantees about non-requirement of permissions:

return std::filesystem::file_size(filename);

Until the upcoming standard is supported by your standard library (some standard libraries already have experimental support for experimental/filesystem technical specification), you will need to resort to OS specific API or a non-standard wrapper library.

eerorika
  • 232,697
  • 12
  • 197
  • 326
1

Well, without read permission your file will be left in error state, and calling file.seekg() will result in an error state as well:

long filesize (const char * filename)
{
    ifstream file (filename, ios::in|ios::binary);
    if(file) { // Check if opening file was successful
        file.seekg (0, ios::end);
        return file.tellg();
    }
    return -1; // <<<< Indicate that an error occured
}

If the file doesn't let you open it, you can still inspect the directory structure and get informations about files using stat(). But this is platform (POSIX compliance) dependent (and of course you need access rights to read the directories content information).

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
1

On a POSIX system, you can use stat.

Summary:

#include <sys/stat.h>

int stat(const char *restrict path, struct stat *restrict buf);

So, you declare a stat structure to hold the result, and pass the pointer to stat:

struct stat buf;
stat(filename, &buf);

The size (in bytes) is contained in buf.st_size.

If your standard library implementation includes <experimental/filesystem> (which should come out of experimental with C++17), you can use that instead. #include <experimental/filesystem>, and then use std::experimental::filesystem::file_size(filename) instead of your filesize function. (This also returns the size in bytes. It just calls the stat function on POSIX systems.)

For GCC, you will need to link with -lstdc++fs (see experimental::filesystem linker error).

Community
  • 1
  • 1
Nick Matteo
  • 4,453
  • 1
  • 24
  • 35