Clearing Contents of a File in C++ knowing only the FILE * - c++

Is it possible to clear the contents (ie. set EOF to the beginning/reset the file) in C++ knowing just the FILE*? I'm writing to a temp file with wb+ access and wish to sometimes clear it and truncate it without adding the calls to fclose and fopen. I dont think it's possible... but if not, why not?
Thanks in advance!

It will depend on your platform. The POSIX standard provides ftruncate(), which requires a file descriptor, not a FILE pointer, but it also provides fileno() to get the file descriptor from the FILE pointer.
The analogous facilities will be available in Windows environments - but under different names.

I don't believe this can be done using just the FILE*. You can always write null data through the end of the file but that won't truncate it.
Alternately if you have access to the filename (I can't tell from the question) you could use freopen which hides the close/open/truncate into a single function call.

#include <cstdio>
freopen(null, "w", filePtr);
see http://www.cplusplus.com/reference/clibrary/cstdio/freopen/ for more. espacialy the description for the parameter filename.

Related

Retrieve information about an open file

Can I retrieve information about a file previously opened with fopen() using only the pointer it returned?
The reason I ask is that I am trying to write a RAII-style wrapper class for FILE *s, and I want to make it as general as possible, and one of the functions I imagined for it was a copy-like operation, that would take a FILE * as an argument, and create a new reference to the same file.
Under POSIX, I can create a duplicate of a file descriptor with dup()/dup2(), and even get how the file is being accessed with fnctl()'s F_GETFL operation. However, even if I do that to the underlying descriptor of a FILE *, it isn't enough for guessing properties such as if the stream is text or binary (under POSIX, there no real difference, but I want to be general), or its orientation towards char- or wchar_t-based text.
So, is there is a way of learning about the stream I'm about to create a wrapper for, how far can I go, and how should I do it?
Thank you for you attention.

Can I read stream produced by open_memstream()?

I create a stream by open_memstream(), fill it and then read. It works fine. But I'm confused that function documentation says: "The open_memstream() function opens a stream for writing to a buffer". But I can read it too. Does I use it in a proper way? Maybe I can read the stream because of function implementation in my platform allows to do that? And when I change a platform I will probably get an error.
But I can read it too. Does I use it in a proper way?
No, not really. Posix specifies open_memstream() is for output only. You're only supposed to write to it. You can access the data
you write via the buffer created by open_memstream(), but not with fread(), fgets() or similar.
Use fmemopen() if you want a stream you can read from too.
Maybe I can read the stream because of function implementation in my platform allows to do that?
Yes, it might be an feature of the implementation that allows you to read from the FILE* too, check its documentation.
To complete nos's answer:
POSIX 7 says http://pubs.opengroup.org/onlinepubs/9699919799/functions/open_memstream.html
The stream shall be opened for writing and shall be seekable.
so no reading, only writing.
you can't change the flags of an open file descriptor in POSIX: Reopen a file descriptor with another access?
Linux has a /proc/self/fd/n workaround however apparently.

fstream delete N bytes from the end of a binary file

Is it possible to delete N bytes from the end of a binary file in C++ using fstream (or something similar)? I don´t want to read the whole file, cut it and write it again, but since it´s from the end of a file it seems like it shouldn't be such a problem.
I'm not aware of a generic C++ (platform independent) way to do this without writing a new file. However, on POSIX systems (Linux, etc.) you can use the ftruncate() function. On Windows, you can use SetEndOfFile().
This also means you'll need to open the file using the native functions instead of fstream since you need the native descriptor/handle for those functions.
EDIT: If you are able to use the Boost library, it has a resize_file() function in its Filesystem library which would do what you want.
Update:
Now in C++17 you can use resize_file from filesystem
Live on Coliru
In case you want to use Qt, QFile also provides two resize() methods that allow to truncate a file.

from file object to file name

I wonder if we can get the file name including its path from the file object that we have created for the file name in C and in C++ respectively
FILE *fp = fopen(filename, mode); // in C
ofstream out(filename); // in C++
ifstream in(filename); // in C++
Thanks!
You can't, in general. The file may not ever have had a file name, as it may be standard input, output, or error, or a socket. The file may have also been deleted; on Unix at least, you can still read to or write from a file that has been deleted, as the process retains a reference to it so the underlying file itself is not deleted until the reference count goes to zero. There may also be more than one name for a file; you can have multiple hard links to a single file.
If you want to retain the information about where a file came from, I would suggest creating your own struct or class that consists of a filename and the file pointer or stream.
There is no portable way to retrieve the file name of a FILE* object. It may not even be associated with an actual file (e.g. a FILE pointer for stdout).
There is no portable way. However particular platforms sometimes have ways to do that.
In Windows, if you can get the file's HANDLE (like the one you get from ::CreateFile() ), you can get the path from that using something like ZwQueryInformationFile().
From a FILE *, you can get a (Unix-style) file id using _fileno(). Then call _get_oshandle() to get the HANDLE.
Not sure how to do that from an std::ofstream, but you can research that.
Not sure how to do that on other OSes but it may be possible.

How can I create a temporary file for writing in C++ on a Linux platform?

In C++, on Linux, how can I write a function to return a temporary filename that I can then open for writing?
The filename should be as unique as possible, so that another process using the same function won't get the same name.
Use one of the standard library "mktemp" functions: mktemp/mkstemp/mkstemps/mkdtemp.
Edit: plain mktemp can be insecure - mkstemp is preferred.
tmpnam(), or anything that gives you a name is going to be vulnerable to race conditions. Use something designed for this purpose that returns a handle, such as tmpfile():
#include <stdio.h>
FILE *tmpfile(void);
The GNU libc manual discusses the various options available and their caveats:
http://www.gnu.org/s/libc/manual/html_node/Temporary-Files.html
Long story short, only mkstemp() or tmpfile() should be used, as others have mentioned.
man tmpfile
The tmpfile() function opens a unique temporary file in binary
read/write (w+b) mode. The file will be automatically deleted when it
is closed or the program terminates.ote
mktemp should work or else get one of the plenty of available libraries to generate a UUID.
The tmpnam() function in the C standard library is designed to solve just this problem. There's also tmpfile(), which returns an open file handle (and automatically deletes it when you close it).
You should simply check if the file you're trying to write to already exists.
This is a locking problem.
Files also have owners so if you're doing it right the wrong process will not be able to write to it.