C++ did not open some existing file - c++

I tried to write some code in C++ that traverses all system files. The problem was that there are some files which returns an error (2) which mean no such file found. Although the path had been found, but cannot been opened or get the pointer on that file or folder!
dirp->search_handle = FindFirstFileA (dirp->patt, &dirp->find_data);
if (dirp->search_handle == INVALID_HANDLE_VALUE)
{
cout << "Error(" << errno << ") opening " << dir<<" erroeno:"<<strerror(errno)<< endl<<endl;
}
The problem is not caused by a lack of administrator permissions because I am an admin on my computer. So what might cause this problem?

There are other reasons you could lack permissions
You could be trying to traverse a directory owned by another user on your domain. Being an Administrator doesn't automatically give you access to all files on a machine.
What you're passing could just have a trivial error. For example, you might have passed "C:\temp", without properly escaping your backslash, and instead getting a tab character.
I would provide more information about what specifically you're passing, or perhaps read up on msdn

Related

When removing the Config.json file from the ProgramData, showing "Permission Denied" in C++

I am trying to remove the config.json file from program data, But with the below code it is showing "Permission Denied".
int main()
{
std::string f_strConfigFile = "C:\\ProgramData\\TestApplication\\TestConfig.json";
std::string l_strFileContents;
std::ifstream l_ifConfigFileStream(f_strConfigFile.c_str());
if (l_ifConfigFileStream)
{
l_ifConfigFileStream.seekg(0, ios::end);
size_t l_szFileSize = (size_t)l_ifConfigFileStream.tellg();
l_ifConfigFileStream.seekg(0, ios::beg);
char* l_chBuffer = new char[l_szFileSize + 1];
memset(l_chBuffer, 0, l_szFileSize + 1);
l_ifConfigFileStream.read(l_chBuffer, l_szFileSize + 1);
l_strFileContents.assign(l_chBuffer);
delete[] l_chBuffer;
}
l_ifConfigFileStream.close();
if (l_strFileContents.empty())
{
l_strFileContents.assign("{}");
}
if (remove(f_strConfigFile.c_str()) != 0)
{
std::cout << "Failed to remove the file" << endl;
}
else
{
std::cout << "Removed the file" << endl;
}
return 0;
}
could any one suggest how to remove the config file?
Common Application Data Folder
There might not be any issue with your code in itself. Although I stand by all the suggestions made in the comments. They will make your code more efficient.
In the comments you said:
I tried by printing errno. It is showing "Permission denied".
Administrator rights are needed to save files to the common application data folder (%programdata%). Whilst all users have read access.
If you want to delete, you would need elevated administrator rights.
Run your executable with elevation and I bet it will delete the file.
The principles of the above are also discussed here in one of the answers (How to write to the common Application Data folder?).
Administrator Rights
You also asked in the comments:
How to provide elevated permissions when removing the file from the code?
This is really a different question. For what it's worth, in my application I have a dedicated executable just for the administrative tasks. And I spawn it with elevated rights. The button on my dialog has a Shield to indicate it will need to run with elevation.
Of course you can right-click an executable and run with elevation. But programatically? If it is even possible? I would start a new question for that.
To address your original question, you need administrative rights to delete froms from that special folder.

Use of `ofstream` appears not to create nor write to file

At the end of a simulation, I want to write some results as an appended row to a data file. The code I am using is the following, where you can assume that outFile was correctly allocated as an std::ofstream, that output_file is a std::string containing a valid path to a file that does not yet exist, and that the variables printed out to the file are just int types that get values during the simulation.
outFile.open(output_file.c_str(), std::ios::out | std::ios::app );
outFile << num_nodes << ", " << tot_s << ", " << tot_c << ", " << tot_d << std::endl;
outFile.close();
I've checked whether it correctly opens the file with the ofstream::is_open() function and it returns false. However, I can't figure out why. I've tried it with many different file names and directory paths, all of which I have checked and they are valid (no typos, etc.)
The file being written is just into a folder on the desktop where I create files all the time, so I don't see how it could be a permissions issue. If it was a permissions issue, how can I check that?
Otherwise, what else can be preventing it from writing to the file?
Added:
Following up on the comments, after adding a call to perror(), it is displaying the "No such file or directory" error. The file path in question is:
/home/ely/Desktop/Evolutionary_Dynamics/GamesOnCycle/data/test.data
I want this file to be created, and all the directories in that path exist, it's all spelled correctly, etc., and there are no weird permission issues with the GamesOnCycle folder or its data subfolder. Note that it is a linux system (Ubuntu 11.04) so the forward slashes are correct for the file path, unless I'm missing something that C++ has to have w.r.t. file paths.
This could be happening due to several reasons.
1) The file is already open.
2) All the directories in the file path are not created.
3) Lack of file permissions.
For an additional reference, please see When will ofstream::open fail?
This may sound bad, but are you on windows or linux? If windows, for your file path, do you have it defined with double "\" in your string, or just one? If just one, you aren't putting the characters in your path that you think you are. To be safe, use the "/" character.
So if you had this:
string pathname = "C:\Users\me\Desktop";
That is NOT a valid path. You are escaping "\U", "\m" and "\D" into your string. You'd need this:
string pathname = "C:\\Users\\me\\Desktop";
or
string pathname = "C:/Users/me/Desktop";
The "/" isn't an escape character.
It's what seems likely to me.

Ifstream open() doesn't set error bits when argument is a directory

In a C++ program, using std::ifstream, I'm attempting to open a user-specified file -- so far so good. However, I accidentally entered a filename that's actually a directory, and I was quite surprised to see that attempting to open() that directory didn't generate any errors.
Here's a minimal example:
std::ifstream f;
f.open("..");
if(!f.is_open() || !f.good() || f.bad() || f.fail()) {
std::cout << "error bit set on open" << std::endl;
return 1;
}
No sign of error here. If I go on and attempt to getline(), getline() sets an error bit all right.
std::string str;
getline(f, str);
if(f.eof()) std::cout << "getline set eofbit" << std::endl;
else if(f.bad()) std::cout << "getline set badbit" << std::endl;
else if(f.fail()) std::cout << "getline set failbit" << std::endl;
This outputs "getline set badbit", which is reasonable. Using the >> operator throws an underflow exception, which is also okay.
Now, my question is, how could I detect that the user entered a directory name instead of a proper filename? Is there any way to do that? Getting and ungetting bytes from the stream seem tedious and error-prone.
Also, why is this so? I realize that it's all just the same data from the point of view of the program, but I'd assume the OS would also send some "hey, this is a directory" kind of message.
You don't say what your system is, so it's hard to say, but generally,
filebuf::open will only return an error if your system level open
fails. And I've worked on Unix systems where you could open() a
directory; I've even worked on some where you could read it after the
open (at least if it was a locally mounted filesystem).
As to what to do about it: about all I can think of is to try to get
the first character, then put it back. But this fails if the file is
empty, so it's not really a solution either. At the system level (and
from a QoI point of view, I'd expect filebuf::open to do this if the
system did allow opening a directory), you can use a system level call
(stat in Unix) to determine whether the file is a directory or not.
(There's a race condition, of course: between the moment you detect that
it's a normal file, and the moment you do the open, another process
could delete the file and create a directory. It's probably not a
frequent occurance, however.)

Check for writing permissions to file in Windows/Linux

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;
}

Reading a stream in C++

I have the following code:
ifstream initFile;
initFile.open("D:\\InitTLM.csv");
if(initFile.is_open())
{
// Process file
}
The file is not opening. The file does exist on the D: drive. Is there a way to find out exactly why this file cannot be found? Like an "errno"?
You should be able to use your OS's underlying error reporting mechanism to get the reason (because the standard library is built on the OS primitives). The code won't be portable, but it should get you to the bottom of your issue.
Since you appear to be using Windows, you would use GetLastError to get the raw code and FormatMessage to convert it to a textual description.
Answered here I believe: Get std::fstream failure error messages and/or exceptions
The STL is not great at reporting errors. Here's the best you can do within the standard:
ifstream initFile;
initFile.exceptions(ifstream::eofbit|ifstream::failbit|ifstream::badbit);
try
{
initFile.open("D:\\InitTLM.csv");
// Process File
}
catch(ifstream::failure e)
{
cout << "Exception opening file:" << e.what() << endl;
}
In my experience, the message returned by what() is usually useless.
Check the permissions on the root of the D: drive. You may find that your compiled executable, or the service under which your debugger is running, does not have sufficient access privileges to open that file.
Try changing the permissions on the D:\ root directory temporarily to "Everyone --> Full Control", and see if that fixes the issue.