The Hackerlab at `regexps.com`

## File-name Manipulation Functions

up: libhackerlab next: Parsing Command-line Options prev: An Errorless Front-end to the VU File-system Interface

The functions in this chapter are for managing strings which are file names. Though the actual implementation is unix-specific, the calling conventions for these functions (based on the design of GNU Emacs) should support other operating systems as well.

WARNING: some of the functions in this chapter use `must_malloc' when it would be better to use some other allocation function. This is likely to be fixed in a future release.

- Home Directories
- File-name Algebra
- Paths

### Home Directories

up: File-name Manipulation Functions next: File-name Algebra

Function `file_name_home_directory`

    char * file_name_home_directory (void);

Return the user's home directory.

The path returned should not be freed by the caller and may be returned more than once by `file_name_home_directory` .

The home directory is defined to be the value of the environment variable HOME, unless that variable is unbound or is bound to an empty string. If HOME is undefined, then the home directory is found using `getpwuid` and the real user id of the process.

If the home directory can not be computed, or storage can not be allocated, `panic` is called to force the process to exit.

The directory name returned is formatted as if returned by `file_name_as_directory` (it will end with a single `/` ).

Function `file_name_is_absolute`

    int file_name_is_absolute (t_uchar * f);

         return f && f[0] && (f[0] == '/');

Function `file_name_tilde_expand`

    t_uchar * file_name_tilde_expand (alloc_limits limits, char * fname);

Return a newly allocated copy of `fname` with a leading `~` or `~user` expanded to the appropriate home directory.

If allocation fails (but does not call `panic` ) this function returns `0` .

If asked to expand `~` , and unable to find a home directory for the current process, this function panics and exits.

If asked to expand `~user` , and unable to find a home directory for `user` , this function returns a newly allocated copy of `fname` .

### File-name Algebra

up: File-name Manipulation Functions next: Paths prev: Home Directories

Function `file_name_tail`

    char * file_name_tail (alloc_limits limits, char * fname);

Return a newly allocated string containing only the last element of the file-name `fname` . The last element is everything following the last `"/"` or all of `fname` if it contains no `"/"` characters.

         "/usr/bin/ls"   =>      "ls"
         "/usr/bin/"     =>      ""
         "ls"            =>      "ls"

If allocation fails (but does not call `panic` ) this function returns `0` .

Function `file_name_head`

    t_uchar * file_name_head (alloc_limits limits, char * fname);

/usr/bin/ls => / usr/bin/ls => usr ls => ls `0` => `0`

Function `file_name_sans_head`

    t_uchar * file_name_sans_head (alloc_limits limits, char * fname);

/ => `0` /usr/bin/ls => usr/bin/ls usr/bin/ls => bin/ls usr/ => `0` ls => `0` 0 => `0`

Function `file_name_as_directory`

    t_uchar * file_name_as_directory (alloc_limits limits, t_uchar * f);

Return a newly allocated copy of file-name `f` , ensuring that the copy ends in a single `"/"` .

         "/usr/bin/ls"   =>      "/usr/bin/ls/"
         "/usr/bin/"     =>      "/usr/bin/"
         "/usr/bin///"   =>      "/usr/bin/"
         "ls"            =>      "ls/"
         "/"             =>      "/"

If allocation fails (but does not call `panic` ) this function returns `0` .

Function `file_name_from_directory`

    t_uchar * file_name_from_directory (alloc_limits limits, t_uchar * f);

Return a newly allocated copy of file-name `f` , removing all trailing `"/"` characters. The root directory is treated specially:

         "/usr/bin/ls"   =>      "/usr/bin/ls"
         "ls"            =>      "ls"
         "/usr/bin/"     =>      "/usr/bin"
         "/usr/bin///"   =>      "/usr/bin"
         "/"             =>      "/"

If allocation fails (but does not call `panic` ) this function returns `0` .

Function `file_name_directory`

    t_uchar * file_name_directory (alloc_limits limits, t_uchar * f);

Return a newly allocated copy of the directory portion of file-name `f` , ensuring that the copy ends with a single `"/"` .

The directory portion is everything except the last component of a file-name. If `f` already ends with a `"/"` , then this function is the same as `file_name_as_directory` . If `f` has no directory component, this function returns `0` :

         "/usr/bin/ls"   =>      "/usr/bin/"
         "/usr/bin///ls" =>      "/usr/bin/"
         "/usr/bin/"     =>      "/usr/bin/"
         "/usr/bin"      =>      "/usr/"
         "ls"            =>      0
         "/"             =>      "/"

If allocation fails (but does not call `panic` ) this function returns `0` .

Function `file_name_directory_file`

    t_uchar * file_name_directory_file (alloc_limits limits, t_uchar * f);

Return a newly allocated copy of the directory portion of file-name `f` , ensuring that the copy does not end with a single `"/"` (with one exception).

The directory portion is everything except the last component of a file-name. If `f` has no directory component, this function returns `0` :

         "/usr/bin/ls"   =>      "/usr/bin"
         "/usr/bin///ls" =>      "/usr/bin"
         "/usr/bin/"     =>      "/usr/bin"
         "/usr/bin"      =>      "/usr"
         "ls"            =>      0
         "/"             =>      "/"

If allocation fails (but does not call `panic` ) this function returns `0` .

Function `file_name_is_path_prefix`

    int file_name_is_path_prefix (t_uchar * maybe_prefix, t_uchar * path);

Return non-zero if `maybe_prefix` is equal to `path` or to some path-prefix of `path` .

For example:

         "/usr/bin"      is a prefix of  "/usr/bin/ls"
         "/usr/bin"      is a prefix of  "/usr/bin"
         "/usr/bin"      is a prefix of  "/usr/bin/"
         "/usr/bin/"     is a prefix of  "/usr/bin/"

but:

         "/usr/bin"      is _not_ a prefix of    "/usr/bin-utils/ls"
         "/usr/bin/"     is _not_ a prefix of    "/usr/bin"

Function `file_name_in_vicinity`

    t_uchar * file_name_in_vicinity (alloc_limits limits,
                                     t_uchar * dir,
                                     t_uchar * file);

Return a newly allocated string which is `dir` , followed by `"/"` , followed by `file` . If `dir` is a directory name and `file` is a relative file-name, then the result is a name for `file` , relative to `dir` . If `dir` already ends in `"/"` , no additional `"/"` is added.

If `dir` is `0` or `""` , a newly allocated copy of `file` is returned.

If `file` is an absolute file name (begins with `"/"` ) a newly allocated copy of `file` is returned.

         "/usr/bin", "ls"        =>      "/usr/bin/ls"
         "/usr/bin/", "ls"       =>      "/usr/bin/ls"
         "/usr/bin///", "ls"     =>      "/usr/bin/ls"
         "/etc", "/usr/bin/ls"   =>      "/usr/bin/ls"
         0, "ls"                 =>      "ls"

If allocation fails (but does not call `panic` ) this function returns `0` .

### Paths

up: File-name Manipulation Functions prev: File-name Algebra

Function `path_parse`

    t_uchar ** path_parse (alloc_limits limits, char * path);

Convert a path of file-names separated by ':' to form a 0-terminated array of file-names.

An empty file-name is converted to `"."` .

The array is allocated by the variable sized array functions and should be freed using `ar_free` (see Variable Size Arrays). Note that `ar_size` returns the size of the array, including the final `0` .

The elements of the array are allocated by `must_malloc` and should be freed using `must_free` . THIS IS A BUG.

The function `free_path` can be used to free a path allocated by `path_parse` .

If allocation fails (but does not call `panic` ) this function returns `0` .

Function `free_path`

    void free_path (alloc_limits limits, t_uchar ** path)

Free a path allocated by `path_parse` .

Function `path_find_executable`

    t_uchar * path_find_executable (alloc_limits limits,
                                    t_uchar ** path,
                                    t_uchar * tail);

Search on `path` for a file named `tail` that is executable by this process. Returns a newly allocated copy of the name of such a file or `0` .

The file-name returned is formed by `file_name_in_vicinity (limits, path[N], tail)` and should be freed by `must_free` .

The effective user and group ids are used to check whether or not the file can be executed (which should be the same rule used by the kernel).

If allocation fails (but does not call `panic` ) this function returns `0` .

libhackerlab: The Hackerlab C Library
The Hackerlab at `regexps.com`