Filesystem » CnxPath module

CnxPath provides utilities for working with filesystem paths and perfoming basic file system operations, such as checking the current status (or lack thereof) of a path on the filesystem, querying attributes of an existing path on the file system, creating and removing files, directories, and symbolic links, and retrieving semantically correct paths for certain special filesystem paths, such as the user home directory.

Example:

#include <Cnx/filesystem/Path.h>

void example(void) {
    CnxScopedPath path = cnx_string_from("/home/my_user/test.txt");
    let create_res = cnx_path_create_file(&path);
    cnx_assert(cnx_result_is_ok(create_res), "Failed to create test path");

    cnx_assert(cnx_path_is_valid(&path),
               "Path is not a valid filesystem path on this platform");
    cnx_assert(cnx_path_exists(&path), "Path does not exist!");
    cnx_assert(cnx_path_is_file(&path), "Path is not a file!");
    cnx_assert(!cnx_path_is_directory(&path), "Path is a directory !?");
    cnx_assert(!cnx_path_is_symlink(&path), "Path is a symlink !?");
    cnx_assert(cnx_path_is_absolute(&path), "Path is not absolute!");

    CnxScopedString name = cnx_string_from("test.txt");
    CnxScopedString name_without_extension = cnx_string_from("test");
    CnxScopedString extension = cnx_string_from("txt");

    CnxScopedString name_actual = cnx_path_get_file_name(&path);
    cnx_assert(cnx_string_equal(name_actual, &name), "path name is not test.txt!");

    CnxScopedString name_without_extension_actual
        = cnx_path_get_file_name_without_extension(&path);
    cnx_assert(cnx_string_equal(name_without_extension_actual, &name_without_extension),
               "path name without extension is not test!");

    cnx_assert(cnx_path_has_file_extension(&path, &extension),
               "path name does not have .txt file extension");

    CnxScopedString parent = cnx_string_from("/home/my_user");

    let maybe_parent = cnx_path_get_parent_directory(&path);
    cnx_assert(cnx_option_is_some(maybe_parent), "Path doesn't have a parent!");

    CnxScopedPath parent = cnx_option_unwrap(maybe_parent);
    cnx_assert(cnx_string_equal(parent_actual, &parent), "Path's parent is not /home/my_user!");

    let remove_res = cnx_path_remove_file(&path);
    cnx_assert(cnx_result_is_ok(remove_res), "Failed to remove test file!");
}

Typedefs

using CnxPath = CnxString
CnxPath is the system-agnostic path type for performing filesystem queries and modifications.

Functions

CnxPath cnx_path_user_home_directory(void)
Returns the path to the home directory of the user running this Program.
CnxPath cnx_path_user_application_data_directory(void)
Returns the path to the application data directory for the current user.
CnxPath cnx_path_user_documents_directory(void)
Returns the path to the documents directory for the current user.
CnxPath cnx_path_common_application_data_directory(void)
Returns the path to the application data directory for the system.
CnxPath cnx_path_common_documents_directory(void)
Returns the path to the shared documents directory.
CnxPath cnx_path_temp_directory(void)
Returns a path to a directory suitable for storing temporary files.
CnxPath cnx_path_current_executable_file(void)
Returns the path to the currently running executable.
CnxPath cnx_path_current_application_file(void)
Returns the path to the currently running application.
CnxPath cnx_path_system_applications_directory(void)
Returns the path to the system applications directory.
CnxPath cnx_path_current_working_directory(void)
Returns the path to the current working directory.
char cnx_path_separator_char(void)
Returns the path separator character of the host platform.

Defines

#define CnxScopedPath
Declare a CnxPath as a CnxScopedPath for the resources associated with the path to be automatically freed when the path leaves the scope.
#define cnx_path_free(path_ptr)
Frees the resources associated with the given path.
#define CNX_PATHS_CASE_SENSITIVE
TRUE if filesystem paths are case-sensitive on the host platform, FALSE otherwise
#define cnx_path_is_valid(path)
Checks if the given string would be a valid path on the host platform's filesystem.
#define cnx_path_new(path)
Creates a new path from the given string, canonicalized so as to be valid on the host platform.
#define cnx_path_is_absolute(path)
Checks if the given path is an absolute path.
#define cnx_path_is_relative(path)
Checks if the given path is a relative path.
#define cnx_path_get_absolute_path(path)
Returns the absolute path of path
#define cnx_path_exists(path)
Checks if the given path exists.
#define cnx_path_is_file(path)
Checks if the given path is a path to a file.
#define cnx_path_is_directory(path)
Checks if the given path is a path to a directory.
#define cnx_path_is_fs_root(path)
Checks if the given path is a path to a filesystem root (ie "C:\\" or "/")
#define cnx_path_is_symlink(path)
Checks if the given path is a path to a symbolic link.
#define cnx_path_get_symlink_target(path)
Attempts to get the path of the target of the symbolic link path
#define cnx_path_has_file_extension(path, extension)
Checks if the given path is a file with the given file extension.
#define cnx_path_get_file_extension(path)
Attempts to get the file extension of the file path
#define cnx_path_get_file_name(path)
Gets the file name of the given path, including file extension.
#define cnx_path_get_file_name_without_extension(path)
Gets the file name of the given path, without the file extension.
#define cnx_path_get_parent_directory(path)
Returns the parent directory of the given path
#define cnx_path_append(path, entry_name)
Appends the relative path entry_name to path
#define cnx_path_create_file(...)
Creates a new file with the path and name indicated by path
#define cnx_path_create_file_overwriting(file_path)
Creates a new file with the path and name indicated by path
#define cnx_path_create_directory(...)
Creates a new directory with the path and name indicated by path
#define cnx_path_create_directory_overwriting(dir_path)
Creates a new directory with the path and name indicated by path
#define cnx_path_remove_file(file_path)
Removes the file located at path
#define cnx_path_remove_directory(...)
Removes the directory located at path
#define cnx_path_remove_directory_recursive(dir_path)
Removes the directory located at path
#define cnx_path_create_symlink(...)
Creates a new symbolic link with the name and path indicated by link_name that points to the file or directory at link_target
#define cnx_path_create_symlink_overwriting(link_name, link_target)
Creates a new symbolic link with the name and path indicated by link_name that points to the file or directory at link_target
#define cnx_path_remove_symlink(link_path)
Removes the symbolic link link_path

Typedef documentation

typedef CnxString CnxPath

CnxPath is the system-agnostic path type for performing filesystem queries and modifications.

Example:

void my_example(void) {
    let_mut my_docs_dir = cnx_path_user_dcouments_directory();
    cnx_path_append(&my_docs_dir, "my_file.txt");
    // create the file "$HOME/Documents/my_file.text" if it doesn't already exist
    let_mut result = cnx_path_create_file(&path);
    // failed to create the file
    if(cnx_result_is_err(result)) {
        // do something
    }

    cnx_path_free(&my_docs_dir);
}

Function documentation

CnxPath cnx_path_user_home_directory(void)

Returns the path to the home directory of the user running this Program.

Returns Path to the current user's home directory

CnxPath cnx_path_user_application_data_directory(void)

Returns the path to the application data directory for the current user.

Returns Path to the current user's application data directory

For example, this would return $HOME/AppData on Windows, or $HOME/Library/Preferences on Mac

CnxPath cnx_path_user_documents_directory(void)

Returns the path to the documents directory for the current user.

Returns Path to the current user's documents directory

For example, this would return $HOME/Documents or "$HOME/My Documents" on Windows, or $HOME/Documents on *NIX

CnxPath cnx_path_common_application_data_directory(void)

Returns the path to the application data directory for the system.

Returns Path to the system application data directory

For example, this would return C:/Users/Public/AppData on Windows, or /Library on Mac

CnxPath cnx_path_common_documents_directory(void)

Returns the path to the shared documents directory.

Returns Path to the shared documents directory

For example, this would return C:/Users/Public/Documents on Windows, or /Users/Shared on Mac

CnxPath cnx_path_temp_directory(void)

Returns a path to a directory suitable for storing temporary files.

Returns Path to a temporary files directory

For example, this would return $HOME/AppData/Local/Temp on Windows, or /tmp on *NIX

CnxPath cnx_path_current_executable_file(void)

Returns the path to the currently running executable.

Returns Path to the current executable

On Mac if the executable is an app, this will return the path to the executable binary contained in the package. If you need the path of the package folder, use cnx_current_application_file instead. On other platforms cnx_current_executable_file and cnx_current_application_file are interchangeable.

CnxPath cnx_path_current_application_file(void)

Returns the path to the currently running application.

Returns Path to the current application

On Mac if the executable is an app, this will return the path to the application package folder. If you need the path of the executable binary, use cnx_current_executable_file instead. On other platforms cnx_current_executable_file and cnx_current_application_file are interchangeable.

CnxPath cnx_path_system_applications_directory(void)

Returns the path to the system applications directory.

Returns Path to the system applications directory

On Windows this returns the 64-bit applications directory ("Program Files"). For the legacy/32-bit applications directory ("Program Files (x86)") use cnx_system_applications_directory_x86 instead.

CnxPath cnx_path_current_working_directory(void)

Returns the path to the current working directory.

Returns Path to the current working directory

char cnx_path_separator_char(void)

Returns the path separator character of the host platform.

Returns The path separator character for the platform

Define documentation

#define CnxScopedPath

Declare a CnxPath as a CnxScopedPath for the resources associated with the path to be automatically freed when the path leaves the scope.

Example:

void my_example(void) {
    CnxScopedPath my_docs_dir = cnx_path_user_dcouments_directory();
    cnx_path_append(&my_docs_dir, "my_file.txt");
    // create the file "$HOME/Documents/my_file.text" if it doesn't already exist
    let_mut result = cnx_path_create_file(&path);
    // failed to create the file
    if(cnx_result_is_err(result)) {
        // do something
    }

    // no need to free `my_docs_dir`, it's automatically freed when it exits scope
    // since we declared it as `CnxScopedPath`
}

#define cnx_path_free(path_ptr)

Frees the resources associated with the given path.

#define CNX_PATHS_CASE_SENSITIVE

TRUE if filesystem paths are case-sensitive on the host platform, FALSE otherwise

For example, on *NIX systems this will usualy be TRUE, but on Windows this is FALSE

#define cnx_path_is_valid(path)

Checks if the given string would be a valid path on the host platform's filesystem.

Parameters
path - The path to check for validity. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
Returns bool - whether the path is valid

Checks if the given path is syntactically valid on the host platform's filesystem. Does not check if the path exists or is semantically logical.

Example:

// fails on all platforms because of mixed path separator use
cnx_assert(cnx_path_is_valid("/home\\my_user"), "Path /home\\my_user was invalid");
// fails on Windows because it uses *NIX style separators and fs root
cnx_assert(cnx_path_is_valid("/home/my_user"), "Path /home/my_user was invalid");
// fails on *NIX because it uses Windows style separators and fs root
cnx_assert(cnx_path_is_valid("C:\\Users\\my_user"), "Path /home/my_user was invalid");

#define cnx_path_new(path)

Creates a new path from the given string, canonicalized so as to be valid on the host platform.

Parameters
path - The string to create a path from. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
Returns CnxPath - path converted to a valid filesystem path

If the given string would be a valid path on the host platform's filesystem, this simply returns a clone of the string. Otherwise, this will return a modified, canonicalized clone of the given string so that it would be a valid filesystem path.

For example, if path is "/home\\user_name//file.txt" on *NIX, path separators will be converted to all be *NIX style separators and redundant separators will be removed. As a result, the returned path would be "/home/user_name/file.txt"

Coincidentally, this means that all paths created through this function can use a consistent path separator for all platforms, and separators will automatically be converted to the correct one for the platform at runtime. IE: all paths can be declared with *NIX style separators, but will be correctly converted to '\' on Windows

Example:

CnxScopedPath home = cnx_path_user_home_directory();
// returns a validated and canonicalized form for the path
CnxScopedPath file_path = cnx_path_new("my_directory/my_file");
cnx_path_append(&home, &file_path);

#define cnx_path_is_absolute(path)

Checks if the given path is an absolute path.

Parameters
path - The path to check. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
Returns bool - whether path is an absolute path

#define cnx_path_is_relative(path)

Checks if the given path is a relative path.

Parameters
path - The path to check. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
Returns bool - whether path is a relative path

#define cnx_path_get_absolute_path(path)

Returns the absolute path of path

Parameters
path - The path to get the absolute path of. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
Returns CnxPath - path as an absolute path

Gets the absolute path of path. For example if path is "my_dir/my_file.txt", this returns "$CWD/my_dir/my_file.txt" where "$CWD" is the absolute path of the current working directory. If path is already an absolute path, this returns a clone of path

#define cnx_path_exists(path)

Checks if the given path exists.

Parameters
path - The path to check. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
Returns bool - whether path exists

#define cnx_path_is_file(path)

Checks if the given path is a path to a file.

Parameters
path - The path to check. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
Returns bool - whether path is a file

#define cnx_path_is_directory(path)

Checks if the given path is a path to a directory.

Parameters
path - The path to check. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
Returns bool - whether path is a directory

#define cnx_path_is_fs_root(path)

Checks if the given path is a path to a filesystem root (ie "C:\\" or "/")

Parameters
path - The path to check. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
Returns bool - whether path is a filesystem root

#define cnx_path_is_symlink(path)

Checks if the given path is a path to a symbolic link.

Parameters
path - The path to check. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
Returns bool - whether path is a symlink

#define cnx_path_get_symlink_target(path)

Attempts to get the path of the target of the symbolic link path

Parameters
path - The symlink to get the target of. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
Returns CnxResult(CnxPath) - If path is a symlink and actively links to a target, the target of path. Otherwise, an error.

#define cnx_path_has_file_extension(path, extension)

Checks if the given path is a file with the given file extension.

Parameters
path - The path to check. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
extension - The extension to check for. This should be without the "." prefix. I.E. for a ".txt" extension, this should be "txt". This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
Returns bool - whether path is a symlink

#define cnx_path_get_file_extension(path)

Attempts to get the file extension of the file path

Parameters
path - Path to the file to get the extension of. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
Returns CnxOption(CnxString) - If path is a file with a file extension, the file extension of path. Otherwise, None(CnxString).

#define cnx_path_get_file_name(path)

Gets the file name of the given path, including file extension.

Parameters
path - The path to get the file name of. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
Returns CnxString - The name of the file indicated by path

#define cnx_path_get_file_name_without_extension(path)

Gets the file name of the given path, without the file extension.

Parameters
path - The path to get the file name of. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
Returns CnxString - The name of the file indicated by path, without the file extension if it has one.

#define cnx_path_get_parent_directory(path)

Returns the parent directory of the given path

Parameters
path - The path to get the parent directory of. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
Returns CnxPath - The parent directory of path

Returns the parent directory of the given path. For example, for a path "/usr/local/bin" on *NIX, the parent directory would be "/usr/local", or for a path "Documents/my_file.txt", the parent directory would be "$CWD/Documents".

If path is a file system root, path is returned.

The returned path is always an absolute path.

#define cnx_path_append(path, entry_name)

Appends the relative path entry_name to path

Parameters
path - The path to append to. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
entry_name - The path to be appended. This must be a relative path. If this is an absolute path, an error will be returned. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
Returns CnxResult - Ok() if appending was successful, an error otherwise

Attempts to append the relative path entry_name to the path path. entry_name must be a relative path: if entry_name is absolute, this will return an error.

#define cnx_path_create_file(...)

Creates a new file with the path and name indicated by path

Parameters
...
  • path - The path of the file to create. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
  • overwrite_existing - Whether existing filesystem contents should be deleted and overwritten if path already exists. This is false by default.
Returns CnxResult - Ok() if creating the file was successful, an error otherwise

Attempts to create a new file with the path and name indicated by path. By default, this will fail if path already exists. If overwrite_existing is given as true, however, all filesystem contents originally existing at path will attempt to be deleted, and a new file will be created if deletion was successful. overwrite_existing may also be given as false to explicitly signal that failure should occur if path exists.

#define cnx_path_create_file_overwriting(file_path)

Creates a new file with the path and name indicated by path

Parameters
file_path - The path of the file to create. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
Returns CnxResult - Ok() if creating the file was successful, an error otherwise

Attempts to create a new file with the path and name indicated by path. Unlike cnx_path_create_file, this will always overwrite existing filesystem contents: if path already exists, all contents originally existing at path will attempt to be deleted, and a new file will be created if deletion was successful.

#define cnx_path_create_directory(...)

Creates a new directory with the path and name indicated by path

Parameters
...
  • path - The path of the directory to create. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
  • overwrite_existing - Whether existing filesystem contents should be deleted and overwritten if path already exists. This is false by default.
Returns CnxResult - Ok() if creating the directory was successful, an error otherwise

Attempts to create a new directory with the path and name indicated by path. By default, this will fail if path already exists. If overwrite_existing is given as true, however, all filesystem contents originally existing at path will attempt to be deleted, and a new directory will be created if deletion was successful. overwrite_existing may also be given as false to explicitly signal that failure should occur if path exists.

#define cnx_path_create_directory_overwriting(dir_path)

Creates a new directory with the path and name indicated by path

Parameters
dir_path - The path of the directory to create. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
Returns CnxResult - Ok() if creating the directory was successful, an error otherwise

Attempts to create a new directory with the path and name indicated by path. Unlike cnx_path_create_directory, this will always overwrite existing filesystem contents: if path already exists, all contents originally existing at path will attempt to be deleted, and a new directory will be created if deletion was successful.

#define cnx_path_remove_file(file_path)

Removes the file located at path

Parameters
file_path - The path of the file to remove. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
Returns CnxResult - Ok() if removing the file was successful, an error otherwise

Attempts to remove the file located at path. If path is not a file (aka, it is a directory), or if path does not exist, this will return an error. This may also return an error if an error occurs when removing the file.

#define cnx_path_remove_directory(...)

Removes the directory located at path

Parameters
...
  • path - The path of the directory to remove. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
  • recursive - Whether path should be deleted recursively, meaning any filesytem contents contained in path would be deleted if path is not empty. This is false by default.
Returns CnxResult - Ok() if removing the directory was successful, an error otherwise

Attempts to remove the directory located at path. By default, this will fail if path is a non-empty directory (aka if path has contents). If recursive is passed as true, however, this will recursively delete all filesystem contents contained in path. recursive can also be passed as false to explicitly signal that path should NOT be removed recursively.

If path is not a directory (aka, it is a file), or if path does not exist, this will return an error. This may also return an error if an error occurs when removing the directory.

#define cnx_path_remove_directory_recursive(dir_path)

Removes the directory located at path

Parameters
dir_path - The path of the directory to remove. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
Returns CnxResult - Ok() if removing the directory was successful, an error otherwise

Attempts to remove the directory located at path. Unlike cnx_path_remove_directory, this will always delete path recursively, and any filesystem contents contained in path will be deleted if path is not empty.

If path is not a directory (aka, it is a file), or if path does not exist, this will return an error. This may also return an error if an error occurs when removing the directory.

#define cnx_path_create_symlink(...)

Creates a new symbolic link with the name and path indicated by link_name that points to the file or directory at link_target

Parameters
...
  • link_name - The path of the symlink to create. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
  • link_target - The path link_name should link to. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
  • overwrite_existing - Whether existing filesystem contents should be deleted and overwritten if path already exists. This is false by default.
Returns CnxResult - Ok() if creating the symlink was successful, an error otherwise

Attempts to create a new symlink with the path and name indicated by link_name that points to the file or directory at link_target. By default, this will fail if link_name already exists. If overwrite_existing is given as true, however, all filesystem contents originally existing at link_name will attempt to be deleted, and a new symlink to link_target will be created if deletion was successful. overwrite_existing may also be given as false to explicitly signal that failure should occur if path exists.

#define cnx_path_create_symlink_overwriting(link_name, link_target)

Creates a new symbolic link with the name and path indicated by link_name that points to the file or directory at link_target

Parameters
link_name - The path of the symlink to create. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
link_target - The path link_name should link to. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
Returns CnxResult - Ok() if creating the symlink was successful, an error otherwise

Attempts to create a new symlink with the path and name indicated by link_name that points to the file or directory at link_target. Unlike cnx_path_create_symlink, this will always delete any filesystem contents at link_name if link_name already exists.

#define cnx_path_remove_symlink(link_path)

Removes the symbolic link link_path

Parameters
link_path - The path of the symlink to remove. This can be a pointer to any string or string-like type (i.e. it can be CnxString*, CnxStringView*, cstring, or a string literal)
Returns CnxResult - Ok() if removing the symlink was successful, an error otherwise

Attempts to remove the symlink link_path. This will not remove the filesystem contents at link_path's target. Any contents pointed to by link_path will be preserved, only the link will be deleted. If link_path is not a symlink, this will return an error.