]> Kevux Git Server - fll/commitdiff
Update: additional file functions, relocate function locations, add path separator...
authorKevin Day <thekevinday@gmail.com>
Thu, 14 May 2020 01:30:37 +0000 (20:30 -0500)
committerKevin Day <thekevinday@gmail.com>
Thu, 14 May 2020 01:30:37 +0000 (20:30 -0500)
level_0/f_file/c/file.c
level_0/f_file/c/file.h
level_0/f_path/c/path.h

index 29cab72ce2d91fe2de20d951d4414099915d1672..1a84d99957809dd1971c33a404ce28586a0f4807 100644 (file)
 extern "C" {
 #endif
 
-#ifndef _di_f_file_open_
-  f_return_status f_file_open(f_file *file, const f_string path) {
-    #ifndef _di_level_0_parameter_checking_
-      if (file == 0) return f_status_set_error(f_invalid_parameter);
-    #endif // _di_level_0_parameter_checking_
+#ifndef _di_f_file_create_
+  f_return_status f_file_create(f_string path, const mode_t mode, const bool exclusive) {
+    int flags = O_CLOEXEC | O_CREAT | O_WRONLY;
 
-    // if file->mode is unset, then this may cause a segfault.
-    if (file->mode == 0) return f_status_set_error(f_invalid_parameter);
+    if (exclusive) {
+      flags |= O_EXCL;
+    }
 
-    file->address = fopen(path, file->mode);
+    int result = open(path, flags, mode);
 
-    if (file->address == 0) return f_status_set_error(f_file_not_found);
-    if (ferror(file->address) != 0) return f_status_set_error(f_file_error_open);
+    if (result < 0) {
+      if (errno == EACCES) {
+        return f_status_set_error(f_access_denied);
+      }
+      else if (errno == EDQUOT) {
+        return f_status_set_error(f_filesystem_quota_blocks);
+      }
+      else if (errno == EEXIST) {
+        return f_status_set_error(f_file_found);
+      }
+      else if (errno == ENAMETOOLONG || errno == EFAULT) {
+        return f_status_set_error(f_invalid_name);
+      }
+      else if (errno == EFBIG || errno == EOVERFLOW) {
+        return f_status_set_error(f_number_overflow);
+      }
+      else if (errno == EINTR) {
+        return f_status_set_error(f_interrupted);
+      }
+      else if (errno == EINVAL) {
+        return f_status_set_error(f_invalid_parameter);
+      }
+      else if (errno == ELOOP) {
+        return f_status_set_error(f_loop);
+      }
+      else if (errno == ENFILE) {
+        return f_status_set_error(f_file_max_open);
+      }
+      else if (errno == ENOENT || errno == ENOTDIR) {
+        return f_status_set_error(f_invalid_directory);
+      }
+      else if (errno == ENOMEM) {
+        return f_status_set_error(f_out_of_memory);
+      }
+      else if (errno == ENOSPC) {
+        return f_status_set_error(f_filesystem_quota_reached);
+      }
+      else if (errno == EPERM) {
+        return f_status_set_error(f_prohibited);
+      }
+      else if (errno == EROFS) {
+        return f_status_set_error(f_read_only);
+      }
+      else if (errno == ETXTBSY) {
+        return f_status_set_error(f_busy);
+      }
 
-    file->id = fileno(file->address);
+      return f_status_set_error(f_failure);
+    }
 
-    if (file->id == -1) return f_status_set_error(f_file_error_descriptor);
+    close(result);
 
     return f_none;
   }
-#endif // _di_f_file_open_
+#endif // _di_f_file_create_
 
 #ifndef _di_f_file_close_
   f_return_status f_file_close(f_file *file) {
@@ -230,6 +274,28 @@ extern "C" {
   }
 #endif // _di_f_file_is_at_
 
+#ifndef _di_f_file_open_
+  f_return_status f_file_open(f_file *file, const f_string path) {
+    #ifndef _di_level_0_parameter_checking_
+      if (file == 0) return f_status_set_error(f_invalid_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    // if file->mode is unset, then this may cause a segfault.
+    if (file->mode == 0) return f_status_set_error(f_invalid_parameter);
+
+    file->address = fopen(path, file->mode);
+
+    if (file->address == 0) return f_status_set_error(f_file_not_found);
+    if (ferror(file->address) != 0) return f_status_set_error(f_file_error_open);
+
+    file->id = fileno(file->address);
+
+    if (file->id == -1) return f_status_set_error(f_file_error_descriptor);
+
+    return f_none;
+  }
+#endif // _di_f_file_open_
+
 #ifndef _di_f_file_read_
   f_return_status f_file_read(f_file *file, f_string_dynamic *buffer) {
     #ifndef _di_level_0_parameter_checking_
index 46528385213f84509b707799e1fde6261dcd41d9..f05e0312b1f28b909c13e761c03534b0b7a53189 100644 (file)
@@ -139,8 +139,6 @@ extern "C" {
 
 /**
  * File mode relation functionality.
- *
- * TODO: This information below needs to be confirmed and updated accordingly..
  */
 #ifndef _di_f_file_modes_
 
@@ -287,26 +285,44 @@ extern "C" {
 #endif // _di_f_macro_file_reset_position_
 
 /**
- * Open a particular file and save its stream.
+ * Create a file based on the given path and file mode.
  *
- * This will open the file and obtain the file descriptor.
+ * The file will not be open after calling this.
+ * This is useful for creating empty files.
  *
- * @param file
- *   The data related to the file being opened.
- *   This will be updated with the file descriptor and file address.
  * @param path
- *   The path file name.
+ *   Full path to the file (including entire filename).
+ * @param mode
+ *   The file mode.
+ * @param exclusive
+ *   If TRUE, will fail when file already exists.
+ *   If FALSE, will not fail if file already exists.
  *
  * @return
  *   f_none on success.
- *   f_file_not_found (with error bit) if the file was not found.
- *   f_file_error_open (with error bit) if the file is already open.
- *   f_file_error_descriptor (with error bit) if unable to load the file descriptor (the file pointer may still be valid).
  *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *   f_access_denied (with error bit) on access denied.
+ *   f_loop (with error bit) on loop error.
+ *   f_file_found (with error bit) if a file was found while exclusive is TRUE.
+ *   f_out_of_memory (with error bit) if out of memory.
+ *   f_prohibited (with error bit) if filesystem does not allow for removing.
+ *   f_read_only (with error bit) if file is read-only.
+ *   f_failure (with error bit) for any other (mkdir()) error.
+ *   f_filesystem_quota_blocks (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_file_found (with error bit) of a directory aleady exists at the path.
+ *   f_invalid_name (with error bit) on path name error.
+ *   f_invalid_directory (with error bit) if a supposed directory in path is not actually a directory.
+ *   f_number_overflow (with error bit) on overflow error.
+ *   f_interrupted (with error bit) when program received an interrupt signal, halting create.
+ *   f_file_max_open (with error bit) when system-wide max open files is reached.
+ *   f_busy (with error bit) if filesystem is too busy to perforrm write.
+ *
+ * @see open()
  */
-#ifndef _di_f_file_open_
-  extern f_return_status f_file_open(f_file *file, const f_string path);
-#endif // _di_f_file_open_
+#ifndef _di_f_file_create_
+  extern f_return_status f_file_create(f_string path, const mode_t mode, const bool exclusive);
+#endif // _di_f_file_create_
 
 /**
  * Close an opened file.
@@ -456,6 +472,30 @@ extern "C" {
 #endif // _di_f_file_is_at_
 
 /**
+ * Open a particular file and save its stream.
+ *
+ * This will open the file and obtain the file descriptor.
+ *
+ * @param file
+ *   The data related to the file being opened.
+ *   This will be updated with the file descriptor and file address.
+ * @param path
+ *   The path file name.
+ *
+ * @return
+ *   f_none on success.
+ *   f_file_not_found (with error bit) if the file was not found.
+ *   f_file_error_open (with error bit) if the file is already open.
+ *   f_file_error_descriptor (with error bit) if unable to load the file descriptor (the file pointer may still be valid).
+ *   f_invalid_parameter (with error bit) if a parameter is invalid.
+ *
+ * @see fopen()
+ */
+#ifndef _di_f_file_open_
+  extern f_return_status f_file_open(f_file *file, const f_string path);
+#endif // _di_f_file_open_
+
+/**
  * Read until a single block is filled or EOF is reached.
  *
  * This does not allocate space to the buffer, so be sure enough space exists (file->size_chunk * file->size_block).
index 5b7ff577a89d5e6ce11eb06c3f98a6615f16d709..a4a11cd4f8ceca4a43f2c73988d147994d7e239e 100644 (file)
@@ -19,10 +19,14 @@ extern "C" {
 /**
  * Standard path defines.
  *
- * The path separator must be a single 1-byte wide string.
+ * The path separator, intended to be represented as a single character.
+ *
+ * The length is intended to provide a UTF-8 compatible width and therefore represents bytes and not characters.
+ * A length of 1 = 1-byte wide character, a length of 4 = 4-byte wide character.
  */
 #ifndef _di_f_path_defines_
   #define f_path_separator "/"
+  #define f_path_separator_length 1
 #endif // _di_f_path_defines_
 
 #ifdef __cplusplus