File system libraries that allow mounting on an application level - c++

I have been looking into libraries for a file system that will allow path mounting on purely an application level. This may not be called just "path mounting" since that has the connotation of os level path mounting, but something else, I am not sure of the terminology. I was hoping to be able to find a few but were unable to find anything to what I am looking for (boost::filesystem was the closest I found). I wanted to be able to compare several different libraries in hopes of seeing what advantages and disadvantages they have.
What I mean by a file system with path mounting is so I would have a path such as
"SomeRoot:data\file.txt"
and the "SomeRoot" would be replaced with C:\SomeFolder", which would be set to the file mount system.
Does anyone know of a file system that will allow path mounting?
Edit:
Since it appears that there may not be many libraries for this, I would also be interested in how to construct one properly.

If you are looking for an "application level file system" then at the most basic level, you are going to need to do a string replace. On the most basic level there are two strings
MountPoint
Which will be used as the "mount point", such as your SomeRoot.
MountResolve
Which is the location to what mount point is pointed at for when "resolving" a file location. This is the same as your C:\SomeFolder.
Besides for the obvious accessor and getters for those variables, there is the need for a function to resolve the path, which is this case can be
bool ResolvePath(const String& mountPath, String& resolvedPath);
The contents of the ResolvePath are very simple, all you need to do is replace the current MountPoint string in mountPath and place the result into resolvedPath.
resolvedPath = mountPath;
resolvedPath.replace(0, mMountPoint.size() + 1, mMountResolve.c_str(), mMountResolve.size());
However, there is more that can be done in that function. The reason why I have it returning a bool is because the function should fail mountPath does not have the MountPoint. To check, just do a simple string::find.
if(mountPath.find(mMountPoint) == String::npos)
return false;
With this, you can now resolve SomeRoot:data\file.txt to C:\SomeFolder\data\file.txt if MountResolve is set to C:\SomeFolder\. However, you mentioned without the trailing slash at the end. Since there is nothing to be currently done to verify that slash, your result would be C:\SomeFolderdata\file.txt. This is wrong.
On your access for setting the mount resolve, you want to check to see if there is there is a trailing folder slash. If there is not, then add it.
void FileSystem::SetMountResolve(const String& mountResolve)
{
mMountResolve = mountResolve;
if(*(mMountResolve.end() - 1) != FOLDERSLASH)
mMountResolve += FOLDERSLASH;
}
This will allow a basic "FileSystem" class to have one MountPoint/MountResolve. It will not be very difficult to extend this to allow multiple mount points either.

I have been looking into libraries for a file system that will allow path mounting
You should forget about it. mounting a path/drive can be blocked on linux (administrator privilegies might be required), and on windows there is no built-in mechanism for that (there are directory junctions, though). On certain distros you have to be root to mount even cdrom drive. Manually.
Does anyone know of a file system that will allow path mounting?
ntfs, ext3, jfs. Operation might require root/administrator privilegies.
and the "SomeRoot" would be replaced with C:\SomeFolder"
You need to use something similar to environmental variables in your program. Use "${SomeDir}/path" and replace ${SomeDir} with whatever you want. That'll be much easier to implement than mounting.
--EDIT--
What I mean by a file system with path mounting is so I would have a path such as
"SomeRoot:data\file.txt"
Provide custom wrapper for fopen or whatever you use instead. Or make custom class that implements "File". In that class/wrapper add support for "mounting" by doing search/replace on provided file path - possibly using collection of variables stored within the program. That's the easiest solution. Of course, you'll also have to wrap other file functions you'll use, but that's still much easier than doing cross-platform mounting.

You might also want to consider PhysicsFS. In essence, it is a library that abstracts the location of files. You may define a "search path" and whenever you read a file it is searched in those locations, i.e., folders or archives. For example, if you want to read "logo.png", it might be searched in locations such as:
C:\mygame\data
E:\mygame\data (read-only CD-ROM)
C:\mygame\data.zip
When writing a file, it is always stored in a special "write path".
PhysicsFS also has a concept of application-level mounting. Citing from their webpage:
PhysicsFS 2.0 adds the concept of "mounting" archives to arbitrary
points in the search path. If a zipfile contains "maps/level.map" and
you mount that archive at "mods/mymod", then you would have to open
"mods/mymod/maps/level.map" to access the file, even though
"mods/mymod" isn't actually specified in the .zip file. Unlike the
Unix mentality of mounting a filesystem, "mods/mymod" doesn't actually
have to exist when mounting the zipfile. It's a "virtual" directory.
And, of course, the whole solution is 100% user-space and requires no kernel support nor administrative privileges.

FUSE on Unix, FUSE4X on MacOS X, our Callback File System with FUSE adapter on Windows. There's no single cross-platform solution because the architecture of file system drivers is different on those platforms.

Seems like you are looking for symbolic links functionality.
On Posix systems, e.g. Linux/Unix you can look into link()/symlink(). This functionality has been there forever and is pretty solid.
On Windows you may want to look into CreateSymbolicLink() and company. These were introduced with Windows 2000 and I'm not sure how robust they are.
Actual mounting of filesystems is trickier business and really depends on what you are mounting - NTFS, FAT, ext3, XFS, NFS, CIFS, WebDAV, etc, etc.

Related

Is there such a thing as a posix lstatat call?

I am working on a FUSE and I have a file descriptor to the directory prior to mounting the fuse on top. I want to use that handle to read/write files with state information underneath the FUSE mounted file system, and then to be able to access that data next time I mount it. So I cannot use the normal lstat call since it won't see the files I want to access, but the files FUSE exposes instead. What I need is the equivalent of fstatat that works for symbolic links, since fstatat apparently gives the the stat info on the file the symbolic link points to, not the symbolic link itself. Yet I cannot find documentation for such a function. Does it exist? Am I thinking of an incorrect name?
There is no lstatat() function in POSIX, however, fstatat()
takes a flag argument which can be AT_SYMLINK_NOFOLLOW,
which may do what you're looking for.

C++ / Qt: track filesystem changes

I'm currently trying to implement a c++ program which monitors a folder on the filesystem. On initalizing the application, it scans the Directory and saves some meta information about it.
when something is chenged while the program is active, i can read changes to the folder (for examlpe changing the name of a folder or a file). But i can't track changes to the Directory while the program isn't running. Upon startup i would get
Removed folder X
Added folder Y
instead of
Renamed folder X to Y
is it possible to identify a directory in another way than it's path/name?
if yes, how would i gather that information in C++ / Qt ?
Rather than reinventing the wheel, you could just use the class QFileSystemWatcher which the Qt docs states: -
The QFileSystemWatcher class provides an interface for monitoring
files and directories for modifications
If you want the program to run all the time, then you may want to look at creating a service (in Windows) or daemon (Linux / OSX).
This is filesystem-specific, but generally yes this is possible. FAT is the main exception, I think. But you won't find code for this in the C++ Standard Library or Qt. It's just too unusual, so you'll need OS-specific code if not filesystem-specific.
Like TheDarkNight said, you need to use QFileSystemWatcher to avoid portability and so other problem.
But if you want to continue your approach:
In GNU/Linux land, you can check this with inode struct of directory (take care of symbolic link issue).
inode struct have an index for example you can get it on shell with:
ls -id /path/to/your/folder
There is an API to access inode. You can google inode struct linux for it.
In Windows garden, you can get file id when accessing handle in the struct BY_HANDLE_FILE_INFORMATION:
nFileIndexHigh
The high-order part of a unique identifier that is associated with a file.
For more information, see nFileIndexLow.
nFileIndexLow
The low-order part of a unique identifier that is associated with a file.

How to create virtual file system that file path can be accessed same as disk

I need to create FileSystem type of thing in memory or on disk, which can be accessed same as file on disk, which path is can be used in function like fopen(),etc.
Details:
I am using AddFontResourceEx function to load font in application. Since this function require file path so that file need to present on disk. But I've requirement, that the user cannot access/see the font file.
I tried AddFontMemResourceEx function, but the loaded font is not enumable so that user cannot see the font in the application. Also I tried with some library which create VFS, but they work like database, i.e you can create file/directory and access them. But cannot use their file path in AddFontResourceEx or any other function.
Is there exist some way by which I can create a Virtual FileSystem in memory or on disk which can be accessible through my application and I can write/read file on this virtual filesystem created and it's file path can be used by AddFontResourceEx function.
It can't really work. Yes, you can add a "virtual" file system. But either it's visible to user X or it isn't. Access Control on Windows works on a per-user base, not a per-program base. So, if user X can see the font in application A, he can also see it in application B - even if B is Explorer.EXE.
If the user is an administrator, you can't really prevent them from seeing the font file if they're determined enough. They could, for example, reverse engineer your program to figure out how you're generating the file and repeat the process by hand to make their own copy. Or (even if you could somehow tie the file permissions to your process) they could insert their own code into your process to retrieve the file, or to retrieve the font information directly from memory.
If it's good enough to make it difficult for them to see the font file, you could try this:
Create a directory in the temp folder, with write-only permission for the current user and no permissions for anyone else.
Create a sub-directory with a long, complex, cryptographically random name, and with full permission for the current user. (The name should be different each time.)
Write the font file to the sub-directory and load it.
Delete the font file and remove both directories.
The entire process should take only a fraction of a second, which should make it somewhat difficult for the user to override the permissions and retrieve the file. If they use a debugger to single-step through the program then I guess you're out of luck, but as I already pointed out, nothing's going to stop everyone.
Another option, presumably, would be to just use AddFontMemResourceEx and put up with the fact that the font isn't then enumerable. You'd just need to change your code so that wherever it enumerates fonts it adds your font(s) to the list manually.
If you didn't get the right answer, maybe you didn't ask the right question
Your post title mentions "virtual filesystem", but. later, you mention "accesing a font".
"Virtual Filesystems" its an ambiguos term used in several ways.
One common case, means adding devices or networks to an O.S.
In your case, seems like accesing from a an application.
There are several ways ( "libraries" ) to emulate or work with a filesystem.
Some of them work independent of the real filesystem. You work with them, save data in those "virtual" folders & files, and copy data from the real and the virtual one.
Some of them work, as a extension layer, between the real filesystem, and the programming filesystem.
Example: I worked with an application, that required temporally fast I.O. access. Found a library, that when you want to create a folder or save a file in the real filesystem, was done.
Additionally, I could add "virtual drives" that where stored in memory, but, accessed with file system operations. When the application finished, the "hard drives" and their data where erased from memory.
Its seems that your case is similar to my example.
What do you want a "virtual filesystem" library for ?
I have seen onb the web, several libraries, for C++, open source, freeware, and commercial.
It depends what do you want to do, to find out, which library its the better for your case.
Good Luck

Export a .sqlite file in C/C++ (on windows)

It is possible to move a .sqlite file somewhere while not corrupting it in C or C++?
Somewhere could be another folder or something.
If so could you give me some tips/pointers.
Yes, of course. It is a regular file that can be moved around just like any other file.
The sqlite engine itself will make sure that it does not corrupt. Either it is in a clean state, or locked when being written to (with journaling).
One thing to remember that you should not use the database file on filesystems that do not have reliable locking, e.g. on network disks.
Well, it depends a little. It is just a regular file that (assuming nothing is connected to it, writing to it at the time) can be copied without problem. Welcome to the world of open source systems where things really are that simple (ie you don't need to update the registry, a config file or two, reapply installer settings or anything like that).
However, things are tricky if something is using the file. When an app opens a sqlite file it can tell the OS to lock it - the default is open with exclusive access for the opening app (using a certain flag). In such a case, you will not be able to move the file as the OS will prevent it until the app that has it locked is stopped.

C++ : Opening a file in non exclusive mode

I have to develop an application which parses a log file and sends specific data to a server. It has to run on both Linux and Windows.
The problem appears when I want to test the log rolling system (which appends .1 to the name of the creates a new one with the same name). On Windows (haven't tested yet on Linux) I can't rename a file that I have opened with std::ifstream() (exclusive access?) even if I open it in "input mode" (ios::in).
Is there a cross-platform way to open file in a non-exclusive way?
Is there a way to open file in a non-exclusive way,
Yes, using Win32, passing the various FILE_SHARE_Xxxx flags to CreateFile.
is it cross platform?
No, it requires platform-specific code.
Due to annoying backwards compatibility concerns (DOS applications, being single-tasking, assume that nothing can delete a file out from under them, i.e. that they can fclose() and then fopen() without anything going amiss; Win16 preserved this assumption to make porting DOS applications easier, Win32 preserved this assumption to make porting Win16 applications easier, and it's awful), Windows defaults to opening files exclusively.
The underlying OS infrastructure supports deleting/renaming open files (although I believe it does have the restriction that memory-mapped files cannot be deleted, which I think isn't a restriction found on *nix), but the default opening semantics do not.
C++ has no notion of any of this; the C++ operating environment is much the same as the DOS operating environment--no other applications running concurrently, so no need to control file sharing.
It's not the reading operation that's requiring the exclusive mode, it's the rename, because this is essentially the same as moving the file to a new location.
I'm not sure but I don't think this can be done. Try copying the file instead, and later delete/replace the old file when it is no longer read.
Win32 filesystem semantics require that a file you rename not be open (in any mode) at the time you do the rename. You will need to close the file, rename it, and then create the new log file.
Unix filesystem semantics allow you to rename a file that's open because the filename is just a pointer to the inode.
If you are only reading from the file I know it can be done with windows api CreateFile. Just specify FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE as the input to dwShareMode.
Unfortunally this is not crossplatform. But there might be something similar for Linux.
See msdn for more info on CreateFile.
EDIT: Just a quick note about Greg Hewgill comment. I've just tested with the FILE_SHARE* stuff (too be 100% sure). And it is possible to both delete and rename files in windows if you open read only and specify the FILE_SHARE* parameters.
I'd make sure you don't keep files open. This leads to weird stuff if your app crashes for example.
What I'd do:
Abstract (reading / writing / rolling over to a new file) into one class, and arrange closing of the file when you want to roll over to a new one in that class. (this is the neatest way, and since you already have the roll-over code you're already halfway there.)
If you must have multiple read/write access points, need all features of fstreams and don't want to write that complete a wrapper then the only cross platform solution I can think of is to always close the file when you don't need it, and have the roll-over code try to acquire exclusive access to the file a few times when it needs to roll-over before giving up.