4

I'm writing a C++ program which will be printing out large (2-4GB) files.

I'd like to make sure that there's sufficient space on the drive to save the files before I start writing them. If possible, I'd like to reserve this space.

This is taking place on a Linux-based system.

Any thoughts on a good way to do this?

Richard
  • 56,349
  • 34
  • 180
  • 251

3 Answers3

8

Take a look at posix_fallocate():

NAME
       posix_fallocate - allocate file space

SYNOPSIS

       int posix_fallocate(int fd, off_t offset, off_t len);

DESCRIPTION
       The function posix_fallocate() ensures that disk space is allocated for
       the file referred to by the descriptor fd for the bytes  in  the  range
       starting  at  offset  and continuing for len bytes.  After a successful
       call to posix_fallocate(), subsequent writes to bytes in the  specified
       range are guaranteed not to fail because of lack of disk space.

edit In the comments you indicate that you use C++ streams to write to the file. As far as I know, there's no standard way to get the file descriptor (fd) from a std::fstream.

With this in mind, I would make disk space pre-allocation a separate step in the process. It would:

  1. open() the file;
  2. use posix_fallocate();
  3. close() the file.

This can be turned into a short function to be called before you even open the fstream.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • 2
    This looks like a C-style function. Thoughts on how to mix it with C++ stream operators? – Richard Feb 28 '12 at 20:00
  • 1
    @Richard: You could try to get the `fd` out of the `ostream`, but AFAIK there's no standard way to do this. I personally would just `open()` the file, use `posix_fallocate()` and `close()` it. Then you can use C++ I/O to re-open it, write the contents etc. – NPE Feb 29 '12 at 07:58
  • You could also write your own streambuf to wrap low-level `read()` and `write()` calls, if you need to be sure nobody replaces the file under you. But reopening is probably easier. – bdonlan Feb 29 '12 at 08:21
  • @aix, that's a cunning solution and I like it! But, I seem to recall, from somewhere, that when you open a file for output its length gets trimmed to zero first. (My testing confirmed this.) I think some additional trick is needed. :-/ – Richard Mar 01 '12 at 16:32
  • @Richard: Specify `ios::in | ios::out` as the second argument to the `ofstream`'s constructor, and the file will not get truncated. – NPE Mar 01 '12 at 16:48
1

If you are using C++ 17, you should do it with std::filesystem::resize_file

As shown in this post

Kari
  • 1,244
  • 1
  • 13
  • 27
1

Use aix's answer (posix_fallocate()), but since you're using C++ streams, you'll need a bit of a hack to get the stream's file descriptor.

For that, use the code here: http://www.ginac.de/~kreckel/fileno/.

Clark Gaebel
  • 17,280
  • 20
  • 66
  • 93