From: Kevin Day Date: Thu, 14 May 2020 01:30:37 +0000 (-0500) Subject: Update: additional file functions, relocate function locations, add path separator... X-Git-Tag: 0.5.0~258 X-Git-Url: https://git.kevux.org/?a=commitdiff_plain;h=67a5fd4d5a302eb02e2e790661f7cd80389eae58;p=fll Update: additional file functions, relocate function locations, add path separator length define --- diff --git a/level_0/f_file/c/file.c b/level_0/f_file/c/file.c index 29cab72..1a84d99 100644 --- a/level_0/f_file/c/file.c +++ b/level_0/f_file/c/file.c @@ -14,27 +14,71 @@ 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_ diff --git a/level_0/f_file/c/file.h b/level_0/f_file/c/file.h index 4652838..f05e031 100644 --- a/level_0/f_file/c/file.h +++ b/level_0/f_file/c/file.h @@ -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). diff --git a/level_0/f_path/c/path.h b/level_0/f_path/c/path.h index 5b7ff57..a4a11cd 100644 --- a/level_0/f_path/c/path.h +++ b/level_0/f_path/c/path.h @@ -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