I am attempting to refactor a very old piece of code that generates a log file:
FILE *File = NULL;
errno_t err = fopen_s(&File, m_pApp->LogFilename(), "a+"); // Open log file to append to
if (err == 0)
{
::fprintf(File, "Date,Time,Serial Number,ASIC Voltage,Ink Temp,Heater Temp, Heater Set Point, PSOC Version,");
if (m_ExtraLog)
::fprintf(File, "T1 Temperature,ASIC Temperature,Proc Temperature,Voltage mA");
::fprintf(File, "\n");
fclose(File);
}
The reason for refactoring is that some users report that it is not possible to copy the file that is being produced (they want to copy it so that it can be analysed by a labview program). I read the documentation regarding fopen_s and saw that "Files that are opened by fopen_s and _wfopen_s are not sharable" - is this the cause of my problem? I am unsure because actually, I do not see the copying problem and seem to be able to copy and paste the file without issue. In any case I have replaced it with the recommended _fsopen function like so:
FILE *File = NULL;
if((File = _fsopen(m_pApp->LogFilename(),"a+", _SH_DENYNO))!= NULL)
{
::fprintf(File, "Date,Time,Serial Number,ASIC Voltage,Ink Temp,Heater Temp, Heater Set Point, PSOC Version,");
if(m_ExtraLog)
{
::fprintf(File, "T1 Temperature,ASIC Temperature,Proc Temperature,Voltage mA");
}
::fprintf(File, "\n");
fclose(File);
}
I've given the refactored code to the user but they still report being unable to copy or access the file from labview. I have very limited knowledge of C++ so I am wondering is there any other explanation as to why the file being generated is not able to copied by another process?
Lets have look into doc
Open a file. These are versions of fopen, _wfopen with security enhancements as described in Security Enhancements in the CRT.
Follow by: link
We can read:
Filesystem security. Secure file I/O APIs support secure file access in the default case.
So to fix that, you must change 'file security' to match 'all users/read access'
Related
I'm solving a VRP with SCIP and I wish to export the results of the optimization into a text file. I use the following code but fails when calls the SCIPwriteBestSol function.
FILE* file;
file = fopen("Solution.sol", "w");
SCIP_CALL(SCIPprintBestSol(scip, file, FALSE));
fclose(file);
If the following call works (i.e., prints the solution to console), then your problem comes from the I/O methods. If it fails as well, you have to check your SCIP status, i.e., whether you have a solution at all. If this does not work, I suggest to write to the SCIP mailing list / report a bug.
SCIP_CALL(SCIPprintBestSol(scip, stdout, FALSE));
check the return value of fopen()
as the manual says fopen will return a null pointer if the function call fails
then firstly do it
if ((file = fopen("Solution.sol", "w")) != nullptr)
{
// do your stuff
}
Why add this constraint when your intentions are to both read and write data to the file?
My application wants to open the file in both reading an writing mode. If I use w+ it will destroy the previous contests of the file, but at the same time it will create the file if it doesn't exist.
However if I use the r+ mode, my application will work properly, but if the file doesn't exist it will throw an exception about the nonexistence of the file.
Try something like this. If the first fopen fails because the file does not exist, the second fopen will try to create it. If the second fopen fails there are serious problems.
if((fp = fopen("filename","r+")) == NULL) {
if((fp = fopen("filename","w+")) == NULL) {
return 1;
}
}
Is there any open source File IO library or easy way in C++ which reports a detail and exact errors for File IO. For examples; If user doesnt have the read or right permission - or if the disk got full etc.
C style file ops do this by default, you just need to include cerrorno and cstring and use strerror after an unsuccessful file operation call:
hFile = fopen(fname, "r+b");
/*-- attempt to create the file if we can't open it for reading --*/
if(!hFile) {
/*-- print out relevant error information --*/
printf("Open File %s Failed, %s\n", fname, std::strerror(errno));
return 1;
}
return 0;
That is of course if you use C style file operations. I think ifstream also supports these on most compilers.
A note, this functionality is not thread safe on some implementations. There is strerror_r on linux which is thread safe.
I would like to know how to check if I have write permissions to a folder.
I'm writing a C++ project and I should print some data to a result.txt file, but I need to know if I have permissions or not.
Is the check different between Linux and Windows? Because my project should run on Linux and currently I'm working in Visual Studio.
The portable way to check permissions is to try to open the file and check if that succeeded. If not, and errno (from the header <cerrno> is set to the value EACCES [yes, with one S], then you did not have sufficient permissions. This should work on both Unix/Linux and Windows. Example for stdio:
FILE *fp = fopen("results.txt", "w");
if (fp == NULL) {
if (errno == EACCES)
cerr << "Permission denied" << endl;
else
cerr << "Something went wrong: " << strerror(errno) << endl;
}
Iostreams will work a bit differently. AFAIK, they do not guarantee to set errno on both platforms, or report more specific errors than just "failure".
As Jerry Coffin wrote, don't rely on separate access test functions since your program will be prone to race conditions and security holes.
About the only reasonable thing to do is try to create the file, and if it fails, tell the user there was a problem. Any attempt at testing ahead of time, and only trying to create the file if you'll be able to create and write to it is open to problems from race conditions (had permission when you checked, but it was removed by the time you tried to use it, or vice versa) and corner cases (e.g., you have permission to create a file in that directory, but attempting to write there will exceed your disk quota). The only way to know is to try...
The most correct way to actually test for file write permission is to attempt to write to the file. The reason for this is because different platforms expose write permissions in very different ways. Even worse, just because the operating system tells you that you can (or cannot) write to a file, it might actually be lying, for instance, on a unix system, the file modes might allow writing, but the file is on read only media, or conversely, the file might actually be a character device created by the kernel for the processes' own use, so even though its filemodes are set to all zeroes, the kernel allows that process (and only that process) to muck with it all it likes.
Similar to the accepted answer but using the non-deprecated fopen_s function as well as modern C++ and append open mode to avoid destroying the file contents:
bool is_file_writable(const std::filesystem::path &file_path)
{
FILE* file_handle;
errno_t file_open_error;
if ((file_open_error = fopen_s(&file_handle, file_path.string().c_str(), "a")) != 0)
{
return false;
}
fclose(file_handle);
return true;
}
I copied this code from the libjpeg example and im passing it standard files;
FILE *soureFile;
if ((soureFile = fopen(sourceFilename, "rb")) == NULL)
{
fprintf(stderr, "can't open %s\n", sourceFilename);
exit(1);
}
jpeg_stdio_src(&jpegDecompress, soureFile);
jpeg_read_header(&jpegDecompress, true);
It results in a file pointer that contains no information and therefore breaks on the last line with access violations.
Any ideas?
EDIT: On Tobias' advice the fopen does appear to open the file ok but the jpeg_read_header is in turn failing with the access violation still.
EDIT: After a little more digging
JPEG support with ijg - getting access violation
Use strerror or perror to get exact reason:
FILE *soureFile;
if ((soureFile = fopen(sourceFilename, "rb")) == NULL)
{
perror("fopen failed");
exit(1);
}
"select isn't broken".
If fopen returned a valid file pointer, and jpeg_read_header can't use it, someone between those two statements has done something bad to it.
The only one in between is the jpg_stdio_src call, which wouldn't fail if all it's preconditions are fulfilled.
Bottom line: see why jpg_stdio_src fails. My guess: it needs to be constructed using the jpeg_create_decompress macro.