]> Kevux Git Server - fll/commitdiff
Update: f_file, add f_file_touch() and f_file_touch_at(), F_search error
authorKevin Day <thekevinday@gmail.com>
Mon, 1 Jun 2020 04:00:59 +0000 (23:00 -0500)
committerKevin Day <thekevinday@gmail.com>
Mon, 1 Jun 2020 04:00:59 +0000 (23:00 -0500)
Minor updates to f_file project.

Add the f_file_touch() and f_file_touch_at() functions.

Add the status code F_search (used by f_file_touch() and f_file_touch_at()).

level_0/f_file/c/file.c
level_0/f_file/c/file.h
level_0/f_file/c/private-file.h
level_0/f_status/c/status.h
level_1/fl_status/c/status.c
level_1/fl_status/c/status.h
level_2/fll_status/c/status.c

index b6731f99cdfe853e43dd189c9a87cac941e78c46..837beede512cd1b0e342fb9455bccf9d471c37e8 100644 (file)
@@ -353,21 +353,17 @@ extern "C" {
       if (path == 0) return F_status_set_error(F_parameter);
     #endif // _di_level_0_parameter_checking_
 
+    f_status status = F_none;
     struct stat file_stat;
 
     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_false;
-      if (errno == EACCES) return F_status_set_error(F_access_denied);
-      if (errno == ELOOP) return F_status_set_error(F_loop);
+    status = private_f_file_stat(path, F_false, &file_stat);
 
-      return F_status_set_error(F_file_stat);
+    if (F_status_is_error(status)) {
+      if (F_status_set_fine(status) == F_file_found_not) return F_false;
+
+      return status;
     }
 
     return F_true;
@@ -375,27 +371,22 @@ extern "C" {
 #endif // _di_f_file_exists_
 
 #ifndef _di_f_file_exists_at_
-  f_return_status f_file_exists_at(const int at_id, const f_string path, const bool follow) {
+  f_return_status f_file_exists_at(const int at_id, const f_string path, const int flag) {
     #ifndef _di_level_0_parameter_checking_
       if (path == 0) return F_status_set_error(F_parameter);
     #endif // _di_level_0_parameter_checking_
 
+    f_status status = F_none;
     struct stat file_stat;
 
     memset(&file_stat, 0, sizeof(struct stat));
 
-    if (fstatat(at_id, path, &file_stat, follow ? 0 : AT_SYMLINK_NOFOLLOW) < 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);
-      if (errno == EBADF) return F_status_set_error(F_directory_descriptor);
+    status = private_f_file_stat_at(at_id, path, flag, &file_stat);
 
-      return F_status_set_error(F_file_stat);
+    if (F_status_is_error(status)) {
+      if (F_status_set_fine(status) == F_file_found_not) return F_false;
+
+      return status;
     }
 
     return F_true;
@@ -548,7 +539,7 @@ extern "C" {
 #endif // _di_f_file_is_
 
 #ifndef _di_f_file_is_at_
-  f_return_status f_file_is_at(const int at_id, const f_string path, const int type, const bool follow) {
+  f_return_status f_file_is_at(const int at_id, const f_string path, const int type, const int flag) {
     #ifndef _di_level_0_parameter_checking_
       if (path == 0) return F_status_set_error(F_parameter);
     #endif // _di_level_0_parameter_checking_
@@ -557,7 +548,7 @@ extern "C" {
 
     memset(&file_stat, 0, sizeof(struct stat));
 
-    if (fstatat(at_id, path, &file_stat, follow ? 0 : AT_SYMLINK_NOFOLLOW) < 0) {
+    if (fstatat(at_id, path, &file_stat, flag) < 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);
@@ -1007,6 +998,86 @@ extern "C" {
   }
 #endif // _di_f_file_stat_by_id_
 
+#ifndef _di_f_file_touch_
+  f_return_status f_file_touch(const f_string path, const mode_t mode, 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_
+
+    f_status status = F_none;
+    struct stat file_stat;
+
+    memset(&file_stat, 0, sizeof(struct stat));
+
+    status = private_f_file_stat(path, F_false, &file_stat);
+
+    if (F_status_set_fine(status) == F_file_found_not) {
+      return private_f_file_create(path, mode, dereference);
+    }
+    else if (F_status_is_error(status)) {
+      return status;
+    }
+
+    if (utimensat(f_file_at_current_working, path, 0, dereference ? 0 : f_file_at_symlink_follow_no) < 0) {
+      if (errno == EACCES) return F_status_set_error(F_access_denied);
+      if (errno == EBADF) return F_status_set_error(F_directory_descriptor);
+      if (errno == EFAULT) return F_status_set_error(F_buffer);
+      if (errno == EINVAL) return F_status_set_error(F_parameter);
+      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 == ENOTDIR) return F_status_set_error(F_directory);
+      if (errno == EPERM) return F_status_set_error(F_prohibited);
+      if (errno == EROFS) return F_status_set_error(F_read_only);
+      if (errno == ESRCH) return  F_status_set_error(F_search);
+
+      return F_status_set_error(F_failure);
+    }
+
+    return F_none;
+  }
+#endif // _di_f_file_touch_
+
+#ifndef _di_f_file_touch_at_
+  f_return_status f_file_touch_at(const int at_id, const f_string path, const mode_t mode, const int flag) {
+    #ifndef _di_level_0_parameter_checking_
+      if (path == 0) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    f_status status = F_none;
+    struct stat file_stat;
+
+    memset(&file_stat, 0, sizeof(struct stat));
+
+    status = private_f_file_stat_at(at_id, path, flag, &file_stat);
+
+    if (F_status_set_fine(status) == F_file_found_not) {
+      return private_f_file_create_at(at_id, path, mode, F_false);
+    }
+    else if (F_status_is_error(status)) {
+      return status;
+    }
+
+    if (utimensat(at_id, path, 0, flag) < 0) {
+      if (errno == EACCES) return F_status_set_error(F_access_denied);
+      if (errno == EBADF) return F_status_set_error(F_directory_descriptor);
+      if (errno == EFAULT) return F_status_set_error(F_buffer);
+      if (errno == EINVAL) return F_status_set_error(F_parameter);
+      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 == ENOTDIR) return F_status_set_error(F_directory);
+      if (errno == EPERM) return F_status_set_error(F_prohibited);
+      if (errno == EROFS) return F_status_set_error(F_read_only);
+      if (errno == ESRCH) return  F_status_set_error(F_search);
+
+      return F_status_set_error(F_failure);
+    }
+
+    return F_none;
+  }
+#endif // _di_f_file_touch_at_
+
 #ifndef _di_f_file_write_
   f_return_status f_file_write(const f_file file, const f_string_dynamic buffer, f_string_length *written) {
     #ifndef _di_level_0_parameter_checking_
index c99b3526625f17c3cc90bbd93c5600ae2d76ccef..c31843f002a364431d6dc7e48324d83a0e3e42e6 100644 (file)
@@ -573,7 +573,7 @@ extern "C" {
 #endif // _di_f_file_copy_
 
 /**
- * Create a file based on the given path and file mode.
+ * Create a (regular) file based on the given path and file mode.
  *
  * The file will not be open after calling this.
  *
@@ -612,7 +612,7 @@ extern "C" {
 #endif // _di_f_file_create_
 
 /**
- * Create a file based on the given path and file mode.
+ * Create a (regular) file based on the given path and file mode.
  *
  * The file will not be open after calling this.
  *
@@ -902,7 +902,7 @@ extern "C" {
  * @param path
  *   The path file name.
  * @param flag
- *   Additional flag to pass, such as AT_EACCESS or AT_SYMLINK_NOFOLLOW.
+ *   Any valid flag, such as f_file_at_path_empty, f_file_at_automount_no, or f_file_at_symlink_follow_no.
  *
  * @return
  *   F_true if file exists.
@@ -919,7 +919,7 @@ extern "C" {
  * @see fstatat()
  */
 #ifndef _di_f_file_exists_at_
-  extern f_return_status f_file_exists_at(const int at_id, const f_string path, const bool follow);
+  extern f_return_status f_file_exists_at(const int at_id, const f_string path, const int flag);
 #endif // _di_f_file_exists_at_
 
 /**
@@ -982,9 +982,8 @@ extern "C" {
  *   The path file name.
  * @param type
  *   The type of the file
- * @param follow
- *   Set to TRUE to follow symbolic links when determining if path is a file.
- *   Set to FALSE to not follow.
+ * @param flag
+ *   Any valid flag, such as f_file_at_path_empty, f_file_at_automount_no, or f_file_at_symlink_follow_no.
  *
  * @return
  *   F_true if path was found and path is type.
@@ -1001,7 +1000,7 @@ extern "C" {
  * @see fstatat()
  */
 #ifndef _di_f_file_is_at_
-  extern f_return_status f_file_is_at(const int at_id, const f_string path, const int type, const bool follow);
+  extern f_return_status f_file_is_at(const int at_id, const f_string path, const int type, const int flag);
 #endif // _di_f_file_is_at_
 
 /**
@@ -1710,6 +1709,89 @@ extern "C" {
 #endif // _di_f_file_write_
 
 /**
+ * Update the files access and modification timestamp, creating the file if it does not already exist.
+ *
+ * When the file is created, it is created as a regular file.
+ *
+ * @param path
+ *   The path file name.
+ * @param mode
+ *   The file mode to use when (regular) file is created.
+ * @param dereference
+ *   Set to TRUE to dereferenc symlinks (often is what is desired).
+ *   Set to FALSE to operate on the symlink itself.
+ *
+ * @return
+ *   F_none on success.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_access_denied (with error bit) on access denied.
+ *   F_directory_descriptor (with error bit) for bad directory descriptor for at_id.
+ *   F_buffer (with error bit) if the buffer is invalid.
+ *   F_loop (with error bit) on loop error.
+ *   F_name (with error bit) on path name error.
+ *   F_file_found (with error bit) if a file aleady exists at the path.
+ *   F_directory (with error bit) if a supposed directory in path is not actually a directory.
+ *   F_prohibited (with error bit) if filesystem does not allow for creating or linking.
+ *   F_read_only (with error bit) if filesystem is read-only.
+ *   F_search (with error bit) if search permission is denied for one of the paths to the file.
+ *   F_memory_out (with error bit) if out of memory.
+ *   F_filesystem_quota_block (with error bit) if filesystem's disk blocks or inodes are exhausted.
+ *   F_filesystem_quota_reached (with error bit) quota reached of filesystem is out of space.
+ *   F_number_overflow (with error bit) on overflow error.
+ *   F_interrupted (with error bit) when program received an interrupt signal, halting create.
+ *   F_file_open_max (with error bit) when system-wide max open files is reached.
+ *   F_busy (with error bit) if filesystem is too busy to perforrm write.
+ *   F_failure (with error bit) for any other error.
+ *
+ * @see utimensat()
+ */
+#ifndef _di_f_file_touch_
+  extern f_return_status f_file_touch(const f_string path, const mode_t mode, const bool dereference);
+#endif // _di_f_file_touch_
+
+/**
+ * Update the files access and modification timestamp, creating the file if it does not already exist.
+ *
+ * When the file is created, it is created as a regular file.
+ *
+ * @param at_id
+ *   The parent directory, as an open directory file descriptor, in which path is relative to.
+ * @param path
+ *   The path file name.
+ * @param mode
+ *   The file mode to use when (regular) file is created.
+ * @param flag
+ *   Any valid flag, such as f_file_at_path_empty, f_file_at_automount_no, or f_file_at_symlink_follow_no.
+ *
+ * @return
+ *   F_none on success.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   F_access_denied (with error bit) on access denied.
+ *   F_directory_descriptor (with error bit) for bad directory descriptor for at_id.
+ *   F_buffer (with error bit) if the buffer is invalid.
+ *   F_loop (with error bit) on loop error.
+ *   F_name (with error bit) on path name error.
+ *   F_file_found (with error bit) if a file aleady exists at the path (when calling utimensat()).
+ *   F_directory (with error bit) if a supposed directory in path is not actually a directory.
+ *   F_prohibited (with error bit) if filesystem does not allow for creating or linking.
+ *   F_read_only (with error bit) if filesystem is read-only.
+ *   F_search (with error bit) if search permission is denied for one of the paths to the file.
+ *   F_memory_out (with error bit) if out of memory.
+ *   F_filesystem_quota_block (with error bit) if filesystem's disk blocks or inodes are exhausted.
+ *   F_filesystem_quota_reached (with error bit) quota reached of filesystem is out of space.
+ *   F_number_overflow (with error bit) on overflow error.
+ *   F_interrupted (with error bit) when program received an interrupt signal, halting create.
+ *   F_file_open_max (with error bit) when system-wide max open files is reached.
+ *   F_busy (with error bit) if filesystem is too busy to perforrm write.
+ *   F_failure (with error bit) for any other error.
+ *
+ * @see utimensat()
+ */
+#ifndef _di_f_file_touch_at_
+  extern f_return_status f_file_touch_at(const int at_id, const f_string path, const mode_t mode, const int flag);
+#endif // _di_f_file_touch_at_
+
+/**
  * Write until a single block is filled or entire buffer is written.
  *
  * To check how much was write into the buffer, record buffer->used before execution and compare to buffer->used after execution.
index 67a6e39442a149ec69b00613ddc88106957238cc..023e83fea2fa8ff99079a34158ca294833c717af 100644 (file)
@@ -131,7 +131,7 @@ extern "C" {
  * @param gid
  *   The new group id to use.
  * @param flag
- *   Any valid flag, such as AT_EMPTY_PATH, AT_NO_AUTOMOUNT, or AT_SYMLINK_NO_FOLLOW.
+ *   Any valid flag, such as f_file_at_path_empty, f_file_at_automount_no, or f_file_at_symlink_follow_no.
  *
  * @return
  *   F_none on success.
@@ -780,10 +780,12 @@ extern "C" {
  *
  * @see f_file_copy()
  * @see f_file_stat()
+ * @see f_file_exists()
+ * @see f_file_touch()
  */
-#if !defined(_di_f_file_stat_) || !defined(_di_f_file_copy_)
+#if !defined(_di_f_file_stat_) || !defined(_di_f_file_copy_) || !defined(_di_f_file_exists_) || !defined(_di_f_file_touch_)
   extern f_return_status private_f_file_stat(const f_string 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_)
+#endif // !defined(_di_f_file_stat_) || !defined(_di_f_file_copy_) || !defined(_di_f_file_exists_) || !defined(_di_f_file_touch_)
 
 /**
  * Private implementation of f_file_close().
@@ -795,11 +797,10 @@ extern "C" {
  * @param file_name
  *   The name of the file.
  * @param flag
- *   Any valid flag, such as AT_EMPTY_PATH, AT_NO_AUTOMOUNT, or AT_SYMLINK_NO_FOLLOW.
+ *   Any valid flag, such as f_file_at_path_empty, f_file_at_automount_no, or f_file_at_symlink_follow_no.
  * @param file_stat
  *   The statistics read.
  *
- *
  * @return
  *   F_none on success.
  *   F_name (with error bit) if the name is somehow invalid.
@@ -812,10 +813,12 @@ extern "C" {
  *   F_parameter (with error bit) if a parameter is invalid.
  *
  * @see f_file_stat_at()
+ * @see f_file_exists_at()
+ * @see f_file_touch_at()
  */
-#if !defined(_di_f_file_stat_at_)
+#if !defined(_di_f_file_stat_at_) || !defined(_di_f_file_exists_at_) || !defined(_di_f_file_touch_at_)
   extern f_return_status private_f_file_stat_at(const int at_id, const f_string file_name, const int flag, struct stat *file_stat) f_gcc_attribute_visibility_internal;
-#endif // !defined(_di_f_file_stat_at_)
+#endif // !defined(_di_f_file_stat_at_) || !defined(_di_f_file_exists_at_) || !defined(_di_f_file_touch_at_)
 
 /**
  * Private implementation of f_file_close().
index 7ba3de7afb67feaaae489d861e94779d584fbc4b..49b644f0b5368b547c767f1db5eb83faa2370184 100644 (file)
@@ -178,6 +178,7 @@ extern "C" {
       F_process_too_many,
       F_prohibited,
       F_read_only,
+      F_search,
       F_space_not,
       F_stop,
       F_syntax,
index dbbddf13c06cd075906167af40cf3b375037ed1e..98f9bed4888ebb47d1ef5cd1632569681e65aebd 100644 (file)
@@ -320,6 +320,9 @@ extern "C" {
         case F_read_only:
           *string = FL_status_string_read_only;
           break;
+        case F_search:
+          *string = FL_status_string_search;
+          break;
         case F_space_not:
           *string = FL_status_string_space_not;
           break;
index ea95a8c3aa797c89fb319a5a2e32226be8de07a4..3ff9b2e867319e5b779fbdf00845af557b4bdc66 100644 (file)
@@ -197,6 +197,7 @@ extern "C" {
     #define FL_status_string_process_too_many "F_process_too_many"
     #define FL_status_string_prohibited       "F_prohibited"
     #define FL_status_string_read_only        "F_read_only"
+    #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_syntax           "F_syntax"
@@ -243,6 +244,7 @@ extern "C" {
     #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_search_length           8
     #define FL_status_string_space_not_length        11
     #define FL_status_string_stop_length             6
     #define FL_status_string_syntax_length           8
index c60a9c8627abf81047658f18130545ea58292b97..59456c753595b20a455bc6ad54e4357ac1e77ef0 100644 (file)
@@ -536,6 +536,11 @@ extern "C" {
         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;
+      }
+
       if (fl_string_compare(string, FL_status_string_space_not, length, FL_status_string_space_not_length) == F_equal_to) {
         *code = F_space_not;
         return F_none;