]> Kevux Git Server - fll/commitdiff
Feature: add f_directory_touch() and f_directory_touch_at().
authorKevin Day <thekevinday@gmail.com>
Tue, 21 Jul 2020 04:44:12 +0000 (23:44 -0500)
committerKevin Day <thekevinday@gmail.com>
Tue, 21 Jul 2020 04:44:12 +0000 (23:44 -0500)
This is the same as f_file_touch() and f_file_touch_at(), except that a directory is created if the file does not exist.

level_0/f_directory/c/directory.c
level_0/f_directory/c/directory.h
level_0/f_directory/c/private-directory.c
level_0/f_directory/c/private-directory.h

index 2467f3b954a233886f47757d75ca4a7038d6b2b8..de23fc88e3116fbdf671460c2c7a8d99eb107d9c 100644 (file)
@@ -7,27 +7,7 @@ extern "C" {
 
 #ifndef _di_f_directory_create_
   f_return_status f_directory_create(const f_string path, const mode_t mode) {
-
-    if (mkdir(path, mode) < 0) {
-      if (errno == EACCES) return F_status_set_error(F_access_denied);
-      if (errno == EDQUOT) return F_status_set_error(F_filesystem_quota_block);
-      if (errno == EEXIST) return F_status_set_error(F_file_found);
-      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 == EMLINK) return F_status_set_error(F_directory_link_max);
-      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 == ENOSPC) return F_status_set_error(F_space_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);
-
-      return F_status_set_error(F_failure);
-    }
-
-    return F_none;
+    return private_f_directory_create(path, mode);
   }
 #endif // _di_f_directory_create_
 
@@ -37,27 +17,7 @@ extern "C" {
       if (at_id <= 0) return F_status_set_error(F_parameter);
     #endif // _di_level_0_parameter_checking_
 
-    if (mkdirat(at_id, path, mode) < 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 == EDQUOT) return F_status_set_error(F_filesystem_quota_block);
-      if (errno == EEXIST) return F_status_set_error(F_file_found);
-      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 == EMLINK) return F_status_set_error(F_directory_link_max);
-      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 == ENOSPC) return F_status_set_error(F_space_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);
-
-      return F_status_set_error(F_failure);
-    }
-
-    return F_none;
+    return private_f_directory_create_at(at_id, path, mode);
   }
 #endif // _di_f_directory_create_at_
 
@@ -388,6 +348,106 @@ extern "C" {
   }
 #endif // _di_f_directory_remove_custom_
 
+#ifndef _di_f_directory_touch_
+  f_return_status f_directory_touch(const f_string path, const mode_t mode) {
+    #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 (stat(path, &file_stat) < 0) {
+
+      if (errno == ENOENT) {
+        return private_f_directory_create(path, mode);
+      }
+
+      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 == 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);
+    }
+
+    if (utimensat(f_directory_at_current_working, path, 0, 0) < 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_directory_touch_
+
+#ifndef _di_f_directory_touch_at_
+  f_return_status f_directory_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));
+
+    if (fstatat(at_id, path, &file_stat, flag) < 0) {
+
+      if (errno == ENOENT) {
+        return private_f_directory_create_at(at_id, path, mode);
+      }
+
+      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_status_set_error(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);
+
+      return F_status_set_error(F_file_stat);
+    }
+
+    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_directory_touch_at_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 86fad4dd7d95a3c4695315db7eb9be55002bb51d..69104b5f686f6fab9509f9deaab9561b420115d0 100644 (file)
@@ -454,6 +454,86 @@ extern "C" {
   extern f_return_status f_directory_remove_custom(const f_string path, const int recursion_max, const bool preserve, int (*custom) (const char *, const struct stat *, int, struct FTW *));
 #endif // _di_f_directory_remove_custom_
 
+/**
+ * Update the files access and modification timestamp, creating the directory if it does not already exist.
+ *
+ * When the file is created, it is created as a directory file.
+ *
+ * @param path
+ *   The path file name.
+ * @param mode
+ *   The file mode to use when (directory) file is created.
+ *
+ * @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_busy (with error bit) if filesystem is too busy to perforrm write.
+ *   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_file_found (with error bit) if a file aleady exists at the path.
+ *   F_file_open_max (with error bit) when system-wide max open files is reached.
+ *   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_interrupted (with error bit) when program received an interrupt signal, halting operation.
+ *   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_number_overflow (with error bit) on overflow error.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   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_failure (with error bit) for any other error.
+ *
+ * @see utimensat()
+ */
+#ifndef _di_f_directory_touch_
+  extern f_return_status f_directory_touch(const f_string path, const mode_t mode);
+#endif // _di_f_directory_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 directory 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 (directory) 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_access_denied (with error bit) on access denied.
+ *   F_buffer (with error bit) if the buffer is invalid.
+ *   F_busy (with error bit) if filesystem is too busy to perforrm write.
+ *   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_file_found (with error bit) if a file aleady exists at the path (when calling utimensat()).
+ *   F_file_open_max (with error bit) when system-wide max open files is reached.
+ *   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_interrupted (with error bit) when program received an interrupt signal, halting operation.
+ *   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_number_overflow (with error bit) on overflow error.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *   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_failure (with error bit) for any other error.
+ *
+ * @see utimensat()
+ */
+#ifndef _di_f_directory_touch_at_
+  extern f_return_status f_directory_touch_at(const int at_id, const f_string path, const mode_t mode, const int flag);
+#endif // _di_f_directory_touch_at_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 42452321f68d08286328036627bf896e4e30e463..cee8474caeb8811d87950db6679a29f9b6807296 100644 (file)
@@ -5,6 +5,59 @@
 extern "C" {
 #endif
 
+#if !defined(_di_f_directory_create_) || !defined(_di_f_directory_touch_)
+  f_return_status private_f_directory_create(const f_string path, const mode_t mode) {
+
+    if (mkdir(path, mode) < 0) {
+      if (errno == EACCES) return F_status_set_error(F_access_denied);
+      if (errno == EDQUOT) return F_status_set_error(F_filesystem_quota_block);
+      if (errno == EEXIST) return F_status_set_error(F_file_found);
+      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 == EMLINK) return F_status_set_error(F_directory_link_max);
+      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 == ENOSPC) return F_status_set_error(F_space_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);
+
+      return F_status_set_error(F_failure);
+    }
+
+    return F_none;
+  }
+#endif // !defined(_di_f_directory_create_) || !defined(_di_f_directory_touch_)
+
+#if !defined(_di_f_directory_create_at_) || !defined(_di_f_directory_touch_at_)
+  f_return_status private_f_directory_create_at(const int at_id, const f_string path, const mode_t mode) {
+
+    if (mkdirat(at_id, path, mode) < 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 == EDQUOT) return F_status_set_error(F_filesystem_quota_block);
+      if (errno == EEXIST) return F_status_set_error(F_file_found);
+      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 == EMLINK) return F_status_set_error(F_directory_link_max);
+      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 == ENOSPC) return F_status_set_error(F_space_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);
+
+      return F_status_set_error(F_failure);
+    }
+
+    return F_none;
+  }
+#endif // !defined(_di_f_directory_create_at_) || !defined(_di_f_directory_touch_at_)
+
 #if !defined(_di_f_directory_remove_)
   int private_f_directory_remove_recursively(const char *path, const struct stat *file_stat, int type, struct FTW *entity) {
     if (entity->level == 0) return 0;
index fdfca22287067f3d6cdb12eb55a22eec99a6b391..51eb71e64e451c0aaa4173f9c7a50a1aa32718a3 100644 (file)
@@ -15,6 +15,77 @@ extern "C" {
 #endif
 
 /**
+ * Private implementation of f_directory_create().
+ *
+ * Intended to be shared to each of the different implementation variations.
+ *
+ * @param path
+ *   The file path to the directory.
+ * @param mode
+ *   The directory mode to use when creating.
+ *
+ * @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_directory_link_max (with error bit) max links limit reached or exceeded.
+ *   F_file_found (with error bit) of a directory aleady exists at the path.
+ *   F_file_found_not (with error bit) if a file within the path is not found (such as a broken symbolic link).
+ *   F_filesystem_quota_block (with error bit) if filesystem's disk blocks or inodes are exhausted.
+ *   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_prohibited (with error bit) if filesystem does not allow for removing.
+ *   F_read_only (with error bit) if file is read-only.
+ *   F_space_not (with error bit) if filesystem is out of space (or filesystem quota is reached).
+ *   F_failure (with error bit) for any other error.
+ *
+ * @see f_directory_create()
+ * @see f_directory_touch()
+ */
+#if !defined(_di_f_directory_create_) || !defined(_di_f_directory_touch_)
+  extern f_return_status private_f_directory_create(const f_string path, const mode_t mode) f_gcc_attribute_visibility_internal;
+#endif // !defined(_di_f_directory_create_) || !defined(_di_f_directory_touch_)
+
+/**
+ * Private implementation of f_directory_create_at().
+ *
+ * Intended to be shared to each of the different implementation variations.
+ *
+ * @param at_id
+ *   The parent directory, as an open directory file descriptor, in which path is relative to.
+ * @param path
+ *   The file path to the directory.
+ * @param mode
+ *   The directory mode to use when creating.
+ *
+ * @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_directory_descriptor (with error bit) for bad directory descriptor for at_id.
+ *   F_directory_link_max (with error bit) max links limit reached or exceeded.
+ *   F_file_found (with error bit) of a directory aleady exists at the path.
+ *   F_file_found_not (with error bit) if a file within the path is not found (such as a broken symbolic link).
+ *   F_filesystem_quota_block (with error bit) if filesystem's disk blocks or inodes are exhausted.
+ *   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_prohibited (with error bit) if filesystem does not allow for removing.
+ *   F_read_only (with error bit) if file is read-only.
+ *   F_space_not (with error bit) if filesystem is out of space (or filesystem quota is reached).
+ *   F_failure (with error bit) for any other error.
+ *
+ * @see f_directory_create_at()
+ * @see f_directory_touch_at()
+ */
+#if !defined(_di_f_directory_create_at_) || !defined(_di_f_directory_touch_at_)
+  extern f_return_status private_f_directory_create_at(const int at_id, const f_string path, const mode_t mode) f_gcc_attribute_visibility_internal;
+#endif // !defined(_di_f_directory_create_at_) || !defined(_di_f_directory_touch_at_)
+
+/**
  * A special function intended to be used directly by nftw().
  *
  * This is intended to be used by the specified function as a function pointer and therefore follows the required structure.