Version

All file system accesses go through the global library Filesystem object that can be retrieved with the GetFilesystem function. A Filesystem object provides a very flexible abstraction of the machine file system.

File driver and mount point

FileDriver abstracts access to files and directories behind a unified API. Different drivers are available to access files on the local machine or on a remote one. The most basic driver, and the one you will almost always need, is StdFileDriver which provides access to the local machine file system.

Mounting a file driver

While a driver can be used directly, all of the library load and save operations are working with files using the global Filesystem object. You can mount a specific driver on the library file system object to control where these operations will get and store their files to.

For example, when saving a file to c:/tree.geo the file system is queried for the adequate driver to write the file with. In this case, mounting StdFileDriver with no prefix will direct the access to the OS standard library.

# create a new StdFileDriver and mount it on the file system
hg.GetFilesystem().Mount(hg.StdFileDriver())

Note: The library file system object is initially empty so you need to mount at least one driver in order to be able to read or write files.

The previous mount operation did not specify any prefix so the driver will be forwarded all accesses to the file system. It is possible to specialize file access to a particular path of the file system by using a mount prefix.

Mount prefix

When mounting a driver with a prefix, all accesses to a path starting with the specified prefix will be forwarded to this driver.

# create a new StdFileDriver and mount it on the engine file system under the "@std" prefix
hg.GetFilesystem().Mount(hg.StdFileDriver(), "@FS/")
handle = hg.GetFilesystem().Open("@FS/c:/tree.geo")  # the driver will operate on "c:/tree.geo"

Once a prefix is matched against a mount point it is stripped from the path before being forwarded to the driver.

Driver chaining

Driver chaining can happen in two different ways. Explicitly, such as with BufferFileDriver which wraps another driver to implement read/write buffering. And implicitly, through mount points.

A typical scenario in which implicit chaining happens is with the ZipFileDriver which needs to access a file before it can serve its content. Here is an example of serving files through a Zip archive stored on the local file system.

std_driver = hg.StdFileDriver("/app_path/", True)  # sandboxed access to the local file system
hg.GetFilesystem().Mount(std_driver, "@app/")  # mount under the "@app/" prefix

zip_driver = hg.ZipFileDriver("@app/data.zip")  # connect to archive on the local file system
hg.GetFilesystem().Mount(zip_driver)  # mount as a root driver (no prefix)

handle = hg.GetFilesystem().Open("test_file")  # open "test_file" on the root zip driver

Note: In the previous example any driver could be sitting in front of the zip archive driver under the @app/ prefix.

Sandboxing

Some file driver such as StdFileDriver supports sandboxing. You can specify a root path to serve through the driver and prevent any access outside of this path.

Let's say that we wish to serve our application files from a known directory on the local file system and prevent any access outside of this directory, this can be done like this:

driver = hg.StdFileDriver("/local_path_to_app_data/", True)  # True to enable sandboxing
hg.GetFilesystem().Mount(driver)  # mount as root driver

okay = hg.GetFilesystem().Open("test_file")  # opens "/local_path_to_app_data/test_file"
fail = hg.GetFilesystem().Open("../test_file")  # fails to open "/local_path_to_app_data/../test_file"