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) {
}
#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_
/**
* File mode relation functionality.
- *
- * TODO: This information below needs to be confirmed and updated accordingly..
*/
#ifndef _di_f_file_modes_
#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.
#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).