How to check if any files are open in a directory? - c++

I am trying to delete all files in a folder, but if a file is left open, it will not delete. I need to check the folder for any open files, write their names to a text document, and then close the open files. As I don't have much experience, I am first trying to check one file in the same folder, then all in the same folder, then all in a different folder. I don't want to be to needy or demanding, so just some help with the first step would be nice.
I don't have a ton of experience coding, but I have tried using fstream and (name.is_open). I may be using them wrong, so I have not yet ruled them out.
// ifstream::is_open
#include <iostream> // std::cout
#include <fstream> // std::ifstream
void checkFiles() {
int done = 0;
while(done != 1){
std::cout << "Enter 0 for continue or 1 for done: ";
std::cin >> done;
std::ifstream ifs ("test.txt");
if (ifs.is_open()) {
// Print that file is open, then close
std::cout << "File is open\n";
std::ifstream.close():
}
else {
std::cout << "File not open\n";
}
}
For this bit of code, if the file is open, it should say "File is open."
If not, it should say "File not open"
Even if I force quit the .txt file, it still says that it is open.
Eventually, I want to have a new file that displays what files were open, as well as closing all the open files.

Standard C++ offers us the filesystem library to handle files and directories (standardized in C++17). However, checking which files are open is not - as far as I can tell - a feature of that library.
The is_open() method for std::fstream's is something completely different than what you're trying to check for: It tells you whether the particular stream object is in an open state (which would mean association with an open file) - and it doesn't use the OS to check which files are open. Typically, it's just a way to check whether you've closed it someplace else in your own program; at most, it might ensure that the OS has not unilaterally closed the OS-side file access handle. So, you won't get anywhere in that direction.
I also believe, though I'm not 100% certain, that Boost doesn't have a library which offers this capability, either. Boost's filesystem library is almost identical to std::filesystem, as the latter was based on it.
So, to the best of my knowledge, you either need to directly use operating-system-specific calls to do this, or look for a library offering this functionality, elsewhere.
If you haven't found anything else, you could track how this is currently done with what's available in userspace. There's a utility called lsof. It's available on some operating systems based on Linux, Darwin, FreeBSD and Solaris (e.g. available on MacOS). It's maintained here. The source code seems to be rather atrocious C. An intrepid developer could parse that mess, figure out what it does, extract the parts relevant for your specific use case, and refactor it into a reasonable, readable and short(ish) C++ function. I realize you (OP) might not be up for it at this point, but - maybe someone else reading this answer will get inspired to do it.

The pfiles command shows the open files for a process. You can run it for all or some processes.
However, Solaris (and UNIX) in general allows you to delete open files. The file can still be read and written while it is open (but deleted), but nobody else can open the same file and the file will be deleted when all processes have the file closed.

Related

Error in a C++(files and streams) program for creating a file

I have written this program in order to create a file using fstream and the output should show either the file has been created or not. I have run it on several online compilers like Codechef,C++ shell etc. The compilers has successfully compiled this program but the output is not coming accordingly, instead of saying file created compiler says error in creating file.
Can this be due to development tool?
Following is the code for this program:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
fstream file;
file.open("a.txt");
if(!file)
{
cout<<"Error in creating file!!!";
}
else
{
cout<<"File created successfully.";
file.close();
}
}
fstream.open() will fail if the file does not exist.
To create the file if it doesn't exist
file.open("a.txt", ios_base::out);
Or use ofstream
ofstream file;
file.open("a.txt");
The fstream constructor and open function open for read/write by default. The file must already exist to be opened in this mode. Instead, open for write:
file.open("a.txt", ios::out);
Your program's behavior is probably depending upon the operating system. BTW, if you want to learn more about them, read Operating Systems: Three Easy Pieces. Perhaps the current working directory already contains the file to be written or does not have the appropriate permissions (it should be writable to enable file creation). Details are operating system (and perhaps file system) specific. IIRC, some OSes (Windows probably) disallow opening a file which is already opened by some other process.
On Linux, you could use strace(1) to find out what system calls have failed (actually, it tells you all the system calls that have been executed by some given program or process).
This is [probably] not always guaranteed by C++ standards (but see sync_with_stdio), but many C++ standard libraries are above (and compatible with) the C standard library which sets errno(3) (see also strerror(3) and perror(3) ...) on failure; then you might try:
fstream file;
file.open("a.txt", ios::out);
if (!file) {
// perror("a.txt");
cout<<"Error in creating file!!!" << strerror(errno) << endl;
}
Of course, as other answers told you (this & that) you need the correct mode for open...
See also std::system_error

Open a txt file with texteditor while its already opend by "fopen()" and in use?

Logger for my program. I saw in another program that it’s somehow possible to open and read a file with text editor while the program is still using it. Seems it just opens a copy for me and continue logging in the background. This kind of log system I need too. But if I use fopen() I only can open and read the file with my text editor if the Programm already closed it with fclose(); This way would work but I think its a very bad solution and also very slow... to open and close the file on every log :S
Someone knows how the needed log system is working?
P.S. I'm working in VisualStudio 2013 on Windows 8.1
Sry for my bad English :S
There are 2 different problems.
First is writing of logs. In a Windows system, the buffering will cause the data to be actually written to disk :
if you close the file
when you have a fair quantity of new data (unsure between several ko and several Mo)
if you explicitely flush
Unless if you have a high throughput, I would advise to at least flush (if not close) after each write to avoid loosing logs if program crashes. And it also allows you to read the log file in real time.
Second is reading. Vim for example is known to be able to monitor a file that can be modified by an external process. It will open a popup saying that file has been modified and offer to reload it. I do not know what notepad does in same conditions. But :
it does not have sense unless first problem has gone
it is not very efficient since you will reload whole file each time
IMHO, you'd better write a custom reader that mimics Linux tail -f :
read (and display) until end of file
repeteadly read (with a short sleep after an unsuccessful read) to process newly added data
It all depends on the text editor you are using. Some will notice edit to the file and ask you if you want to reload a fresh version.
If you work on linux, and you'd like to have an idea of what's happening in real time you could do someting like
tail -f <path-to-file>
or if the file doesnt yet exist
watch -n 0,2 "cat <path-to-file> | tail"
which will display the content of the file and refresh it every 0.2 sec
Thx for your fast answers :)
Crazy.. i was working so long with fopen() and found no solution.. also the fflush(pFile) didnt help (I wasnt able to open file.. always error that its already in use by another program). I never tryed the fstream. Seems fstream solved my problem now. I can open my file with msnotepad.exe while the program is still writing to the file :) Here a small test-code:
#include <fstream> #include <iostream> using namespace std;
int main(){
ofstream FILE;
FILE.open("E:\\Log.txt");
for (size_t i = 0; i < 50; i++)
{
FILE << "Hello " << i << endl;
cout << "log" << endl;
_sleep(500);
}
FILE.close();
cout << "finish" << endl;
return 0;}

What would cause ifstream code to fail on OS X?

I have the following code
string fileName = "assets/maps/main.json";
std::ifstream file(fileName);
std::string temp;
if(!file.good())
{
LOG(logERROR) << "Failed to open map file: " << fileName;
//return;
}
LOG(logDEBUG) << "file Char Count: " << file.gcount();
while(std::getline(file, temp))
{
mapString += temp;
}
file.close();
This code works superbly on Windows 8. When I take this program over to OS X, the file fails to open 100% of the time. Or to be more concise, file.good() never returns true. I intentionally commented out the return there to help debugging for later code.
Anyway, this has driven me insane. I cannot figure out why it's failing on OS X. I've tried different directories, re-created the file on OS X to make sure it wasn't an encoding or line-end issue, nothing at all.
What else can I do to debug, or what might I try as an alternative?
I've also checked the file permissions themselves and they are all fine. I have many other types of files in the same directory structure (images, music, fonts) and they all open fine, it's just this JSON file that fails, and any new derivatives of this file also fail.
When you start a program on Linux or MacOSX, the working directory will be wherever the user is. So, if your game needs to find files, you need to make use of the appropriate preference system. Mac has a concept of a 'bundle' that allows a program to come with data files and use find them, you'll have to learn how to make one. You can look inside all the '.app' directories in your /Applications directories for many examples.

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

Checking for file existence in C++

Currently I use something like:
#include <sys/stat.h>
#include "My_Class.h"
void My_Class::my_function(void)
{
std::ofstream my_file;
struct stat file_info;
if ( filename_str.compare("")!=0 &&
stat(filename_str.c_str(),&file_info) == 0 )
{
my_file.open(filename_str.data(),std::ios::trunc);
//do stuff
my_file.close();
}
else if ( filename_str.compare("")==0 )
{
std::cout << "ERROR! ... output filename not assigned!" << std::endl;
}
else
{
std::cout << "ERROR! File :" << std::endl
<< filename_str << std::endl
<< "does not exist!!" << std::endl;
}
}
...is this a decent way to go, or is there a better alternative? Seems like I could run amuck of permissions if I don't have permissions to read the file.
This is NOT a homework, question, it is a question about best practice.
I'd use the boost::filesystem constructs. Not only are they cross platform, they're part of the next standard library.
Generally I think it is best to just try opening it and catch an error.
IMO, checking permissions is unwise because what if it's a Linux box and you check its attributes, decide you can't write to it, but the filesystem supports ACL's and they do grant you permission? (As a sysadmin I can't stand when apps do this. I like ACL's and if you're an app, don't tell me you can't write to a file unless you've tried first.)
Conceptually, I'd say it depends on what you're planning to do with that file..
If you need its contents, go ahead and try to open it, and be prepared to handle failure gracefully, for the reasons Ken detailed.
If you are not currently interested in its contents (for example, when enumerating directory contents, or only planning to access a file at some point in the future, etc.), you might be better off just checking attributes for now. Otherwise, nasty things like hierarchical storage management may trigger an expensive (=slow) recall of file contents from, say, a tape backup or network (whereas attributes may have been cached). You could try to avoid that by checking for respective file attributes, but that's additional complexity, too.
So as a best practice, I'd suggest to open files sparingly (i.e., if you're not immediately interested in the contents, contend yourself with file attribute-based information), AND handle failure strictly in response to the actual call that opens the file when you need it.