.. _files: ********************* Files and directories ********************* .. highlight:: c :: #include The functions in this section let you interact with files and directories in the local filesystem. Paths ===== We provide several functions for constructing and handling paths into the local filesystem. .. type:: struct cork_path Represents a path in the local filesystem. The path can be relative or absolute. The paths don't have to refer to existing files or directories. .. function:: struct cork_path \*cork_path_new(const char \*path) struct cork_path \*cork_path_clone(const struct cork_path \*other) Construct a new path object from the given path string, or as a copy of another path object. .. function:: void cork_path_free(struct cork_path \*path) Free a path object. .. function:: const char \*cork_path_get(const struct cork_path \*path) Return the string content of a path. This is not normalized in any way. The result is guaranteed to be non-``NULL``, but may refer to an empty string. The return value belongs to the path object; you must not modify the contents of the string, nor should you try to free the underlying memory. .. function:: struct cork_path \*cork_path_absolute(const struct cork_path \*other) int cork_path_make_absolute(struct cork_path \path) Convert a relative path into an absolute path. The first variant constructs a new path object to hold the result; the second variant overwritesthe contents of *path*. If there is a problem obtaining the current working directory, these functions will return an error condition. .. function:: struct cork_path \*cork_path_join(const struct cork_path \*path, const char \*more) struct cork_path \*cork_path_join_path(const struct cork_path \*path, const struct cork_path \*more) void \*cork_path_append(struct cork_path \path, const char \*more) void \*cork_path_append_path(struct cork_path \*path, const struct cork_path \*more) Concatenate two paths together. The ``join`` variants create a new path object containing the concatenated results. The ``append`` variants overwrite the contents of *path* with the concatenated results. .. function:: struct cork_path \*cork_path_basename(const struct cork_path \*path) void \*cork_path_set_basename(struct cork_path \*path) Extract the base name of *path*. This is the portion after the final trailing slash. The first variant constructs a new path object to hold the result; the second variant overwritesthe contents of *path*. .. note:: These functions return a different result than the standard ``basename(3)`` function. We consider a trailing slash to be significant, whereas ``basename(3)`` does not:: basename("a/b/c/") == "c" cork_path_basename("a/b/c/") == "" .. function:: struct cork_path \*cork_path_dirname(const struct cork_path \*path) void \*cork_path_set_dirname(struct cork_path \*path) Extract the directory name of *path*. This is the portion before the final trailing slash. The first variant constructs a new path object to hold the result; the second variant overwritesthe contents of *path*. .. note:: These functions return a different result than the standard ``dirname(3)`` function. We consider a trailing slash to be significant, whereas ``dirname(3)`` does not:: dirname("a/b/c/") == "a/b" cork_path_dirname("a/b/c/") == "a/b/c" Lists of paths ============== .. type:: struct cork_path_list A list of paths in the local filesystem. .. function:: struct cork_path_list \*cork_path_list_new_empty(void) struct cork_path_list \*cork_path_list_new(const char \*list) Create a new list of paths. The first variant creates a list that is initially empty. The second variant takes in a colon-separated list of paths as a single string, and adds each of those paths to the new list. .. function:: void cork_path_list_free(struct cork_path_list \*list) Free a path list. .. function:: void cork_path_list_add(struct cork_path_list \*list, struct cork_path \*path) Add *path* to *list*. The list takes control of the path instance; you must not try to free *path* yourself. .. function:: size_t cork_path_list_size(const struct cork_path_list \*list) Return the number of paths in *list*. .. function:: const struct cork_path \*cork_path_list_get(const struct cork_path_list \*list, size_t index) Return the path in *list* at the given *index*. The list still owns the path instance that's returned; you must not try to free it or modify its contents. .. function:: const char \*cork_path_list_to_string(const struct cork_path_list \*list) Return a string containing all of the paths in *list* separated by colons. .. function:: struct cork_file \*cork_path_list_find_file(const struct cork_path_list \*list, const char \*rel_path) struct cork_file_list \*cork_path_list_find_files(const struct cork_path_list \*list, const char \*rel_file) Search for a file in a list of paths. *rel_path* gives the path of the sought-after file, relative to each of the directories in *list*. The first variant returns a :c:type:`cork_file` instance for the first match. In no file can be found, it returns ``NULL`` and sets an error condition. The second variant returns a :c:type:`cork_file_list` instance containing all of the matches. In no file can be found, we return an empty list. (Unlike the first variant, this is not considered an error.) Standard paths ============== .. function:: struct cork_path \*cork_path_home(void) Return a :c:type:`cork_path` that refers to the current user's home directory. If we can't determine the current user's home directory, we set an error condition and return ``NULL``. On POSIX systems, this directory is determined by the ``HOME`` environment variable. .. function:: struct cork_path_list \*cork_path_config_paths(void) Return a :c:type:`cork_path_list` that includes all of the standard directories that can be used to store configuration files. This includes a user-specific directory that allows the user to override any global configuration files. On POSIX systems, these directories are defined XDG Base Directory Specification. .. function:: struct cork_path_list \*cork_path_data_paths(void) Return a :c:type:`cork_path_list` that includes all of the standard directories that can be used to store application data files. This includes a user-specific directory that allows the user to override any global data files. On POSIX systems, these directories are defined XDG Base Directory Specification. .. function:: struct cork_path \*cork_path_user_cache_path(void) Return a :c:type:`cork_path` that refers to a directory that can be used to store cache files created on behalf of the current user. This directory should only be used to store data that you can reproduce if needed. On POSIX systems, these directories are defined XDG Base Directory Specification. .. function:: struct cork_path \*cork_path_user_runtime_path(void) Return a :c:type:`cork_path` that refers to a directory that can be used to store small runtime management files on behalf of the current user. On POSIX systems, these directories are defined XDG Base Directory Specification. Files ===== .. type:: struct cork_file Represents a file on the local filesystem. The file in question does not necessarily have to exist; you can use :c:type:`cork_file` instances to refer to files that you have not yet created, for instance. .. type:: typedef unsigned int cork_file_mode Represents a Unix-style file permission set. .. function:: struct cork_file \*cork_file_new(const char \*path) struct cork_file \*cork_file_new_from_path(struct cork_path \*path) Create a new :c:type:`cork_file` instance to represent the file with the given *path*. The ``_from_path`` variant uses an existing :c:type:`cork_path` instance to specify the path. The new file instance will take control of the :c:type`cork_path` instance, so you should not try to free it yourself. .. function:: void cork_file_free(struct cork_file \*file) Free a file instance. .. function:: const struct cork_path \*cork_file_path(struct cork_file \*file) Return the path of a file. The :c:type:`cork_path` instance belongs to the file; you must not try to modify or free the path instance. .. function:: int cork_file_exists(struct cork_file \*file, bool \*exists) Check whether a file exists in the filesystem, storing the result in *exists*. The function returns an error condition if we are unable to determine whether the file exists --- for instance, because you do not have permission to look into one of the containing directories. .. function:: int cork_file_type(struct cork_file \*file, enum cork_file_type \*type) Return what kind of file the given :c:type:`cork_file` instance refers to. The function returns an error condition if there is an error accessing the file --- for instance, because you do not have permission to look into one of the containing directories. If the function succeeds, it will fill in *type* with one of the following values: .. type:: enum cork_file_type .. member:: CORK_FILE_MISSING *file* does not exist. .. member:: CORK_FILE_REGULAR *file* is a regular file. .. member:: CORK_FILE_DIRECTORY *file* is a directory. .. member:: CORK_FILE_SYMLINK *file* is a symbolic link. .. member:: CORK_FILE_UNKNOWN We can access *file*, but we do not know what type of file it is. .. function:: int cork_file_remove(struct cork_file \*file, unsigned int flags) Remove *file* from the filesystem. *flags* must be the bitwise OR (``|``) of the following flags. (Use ``0`` if you do not want any of the flags.) .. macro:: CORK_FILE_PERMISSIVE If this flag is given, then it is not considered an error if *file* does not exist. If the flag is not given, then the function function returns an error if *file* doesn't exist. (This mimics the standard ``rm -f`` command.) .. macro:: CORK_FILE_RECURSIVE If this flag is given, and *file* refers to a directory, then the function will automatically remove the directory and all of its contents. If the flag is not given, and *file* refers to a directory, then the directory must be empty for this function to succeed. If *file* does not refer to a directory, this flag has no effect. (This mimics the standard ``rmdir -r`` command.) Directories =========== Certain functions can only be applied to a :c:type:`cork_file` instance that refers to a directory. .. function:: int cork_file_mkdir(struct cork_file \*directory, cork_file_mode mode, unsigned int flags) Create a new directory in the filesystem, with permissions given by *mode*. *flags* must be the bitwise OR (``|``) of the following flags. (Use ``0`` if you do not want any of the flags.) .. macro:: CORK_FILE_PERMISSIVE If this flag is given, then it is not considered an error if *directory* already exists. If the flag is not given, then the function function returns an error if *directory* exists. (This mimics part of the standard ``mkdir -p`` command.) .. macro:: CORK_FILE_RECURSIVE If this flag is given, then the function will ensure that all of the parent directories of *directory* exist, creating them if necessary. Each directory created will have permissions given by *mode*. (This mimics part of the standard ``mkdir -p`` command.) .. function:: int cork_file_iterate_directory(struct cork_file \*directory, cork_file_directory_iterator iterator, void \*user_data) Call *iterator* for each file or subdirectory contained in *directory* (not including the directory's ``.`` and ``..`` entries). This function does not recurse into any subdirectories; it only iterates through the immediate children of *directory*. If your iteration function returns a non-zero result, we will abort the iteration and return that value. Otherwise, if each call to the iteration function returns ``0``, then we will return ``0`` as well. *iterator* must be an instance of the following function type: .. type:: typedef int (\*cork_file_directory_iterator)(struct cork_file \*child, const char \*rel_name, void \*user_data) Called for each child entry in *directory*. *child* will be a file instance referring to the child entry. *rel_name* gives the relative name of the child entry within its parent *directory*. Lists of files ============== .. type:: struct cork_file_list A list of files in the local filesystem. .. function:: struct cork_file_list \*cork_file_list_new_empty(void) struct cork_file_list \*cork_file_list_new(struct cork_path_list \*path_list) Create a new list of files. The first variant creates a list that is initially empty. The second variant adds a new file instance for each of the paths in *path_list*. .. function:: void cork_file_list_free(struct cork_file_list \*list) Free a file list. .. function:: void cork_file_list_add(struct cork_file_list \*list, struct cork_file \*file) Add *file* to *list*. The list takes control of the file instance; you must not try to free *file* yourself. .. function:: size_t cork_file_list_size(const struct cork_file_list \*list) Return the number of files in *list*. .. function:: struct cork_file \*cork_file_list_get(const struct cork_file_list \*list, size_t index) Return the file in *list* at the given *index*. The list still owns the file instance that's returned; you must not try to free it. Directory walking ================= .. function:: int cork_walk_directory(const char \*path, struct cork_dir_walker \*walker) Walk through the contents of a directory. *path* can be an absolute or relative path. If it's relative, it will be interpreted relative to the current directory. If *path* doesn't exist, or there are any problems reading the contents of the directory, we'll set an error condition and return ``-1``. To process the contents of the directory, you must provide a *walker* object, which contains several callback methods that we will call when files and subdirectories of *path* are encountered. Each method should return ``0`` on success. Unless otherwise noted, if we receive any other return result, we will abort the directory walk, and return that same result from the :c:func:`cork_walk_directory` call itself. In all of the following methods, *base_name* will be the base name of the entry within its immediate subdirectory. *rel_path* will be the relative path of the entry within the *path* that you originally asked to walk through. *full_path* will the full path to the entry, including *path* itself. .. type:: struct cork_dir_walker .. member:: int (\*file)(struct cork_dir_walker \*walker, const char \*full_path, const char \*rel_path, const char \*base_name) Called when a regular file is encountered. .. member:: int (\*enter_directory)(struct cork_dir_walker \*walker, const char \*full_path, const char \*rel_path, const char \*base_name) Called when a subdirectory of *path* of encountered. If you don't want to recurse into this directory, return :c:data:`CORK_SKIP_DIRECTORY`. .. macro:: CORK_SKIP_DIRECTORY .. member:: int (\*leave_directory)(struct cork_dir_walker \*walker, const char \*full_path, const char \*rel_path, const char \*base_name) Called when a subdirectory has been fully processed.