]> Kevux Git Server - fll/commitdiff
Progress: featureless make.
authorKevin Day <thekevinday@gmail.com>
Mon, 7 Sep 2020 05:20:55 +0000 (00:20 -0500)
committerKevin Day <thekevinday@gmail.com>
Mon, 7 Sep 2020 05:45:13 +0000 (00:45 -0500)
Implement recursive change owner, change groups, and change modes functions.
These are implemented in the fll_file project.

Then utilize these for the recursive owners, groups, and modes section operations.

Fix specification where I forgot to rename "archiver" to "indexer".
In documentation it is "indexer" and not "index" for the indexer program whereas "index" is a section operation name.
Fix documentation where I forgot to rename "archive" to "index".

A bug in fl_directory_list() was discovered where the parameter check for path is incorrect.

19 files changed:
build/level_2/settings
build/monolithic/settings
level_0/f_file/c/file.c
level_0/f_file/c/file.h
level_0/f_file/c/private-file.h
level_1/fl_directory/c/directory.c
level_2/fll_file/c/file.c
level_2/fll_file/c/file.h
level_2/fll_file/c/private-file.c [new file with mode: 0644]
level_2/fll_file/c/private-file.h [new file with mode: 0644]
level_2/fll_file/data/build/dependencies
level_2/fll_file/data/build/settings
level_3/fake/c/fake.h
level_3/fake/c/private-make.c
level_3/fake/c/private-make.h
level_3/fake/c/private-print.c
level_3/fake/c/private-skeleton.c
level_3/fake/documents/fakefile.txt
level_3/fake/specifications/fakefile.txt

index 546d33aa81995c3204b44549384cf8b22e1c01c8..be4d73da7a0b52bbd7045c420ac08357f4146e94 100644 (file)
@@ -20,7 +20,7 @@ build_indexer ar
 build_language c
 build_libraries -lc
 build_libraries-level -lfll_1 -lfll_0
-build_sources_library execute.c private-execute.c file.c fss.c private-fss.c fss_basic.c fss_basic_list.c fss_extended.c fss_extended_list.c fss_status.c path.c program.c status.c
+build_sources_library execute.c private-execute.c file.c private-file.c fss.c private-fss.c fss_basic.c fss_basic_list.c fss_extended.c fss_extended_list.c fss_status.c path.c program.c status.c
 build_sources_program
 build_sources_headers execute.h file.h fss.h fss_basic.h fss_basic_list.h fss_extended.h fss_extended_list.h fss_status.h path.h program.h status.h
 build_sources_script
index 88f48627f138433508a449d1c08746a5b6703ca5..3bc7f4f52264f200c111b93d612f98369ffbab2d 100644 (file)
@@ -20,7 +20,7 @@ build_indexer ar
 build_language c
 build_libraries -lc
 build_libraries-monolithic
-build_sources_library level_0/account.c 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/environment.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/path.c level_2/program.c level_2/status.c
+build_sources_library level_0/account.c 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/environment.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/private-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/path.c level_2/program.c level_2/status.c
 build_sources_program
 build_sources_headers level_0/account.h 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/environment.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/path.h level_2/program.h level_2/status.h
 build_sources_script
index 924e27ae7a4b9efbc6697253ddd67f15e8d68b22..79bb6e2a180f3ca1a7a646ad02d9103e3fd8bfb9 100644 (file)
@@ -378,7 +378,7 @@ extern "C" {
 #endif // _di_f_file_group_read_
 
 #ifndef _di_f_file_is_
-  f_return_status f_file_is(const f_string_t path, const int type) {
+  f_return_status f_file_is(const f_string_t path, const int type, const bool dereference) {
     #ifndef _di_level_0_parameter_checking_
       if (path == 0) return F_status_set_error(F_parameter);
     #endif // _di_level_0_parameter_checking_
@@ -387,18 +387,8 @@ extern "C" {
 
     memset(&file_stat, 0, sizeof(struct stat));
 
-    if (stat(path, &file_stat) < 0) {
-      if (errno == ENAMETOOLONG) return F_status_set_error(F_name);
-      if (errno == EFAULT) return F_status_set_error(F_buffer);
-      if (errno == ENOMEM) return F_status_set_error(F_memory_out);
-      if (errno == EOVERFLOW) return F_status_set_error(F_number_overflow);
-      if (errno == ENOTDIR) return F_status_set_error(F_directory);
-      if (errno == ENOENT) return F_file_found_not;
-      if (errno == EACCES) return F_status_set_error(F_access_denied);
-      if (errno == ELOOP) return F_status_set_error(F_loop);
-
-      return F_status_set_error(F_file_stat);
-    }
+    f_status_t status = private_f_file_stat(path, dereference, &file_stat);
+    if (F_status_is_error(status)) return status;
 
     if (f_macro_file_type_get(file_stat.st_mode) == type) return F_true;
 
index 58245ada3661b2ab4c619177be1c48ec21151066..b14f4abb9ccef76fcf70e101dce274d60529fc71 100644 (file)
@@ -916,6 +916,9 @@ extern "C" {
  *   The path file name.
  * @param type
  *   The type of the file.
+ * @param dereference
+ *   Set to TRUE to dereference symlinks (often is what is desired).
+ *   Set to FALSE to operate on the symlink itself.
  *
  * @return
  *   F_true if path was found and path is type.
@@ -932,7 +935,7 @@ extern "C" {
  * @see stat()
  */
 #ifndef _di_f_file_is_
-  extern f_return_status f_file_is(const f_string_t path, const int type);
+  extern f_return_status f_file_is(const f_string_t path, const int type, const bool dereference);
 #endif // _di_f_file_is_
 
 /**
index 80571149e7b9bc9ddb0ea3c1c89ebd90bfa3f143..05ce890f2028fd5809c8d40f31c7dae687cae24e 100644 (file)
@@ -787,9 +787,9 @@ extern "C" {
  * @see f_file_exists()
  * @see f_file_touch()
  */
-#if !defined(_di_f_file_stat_) || !defined(_di_f_file_copy_) || !defined(_di_f_file_exists_) || !defined(_di_f_file_touch_)
+#if !defined(_di_f_file_stat_) || !defined(_di_f_file_copy_) || !defined(_di_f_file_exists_) || !defined(_di_f_file_is_) || !defined(_di_f_file_touch_)
   extern f_return_status private_f_file_stat(const f_string_t file_name, const bool dereference, struct stat *file_stat) f_gcc_attribute_visibility_internal;
-#endif // !defined(_di_f_file_stat_) || !defined(_di_f_file_copy_) || !defined(_di_f_file_exists_) || !defined(_di_f_file_touch_)
+#endif // !defined(_di_f_file_stat_) || !defined(_di_f_file_copy_) || !defined(_di_f_file_exists_) || !defined(_di_f_file_is_) || !defined(_di_f_file_touch_)
 
 /**
  * Private implementation of f_file_stat_at().
index f27ea3f05033cc020d0fcfd955d145552119b367..aeac5543607d67bc8b15bdf17bc9b7488756ad34 100644 (file)
@@ -220,8 +220,8 @@ extern "C" {
 #ifndef _di_fl_directory_list_
   f_return_status fl_directory_list(const f_string_t path, int (*filter)(const struct dirent *), int (*sort)(const struct dirent **, const struct dirent **), const bool dereference, f_directory_listing_t *listing) {
     #ifndef _di_level_1_parameter_checking_
-      if (path) return F_status_set_error(F_parameter);
-      if (listing == 0) return F_status_set_error(F_parameter);
+      if (!path) return F_status_set_error(F_parameter);
+      if (!listing) return F_status_set_error(F_parameter);
     #endif // _di_level_1_parameter_checking_
 
     return private_fl_directory_list(path, filter, sort, dereference, listing);
index d2b9ed35738e1a7ffc815aa5225aa564cf810d42..2bbb6cf27248ec2a37984b02b64f7a52693c0aff 100644 (file)
@@ -1,4 +1,5 @@
 #include "file.h"
+#include "private-file.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -63,6 +64,27 @@ extern "C" {
   }
 #endif // _di_fll_file_error_print_
 
+#ifndef _di_fll_file_mode_set_all_
+  f_return_status fll_file_mode_set_all(const f_string_t path, const mode_t mode, const f_number_unsigned_t depth_max) {
+    #ifndef _di_level_0_parameter_checking_
+      if (path == 0) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    return private_fll_file_mode_set_all(path, mode, depth_max, 0);
+  }
+#endif // _di_fll_file_mode_set_all__
+
+#ifndef _di_fll_file_role_change_all_
+  f_return_status fll_file_role_change_all(const f_string_t path, const uid_t uid, const gid_t gid, const bool dereference, const f_number_unsigned_t depth_max) {
+    #ifndef _di_level_0_parameter_checking_
+      if (path == 0) return F_status_set_error(F_parameter);
+      if (uid == -1 && gid == -1) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    return private_fll_file_role_change_all(path, uid, gid, dereference, depth_max, 0);
+  }
+#endif // _di_fll_file_role_change_all_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index e45fe4d3ed73e23207f96dff4b4bc96b5fea704e..dbc4caee0cdb005c9ca29f1a7b75f5ee81bec081 100644 (file)
 #include <level_0/status.h>
 #include <level_0/memory.h>
 #include <level_0/string.h>
+#include <level_0/directory.h>
+#include <level_0/file.h>
 
 // fll-1 includes
 #include <level_1/color.h>
+#include <level_1/directory.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -49,6 +52,82 @@ extern "C" {
   extern f_return_status fll_file_error_print(FILE *file, const fl_color_context_t context, const f_string_t function_name, const f_string_t file_name, const f_status_t status);
 #endif // _di_fll_file_error_print_
 
+/**
+ * Change mode of a given file or directory at the specified path.
+ *
+ * This does not set mode based on umask(), be sure to apply umask if so desired.
+ * (such as: mode & ~mask).
+ *
+ * If the file is a directory then recurse into that directory and apply mode to all files within.
+ *
+ * @param path
+ *   The path file name.
+ * @param mode
+ *   The new mode to use.
+ * @param depth_max
+ *   The max recursion depth.
+ *
+ * @return
+ *   F_none on success.
+ *   F_access_denied (with error bit) on access denied.
+ *   F_access_mode (with error bit) if the current user does not have access to assign the file mode.
+ *   F_directory (with error bit) on invalid directory.
+ *   F_file_found_not (with error bit) if file at path was not found.
+ *   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_read_only (with error bit) if file is read-only.
+ *   F_recurse (with error bit) if recursion failed, due to max depth reached.
+ *   F_failure (with error bit) for any other error.
+ */
+#ifndef _di_fll_file_mode_set_all_
+  extern f_return_status fll_file_mode_set_all(const f_string_t path, const mode_t mode, const f_number_unsigned_t depth_max);
+#endif // _di_fll_file_mode_set_all_
+
+/**
+ * Change owner and/or group of a given file at the specified path.
+ *
+ * At least one of uid or gid must not be -1.
+ *
+ * If the file is a directory then recurse into that directory and apply mode to all files within.
+ *
+ * @param path
+ *   The path file name.
+ * @param uid
+ *   The new user id to use.
+ *   Set to -1 to not change.
+ * @param gid
+ *   The new group id to use.
+ *   Set to -1 to not change.
+ * @param dereference
+ *   Set to TRUE to dereferenc symlinks (often is what is desired).
+ *   Set to FALSE to operate on the symlink itself.
+ * @param depth_max
+ *   The max recursion depth.
+ *
+ * @return
+ *   F_none on success.
+ *   F_access_denied (with error bit) on access denied.
+ *   F_access_group (with error bit) if the current user does not have access to assign the specified group.
+ *   F_access_owner (with error bit) if the current user does not have access to assign the specified owner.
+ *   F_buffer (with error bit) if the buffer is invalid.
+ *   F_directory (with error bit) on invalid directory.
+ *   F_file_found_not (with error bit) if file at path was not found.
+ *   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_read_only (with error bit) if file is read-only.
+ *   F_recurse (with error bit) if recursion failed, due to max depth reached.
+ *   F_failure (with error bit) for any other error.
+ */
+#ifndef _di_fll_file_role_change_all_
+  extern f_return_status fll_file_role_change_all(const f_string_t path, const uid_t uid, const gid_t gid, const bool dereference, const f_number_unsigned_t depth_max);
+#endif // _di_fll_file_role_change_all_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
diff --git a/level_2/fll_file/c/private-file.c b/level_2/fll_file/c/private-file.c
new file mode 100644 (file)
index 0000000..d8106ae
--- /dev/null
@@ -0,0 +1,194 @@
+#include "file.h"
+#include "private-file.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(_di_fll_file_mode_set_all_)
+  f_return_status private_fll_file_mode_set_all(const f_string_t path, const mode_t mode, const f_number_unsigned_t depth_max, const f_number_unsigned_t depth) {
+
+    if (depth >= depth_max) return F_status_set_error(F_recurse);
+
+    f_status_t status = F_none;
+
+    status = f_directory_is(path);
+    if (F_status_is_error(status)) return status;
+
+    if (status == F_false) {
+      return f_file_mode_set(path, mode);
+    }
+
+    f_directory_listing_t listing = f_directory_listing_t_initialize;
+
+    status = fl_directory_list(path, 0, 0, F_false, &listing);
+
+    if (F_status_is_error(status)) {
+      f_macro_directory_listing_t_delete_simple(listing);
+      return status;
+    }
+
+    status = F_none;
+
+    const f_string_length_t path_length = strnlen(path, f_path_max);
+
+    {
+      f_string_dynamics_t *list[] = {
+        &listing.block,
+        &listing.character,
+        &listing.regular,
+        &listing.link,
+        &listing.fifo,
+        &listing.socket,
+        &listing.unknown,
+      };
+
+      uint8_t i = 0;
+      f_array_length_t j = 0;
+
+      for (; i < 7; i++) {
+        for (j = 0; F_status_is_fine(status) && j < list[i]->used; j++) {
+          const f_string_length_t length = path_length + list[i]->array[j].used + 1;
+
+          char path_sub[length + 1];
+
+          memcpy(path_sub, path, path_length);
+          memcpy(path_sub + path_length + 1, list[i]->array[j].string, list[i]->array[j].used);
+
+          path_sub[path_length] = f_path_separator[0];
+          path_sub[length] = 0;
+
+          status = f_file_mode_set(path_sub, mode);
+        } // for
+
+        f_macro_string_dynamics_t_delete_simple((*list[i]));
+      } // for
+    }
+
+    f_macro_string_dynamics_t_delete_simple(listing.unknown);
+
+    for (f_array_length_t i = 0; F_status_is_fine(status) && i < listing.directory.used; i++) {
+      const f_string_length_t length = path_length + listing.directory.array[i].used + 1;
+
+      char path_sub[length + 1];
+
+      memcpy(path_sub, path, path_length);
+      memcpy(path_sub + path_length + 1, listing.directory.array[i].string, listing.directory.array[i].used);
+
+      path_sub[path_length] = f_path_separator[0];
+      path_sub[length] = 0;
+
+      status = f_directory_exists(path_sub);
+      if (F_status_is_error(status)) break;
+
+      if (status == F_false) {
+        status = F_status_set_error(F_directory);
+        break;
+      }
+
+      status = private_fll_file_mode_set_all(path_sub, mode, depth_max, depth + 1);
+      if (F_status_is_error(status)) break;
+    } // for
+
+    f_macro_string_dynamics_t_delete_simple(listing.directory);
+
+    if (F_status_is_error(status)) return status;
+
+    return f_file_mode_set(path, mode);
+  }
+#endif // !defined(_di_fll_file_mode_set_all_)
+
+#if !defined(_di_fll_file_role_change_all_)
+  f_return_status private_fll_file_role_change_all(const f_string_t path, const uid_t uid, const gid_t gid, const bool dereference, const f_number_unsigned_t depth_max, const f_number_unsigned_t depth) {
+
+    if (depth >= depth_max) return F_status_set_error(F_recurse);
+
+    f_status_t status = F_none;
+
+    status = f_directory_is(path);
+    if (F_status_is_error(status)) return status;
+
+    if (status == F_false) {
+      return f_file_role_change(path, uid, gid, dereference);
+    }
+
+    f_directory_listing_t listing = f_directory_listing_t_initialize;
+
+    status = fl_directory_list(path, 0, 0, F_false, &listing);
+
+    if (F_status_is_error(status)) {
+      f_macro_directory_listing_t_delete_simple(listing);
+      return status;
+    }
+
+    status = F_none;
+
+    const f_string_length_t path_length = strnlen(path, f_path_max);
+
+    {
+      f_string_dynamics_t *list[] = {
+        &listing.block,
+        &listing.character,
+        &listing.regular,
+        &listing.link,
+        &listing.fifo,
+        &listing.socket,
+        &listing.unknown,
+      };
+
+      uint8_t i = 0;
+      f_array_length_t j = 0;
+
+      for (; i < 7; i++) {
+        for (j = 0; F_status_is_fine(status) && j < list[i]->used; j++) {
+          const f_string_length_t length = path_length + list[i]->array[j].used + 1;
+
+          char path_sub[length + 1];
+
+          memcpy(path_sub, path, path_length);
+          memcpy(path_sub + path_length + 1, list[i]->array[j].string, list[i]->array[j].used);
+
+          path_sub[path_length] = f_path_separator[0];
+          path_sub[length] = 0;
+
+          status = f_file_role_change(path_sub, uid, gid, dereference);
+        } // for
+
+        f_macro_string_dynamics_t_delete_simple((*list[i]));
+      } // for
+    }
+
+    for (f_array_length_t i = 0; F_status_is_fine(status) && i < listing.directory.used; i++) {
+      const f_string_length_t length = path_length + listing.directory.array[i].used + 1;
+
+      char path_sub[length + 1];
+
+      memcpy(path_sub, path, path_length);
+      memcpy(path_sub + path_length + 1, listing.directory.array[i].string, listing.directory.array[i].used);
+
+      path_sub[path_length] = f_path_separator[0];
+      path_sub[length] = 0;
+
+      status = f_directory_exists(path_sub);
+      if (F_status_is_error(status)) break;
+
+      if (status == F_false) {
+        status = F_status_set_error(F_directory);
+        break;
+      }
+
+      status = private_fll_file_role_change_all(path_sub, uid, gid, dereference, depth_max, depth + 1);
+      if (F_status_is_error(status)) break;
+    } // for
+
+    f_macro_string_dynamics_t_delete_simple(listing.directory);
+
+    if (F_status_is_error(status)) return status;
+
+    return f_file_role_change(path, uid, gid, dereference);
+  }
+#endif // !defined(_di_fll_file_role_change_all_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_2/fll_file/c/private-file.h b/level_2/fll_file/c/private-file.h
new file mode 100644 (file)
index 0000000..d8018e4
--- /dev/null
@@ -0,0 +1,94 @@
+/**
+ * FLL - Level 2
+ *
+ * Project: File
+ * API Version: 0.5
+ * Licenses: lgplv2.1
+ *
+ * Provides structures and data types for a file I/O.
+ * Provides operations for opening/closing files.
+ */
+#ifndef _PRIVATE_FLL_file_h
+#define _PRIVATE_FLL_file_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Private implementation of fll_file_mode_set_all().
+ *
+ * Intended to be shared to each of the different implementation variations.
+ *
+ * @param path
+ *   The path file name.
+ * @param mode
+ *   The new mode to use.
+ * @param depth_max
+ *   The max recursion depth.
+ * @param depth
+ *   The current depth.
+ *
+ * @return
+ *   F_none on success.
+ *   F_access_denied (with error bit) on access denied.
+ *   F_access_mode (with error bit) if the current user does not have access to assign the file mode.
+ *   F_directory (with error bit) on invalid directory.
+ *   F_file_found_not (with error bit) if file at path was not found.
+ *   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_read_only (with error bit) if file is read-only.
+ *   F_recurse (with error bit) if recursion failed, due to max depth reached.
+ *   F_failure (with error bit) for any other error.
+ */
+#if !defined(_di_fll_file_mode_set_all_)
+  extern f_return_status private_fll_file_mode_set_all(const f_string_t path, const mode_t mode, const f_number_unsigned_t depth_max, const f_number_unsigned_t depth) f_gcc_attribute_visibility_internal;
+#endif // !defined(_di_fll_file_mode_set_all_)
+
+/**
+ * Private implementation of fll_file_role_change_all().
+ *
+ * Intended to be shared to each of the different implementation variations.
+ *
+ * @param path
+ *   The path file name.
+ * @param uid
+ *   The new user id to use.
+ * @param gid
+ *   The new group id to use.
+ * @param dereference
+ *   Set to TRUE to dereference symlinks (often is what is desired).
+ *   Set to FALSE to operate on the symlink itself.
+ * @param depth_max
+ *   The max recursion depth.
+ * @param depth
+ *   The current depth.
+ *
+ * @return
+ *   F_none on success.
+ *   F_access_denied (with error bit) on access denied.
+ *   F_access_group (with error bit) if the current user does not have access to assign the specified group.
+ *   F_access_owner (with error bit) if the current user does not have access to assign the specified owner.
+ *   F_buffer (with error bit) if the buffer is invalid.
+ *   F_directory (with error bit) on invalid directory.
+ *   F_file_found_not (with error bit) if file at path was not found.
+ *   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_read_only (with error bit) if file is read-only.
+ *   F_failure (with error bit) for any other error.
+ */
+#if !defined(_di_fll_file_role_change_all_)
+  extern f_return_status private_fll_file_role_change_all(const f_string_t path, const uid_t uid, const gid_t gid, const bool dereference, const f_number_unsigned_t depth_max, const f_number_unsigned_t depth) f_gcc_attribute_visibility_internal;
+#endif // !defined(_di_fll_file_role_change_all_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _PRIVATE_FLL_file_h
index 0759aad5d08dcbd9fe840b7b48d5d9648052a908..3d952dc544a7ea73d943471b389a78fa2c277dc5 100644 (file)
@@ -4,4 +4,7 @@ f_type
 f_status
 f_memory
 f_string
+f_directory
+f_file
 fl_color
+fl_directory
index 93b342a2edeacfd85d4d29ecf00c1d5fb06d77f5..0b6f635c7ee02c685241d57432da8d7b3244ddd1 100644 (file)
@@ -19,8 +19,8 @@ build_compiler gcc
 build_indexer ar
 build_language c
 build_libraries -lc
-build_libraries-individual -lfl_color -lf_print -lf_file -lf_memory
-build_sources_library file.c
+build_libraries-individual -lfl_color -lfl_directory -lf_print -lf_file -lf_directory -lf_memory
+build_sources_library file.c private-file.c
 build_sources_program
 build_sources_headers file.h
 build_sources_script
index da8ab33e19953318811ddaaf383c6091ea0727fe..28f15192e936bca38db65f0e0ce6455a340e3a13 100644 (file)
@@ -73,6 +73,7 @@
 
 // fll-2 includes
 #include <level_2/execute.h>
+#include <level_2/file.h>
 #include <level_2/fss.h>
 #include <level_2/fss_basic_list.h>
 #include <level_2/fss_extended.h>
index 245513edc75d83e6446c6bc5d0d68d120bc477a2..8e9fcb169445df17e0792e88017fef35bfb11d28 100644 (file)
@@ -1958,10 +1958,24 @@ extern "C" {
       *status = fake_make_get_id_group(data, data_make->print, arguments.array[0], &id);
       if (F_status_is_error(*status)) return;
 
+      f_status_t status_file = F_none;
+
       for (f_array_length_t i = 1; i < arguments.used; i++) {
-        *status = f_file_role_change(arguments.array[i].string, -1, id, F_false);
+        status_file = fake_make_assure_inside_project(data, arguments.array[i], data_make);
+
+        if (F_status_is_error(status_file)) {
+          *status = status_file;
+
+          fake_print_message_section_operation_path_outside(data, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[i].string, data_make->print);
+
+          continue;
+        }
+
+        status_file = f_file_role_change(arguments.array[i].string, -1, id, F_false);
+
+        if (F_status_is_error(status_file)) {
+          *status = status_file;
 
-        if (F_status_is_error(*status)) {
           fake_print_message_file(data, *status, "f_file_role_change", arguments.array[i].string, "change group of", F_true, F_true, data_make->print);
         }
         else if (data.verbosity == fake_verbosity_verbose) {
@@ -1978,12 +1992,25 @@ extern "C" {
       *status = fake_make_get_id_group(data, data_make->print, arguments.array[0], &id);
       if (F_status_is_error(*status)) return;
 
+      f_status_t status_file = F_none;
+
       for (f_array_length_t i = 1; i < arguments.used; i++) {
-        // @todo: recursive.
-        *status = f_file_role_change(arguments.array[i].string, -1, id, F_false);
+        status_file = fake_make_assure_inside_project(data, arguments.array[i], data_make);
 
-        if (F_status_is_error(*status)) {
-          fake_print_message_file(data, *status, "f_file_role_change", arguments.array[i].string, "change group of", F_true, F_true, data_make->print);
+        if (F_status_is_error(status_file)) {
+          *status = status_file;
+
+          fake_print_message_section_operation_path_outside(data, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[i].string, data_make->print);
+
+          continue;
+        }
+
+        status_file = fll_file_role_change_all(arguments.array[i].string, -1, id, F_false, fake_make_operation_recursion_depth_max);
+
+        if (F_status_is_error(status_file)) {
+          *status = status_file;
+
+          fake_print_message_file(data, F_status_set_fine(*status), "fll_file_role_change_all", arguments.array[i].string, "change group of", F_true, F_true, data_make->print);
         }
         else if (data.verbosity == fake_verbosity_verbose) {
           printf("Changed group of '%s' to %llu.%c", arguments.array[i].string, id, f_string_eol[0]);
@@ -2527,7 +2554,6 @@ extern "C" {
       mode_t mode_file = 0;
 
       for (f_array_length_t i = 1; i < arguments.used; i++) {
-        // @todo recursive.
         mode = 0;
 
         *status = f_file_mode_read(arguments.array[i].string, &mode_file);
@@ -2542,9 +2568,9 @@ extern "C" {
           break;
         }
 
-        *status = f_file_mode_set(arguments.array[i].string, mode);
+        *status = fll_file_mode_set_all(arguments.array[i].string, mode, fake_make_operation_recursion_depth_max);
         if (F_status_is_error(*status)) {
-          fake_print_message_file(data, F_status_set_fine(*status), "f_file_mode_set", arguments.array[i].string, "change mode of", F_true, F_true, data_make->print);
+          fake_print_message_file(data, F_status_set_fine(*status), "fll_file_mode_set_all", arguments.array[i].string, "change mode of", F_true, F_true, data_make->print);
           break;
         }
 
@@ -2588,14 +2614,28 @@ extern "C" {
       *status = fake_make_get_id_owner(data, data_make->print, arguments.array[0], &id);
       if (F_status_is_error(*status)) return;
 
+      f_status_t status_file = F_none;
+
       for (f_array_length_t i = 1; i < arguments.used; i++) {
-        *status = f_file_role_change(arguments.array[i].string, id, -1, F_false);
-        if (F_status_is_error(*status)) {
+        status_file = fake_make_assure_inside_project(data, arguments.array[i], data_make);
+
+        if (F_status_is_error(status_file)) {
+          *status = status_file;
+
+          fake_print_message_section_operation_path_outside(data, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[i].string, data_make->print);
+
+          continue;
+        }
+
+        status_file = f_file_role_change(arguments.array[i].string, id, -1, F_false);
+
+        if (F_status_is_error(status_file)) {
+          *status = status_file;
+
           fake_print_message_file(data, F_status_set_fine(*status), "f_file_role_change", arguments.array[i].string, "change owner of", F_true, F_true, data_make->print);
           break;
         }
-
-        if (data.verbosity == fake_verbosity_verbose) {
+        else if (data.verbosity == fake_verbosity_verbose) {
           printf("Changed owner of '%s' to %d.%c", arguments.array[i].string, id, f_string_eol[0]);
         }
       } // for
@@ -2609,14 +2649,27 @@ extern "C" {
       *status = fake_make_get_id_owner(data, data_make->print, arguments.array[0], &id);
       if (F_status_is_error(*status)) return;
 
+      f_status_t status_file = F_none;
+
       for (f_array_length_t i = 1; i < arguments.used; i++) {
-        // @todo recursive.
-        *status = f_file_role_change(arguments.array[i].string, id, -1, F_false);
-        if (F_status_is_error(*status)) {
-          fake_print_message_file(data, F_status_set_fine(*status), "f_file_role_change", arguments.array[i].string, "change owner of", F_true, F_true, data_make->print);
+        status_file = fake_make_assure_inside_project(data, arguments.array[i], data_make);
+
+        if (F_status_is_error(status_file)) {
+          *status = status_file;
+
+          fake_print_message_section_operation_path_outside(data, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[i].string, data_make->print);
+
+          continue;
         }
 
-        if (data.verbosity == fake_verbosity_verbose) {
+        status_file = fll_file_role_change_all(arguments.array[i].string, id, -1, F_false, fake_make_operation_recursion_depth_max);
+
+        if (F_status_is_error(status_file)) {
+          *status = status_file;
+
+          fake_print_message_file(data, F_status_set_fine(*status), "fll_file_role_change_all", arguments.array[i].string, "change owner of", F_true, F_true, data_make->print);
+        }
+        else if (data.verbosity == fake_verbosity_verbose) {
           printf("Changed owner of '%s' to %o.%c", arguments.array[i].string, id, f_string_eol[0]);
         }
       } // for
@@ -3093,7 +3146,7 @@ extern "C" {
 
           path_file[data.path_data_build.used + arguments.array[0].used] = 0;
 
-          f_status_t status_file = f_file_is(path_file, f_file_type_regular);
+          f_status_t status_file = f_file_is(path_file, f_file_type_regular, F_false);
 
           if (status_file == F_file_found_not) {
             if (data.verbosity != fake_verbosity_quiet && data_make->print.to) {
@@ -3362,7 +3415,7 @@ extern "C" {
         f_status_t status_file = F_none;
 
         for (f_array_length_t i = 1; i < arguments.used; i++) {
-          status_file = f_file_is(arguments.array[i].string, f_file_type_regular);
+          status_file = f_file_is(arguments.array[i].string, f_file_type_regular, F_false);
 
           if (status_file == F_file_found_not) {
             if (data.verbosity != fake_verbosity_quiet && data_make->print.to) {
@@ -3877,7 +3930,7 @@ extern "C" {
       }
       else if (arguments.used) {
         if (arguments.array[0].used) {
-          f_status_t status_file = f_file_is(arguments.array[0].string, f_file_type_directory);
+          f_status_t status_file = f_file_is(arguments.array[0].string, f_file_type_directory, F_false);
 
           if (status_file == F_file_found_not) {
             if (data.verbosity != fake_verbosity_quiet && data_make->print.to) {
index 04f9d119639a7cdb5352e2b4667f96dd0d299a4e..5baa17f2a50b1512cb351349f8187cb7909a9a90 100644 (file)
@@ -248,6 +248,8 @@ extern "C" {
     fake_make_operation_fail_type_warn,
     fake_make_operation_fail_type_ignore,
   };
+
+  #define fake_make_operation_recursion_depth_max 65535
 #endif // _di_fake_make_operation_
 
 // @todo each one of these should be made available to be passed to the program as "$parameter_define[X]" for multi-value (define) or "$parameter_no_color" for single-value (no_color).
index 0baf69f36b2c6467e133f68e269548924ae64dea..4b6c09cff3fe2bf2d91d775fe0897f9b7525bdd8 100644 (file)
@@ -500,6 +500,28 @@ extern "C" {
       return F_false;
     }
 
+    if (status == F_access_owner) {
+      if (data.verbosity != fake_verbosity_quiet) {
+        fprintf(print.to, "%c", f_string_eol[0]);
+        fl_color_print(print.to, print.context, data.context.reset, "%s: Currrent user is not allowed to use the given owner while trying to %s %s '", print.prefix, operation, file_or_directory);
+        fl_color_print(print.to, data.context.notable, data.context.reset, "%s", name);
+        fl_color_print_line(print.to, print.context, data.context.reset, "'.");
+      }
+
+      return F_false;
+    }
+
+    if (status == F_access_group) {
+      if (data.verbosity != fake_verbosity_quiet) {
+        fprintf(print.to, "%c", f_string_eol[0]);
+        fl_color_print(print.to, print.context, data.context.reset, "%s: Currrent user is not allowed to use the given group while trying to %s %s '", print.prefix, operation, file_or_directory);
+        fl_color_print(print.to, data.context.notable, data.context.reset, "%s", name);
+        fl_color_print_line(print.to, print.context, data.context.reset, "'.");
+      }
+
+      return F_false;
+    }
+
     if (is_file) {
       if (status == F_directory_found_not) {
         if (data.verbosity != fake_verbosity_quiet) {
index 254c2faba6fb67d4612f0d423b3d6a20c5edd523..95eedaacd4311d08f632fff1b974f4cd9107bc9f 100644 (file)
@@ -179,7 +179,7 @@ extern "C" {
 
     if (path.used == 0) return F_none;
 
-    status = f_file_is(path.string, f_file_type_regular);
+    status = f_file_is(path.string, f_file_type_regular, F_false);
     if (status == F_true) {
       if (data.verbosity == fake_verbosity_verbose) {
         printf("File '%s' already exists.%c", path.string, f_string_eol[0]);
@@ -190,7 +190,7 @@ extern "C" {
 
     // symbolic links might also be fine.
     if (status == F_false) {
-      status = f_file_is(path.string, f_file_type_link);
+      status = f_file_is(path.string, f_file_type_link, F_false);
 
       if (status == F_true) {
         if (data.verbosity == fake_verbosity_verbose) {
index 5e7ca58353322da1f1282a20fa84be889b568a70..b985a92ab208fc42fcae13d4691056fce0951877 100644 (file)
@@ -41,7 +41,7 @@ Fakefile Documentation:
 
       The return code for programs can still be retrieved through using the reserved iki vaiable "return".
 
-    - index\:
+    - indexer\:
       This represents the name of the indexer program to use, such as "ar".
 
       When specified and "load_build" is "true", then this will override the "build_indexer" specified in the loaded build settings.
@@ -65,12 +65,6 @@ Fakefile Documentation:
     This is processed top-down until the end of the list is reached.
 
     The following operations are available\:
-    - archive\:
-      Execute the linker program, such as "ar".
-      This uses "archive" instead of "link" to avoid confusion between this and generating a symbolic link to some file.
-
-      All Content are passed as arguments to the respective "ar" program.
-
     - build\:
       Run the fake build operation as if "fake build" was run instead of "fake make".
       Command line arguments are automatically passed to the fake build operation.
@@ -217,6 +211,11 @@ Fakefile Documentation:
           for example, "if defined parameter verbose silent" would test if both the "verbose" and the "silent" variables are defined via the "parameter" setting.
           for example, "if defined environment PWD SHELL" would test if both the "PWD" and the "SHELL" variables are defined via the "environment" variables.
 
+    - index\:
+      Execute the linker program, such as "ar".
+
+      All Content are passed as arguments to the respective "ar" program.
+
     - link\:
       Create a symbolic link from some point to some target.
 
index d73bad54b87d9c1ceaafcc497cc5fb3c9d1955ab..38e185f90cb5af9b7d6bea2a1d83822c0abeb3de 100644 (file)
@@ -25,11 +25,11 @@ Fakefile Specification:
   - main: contains a list of Operation Objects and Content in FSS-0001 (Extended) format.
 
   The Settings Objects are\:
-  - archiver: Only one Content, which must only be a valid filename.
   - compiler: Only one Content, which must only be a valid filename.
   - define: First Content represents variable name (case-sensitive), remaining Content represents varaiable value for IKI substitution.
   - environment: Zero or more Content representing valid environment variable names (alpha-numeric with underscore, but cannot begin with a number).
   - fail: Only one Content, which must be either "exit", "warn" or "ignore" (quotes not required) (case-sensitive).
+  - indexer: Only one Content, which must only be a valid filename.
   - load_build: Only one Content, which must be either "yes" or "no" (quotes not required) (case-sensitive).
   - parameter: First Content represents variable name (case-sensitive), remaining Content represents varaiable value for IKI substitution.