I have created a text file using an editor and put some information in it
When calling inquire as follows I am getting UNDEFINED and UNKNOWN
Inquire (file=nm, exist=fe, form=fm, access=ac)
Inquire (file=nm, sequential=seq, direct=drc)
Inquire (file=nm, formatted=fmt, unformatted=uft)
Outputs
fm, ac: UNDEFINED UNDEFINED
seq: UNKNOWN
drc: UNKNOWN
fmt: UNKNOWN
uft: UNKNOWN
It's appealing to think that so-called inquire by file tells us what we can do with a file. Indeed, using the file= specifier in the inquire statement inquires about a file which needn't exist or be connected (through, say, an open statement). It seems that you're finding existence testing not to be troubling.
However, the information we get from such an inquiry is limited. Yes, it would be nice if an inquire by file like
inquire(file="some_file", direct=isdirect, formatted=isformatted, ...)
tells us whether it is possible to establish a direct access connection to a file which has unformatted records, but we're in the realms of "processor dependent".
First, though, the easy ones in the question: form= and access= specifiers. You are seeing undefined, which is precisely the result that is expected when the files are not currently connected. You can see in Fortran 2008 9.2.10.3 for access=
If there is no connection, it is assigned the value UNDEFINED.
and similarly in 9.2.10.12 for form=. Even with inquire by file, these two specifiers tell us about the connection not the file. That is, not what may we do with the file, but what are we doing with the file.
The others, which have unknown are covered by statements such as
UNKNOWN if the processor is unable to determine whether SEQUENTIAL is
included in the set of allowed access methods for the file
(for sequential=). Knowing whether an access mode, say, is allowed is more expected for things like
For example, a processor may allow only sequential access to a file on magnetic tape. Thus, the set of
allowed access methods depends on the file and the processor.
Related
This recently asked question has raised another interesting issue, as discussed in the comments to one of its answers.
To summarize: the OP there was having issues with code like that below, when subsequently attempting to read and write data from/to the two streams 'concurrently':
ifstream infile;
infile.open("accounts.txt");
ofstream outfile;
outfile.open("accounts.txt");
Although the issue, in itself, was successfully resolved, it has raised a question to which I cannot find an authoritative answer (and I've made some quite extensive searches of Stack Overflow and the wider web).
It is very clearly stated what happens when calling the open() method of a stream that is already associated with a file (cppreference), but what I cannot find an answer to is what happens when (as in this case) the file is already associated with a (different) stream.
If the stream is already associated with a file (i.e., it is already
open), calling this function fails.
I can see several possible scenarios here:
The second open call will fail and any attempted writes to it will also fail (but that is not the case in the cited question).
The second open call will 'override' the first, effectively closing it (this could explain the issues encountered in said code).
Both streams remain open but enter into a 'mutual clobbering' match regarding their internal file pointers and buffers.
We enter the realm of undefined (or implementation-defined) behaviour.
Note that, as the first open() call is made by an input stream, the operating system will not necessarily 'lock' the file, as it probably would for an output stream.
So, does anyone have a definitive answer to this? Or a citation from the Standard (cppreference will be 'acceptable' if nothing more authoritative can be found)?
basic_filebuf::open (and all things that depend on it, like fstream::open) has no statement about what will happen in this case. A filesystem may allow it or it may not.
What the standard says is that, if the file successfully opens, then you can play with it in accord with the interface. And if it doesn't successfully open, then there will be an error. That is, the standard allows a filesystem to permit it or forbid it, but it doesn't say which must happen. The implementation can even randomly forbid it. Or forbid you from opening any files in any way. All are (theoretically) valid.
To me, this falls even out of the 'implementation defined' field. The very same code will have different behaviour depending of the underlying filesystem or OS (some OSes forbid to open a file twice).
No.
Such a scenario is not discussed by the standard.
It's not even managed by the implementation (your compiler, standard library implementation etc).
The stream ultimately asks the operating system for access to that file in the desired mode, and it's up to the operating system to decide whether that access shall be granted at that time.
A simple analogy would be your program making some API call to a web application over a network. Perhaps the web application does not permit more than ten calls per minute, and returns some error code if you attempt more than that. But that doesn't mean your program has undefined behaviour in such a case.
C implementations exist for many different platforms, whose underlying file systems may handle such corner cases differently. For the Standard to mandate any particular corner-case behavior would have made the language practical only on platforms whose file systems behave in such fashion. Instead, the Standard regards such issues as being outside its jurisdiction (i.e. to use its own terminology, "Undefined Behavior"). That doesn't mean that implementations whose target OS offers useful guarantees shouldn't make such guarantees to programs when practical, but implementation designers are presumed to know more than the Committee about how best to serve their customers.
On the other hand, it may sometime be helpful for an implementation not to expose the underlying OS behavior. On an OS that doesn't have a distinct "append" mode, for example, but code needing an "open for append" could do an "open existing file for write" followed by "seek to end of file", an attempt to open two streams for appending to the same file could result in data corruption when one stream writes part of a file, and the other stream then rewrites that same portion. It may be helpful for an implementation that detects that condition to either inject its own logic to either ensure smooth merging of the data or block the second open request. Either course of action might be better, depending upon an application's purpose, but--as noted above--the choice is outside the Standard's jurisdiction.
I open the zip file as stream twice.The zip file contains some XML files.
std::ifstream("filename") file;
zipstream *p1 = new zipstream(file);
zipstream *p2 = new zipstream(file);
p1->getNextEntry();
auto p3 = p1.rdbuf();
autp p4 = p2.rdbuf();
Then see p3 address = p4 address, but the member variables are different between them. Such as _IGfirst.
The contents of one of the XML files are as follows:
<test>
<one value="0.00001"/>
</test>
When the contents of file are read in two thread at the same time.error happend.
string One = p1.getPropertyValue("one");
// one = "0001two"
I am trying to compile and link a Fortran project that includes code written by me as well as code written by some other team. The main program includes a lot of header files where for example common blocks are set up. While compiling the file with the main program, I got plenty of error messages by gfortran stating that The equivalence set for ‘%VARIABLENAME’ cause an invalid extension to COMMON '%BLOCKNAME'
The same main program and header files already worked in other programs. I have never seen this message before and could not find any description of what it means. Can anyone tell me more about it?
I found it out on my own and it was very simple: %VARIABLENAME in the above error message was in fact an array and had a size that was obviously too large (in the order of some millions) for a common block. This was due to the fact that the array dimensionality was set by a parameter in the code I got from another team where they set it to an arbitrary value. Reducing the array size to a value that actually made sense helped immediately.
Take home messages: avoid common blocks, always cross-check the code others give you.
I need to develop a C++ routine performing this apparently trivial task: create a file only if it does not exist, else do nothing/raise error.
As I need to avoid race conditions, I want to use the "ask forgiveness not permission" principle (i.e. attempting the intended operation and checking if it succeeded, as opposed to checking preconditions in advance), which, to my knowledge, is the only robust and portable method for this purpose [Wikipedia article][an example with getline].
Still, I could not find a way to implement it in my case. The best I could come up with is opening a fstream in app mode (or fopening with "a"), checking the output position with tellp (C++) or ftell (C) and aborting if such position is not zero. This has however two disadvantages, namely that if the file exists it gets locked (although for a short time) and its modification date is altered.
I checked other possible combinations of ios_base::openmode for fstream, as well as the mode strings of fopen but found no option that suited my needs. Further search in the C and C++ standard libraries, as well as Boost Filesystem, proved unfruitful.
Can someone point out a method to perform my task in a robust way (no collateral effects, no race conditions) without relying on OS-specific functions?
My specific problem is in Windows, but portable solutions would be preferred.
EDIT: The answer by BitWhistler completely solves the problem for C programs. Still, I am amazed that no C++ idiomatic solution seems to exist. Either one uses open with the O_EXCL attribute as proposed by Andrew Henle, which is however OS-specific (in Windows the attribute seems to be called _O_EXCL with an additional underscore [MSDN]) or one separately compiles a C11 file and links it from the C++ code. Moreover, the file descriptor obtained cannot be converted to a stream except with nonstandard extensions (e.g. GCC's __gnu_cxx::stdio_filebuf). I hope a future version of C++ will implement the "x" subattribute and possibly also a corresponding ios:: modificator for file streams.
The new C standard (C2011, which is not part of C++) adds a new standard subspecifier ("x"), that can be appended to any "w" specifier (to form "wx", "wbx", "w+x" or "w+bx"/"wb+x"). This subspecifier forces the function to fail if the file exists, instead of overwriting it.
source: http://www.cplusplus.com/reference/cstdio/fopen/
The problem is that std::fstream doesn't throw exceptions by default but rather sets bits that can then be examined. Apparently, it can then be made to throw exceptions (I think) by using the exceptions function as explained here -- see e.g. c++ reference page
But what if, for example, the write permissions of the file mean that the file cannot be written to? This would mean that when I try and do
ofstream file("file", ios::out);
a failure would result. But how can it be determined if it failed for the precise reason that the uid didn't have write permissions? I guess what I am looking for is some mechanism that will tell me precisely this e.g. it might show "File cannot be written to because...". I do not want to have to check file permissions because there are so many reasons why write failure could occur (hard-drive failures/corruption etc.). It would be better if it would just tell me exactly why it failed.
Does anybody know if such an error checking system exists for iostreams (ostreams in particular)? (Maybe in boost?)
You can try to check errno and perhaps convert it to a human-readable form with strerror.
The standard doesn't guarantee anything about applicability of errno to I/O failures, but in practice it should work.
In the mold of a previous question I asked about the so-called safe library deprecations, I find myself similarly bemused as to why fopen() should be deprecated.
The function takes two C strings, and returns a FILE* ptr, or NULL on failure. Where are the thread-safety problems / string overrun problems? Or is it something else?
Thanks in advance
You can use fopen(). Seriously, don't take any notice of Microsoft here, they're doing programmers a real disservice by deviating from the ISO standards . They seem to think that people writing code are somehow brain-dead and don't know how to check parameters before calling library functions.
If someone isn't willing to learn the intricacies of C programming, they really have no business doing it. They should move on to a safer language.
This appears to be just another attempt at vendor lock-in by Microsoft of developers (although they're not the only ones who try it, so I'm not specifically berating them). I usually add:
#define _CRT_SECURE_NO_WARNINGS
(or the "-D" variant on the command line) to most of my projects to ensure I'm not bothered by the compiler when writing perfectly valid, legal C code.
Microsoft has provided extra functionality in the fopen_s() function (file encodings, for one) as well as changing how things are returned. This may make it better for Windows programmers but makes the code inherently unportable.
If you're only ever going to code for Windows, by all means use it. I myself prefer the ability to compile and run my code anywhere (with as little change as possible).
As of C11, these safe functions are now a part of the standard, though optional. Look into Annex K for full details.
There is an official ISO/IEC JTC1/SC22/WG14 (C Language) technical report TR24731-1 (bounds checking interfaces) and its rationale available at:
http://www.open-std.org/jtc1/sc22/wg14
There is also work towards TR24731-2 (dynamic allocation functions).
The stated rationale for fopen_s() is:
6.5.2 File access functions
When creating a file, the fopen_s and freopen_s functions improve security by protecting the file from unauthorized access by setting its file protection and opening the file with exclusive access.
The specification says:
6.5.2.1 The fopen_s function
Synopsis
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
errno_t fopen_s(FILE * restrict * restrict streamptr,
const char * restrict filename,
const char * restrict mode);
Runtime-constraints
None of streamptr, filename, or mode shall be a null pointer.
If there is a runtime-constraint violation, fopen_s does not attempt to open a file.
Furthermore, if streamptr is not a null pointer, fopen_s sets *streamptr to the
null pointer.
Description
The fopen_s function opens the file whose name is the string pointed to by
filename, and associates a stream with it.
The mode string shall be as described for fopen, with the addition that modes starting
with the character ’w’ or ’a’ may be preceded by the character ’u’, see below:
uw truncate to zero length or create text file for writing, default permissions
ua append; open or create text file for writing at end-of-file, default permissions
uwb truncate to zero length or create binary file for writing, default permissions
uab append; open or create binary file for writing at end-of-file, default
permissions
uw+ truncate to zero length or create text file for update, default permissions
ua+ append; open or create text file for update, writing at end-of-file, default
permissions
uw+b or uwb+ truncate to zero length or create binary file for update, default
permissions
ua+b or uab+ append; open or create binary file for update, writing at end-of-file,
default permissions
To the extent that the underlying system supports the concepts, files opened for writing
shall be opened with exclusive (also known as non-shared) access. If the file is being
created, and the first character of the mode string is not ’u’, to the extent that the
underlying system supports it, the file shall have a file permission that prevents other
users on the system from accessing the file. If the file is being created and first character
of the mode string is ’u’, then by the time the file has been closed, it shall have the
system default file access permissions10).
If the file was opened successfully, then the pointer to FILE pointed to by streamptr
will be set to the pointer to the object controlling the opened file. Otherwise, the pointer
to FILE pointed to by streamptr will be set to a null pointer.
Returns
The fopen_s function returns zero if it opened the file. If it did not open the file or if
there was a runtime-constraint violation, fopen_s returns a non-zero value.
10) These are the same permissions that the file would have been created with by fopen.
The fopen_s() function has been added by Microsoft to the C runtime with the following fundamental differences from fopen():
if the file is opened for writing ("w" or "a" specified in the mode) then the file is opened for exclusive (non-shared) access (if the platform supports it).
if the "u" specifier is used in the mode argument with the "w" or "a" specifiers, then by the time the file is closed, it will have system default permissions for others users to access the file (which may be no access if that's the system default).
if the "u" specified is not used in those cases, then when the file is closed (or before) the permissions for the file will be set such that other users will not have access to the file.
Essentially it means that files the application writes are protected from other users by default.
They did not do this to fopen() due to the likelyhood that existing code would break.
Microsoft has chosen to deprecate fopen() to encourage developers for Windows to make conscious decisions about whether the files their applications use will have loose permissions or not.
Jonathan Leffler's answer provides the proposed standardization language for fopen_s(). I added this answer hoping to make clear the rationale.
Or is it something else?
Some implementations of the FILE structure used by 'fopen' has the file descriptor defined as 'unsigned short'. This leaves you with a maximum of 255 simultaneously open files, minus stdin, stdout, and stderr.
While the value of being able to have 255 open files is debatable, of course, this implementation detail materializes on the Solaris 8 platform when you have more than 252 socket connections! What first appeared as a seemingly random failure to establish an SSL connection using libcurl in my application turned out to be caused by this, but it took deploying debug versions of libcurl and openssl and stepping the customer through debugger script to finally figure it out.
While it's not entirely the fault of 'fopen', one can see the virtues of throwing off the shackles of old interfaces; the choice to deprecate might be based on the pain of maintaining binary compatibility with an antiquated implementation.
The new versions do parameter validation whereas the old ones didn't.
See this SO thread for more information.
Thread safety. fopen() uses a global variable, errno, while the fopen_s() replacement returns an errno_t and takes a FILE** argument to store the file pointer to.