i am trying to output a buffer to a file using visual c++.
my code for doing it is-
FILE *stream;
stream=fopen("C:\\Users\\sshekha\\Desktop\\z.txt","r");
//I also tried with "w" mode
//the differencein behavious on executing these two is that when it is in read mode it
//executes the else condition in the code below whereas in "w" mode it executes the "if"
// condition,
//moreover even if i change the path it don't execute the "else" condition-that means this path
//is effective to the code. and the another surprising thing is when i open the file manually
// and then run the code with "r" mode it still executes the "else" part (which it shouldn't
// because the file is already open.)
if( stream == 0 )
{
MessageBox(m_hwndPreview,L" the file is not opened ",L"BTN WND",MB_ICONINFORMATION);
}
else
{
MessageBox(m_hwndPreview,L" the file is opened ",L"BTN WND",MB_ICONINFORMATION);
int check=fputs (HtmlFileContents,stream);
fclose(stream);
return 0;
}
I tried to check the results using different mode in order to understand whats teh probem going on . when i debug it , i get the value of (in Read mode) :
stream = 0x000000005c5c76f0 { _ptr=0x0000000000000000 _cnt=0 _base=0x0000000000000000 ...}
I don't know it gib=ves bad pointer and even then it go to else part of the loop. Why ?
and in write mode
stream = 0x0000000000000000 {_ptr=??? _cnt=??? _base=??? ...}
So go to the if part of the loop.
Moreover my path is correct and i have enough permission to do the task I wish. But why does it give bad pointer ? Why have I these strange values of stream and what should I do to copy the content of my buffer HtmlFileContents in to z.txt ? Any ideas ?
You're opening the file in read-only mode: fopen("C:\\Users\\sshekha\\Desktop\\z.txt","r");. Here "r" says you only intend to read from file. To be able to write contents (i.e. fputs(...)), open the file in write mode like so: fopen("C:\Users\sshekha\Desktop\z.txt","w")(or"a"` if you want to append). For more information, read fopen documentation.
EDIT: I see that you've tried both read and write modes. You're code only shows read-mode and hence my assumption on the read-only problem. Let me do a bit more research and get back.
Please write the following code in your if statement:
perror("The following error occurred:");
if you don't have a console, use this to store the error string:
char* errorCause = strerror(errno); MessageBoxA(m_hwndPreview, errorCause, "BTN WND", MB_ICONINFORMATION);
and let us know what you see as the cause.
EDIT 2: Since you've mentioned that you're using Visual Studio 2010, are you running it as yourself? This stackoverflow answer shows that VS2010 has different options when debugging applications; https://stackoverflow.com/a/3704942/210634
NOTE: That feature is only available on 'Pro' versions.
Here's a working example: https://ideone.com/hVLgc4
If the file is "read only", opening with it with write permissions should fail.
to see if that is the case,under windows:
right click the file
press properties
at the bottom, see if "Read-only" attribute i marked with "v"
(uncheck it if you desire writing to the file)
refer to :
http://msdn.microsoft.com/en-us/library/aa365535(v=vs.85).aspx
on how to change file permissions from your code
Related
I am currently working on a project where I need to read windows events .
I am using OpenEventLog() and ReadEventLog() from Win API. I can read the events from system using the typename of the event.
But I need to specify the file name or file path of the .evtx file that I have saved from the EventViewer.I tried the below code,
HANDLE logHandle = OpenEventLog(NULL, "C:\\Users\\MyAccount\\Documents\\myevents.evtx");
DWORD status = GetLastError();
if(logHandle == NULL){
cerr<<"NO HANDLE GENERATED!!!"<<endl;
}else if(status == ERROR_INVALID_HANDLE){
cerr<<"INVALID HANDLE!!!"<<endl;
}else if(status!=0){
cout<<"OPENEVENTLOG ERROR STATUS::>"<<status<<endl;
}
But it does not find the specified file and switches over to default Application Events. Can anyone please tell me what the problem could be? or if there is anything to be changed in the code?
PS: I even tried placing the file in project folder and specifying just the filename(myevents.evtx) , but still doesn't work.I also tried reading the evtx directly as shown in "Reading .evt/.evtx files directly" , but later I found this can't be done. Apparently there is no way to read them directly without win API or without writing a whole bunch of parser code.
Thanks in advance.
Well, it turns out OpenEventLog() is not meant for opening saved .evtx files.
I should've been using OpenBackupEventLog() for that.
For completeness, I'm using C++ in Visual Studio 2012 under Windows 7.
I have some basic file reading code:
Defined in class:
std::ifstream iniFileHandle;
Method in question:
FileLoader::FILE_STATUS FileLoader::loadFile(const std::string& fullpathandfilename)
{
if (fullpathandfilename.empty())
{
iniFileStatus = FILE_NOT_SPECIFIED;
}
else // parameter has 'something'...
{
if (!doesFileExist(fullpathandfilename))
{
iniFileStatus = FILE_NOT_FOUND;
}
else // file found...
{
iniFileHandle.open(fullpathandfilename, std::ios::in);
if (!iniFileHandle.is_open()) // something went wrong
{
iniFileStatus = FILE_CANNOT_LOAD; // <== HOW TO TEST?
}
else // file opened!
{
iniFileStatus = FILE_OPEN;
}
}
}
return iniFileStatus;
}
All this works fine but I'm having difficulty getting coverage with Google Unit Tests.
What i'm missing is a way to simulate/create a scenario where is_open() fails.
I've tried:
read only files
the 'exe' being currently run
a file opened in another application
but they all open.
Is this error condition actually possible to occur? If so, how can I mimic the failure so I can test it?
As mentioned in the comments, trying to open a directory will cause is_open() to return false. The cases you tried all succeed because you open the file as read-only (std::ios::in, which is also the default for an ifstream).
I've tried:
a file opened in another application but they all open.
This happens because file is opened in share mode which allows reading for others. You need to open file in exclusive file access mode. To achieve it, if you use MSVS, you could pass the third parameter int _Prot to the ifstream, otherwise you could use CreateFile().
To emulate the problem you could open file exclusively used by Windows, e.g:
c:\pagefile.sys
create a any file, and set its permission as read only, and in your code try to open this file for writing
I have been trying the following piece of code that does not work. What I am trying to do is to start executing my exe (one that I created a simple dialog based application using VC6.0) then from inside this application modify its own contents stored on the hard drive.
So there is a running copy of the exe and from this running copy it will open the disk copy into a buffer. Once loaded into a buffer then begin a search for a string. Once the string is found it will be replaced with another string which may not be the same size as the original.
Right now I am having an issue of not being able to open the file on disk for reading/writing. GetLastError returns the following error "ERROR_SHARING_VIOLATION The process cannot access the file because it is being used by another process.".
So what I did I renamed the file on disk to another name (essential same name except for the extension). Same error again about sharing violation. I am not sure why I am getting this sharing violation error code of 32. Any suggestions would be appreciated. I'll ask my second part of the question in another thread.
FILE * pFile;
pFile = fopen ("Test.exe","rb");
if (pFile != NULL)
{
// do something like search for a string
}
else
{
// fopen failed.
int value = GetLastError(); // returns 32
exit(1);
}
Read the Windows part of the File Locking wikipedia entry: you can't modify files that are currently executing.
You can rename and copy them, but you can't change them. So what you are trying to do is simply not possible. (Renaming the file doesn't unlock it at all, it's still the same file after the rename, so still not modifiable.)
You could copy your executable, modify that copy, then run that though.
void bot_manager_item::create_games()
{
games.clear();
std::ifstream paths_in("C:\\Users\\bill hank\\Documents\\bot_plugins\\directory_listing.txt", std::ios::in);
while (paths_in.good())
{
send_message("The path was good.");
char q[5000];
paths_in.getline(q, 5000);
send_message(q);
games.push_back(qanda(q));
}
paths_in.close();
}
The file I'm loading exists, what else might be wrong? paths_in.good keeps failing.
Edit: I figured it out. Wow am I annoyed by the answer to this. Basically Windows lets you say whether you want to show file extensions or not. This windows installation is set to say that the extension shouldn't be shown. So when I'm checking the file again and again I'm seeing: directory.txt and thinking that this means that everything is fine with the directory when in reality the filename was directory.txt.txt
If paths_in.good() keeps failing then it means that some of the stream error flags are set (badbit, eofbit or failbit).
eofbit - end of file was reached
badbit - error with the stream buffer such as memory shortage or an exception inside the stream buffer is cast
failbit - some other error beside eof was reached
In order to find out what happened, you need to check which errorbit is set first, and then find out more about the specific error, and what can cause it.
Out of curiosity, does this code output the contents of the file correctly? If this code works, then the problem is something else. If this code doesn't work, then that likely means that the file either isn't where you specified, or you don't have read permissions on it.
void bot_manager_item::create_games() {
std::ifstream paths_in("C:\\Users\\bill hank\\Documents\\bot_plugins\\directory_listing.txt");
char q[5000];
while (paths_in.getline(q, 5000)) {
std::cout << q << std::endl;
}
}
This code does a few minor things differently.
std::ios::in doesn't need to be explicitly specified for std::ifstream.
it doesn't use is_good, while that should be fine, you can just treat the std::ifstream as a bool which will be true when it is in a good state.
getline() returns a reference to the stream it operated on, so you can just put that whole line in the condition.
cosmetic, but no need to explicitly close the ifstream if it is about to go out of scope.
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;
}