Directory watcher for file open - c++

I am using ReadDirectoryChanges (for windows) and FSEventStreamCreate (for macosx) to watch for activities in a particular directory.
Unfortunately they both seem to be limited to reporting for events that modify in one or another way the content in the directory.
Is there any API (documented or not), tricks or whatever way that I can use to detect open for read access to a file in a directory.
P.S. My priority is windows and mac, but if you know how to do it in linux please feel free to share it.

Related

Running a process inside a virtual file system?

What I'm trying to achieve is to run a program, which thinks a folder exists within its own folder while actually the folder is somewhere else on the system.
So my program would launch a process and say to the process: Folder A which is at C:\A is within your own directory at C:\Program Files (x86)\SomeProgram\A
So the "virtual" directory would only be visible to that process.
I'm using Qt to program my program, so if there are any Qt functions I could use that would be great (in relation to portability). However, plan C++ or any windows-bound API's would be fine.
I was thinking about NTFS junctions or symbolic links but I would have no idea how to create either of those in C++, let alone bind them to a specific process.
Thanks in advance!
EDIT:
In relation to the above, I've found this question: https://superuser.com/questions/234422/does-windows7-support-symbolic-links-folder-shortcuts. However, it only shows how to perform the required actions from the command-line and it wouldn't be process bound.
EDIT 2:
Some extra information: I'm trying to create a virtual directory that is made up of a couple of other directories but then merged (I'm using a priority system to decide which files "win" from other files). These merged directories would then appear to the target process as one directory containing the merged files.
I think I'm going to stick with Window's mklink command. It seems to suit my needs the best.
What I'm going to do is use QFile::link() on all operating systems that aren't Windows, and QProcess with mklink on windows. This should work on every operating system.
For a good example look here: https://stackoverflow.com/a/21013935/979732
Such tasks are accomplished by use of a filesystem filter driver. The driver intercepts OS requests going to the filesystem and lets you insert your own virtual files and directories into the existing directory on the disk. Filter driver can be an overkill for your particular task, though.
Detours approach mentioned in comments requires system-wide hooking of file APIs and will slowdown the whole system(filesystem filter driver is attached to one disk and it's a documented approach, so it's faster and more robust).

How does Pismo File Mount mount ZIP files onto Windows Explorer?

I have been using Pismo File Mount for many years, and I have always wondered how it actually works.
Let's say, I am currently working on an application that creates a package format similar to the ZIP format. For ease of access, I want to create a shell extension that works similar to how Pismo File Mount works. For those who have not used Pismo File Mount before, this is how it works:
The user right-clicks a ZIP file in Windows Explorer.
The user then clicks "Mount" to mount the ZIP file.
The user can now access his/her files immediately.
The user does not have to extract the ZIP file to view its contents.
There's a catch. I do not want to use the Pismo File Mount API, perhaps for various reasons like commercial or legal ones.
The question is, how does Pismo File Mount integrate itself into Windows Explorer programmatically, in terms of the Windows API and C++?
I wrote Pismo File Mount, and the ZIP reader included in the PFM Audit Package.
There is no consise or realistically postable answer to the question. To do what PFM does, in C/C++, to Windows API's (kernel and user), it would take 10's of thousands of lines of difficult code and a large time investment.
PFM is built as a file system driver (kernel module), with user mode support DLL's and executables. The driver uses a protocol to talk with user mode formatting code that (for example) decodes the ZIP file format and serves the contents through the kernel mode driver to client applications.
There exist two ways:
Shell namespace extension. The folder created by the shell namespace extension is not an actual filesystem folder and accessibility of the files in such folder is usually limited to Explorer itself and applications aware of shell extensions and the ways to work with them.
Filesystem filter driver which creates a virtual directory on the existing disk. Such directory is seen by all applications as a real directory, where those applications can read and write files and subdirectories. All filesystem operations go through such driver.
Pismo File Mount works via the filter driver, AFAIK.
Our CallbackFilter product provides a way to create virtual directories and files. It includes a driver and calls your user-mode code for actual operations. But filter approach is a bit complicated -- a virtual disk created with a filesystem driver (eg. with our Callback File System product) is easier to implement and manage due to differences in architectures of the filter driver stack and filesystem drivers.
Sounds like a fairly ordinary shell extension. Explorer has a powerful extension mechanism which allows it to list non-file objects such as Printers and the contents of a zip file. The particular details (columns and rows) are provided by a DLL.
You can observe this by zipping up a set of images; the ordinary thumbnail view probably won't work as that part of Explorer is usually not copied.

How to open a "Open directory" GUI with C++ in ubuntu?

I am writing a C++ program for pattern recognition in OpenCV. Prompting for a user input, when user enters the option for "Viewing the Image Database", I want a window showing the files in that directory. I tried a system call with
system("nautilus /home/sample/index.jpg");
but it says that it could not find the directory and asks to check spelling. I was wondering if it was because of executing the program from a different directory. Could anyone explain why this is happening? If so, how to go around it?
You have to use default set file manager, not nautilus or any other.
Try to look over here: Linux default applications, How to find the default file manager
If you want to open nautilus, put the full path (probably /usr/bin/nautilus but you can easily discover using the which command).
Some further notes:
Not all Linux systems have Nautilus (Mint, for example, has replaced Nautilus with nemo)
If you want to make interactive windows, then you need a proper graphics library. In this case, since you are programming in C++, I suggest you to use Qt which is available on all Linux desktop distributions.

c++ find main operation system directory

I am trying to create file in main directory of operation system(for example Windows in my "c" disk) using c++.
Is there any better way than iterating all disks and search for "Windows" folder? Also its similar in mac and linux?
In Windows, you can call GetWindowsDirectory function (link). In Linux and Mac (I think), there's no such thing as main system directory.
However, as David noted, you should not put any files there:
This function is provided primarily for compatibility with legacy applications. New applications should store code in the Program Files folder and persistent data in the Application Data folder in the user's profile. For more information, see ShGetFolderPath.

Win32 files locked for reading: how to find out who's locking them

In C++ (specifically on Visual C++), sometimes you cannot open a file because another executable has it opened and is not sharing it for reads. If I try to open such a file, how can I programatically find out who's locking the file?
In Windows 2000 and higher, you cannot do this without using a kernel-mode driver. Process Explorer and other similar tools load a driver automatically to accomplish this. This is because the file handles are in kernel space and not accessible by user-mode applications (EXE files).
If you are really interested in doing this, take a look at this project.
The MSDN approved way is IFileIsInUse::GetAppName(). Requires Vista, though.