f_directory and f_path overlap.
I believe that f_path is the better choice for getting the current directory/path and related.
Add f_path_change(), f_path_change_at(), f_path_current(), and f_path_real().
Add F_absolute and F_relative status codes.
The define FL_status_string_recurse_length did not include the leading f_ in the derived length.
Minor documentation comment changes.
build_linker ar
build_libraries -lc
build_libraries-level
-build_sources_library console.c conversion.c directory.c private-directory.c environment.c private-environment.c file.c private-file.c fss.c iki.c memory.c path.c pipe.c print.c serialize.c private-serialize.c socket.c utf.c private-utf.c
+build_sources_library console.c conversion.c directory.c private-directory.c environment.c private-environment.c file.c private-file.c fss.c iki.c memory.c path.c private-path.c pipe.c print.c serialize.c private-serialize.c socket.c utf.c private-utf.c
build_sources_program
build_sources_headers color.h console.h conversion.h directory.h directory_type.h environment.h file.h fss.h fss-common.h fss-named.h fss-nest.h fss-quoted.h fss-set.h iki.h iki-common.h memory.h memory-structure.h path.h pipe.h print.h serialize.h socket.h status.h status_array.h string.h string_common.h string_dynamic.h string_map.h string_quantity.h string_range.h type.h type_array.h utf.h utf-common.h
build_sources_script
build_linker ar
build_libraries -lc
build_libraries-monolithic
-build_sources_library level_0/console.c level_0/conversion.c level_0/directory.c level_0/private-directory.c level_0/environment.c level_0/private-environment.c level_0/file.c level_0/private-file.c level_0/fss.c level_0/iki.c level_0/memory.c level_0/path.c level_0/pipe.c level_0/print.c level_0/serialize.c level_0/private-serialize.c level_0/socket.c level_0/utf.c level_0/private-utf.c level_1/color.c level_1/console.c level_1/conversion.c level_1/directory.c level_1/private-directory.c level_1/private-fss.c level_1/fss_basic.c level_1/fss_basic_list.c level_1/fss_extended.c level_1/fss_extended_list.c level_1/iki.c level_1/print.c level_1/status.c level_1/string.c level_1/private-string.c level_1/utf.c level_1/private-utf.c level_1/utf_file.c level_1/private-utf_file.c level_2/execute.c level_2/private-execute.c level_2/file.c level_2/fss.c level_2/private-fss.c level_2/fss_basic.c level_2/fss_basic_list.c level_2/fss_extended.c level_2/fss_extended_list.c level_2/fss_status.c level_2/program.c level_2/status.c
+build_sources_library level_0/console.c level_0/conversion.c level_0/directory.c level_0/private-directory.c level_0/environment.c level_0/private-environment.c level_0/file.c level_0/private-file.c level_0/fss.c level_0/iki.c level_0/memory.c level_0/path.c level_0/private-path.c level_0/pipe.c level_0/print.c level_0/serialize.c level_0/private-serialize.c level_0/socket.c level_0/utf.c level_0/private-utf.c level_1/color.c level_1/console.c level_1/conversion.c level_1/directory.c level_1/private-directory.c level_1/private-fss.c level_1/fss_basic.c level_1/fss_basic_list.c level_1/fss_extended.c level_1/fss_extended_list.c level_1/iki.c level_1/print.c level_1/status.c level_1/string.c level_1/private-string.c level_1/utf.c level_1/private-utf.c level_1/utf_file.c level_1/private-utf_file.c level_2/execute.c level_2/private-execute.c level_2/file.c level_2/fss.c level_2/private-fss.c level_2/fss_basic.c level_2/fss_basic_list.c level_2/fss_extended.c level_2/fss_extended_list.c level_2/fss_status.c level_2/program.c level_2/status.c
build_sources_program
build_sources_headers level_0/color.h level_0/console.h level_0/conversion.h level_0/directory.h level_0/directory_type.h level_0/environment.h level_0/file.h level_0/fss.h level_0/fss-common.h level_0/fss-named.h level_0/fss-nest.h level_0/fss-quoted.h level_0/fss-set.h level_0/iki.h level_0/iki-common.h level_0/memory.h level_0/memory-structure.h level_0/path.h level_0/pipe.h level_0/print.h level_0/serialize.h level_0/socket.h level_0/status.h level_0/status_array.h level_0/string.h level_0/string_common.h level_0/string_dynamic.h level_0/string_map.h level_0/string_quantity.h level_0/string_range.h level_0/type.h level_0/type_array.h level_0/utf.h level_0/utf-common.h level_1/color.h level_1/console.h level_1/conversion.h level_1/directory.h level_1/fss.h level_1/fss_basic.h level_1/fss_basic_list.h level_1/fss_extended.h level_1/fss_extended_list.h level_1/fss_macro.h level_1/fss_status.h level_1/iki.h level_1/print.h level_1/status.h level_1/string.h level_1/utf.h level_1/utf_file.h level_2/execute.h level_2/file.h level_2/fss.h level_2/fss_basic.h level_2/fss_basic_list.h level_2/fss_extended.h level_2/fss_extended_list.h level_2/fss_status.h level_2/program.h level_2/status.h
build_sources_script
#ifndef _di_f_directory_limitations_
#define f_directory_default_allocation_step f_memory_default_allocation_step
- #define f_directory_name_max NAME_MAX
#define f_directory_descriptors_max 255
+ #define f_directory_name_max NAME_MAX
#endif // _di_f_directory_limitations_
/**
* Create a directory at the given path.
*
* @param path
- * The path file name.
+ * The file path to the directory.
* @param mode
* The directory mode to use when creating.
*
* @param at_id
* The parent directory, as an open directory file descriptor, in which path is relative to.
* @param path
- * The path file name.
+ * The file path to the directory.
* @param mode
* The directory mode to use when creating.
*
* Identify whether or not a file exists at the given path and if that file is a directory or a symlink to a directory.
*
* @param path
- * The path file name.
+ * The file path to the directory.
*
* @return
* F_true if path was found and path is a directory (or a symlink to a directory).
* @param at_id
* The parent directory, as an open directory file descriptor, in which path is relative to.
* @param path
- * The path file name.
+ * The file path to the directory.
* @param flag
* Any valid flag, such as f_directory_at_path_empty, f_directory_at_automount_no, or f_directory_at_symlink_follow_no.
*
* Identify whether or not a file exists at the given path and if that file is a directory.
*
* @param path
- * The path file name.
+ * The file path to the directory.
*
* @return
* F_true if path was found and path is a directory.
* @param at_id
* The parent directory, as an open directory file descriptor, in which path is relative to.
* @param path
- * The path file name.
+ * The file path to the directory.
* @param flag
* Any valid flag, such as f_directory_at_path_empty, f_directory_at_automount_no, or f_directory_at_symlink_follow_no.
*
* Allows specifying a custom filter and custom sort.
*
* @param path
- * Filesystem path to the directory.
+ * The file path to the directory.
* @param filter
* A filter function of the form: int xxx(const struct direct *).
* Set to 0 to not use (NULL).
* This opens with O_PATH and O_CLOEXEC.
*
* @param path
- * The path file name.
+ * The file path to the directory.
* @param dereference
* Set to TRUE to dereferenc symlinks (often is what is desired).
* Set to FALSE to operate on the symlink itself.
* @see open()
*/
#ifndef _di_f_directory_open_
- extern f_return_status f_directory_open(const f_string path, const bool dereference, int *id) f_gcc_attribute_visibility_internal;
+ extern f_return_status f_directory_open(const f_string path, const bool dereference, int *id);
#endif // _di_f_directory_open_
/**
* @param at_id
* The parent directory, as an open directory file descriptor, in which path is relative to.
* @param path
- * The path file name.
+ * The file path to the directory.
* @param dereference
* Set to TRUE to dereferenc symlinks (often is what is desired).
* Set to FALSE to operate on the symlink itself.
* @see openat()
*/
#ifndef _di_f_directory_open_at_
- extern f_return_status f_directory_open_at(const int at_id, const f_string path, const bool dereference, int *id) f_gcc_attribute_visibility_internal;
+ extern f_return_status f_directory_open_at(const int at_id, const f_string path, const bool dereference, int *id);
#endif // _di_f_directory_open_at_
/**
* Remove a directory and possibly its contents.
*
* @param path
- * The path file name.
+ * The file path to the directory.
* @param recursion_max
* Represents the max recursion depth, set to 0 to disable recursive delete.
* @param preserve
* Remove a directory and possibly its contents.
*
* @param path
- * The path file name.
+ * The file path to the directory.
* @param recursion_max
* Represents the max recursion depth, set to 0 to disable recursive delete.
* @param preserve
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
+#include <limits.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <level_0/path.h>
+#include "private-path.h"
#ifdef __cplusplus
extern "C" {
#endif
+#ifndef _di_f_path_change_
+ f_return_status f_path_change(const f_string path) {
+
+ if (chdir(path) < 0) {
+ if (errno == EACCES) return F_status_set_error(F_access_denied);
+ if (errno == EFAULT) return F_status_set_error(F_buffer);
+ if (errno == EIO) return F_status_set_error(F_input_output);
+ if (errno == ELOOP) return F_status_set_error(F_loop);
+ if (errno == ENAMETOOLONG) return F_status_set_error(F_name);
+ if (errno == ENOENT) return F_status_set_error(F_file_found_not);
+ if (errno == ENOMEM) return F_status_set_error(F_memory_out);
+ if (errno == ENOTDIR) return F_status_set_error(F_directory);
+
+ return F_status_set_error(F_failure);
+ }
+
+ return F_none;
+ }
+#endif // _di_f_path_change_
+
+#ifndef _di_f_path_change_at_
+ f_return_status f_path_change_at(const int at_id) {
+ #ifndef _di_level_0_parameter_checking_
+ if (at_id <= 0) return F_status_set_error(F_parameter);
+ #endif // _di_level_0_parameter_checking_
+
+ if (fchdir(at_id) < 0) {
+ if (errno == EACCES) return F_status_set_error(F_access_denied);
+ if (errno == EFAULT) return F_status_set_error(F_buffer);
+ if (errno == EIO) return F_status_set_error(F_input_output);
+ if (errno == ELOOP) return F_status_set_error(F_loop);
+ if (errno == ENAMETOOLONG) return F_status_set_error(F_name);
+ if (errno == ENOENT) return F_status_set_error(F_file_found_not);
+ if (errno == ENOMEM) return F_status_set_error(F_memory_out);
+ if (errno == ENOTDIR) return F_status_set_error(F_directory);
+ if (errno == EBADF) return F_status_set_error(F_directory_descriptor);
+
+ return F_status_set_error(F_failure);
+ }
+
+ return F_none;
+ }
+#endif // _di_f_path_change_at_
+
+#ifndef _di_f_path_current_
+ f_return_status f_path_current(const bool real, f_string_dynamic *path) {
+ #ifndef _di_level_0_parameter_checking_
+ if (path == 0) return F_status_set_error(F_parameter);
+ #endif // _di_level_0_parameter_checking_
+
+ char buffer[f_path_max];
+
+ if (!getcwd(buffer, f_path_max)) {
+ if (errno == EACCES) return F_status_set_error(F_access_denied);
+ if (errno == EFAULT) return F_status_set_error(F_buffer);
+ if (errno == EINVAL) return F_status_set_error(F_parameter);
+ if (errno == ENAMETOOLONG) return F_status_set_error(F_name);
+ if (errno == ENOENT) return F_status_set_error(F_file_found_not);
+ if (errno == ENOMEM) return F_status_set_error(F_memory_out);
+ if (errno == ERANGE) return F_status_set_error(F_buffer_too_small);
+
+ return F_status_set_error(F_failure);
+ }
+
+ if (real) {
+ return private_f_path_real(buffer, path);
+ }
+
+ const f_string_length length = strnlen(buffer, f_path_max);
+
+ if (length + 1 > path->size) {
+ f_status status = F_none;
+
+ f_macro_string_dynamic_new(status, (*path), length + 1);
+ if (F_status_is_error(status)) return status;
+ }
+
+ memcpy(path->string, buffer, length);
+
+ path->string[length] = 0;
+ path->used = length;
+
+ return F_none;
+ }
+#endif // _di_f_path_current_
+
#ifndef _di_f_path_explode_
f_return_status f_path_explode(const f_string path, f_string_dynamics *paths) {
#ifndef _di_level_0_parameter_checking_
}
#endif // _di_f_path_explode_dynamic_
+#ifndef _di_f_path_real_
+ f_return_status f_path_real(const f_string path, f_string_dynamic *real) {
+ #ifndef _di_level_0_parameter_checking_
+ if (real == 0) return F_status_set_error(F_parameter);
+ #endif // _di_level_0_parameter_checking_
+
+ return private_f_path_real(path, real);
+ }
+#endif // _di_f_path_real_
+
#ifndef _di_f_path_explode_reverse_
f_return_status f_path_explode_reverse(const f_string path, f_string_dynamics *paths) {
#ifndef _di_level_0_parameter_checking_
#define _F_path_h
// libc includes
+#include <limits.h>
#include <linux/limits.h> // defines PATH_MAX
+#include <stdlib.h>
#include <string.h>
// fll-0 includes
#endif // _di_f_path_defines_
/**
+ * Change to a path.
+ *
+ * @param path
+ * The file path.
+ *
+ * @return
+ * F_none on success.
+ * F_access_denied (with error bit) on access denied.
+ * F_buffer (with error bit) if the buffer is invalid.
+ * F_directory (with error bit) if a supposed directory in path is not actually a directory.
+ * F_input_output (with error bit) on I/O error.
+ * F_loop (with error bit) on loop error.
+ * F_memory_out (with error bit) if out of memory.
+ * F_name (with error bit) on path name error.
+ * F_parameter (with error bit) if a parameter is invalid.
+ * F_file_found_not if the path was not found.
+ * F_failure (with error bit) for any other error.
+ *
+ * @see chdir()
+ */
+#ifndef _di_f_path_change_
+ extern f_return_status f_path_change(const f_string path);
+#endif // _di_f_path_change_
+
+/**
+ * Change to a path at the given open file descriptor.
+ *
+ * @param at_id
+ * An open directory file descriptor, in which path is relative to.
+ *
+ * @return
+ * F_none on success.
+ * F_access_denied (with error bit) on access denied.
+ * F_buffer (with error bit) if the buffer is invalid.
+ * F_directory (with error bit) if a supposed directory in path is not actually a directory.
+ * F_directory_descriptor (with error bit) for bad directory descriptor for at_id.
+ * F_input_output (with error bit) on I/O error.
+ * F_loop (with error bit) on loop error.
+ * F_memory_out (with error bit) if out of memory.
+ * F_name (with error bit) on path name error.
+ * F_parameter (with error bit) if a parameter is invalid.
+ * F_file_found_not if the path was not found.
+ * F_failure (with error bit) for any other error.
+ *
+ * @see fchdir()
+ */
+#ifndef _di_f_path_change_at_
+ extern f_return_status f_path_change_at(const int at_id);
+#endif // _di_f_path_change_at_
+
+/**
+ * Get the current path.
+ *
+ * @param real
+ * If F_true, then get the real path and will result in an absolute path (resolving symlinks, etc..).
+ * Otherwise, this gets the path as it appears to be.
+ * @param path
+ * The (allocated) file path.
+ * This will have a max size of f_path_max + 1.
+ * This will be NULL terminated at real->used + 1.
+ *
+ * @return
+ * F_none on success.
+ * F_access_denied (with error bit) on access denied.
+ * F_buffer (with error bit) if the buffer is invalid.
+ * F_buffer_too_small (with error bit) if the buffer is too small to store the path.
+ * F_directory (with error bit) if a supposed directory in path is not actually a directory.
+ * F_input_output (with error bit) on I/O error.
+ * F_loop (with error bit) on loop error.
+ * F_memory_allocation (with error bit) on allocation error.
+ * F_memory_out (with error bit) if out of memory.
+ * F_name (with error bit) on path name error.
+ * F_parameter (with error bit) if a parameter is invalid.
+ * F_file_found_not if the path was not found.
+ * F_failure (with error bit) for any other error.
+ *
+ * @see getcwd()
+ */
+#ifndef _di_f_path_current_
+ extern f_return_status f_path_current(const bool real, f_string_dynamic *path);
+#endif // _di_f_path_current_
+
+/**
* Separate a given PATH-style string into multiple separate paths.
*
* @param path
#endif // _di_f_path_explode_dynamic_
/**
+ * Get the real path for some path.
+ *
+ * All symbolic links and relative path parts are expanded to yield the real full path.
+ *
+ * @param path
+ * The source path to determine what the real path is.
+ * @param real
+ * The (allocated) real file path.
+ * This will have a max size of f_path_max + 1.
+ * This will be NULL terminated at real->used + 1.
+ *
+ * @return
+ * F_none on success.
+ * F_access_denied (with error bit) on access denied.
+ * F_buffer (with error bit) if the buffer is invalid.
+ * F_buffer_too_small (with error bit) if the buffer is too small to store the path.
+ * F_directory (with error bit) if a supposed directory in path is not actually a directory.
+ * F_input_output (with error bit) on I/O error.
+ * F_loop (with error bit) on loop error.
+ * F_memory_allocation (with error bit) on allocation error.
+ * F_memory_out (with error bit) if out of memory.
+ * F_name (with error bit) on path name error.
+ * F_parameter (with error bit) if a parameter is invalid.
+ * F_file_found_not if the path was not found.
+ * F_failure (with error bit) for any other error.
+ *
+ * @see realpath()
+ */
+#ifndef _di_f_path_real_
+ extern f_return_status f_path_real(const f_string path, f_string_dynamic *real);
+#endif // _di_f_path_real_
+
+/**
* Separate a given PATH-style string into multiple separate paths.
*
* The paths are created in reverse order.
--- /dev/null
+#include <level_0/path.h>
+#include "private-path.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(_di_f_path_current_) || !defined(_di_f_path_real_)
+ f_return_status private_f_path_real(const f_string path, f_string_dynamic *real) {
+ char buffer[f_path_max];
+
+ if (!realpath(path, buffer)) {
+ if (errno == EACCES) return F_status_set_error(F_access_denied);
+ if (errno == EINVAL) return F_status_set_error(F_parameter);
+ if (errno == EIO) return F_status_set_error(F_input_output);
+ if (errno == ELOOP) return F_status_set_error(F_loop);
+ if (errno == ENAMETOOLONG) return F_status_set_error(F_name);
+ if (errno == ENOENT) return F_status_set_error(F_file_found_not);
+ if (errno == ENOMEM) return F_status_set_error(F_memory_out);
+ if (errno == ENOTDIR) return F_status_set_error(F_directory);
+
+ return F_status_set_error(F_failure);
+ }
+
+ const f_string_length length = strnlen(buffer, f_path_max);
+
+ if (length + 1 > real->size) {
+ f_status status = F_none;
+
+ f_macro_string_dynamic_new(status, (*real), length + 1);
+ if (F_status_is_error(status)) return status;
+ }
+
+ memcpy(real->string, buffer, length);
+
+ real->string[length] = 0;
+ real->used = length;
+
+ return F_none;
+ }
+#endif // !defined(_di_f_path_current_) || !defined(_di_f_path_real_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * FLL - Level 0
+ *
+ * Project: Path
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ *
+ * These are provided for internal reduction in redundant code.
+ * These should not be exposed/used outside of this project.
+ */
+#ifndef _PRIVATE_F_path_h
+#define _PRIVATE_F_path_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Private implementation of f_path_real().
+ *
+ * Intended to be shared to each of the different implementation variations.
+ *
+ * @param path
+ * The source path to determine what the real path is.
+ * @param real
+ * The (allocated) real file path.
+ * This will have a max size of f_path_max + 1.
+ * This will be NULL terminated at real->used + 1.
+ *
+ * @return
+ * F_none on success.
+ * F_access_denied (with error bit) on access denied.
+ * F_directory (with error bit) if a supposed directory in path is not actually a directory.
+ * F_input_output (with error bit) on I/O error.
+ * F_loop (with error bit) on loop error.
+ * F_memory_allocation (with error bit) on allocation error.
+ * F_memory_out (with error bit) if out of memory.
+ * F_parameter (with error bit) if a parameter is invalid.
+ * F_failure (with error bit) for any other error.
+ *
+ * @see f_path_current()
+ * @see f_path_real()
+ */
+#if !defined(_di_f_path_current_) || !defined(_di_f_path_real_)
+ extern f_return_status private_f_path_real(const f_string path, f_string_dynamic *real) f_gcc_attribute_visibility_internal;
+#endif // !defined(_di_f_path_current_) || !defined(_di_f_path_real_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _PRIVATE_F_path_h
build_linker ar
build_libraries -lc
build_libraries-individual -lf_memory
-build_sources_library path.c
+build_sources_library path.c private-path.c
build_sources_program
build_sources_headers path.h
build_sources_script
// Start at 197 to allow compatibility with the reserved bash return codes (keep in mind fss return codes can be larger than 255).
#ifndef _di_F_status_basic_
F_none = 197,
+ F_absolute,
F_address,
F_block,
F_bound_out,
F_prohibited,
F_read_only,
F_recurse,
+ F_relative,
F_search,
F_space_not,
F_stop,
case F_none:
*string = FL_status_string_none;
break;
+ case F_absolute:
+ *string = FL_status_string_absolute;
+ break;
case F_address:
*string = FL_status_string_address;
break;
case F_recurse:
*string = FL_status_string_recurse;
break;
+ case F_relative:
+ *string = FL_status_string_relative;
+ break;
case F_search:
*string = FL_status_string_search;
break;
#ifndef _di_F_status_basic_
#define FL_status_string_none "F_none"
+ #define FL_status_string_absolute "F_absolute"
#define FL_status_string_address "F_address"
#define FL_status_string_block "F_block"
#define FL_status_string_bound_out "F_bound_out"
#define FL_status_string_prohibited "F_prohibited"
#define FL_status_string_read_only "F_read_only"
#define FL_status_string_recurse "F_recurse"
+ #define FL_status_string_relative "F_relative"
#define FL_status_string_search "F_search"
#define FL_status_string_space_not "F_space_not"
#define FL_status_string_stop "F_stop"
#define FL_status_string_write_only "F_write_only"
#define FL_status_string_none_length 6
+ #define FL_status_string_absolute_length 10
#define FL_status_string_address_length 9
#define FL_status_string_block_length 7
#define FL_status_string_bound_out_length 11
#define FL_status_string_process_too_many_length 18
#define FL_status_string_prohibited_length 12
#define FL_status_string_read_only_length 11
- #define FL_status_string_recurse_length 7
+ #define FL_status_string_recurse_length 9
+ #define FL_status_string_relative_length 10
#define FL_status_string_search_length 8
#define FL_status_string_space_not_length 11
#define FL_status_string_stop_length 6
return F_none;
}
+ if (fl_string_compare(string, FL_status_string_absolute, length, FL_status_string_absolute_length) == F_equal_to) {
+ *code = F_absolute;
+ return F_none;
+ }
+
if (fl_string_compare(string, FL_status_string_address, length, FL_status_string_address_length) == F_equal_to) {
*code = F_address;
return F_none;
return F_none;
}
+ if (fl_string_compare(string, FL_status_string_relative, length, FL_status_string_relative_length) == F_equal_to) {
+ *code = F_relative;
+ return F_none;
+ }
+
if (fl_string_compare(string, FL_status_string_search, length, FL_status_string_search_length) == F_equal_to) {
*code = F_search;
return F_none;