From: Kevin Day Date: Sun, 24 May 2020 03:54:53 +0000 (-0500) Subject: Update: minor improvements, finish f_file_copy(), add fifo file type X-Git-Tag: 0.5.0~239 X-Git-Url: https://git.kevux.org/?a=commitdiff_plain;h=6efce416177d1b4734f0b8a18557d0ea6428b28e;p=fll Update: minor improvements, finish f_file_copy(), add fifo file type Finish implementing the f_file_copy(), adding support for all file types (except unknown). The documentation for block, character, and FIFO is unclear to me at this time and my attempts to copy using mknod(2) is an educated guess. Attempt to prevent file type from being passed via the mode_t when doing a copy (currently untested). Add the appropriate file create functions to implement the copy operations. Have the copy file copy only the directory itself and not the contents (to copy contents, the fl_directory_copy() function should be used). The added fifo type is pretty much the same as pipe. Mixing fifo with pipe terminology ended up being confusing so I opted to create redundant FIFO types to simplify the readability. Use the word "regular" for a regular file instead of "file". Using "regular" is a less confusing than using "file" (i.e. Regular File Type vs File File Type). --- diff --git a/level_0/f_directory/c/directory.h b/level_0/f_directory/c/directory.h index ae57581..6eb8edd 100644 --- a/level_0/f_directory/c/directory.h +++ b/level_0/f_directory/c/directory.h @@ -65,7 +65,7 @@ extern "C" { f_string_dynamics block; // S_IFBLK f_string_dynamics character; // S_IFCHR f_string_dynamics directory; // S_IFDIR - f_string_dynamics file; // S_IFREG + f_string_dynamics regular; // S_IFREG f_string_dynamics link; // S_IFLNK f_string_dynamics pipe; // S_IFIFO f_string_dynamics socket; // S_IFSOCK @@ -87,7 +87,7 @@ extern "C" { f_macro_string_dynamics_delete(status, listing.block) \ if (!F_status_is_error(status)) f_macro_string_dynamics_delete(status, listing.character) \ if (!F_status_is_error(status)) f_macro_string_dynamics_delete(status, listing.directory) \ - if (!F_status_is_error(status)) f_macro_string_dynamics_delete(status, listing.file) \ + if (!F_status_is_error(status)) f_macro_string_dynamics_delete(status, listing.regular) \ if (!F_status_is_error(status)) f_macro_string_dynamics_delete(status, listing.link) \ if (!F_status_is_error(status)) f_macro_string_dynamics_delete(status, listing.pipe) \ if (!F_status_is_error(status)) f_macro_string_dynamics_delete(status, listing.socket) \ @@ -97,7 +97,7 @@ extern "C" { f_macro_string_dynamics_destroy(status, listing.block) \ if (!F_status_is_error(status)) f_macro_string_dynamics_destroy(status, listing.character) \ if (!F_status_is_error(status)) f_macro_string_dynamics_destroy(status, listing.directory) \ - if (!F_status_is_error(status)) f_macro_string_dynamics_destroy(status, listing.file) \ + if (!F_status_is_error(status)) f_macro_string_dynamics_destroy(status, listing.regular) \ if (!F_status_is_error(status)) f_macro_string_dynamics_destroy(status, listing.link) \ if (!F_status_is_error(status)) f_macro_string_dynamics_destroy(status, listing.pipe) \ if (!F_status_is_error(status)) f_macro_string_dynamics_destroy(status, listing.socket) \ @@ -107,7 +107,7 @@ extern "C" { f_macro_string_dynamics_delete_simple(listing.block) \ f_macro_string_dynamics_delete_simple(listing.character) \ f_macro_string_dynamics_delete_simple(listing.directory) \ - f_macro_string_dynamics_delete_simple(listing.file) \ + f_macro_string_dynamics_delete_simple(listing.regular) \ f_macro_string_dynamics_delete_simple(listing.link) \ f_macro_string_dynamics_delete_simple(listing.pipe) \ f_macro_string_dynamics_delete_simple(listing.socket) \ @@ -117,7 +117,7 @@ extern "C" { f_macro_string_dynamics_destroy_simple(listing.block) \ f_macro_string_dynamics_destroy_simple(listing.character) \ f_macro_string_dynamics_destroy_simple(listing.directory) \ - f_macro_string_dynamics_destroy_simple(listing.file) \ + f_macro_string_dynamics_destroy_simple(listing.regular) \ f_macro_string_dynamics_destroy_simple(listing.link) \ f_macro_string_dynamics_destroy_simple(listing.pipe) \ f_macro_string_dynamics_destroy_simple(listing.socket) \ @@ -136,7 +136,7 @@ extern "C" { mode_t block; // S_IFBLK mode_t character; // S_IFCHR mode_t directory; // S_IFDIR - mode_t file; // S_IFREG + mode_t regular; // S_IFREG mode_t link; // S_IFLNK mode_t socket; // S_IFSOCK mode_t unknown; @@ -156,14 +156,14 @@ extern "C" { modes.block = mode; \ modes.character = mode; \ modes.directory = mode; \ - modes.file = mode; \ + modes.regular = mode; \ modes.link = mode; \ modes.socket = mode; \ modes.unknown = mode; #define f_macro_directory_mode_set_common(modes, mode_directory, mode_file, mode_link) \ modes.directory = mode_directory; \ - modes.file = mode_file; \ + modes.regular = mode_file; \ modes.link = mode_link; #define f_macro_directory_mode_set_uncommon(modes, mode_block, mode_character, mode_socket, mode_unknown) \ diff --git a/level_0/f_file/c/file.c b/level_0/f_file/c/file.c index 488c0ec..5e63d73 100644 --- a/level_0/f_file/c/file.c +++ b/level_0/f_file/c/file.c @@ -61,32 +61,90 @@ extern "C" { f_status status = F_none; struct stat source_stat; + // remove the file type from the mode. + const mode_t mode_access = (~f_file_type_mask) & mode; + memset(&source_stat, 0, sizeof(struct stat)); status = private_f_file_stat(source, &source_stat, F_false); if (F_status_is_error(status)) return status; - if (f_macro_file_type_is_file(source_stat.st_mode)) { - status = private_f_file_create(destination, mode, exclusive, F_false); + if (f_macro_file_type_is_regular(source_stat.st_mode)) { + status = private_f_file_create(destination, mode_access, exclusive, F_false); if (F_status_is_error(status)) return status; if (!exclusive) { - status = private_f_file_change_mode(destination, mode, F_false); + status = private_f_file_change_mode(destination, mode_access, F_false); if (F_status_is_error(status)) return status; } return private_f_file_copy_content(source, destination, size_block); } + else if (f_macro_file_type_is_directory(source_stat.st_mode)) { + status = private_f_file_create_directory(destination, mode_access); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) != F_file_found || exclusive) { + return status; + } + } + + status = private_f_file_change_mode(destination, mode_access, F_false); + if (F_status_is_error(status)) return status; + + return F_none; + } else if (f_macro_file_type_is_link(source_stat.st_mode)) { status = private_f_file_link(destination, source); - if (F_status_set_fine(status) == F_file_found) { - if (exclusive) return status; + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) != F_file_found || exclusive) { + return status; + } } - else if (F_status_is_error(status)) { - return status; + + status = private_f_file_change_mode(destination, mode_access, F_false); + if (F_status_is_error(status)) return status; + + return F_none; + } + else if (f_macro_file_type_is_fifo(source_stat.st_mode)) { + status = private_f_file_create_fifo(destination, mode_access); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) != F_file_found || exclusive) { + return status; + } } - status = private_f_file_change_mode(destination, mode, F_false); + status = private_f_file_change_mode(destination, mode_access, F_false); + if (F_status_is_error(status)) return status; + + return F_none; + } + else if (f_macro_file_type_is_socket(source_stat.st_mode)) { + status = private_f_file_create_node(destination, f_macro_file_type_get(source_stat.st_mode) | mode_access, source_stat.st_rdev); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) != F_file_found || exclusive) { + return status; + } + } + + status = private_f_file_change_mode(destination, mode_access, F_false); + if (F_status_is_error(status)) return status; + + } + else if (f_macro_file_type_is_block(source_stat.st_mode) || f_macro_file_type_is_character(source_stat.st_mode)) { + status = private_f_file_create_node(destination, f_macro_file_type_get(source_stat.st_mode) | mode_access, source_stat.st_rdev); + + if (F_status_is_error(status)) { + if (F_status_set_fine(status) != F_file_found || exclusive) { + return status; + } + } + + status = private_f_file_change_mode(destination, mode_access, F_false); if (F_status_is_error(status)) return status; return F_none; @@ -110,7 +168,7 @@ extern "C" { status = private_f_file_stat(source, &source_stat, F_false); if (F_status_is_error(status)) return status; - if (f_macro_file_type_is_file(source_stat.st_mode)) { + if (f_macro_file_type_is_regular(source_stat.st_mode)) { status = private_f_file_create(destination, source_stat.st_mode, exclusive, F_false); if (F_status_is_error(status)) return status; @@ -172,6 +230,62 @@ extern "C" { } #endif // _di_f_file_create_at_ +#ifndef _di_f_file_create_device_ + f_return_status f_file_create_device(const f_string path, const mode_t mode, const unsigned int major, const unsigned int minor) { + if (!f_macro_file_type_is_fifo(mode) && !f_macro_file_type_is_character(mode) && !f_macro_file_type_is_block(mode)) { + return F_status_set_error(F_unsupported); + } + + const dev_t device = makedev(major, minor); + + return private_f_file_create_node(path, mode, device); + } +#endif // _di_f_file_create_device_ + +#ifndef _di_f_file_create_device_at_ + f_return_status f_file_create_device_at(const int at_id, const f_string path, const mode_t mode, const unsigned int major, const unsigned int minor) { + if (!f_macro_file_type_is_fifo(mode) && !f_macro_file_type_is_character(mode) && !f_macro_file_type_is_block(mode)) { + return F_status_set_error(F_unsupported); + } + + const dev_t device = makedev(major, minor); + + return private_f_file_create_node_at(at_id, path, mode, device); + } +#endif // _di_f_file_create_device_at_ + +#ifndef _di_f_file_create_fifo_ + f_return_status f_file_create_fifo(const f_string path, const mode_t mode) { + return private_f_file_create_fifo(path, mode); + } +#endif // _di_f_file_create_fifo_ + +#ifndef _di_f_file_create_fifo_at_ + f_return_status f_file_create_fifo_at(const int at_id, const f_string path, const mode_t mode) { + return private_f_file_create_fifo_at(at_id, path, mode); + } +#endif // _di_f_file_create_fifo_at_ + +#ifndef _di_f_file_create_node_ + f_return_status f_file_create_node(const f_string path, const mode_t mode, const dev_t device) { + if (!f_macro_file_type_is_fifo(mode) && !f_macro_file_type_is_character(mode) && !f_macro_file_type_is_block(mode)) { + return F_status_set_error(F_unsupported); + } + + return private_f_file_create_node(path, mode, device); + } +#endif // _di_f_file_create_node_ + +#ifndef _di_f_file_create_node_at_ + f_return_status f_file_create_node_at(const int at_id, const f_string path, const mode_t mode, const dev_t device) { + if (!f_macro_file_type_is_fifo(mode) && !f_macro_file_type_is_character(mode) && !f_macro_file_type_is_block(mode)) { + return F_status_set_error(F_unsupported); + } + + return private_f_file_create_node_at(at_id, path, mode, device); + } +#endif // _di_f_file_create_node_at_ + #ifndef _di_f_file_exists_ f_return_status f_file_exists(const f_string path) { struct stat file_stat; diff --git a/level_0/f_file/c/file.h b/level_0/f_file/c/file.h index 9d4e556..a088b1a 100644 --- a/level_0/f_file/c/file.h +++ b/level_0/f_file/c/file.h @@ -7,6 +7,10 @@ * * Provides structures and data types for a file I/O. * Provides operations for opening/closing files. + * + * @fixme Currently this uses makedev(3) to create devices, which is non-standad. + * The documentation for mknod(2) isn't clear on how to make major/minor based block and character devices. + * Find out how to implement this and elliminate the use of the non-standard makedev(3) call. */ #ifndef _F_file_h #define _F_file_h @@ -21,6 +25,9 @@ #include #include +// non-standard libc includs +#include + // fll-0 includes #include #include @@ -59,26 +66,30 @@ extern "C" { /** * Provide file type macros. + * + * Note: f_file_type_pipe and f_file_type_fifo are the same. */ #ifndef _di_f_file_type_ #define f_file_type_mask S_IFMT - #define f_file_type_pipe S_IFIFO + #define f_file_type_block S_IFBLK #define f_file_type_character S_IFCHR #define f_file_type_directory S_IFDIR - #define f_file_type_block S_IFBLK - #define f_file_type_file S_IFREG + #define f_file_type_fifo S_IFIFO #define f_file_type_link S_IFLNK + #define f_file_type_pipe S_IFIFO + #define f_file_type_regular S_IFREG #define f_file_type_socket S_IFSOCK #define f_macro_file_type_get(mode) (f_file_type_mask & mode) - #define f_macro_file_type_is_pipe(mode) f_macro_file_type_get(mode) == f_file_type_pipe + #define f_macro_file_type_is_block(mode) f_macro_file_type_get(mode) == f_file_type_block #define f_macro_file_type_is_character(mode) f_macro_file_type_get(mode) == f_file_type_character #define f_macro_file_type_is_directory(mode) f_macro_file_type_get(mode) == f_file_type_directory - #define f_macro_file_type_is_block(mode) f_macro_file_type_get(mode) == f_file_type_block - #define f_macro_file_type_is_file(mode) f_macro_file_type_get(mode) == f_file_type_file + #define f_macro_file_type_is_fifo(mode) f_macro_file_type_get(mode) == f_file_type_fifo #define f_macro_file_type_is_link(mode) f_macro_file_type_get(mode) == f_file_type_link + #define f_macro_file_type_is_pipe(mode) f_macro_file_type_get(mode) == f_file_type_pipe + #define f_macro_file_type_is_regular(mode) f_macro_file_type_get(mode) == f_file_type_regular #define f_macro_file_type_is_socket(mode) f_macro_file_type_get(mode) == f_file_type_socket #endif // _di_f_file_type_ @@ -404,6 +415,8 @@ extern "C" { * The paths must not contain NULL except for the terminating NULL. * The paths must be NULL terminated. * + * For directory file types, this will only copy the directory itself and not its contents. + * * @param source * The path to the file to copy from. * @param destination @@ -419,6 +432,7 @@ extern "C" { * * @return * F_none on success. + * F_unsupported if copying a given type of file is unsupported. * F_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. @@ -449,6 +463,8 @@ extern "C" { * The paths must not contain NULL except for the terminating NULL. * The paths must be NULL terminated. * + * For directory file types, this will only copy the directory itself and not its contents. + * * @todo provide a return status for when owner/role cannot be assigned. * This will be returned when complete so that caller can decide if this is an error or not. * @@ -469,6 +485,7 @@ extern "C" { * * @return * F_none on success. + * F_unsupported if copying a given type of file is unsupported. * F_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. @@ -607,6 +624,219 @@ extern "C" { #endif // _di_f_file_create_at_ /** + * Create a device node based on the given path and file mode. + * + * Warning: Due to the current status of POSIX and LINUX in regards to major and minor devices, this utilizes the non-POSI makedev() function. + * + * @param path + * The path file name. + * @param mode + * The file mode to assign. + * @param major + * The major device number for character and block file types. + * Is ignored by pipe file types. + * @param minor + * The minor device number for character and block file types. + * Is ignored by pipe file types. + * + * @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_loop (with error bit) on loop error. + * F_file_found (with error bit) if a file was found while exclusive is TRUE. + * F_memory_out (with error bit) if out of memory. + * F_prohibited (with error bit) if filesystem does not allow for removing. + * F_failure (with error bit) for any other (mknod()) error. + * F_filesystem_quota_block (with error bit) if filesystem's disk blocks or inodes are exhausted. + * F_space_not (with error bit) if filesystem is out of space (or filesystem quota is reached). + * F_file_found (with error bit) of a directory aleady exists at the path. + * F_name (with error bit) on path name error. + * F_directory (with error bit) if a supposed directory in path is not actually a directory. + * F_unsupported (with error bit) for unsupported file types. + * + * @see makedev() + * @see mknod() + */ +#ifndef _di_f_file_create_device_ + extern f_return_status f_file_create_device(const f_string path, const mode_t mode, const unsigned int major, const unsigned int minor); +#endif // _di_f_file_create_device_ + +/** + * Create a device node based on the given path and file mode. + * + * Warning: Due to the current status of POSIX and LINUX in regards to major and minor devices, this utilizes the non-POSI makedev() function. + * + * @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 assign. + * @param major + * The major device number for character and block file types. + * Is ignored by pipe file types. + * @param minor + * The minor device number for character and block file types. + * Is ignored by pipe file types. + * + * @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_loop (with error bit) on loop error. + * F_file_found (with error bit) if a file was found while exclusive is TRUE. + * F_memory_out (with error bit) if out of memory. + * F_prohibited (with error bit) if filesystem does not allow for removing. + * F_failure (with error bit) for any other (mknod()) error. + * F_filesystem_quota_block (with error bit) if filesystem's disk blocks or inodes are exhausted. + * F_space_not (with error bit) if filesystem is out of space (or filesystem quota is reached). + * F_file_found (with error bit) of a directory aleady exists at the path. + * F_name (with error bit) on path name error. + * F_directory (with error bit) if a supposed directory in path is not actually a directory. + * F_unsupported (with error bit) for unsupported file types. + * F_file_descriptor (with error bit) for bad file descriptor. + * + * @see makedev() + * @see mknodat() + */ +#ifndef _di_f_file_create_device_at_ + extern f_return_status f_file_create_device_at(const int at_id, const f_string path, const mode_t mode, const unsigned int major, const unsigned int minor); +#endif // _di_f_file_create_device_at_ + +/** + * Create a fifo based on the given path and file mode. + * + * @param path + * The path file name. + * @param mode + * The file mode to assign. + * + * @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_loop (with error bit) on loop error. + * F_file_found (with error bit) if a file was found while exclusive is TRUE. + * F_memory_out (with error bit) if out of memory. + * F_prohibited (with error bit) if filesystem does not allow for removing. + * F_failure (with error bit) for any other (mknod()) error. + * F_filesystem_quota_block (with error bit) if filesystem's disk blocks or ififos are exhausted. + * F_space_not (with error bit) if filesystem is out of space (or filesystem quota is reached). + * F_file_found (with error bit) of a directory aleady exists at the path. + * F_name (with error bit) on path name error. + * F_directory (with error bit) if a supposed directory in path is not actually a directory. + * F_unsupported (with error bit) for unsupported file types. + * + * @see mkfifo() + */ +#ifndef _di_f_file_create_fifo_ + extern f_return_status f_file_create_fifo(const f_string path, const mode_t mode); +#endif // _di_f_file_create_fifo_ + +/** + * Create a fifo based on the given path and file mode. + * + * @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 assign. + * + * @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_loop (with error bit) on loop error. + * F_file_found (with error bit) if a file was found while exclusive is TRUE. + * F_memory_out (with error bit) if out of memory. + * F_prohibited (with error bit) if filesystem does not allow for removing. + * F_failure (with error bit) for any other (mknod()) error. + * F_filesystem_quota_block (with error bit) if filesystem's disk blocks or ififos are exhausted. + * F_space_not (with error bit) if filesystem is out of space (or filesystem quota is reached). + * F_file_found (with error bit) of a directory aleady exists at the path. + * F_name (with error bit) on path name error. + * F_directory (with error bit) if a supposed directory in path is not actually a directory. + * F_unsupported (with error bit) for unsupported file types. + * F_file_descriptor (with error bit) for bad file descriptor. + * + * @see mkfifoat() + */ +#ifndef _di_f_file_create_fifo_at_ + extern f_return_status f_file_create_fifo_at(const int at_id, const f_string path, const mode_t mode); +#endif // _di_f_file_create_fifo_at_ + +/** + * Create a node based on the given path and file mode. + * + * @param path + * The path file name. + * @param mode + * The file mode to assign. + * @param device + * The device number for character and block file types. + * Is ignored by pipe file types. + * + * @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_loop (with error bit) on loop error. + * F_file_found (with error bit) if a file was found while exclusive is TRUE. + * F_memory_out (with error bit) if out of memory. + * F_prohibited (with error bit) if filesystem does not allow for removing. + * F_failure (with error bit) for any other (mknod()) error. + * F_filesystem_quota_block (with error bit) if filesystem's disk blocks or inodes are exhausted. + * F_space_not (with error bit) if filesystem is out of space (or filesystem quota is reached). + * F_file_found (with error bit) of a directory aleady exists at the path. + * F_name (with error bit) on path name error. + * F_directory (with error bit) if a supposed directory in path is not actually a directory. + * F_unsupported (with error bit) for unsupported file types. + * + * @see mknod() + */ +#ifndef _di_f_file_create_node_ + extern f_return_status f_file_create_node(const f_string path, const mode_t mode, const dev_t device); +#endif // _di_f_file_create_node_ + +/** + * Create a node based on the given path and file mode. + * + * @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 assign. + * @param device + * The device number for character and block file types. + * Is ignored by pipe file types. + * + * @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_loop (with error bit) on loop error. + * F_file_found (with error bit) if a file was found while exclusive is TRUE. + * F_memory_out (with error bit) if out of memory. + * F_prohibited (with error bit) if filesystem does not allow for removing. + * F_failure (with error bit) for any other (mknod()) error. + * F_filesystem_quota_block (with error bit) if filesystem's disk blocks or inodes are exhausted. + * F_space_not (with error bit) if filesystem is out of space (or filesystem quota is reached). + * F_file_found (with error bit) of a directory aleady exists at the path. + * F_name (with error bit) on path name error. + * F_directory (with error bit) if a supposed directory in path is not actually a directory. + * F_unsupported (with error bit) for unsupported file types. + * F_file_descriptor (with error bit) for bad file descriptor. + * + * @see mknodat() + */ +#ifndef _di_f_file_create_node_at_ + extern f_return_status f_file_create_node_at(const int at_id, const f_string path, const mode_t mode, const dev_t device); +#endif // _di_f_file_create_node_at_ + +/** * Identify whether or not a file exists at the given path. * * This does not require access on the file itself. @@ -839,7 +1069,7 @@ extern "C" { * Set to 0 to not use. * @param file * The data related to the file being opened. - * This will be updated with the file descriptor and file address. + * This will be updated with the file descriptor. * * @return * F_none on success. @@ -868,7 +1098,7 @@ extern "C" { * Set to 0 to not use. * @param file * The data related to the file being opened. - * This will be updated with the file descriptor and file address. + * This will be updated with the file descriptor. * * @return * F_none on success. diff --git a/level_0/f_file/c/private-file.c b/level_0/f_file/c/private-file.c index 67b7258..bd78d57 100644 --- a/level_0/f_file/c/private-file.c +++ b/level_0/f_file/c/private-file.c @@ -205,6 +205,154 @@ extern "C" { } #endif // !defined(_di_f_file_create_at_) || !defined(_di_f_file_copy_at_) +#if !defined(_di_f_file_copy_) + f_return_status private_f_file_create_directory(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 == ENAMETOOLONG) return F_status_set_error(F_name); + 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 == 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_file_copy_) + +#if !defined(_di_f_file_copy_at_) + f_return_status private_f_file_create_directory_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 == EDQUOT) return F_status_set_error(F_filesystem_quota_block); + if (errno == EEXIST) return F_status_set_error(F_file_found); + if (errno == ENAMETOOLONG) return F_status_set_error(F_name); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINVAL || errno == EBADF) 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 == 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_file_copy_at_) + +#if !defined(_di_f_file_create_fifo_) || !defined(_di_f_file_copy_) + f_return_status private_f_file_create_fifo(const f_string path, const mode_t mode) { + + if (mkfifo(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 == ENAMETOOLONG) return F_status_set_error(F_name); + if (errno == ENOENT) return F_status_set_error(F_file_found_not); + 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_file_create_fifo_) || !defined(_di_f_file_copy_) + +#if !defined(_di_f_file_create_fifo_at_) || !defined(_di_f_file_copy_at_) + f_return_status private_f_file_create_fifo_at(const int at_id, const f_string path, const mode_t mode) { + + if (mkfifoat(at_id, 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 == ENAMETOOLONG) return F_status_set_error(F_name); + if (errno == ENOENT) return F_status_set_error(F_file_found_not); + 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); + if (errno == EBADF) return F_status_set_error(F_file_descriptor); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // !defined(_di_f_file_create_fifo_at_) || !defined(_di_f_file_copy_at_) + +#if !defined(_di_f_file_create_device_) || !defined(_di_f_file_create_node_) || !defined(_di_f_file_copy_) + f_return_status private_f_file_create_node(const f_string path, const mode_t mode, const dev_t device) { + + if (mknod(path, mode, device) < 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 == ENAMETOOLONG) return F_status_set_error(F_name); + 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 == ENOENT) return F_status_set_error(F_file_found_not); + if (errno == ENOTDIR) return F_status_set_error(F_directory); + if (errno == ENOMEM) return F_status_set_error(F_memory_out); + if (errno == ENOSPC) return F_status_set_error(F_space_not); + if (errno == EPERM) return F_status_set_error(F_prohibited); + if (errno == EROFS) return F_status_set_error(F_read_only); + if (errno == ETXTBSY) return F_status_set_error(F_busy); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // !defined(_di_f_file_create_device_) || !defined(_di_f_file_create_node_) || !defined(_di_f_file_copy_) + +#if !defined(_di_f_file_create_device_at_) || !defined(_di_f_file_create_node_at_) || !defined(_di_f_file_copy_at_) + f_return_status private_f_file_create_node_at(const int at_id, const f_string path, const mode_t mode, const dev_t device) { + + if (mknodat(at_id, path, mode, device) < 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 == ENAMETOOLONG) return F_status_set_error(F_name); + 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 == EBADF) return F_status_set_error(F_file_descriptor); + if (errno == ENOENT) return F_status_set_error(F_file_found_not); + if (errno == ENOTDIR) return F_status_set_error(F_directory); + if (errno == ENOMEM) return F_status_set_error(F_memory_out); + if (errno == ENOSPC) return F_status_set_error(F_space_not); + if (errno == EPERM) return F_status_set_error(F_prohibited); + if (errno == EROFS) return F_status_set_error(F_read_only); + if (errno == ETXTBSY) return F_status_set_error(F_busy); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // !defined(_di_f_file_create_device_at_) || !defined(_di_f_file_create_node_at_) || !defined(_di_f_file_copy_at_) + #if !defined(_di_f_file_flush_) || !defined(_di_f_file_close_) || !defined(_di_f_file_copy_) f_return_status private_f_file_flush(const int id) { diff --git a/level_0/f_file/c/private-file.h b/level_0/f_file/c/private-file.h index a8c12dd..8579833 100644 --- a/level_0/f_file/c/private-file.h +++ b/level_0/f_file/c/private-file.h @@ -242,7 +242,7 @@ extern "C" { * The file mode to open in. * @param file * The data related to the file being opened. - * This will be updated with the file descriptor and file address. + * This will be updated with the file descriptor. * This will be updated with the create flags (ignoring and overriding existing file.flags). * @param exclusive * If TRUE, will fail when file already exists. @@ -288,7 +288,7 @@ extern "C" { * The parent directory, as an open directory file descriptor, in which path is relative to. * @param file * The data related to the file being opened. - * This will be updated with the file descriptor and file address. + * This will be updated with the file descriptor. * This will be updated with the create flags (ignoring and overriding existing file.flags). * @param path * The path file name. @@ -330,6 +330,216 @@ extern "C" { #endif // !defined(_di_f_file_create_at_) || !defined(_di_f_file_copy_at_) /** + * Private implementation for creating directories. + * + * Intended to be shared to each of the different implementation variations. + * + * @param path + * The path file name. + * @param mode + * The directory mode to use when creating. + * + * @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_loop (with error bit) on loop error. + * F_file_found_not (with error bit) if a file within the path is not found (such as a broken symbolic link). + * F_memory_out (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_block (with error bit) if filesystem's disk blocks or inodes are exhausted. + * F_space_not (with error bit) if filesystem is out of space (or filesystem quota is reached). + * F_file_found (with error bit) of a directory aleady exists at the path. + * F_name (with error bit) on path name error. + * F_directory_link_max (with error bit) max links limit reached or exceeded. + * F_directory (with error bit) if a supposed directory in path is not actually a directory. + * + * @see f_file_copy() + * @see mkdir() + */ +#if !defined(_di_f_file_copy_) + extern f_return_status private_f_file_create_directory(const f_string path, const mode_t mode) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_file_copy_) + +/** + * Private implementation for creating directories. + * + * Intended to be shared to each of the different implementation variations. + * + * @param at_id + * The file descriptor in which the directory will be created within. + * @param path + * The path file name. + * @param mode + * The directory mode to use when creating. + * + * @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_loop (with error bit) on loop error. + * F_file_found_not (with error bit) if a file within the path is not found (such as a broken symbolic link). + * F_memory_out (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_block (with error bit) if filesystem's disk blocks or inodes are exhausted. + * F_space_not (with error bit) if filesystem is out of space (or filesystem quota is reached). + * F_file_found (with error bit) of a directory aleady exists at the path. + * F_name (with error bit) on path name error. + * F_directory_link_max (with error bit) max links limit reached or exceeded. + * F_directory (with error bit) if a supposed directory in path is not actually a directory. + * + * @see f_file_copy_at() + * @see mkdirat() + */ +#if !defined(_di_f_file_copy_at_) + extern f_return_status private_f_file_create_directory_at(const int at_id, const f_string path, const mode_t mode) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_file_copy_at_) + +/** + * Create a fifo based on the given path and file mode. + * + * @param path + * The path file name. + * @param mode + * The file mode to assign. + * + * @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_file_found (with error bit) if a file was found while exclusive is TRUE. + * F_prohibited (with error bit) if filesystem does not allow for removing. + * F_failure (with error bit) for any other (mknod()) error. + * F_filesystem_quota_block (with error bit) if filesystem's disk blocks or ififos are exhausted. + * F_space_not (with error bit) if filesystem is out of space (or filesystem quota is reached). + * F_file_found (with error bit) of a directory aleady exists at the path. + * F_name (with error bit) on path name error. + * F_directory (with error bit) if a supposed directory in path is not actually a directory. + * F_unsupported (with error bit) for unsupported file types. + * + * @see mkfifo() + */ +#if !defined(_di_f_file_create_fifo_) || !defined(_di_f_file_copy_) + extern f_return_status private_f_file_create_fifo(const f_string path, const mode_t mode) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_file_create_fifo_) || !defined(_di_f_file_copy_) + +/** + * Create a fifo based on the given path and file mode. + * + * @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 assign. + * + * @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_file_found (with error bit) if a file was found while exclusive is TRUE. + * F_prohibited (with error bit) if filesystem does not allow for removing. + * F_failure (with error bit) for any other (mknod()) error. + * F_filesystem_quota_block (with error bit) if filesystem's disk blocks or ififos are exhausted. + * F_space_not (with error bit) if filesystem is out of space (or filesystem quota is reached). + * F_file_found (with error bit) of a directory aleady exists at the path. + * F_name (with error bit) on path name error. + * F_directory (with error bit) if a supposed directory in path is not actually a directory. + * F_unsupported (with error bit) for unsupported file types. + * F_file_descriptor (with error bit) for bad file descriptor. + * + * @see mkfifoat() + */ +#if !defined(_di_f_file_create_fifo_at_) || !defined(_di_f_file_copy_at_) + extern f_return_status private_f_file_create_fifo_at(const int at_id, const f_string path, const mode_t mode) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_file_create_fifo_at_) || !defined(_di_f_file_copy_at_) + +/** + * Private implementation of f_file_create_node(). + * + * Intended to be shared to each of the different implementation variations. + * + * @param path + * The path file name. + * @param mode + * The file mode to assign. + * @param device + * The device number for character and block file types. + * Is ignored by pipe file types. + * @param file + * The data related to the file being created. + * This will be updated with the file descriptor. + * + * @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_loop (with error bit) on loop error. + * F_file_found (with error bit) if a file was found while exclusive is TRUE. + * F_memory_out (with error bit) if out of memory. + * F_prohibited (with error bit) if filesystem does not allow for removing. + * F_failure (with error bit) for any other (mknod()) error. + * F_filesystem_quota_block (with error bit) if filesystem's disk blocks or inodes are exhausted. + * F_space_not (with error bit) if filesystem is out of space (or filesystem quota is reached). + * F_file_found (with error bit) of a directory aleady exists at the path. + * F_name (with error bit) on path name error. + * F_directory (with error bit) if a supposed directory in path is not actually a directory. + * F_unsupported (with error bit) for unsupported file types. + * + * @see f_file_create_device() + * @see f_file_create_node() + */ +#if !defined(_di_f_file_create_device_) || !defined(_di_f_file_create_node_) || !defined(_di_f_file_copy_) + extern f_return_status private_f_file_create_node(const f_string path, const mode_t mode, const dev_t device) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_file_create_device_) || !defined(_di_f_file_create_node_) || !defined(_di_f_file_copy_) + +/** + * Private implementation of f_file_create_node_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 path file name. + * @param mode + * The file mode to assign. + * @param device + * The device number for character and block file types. + * Is ignored by pipe file types. + * @param file + * The data related to the file being created. + * This will be updated with the file descriptor. + * + * @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_loop (with error bit) on loop error. + * F_file_found (with error bit) if a file was found while exclusive is TRUE. + * F_memory_out (with error bit) if out of memory. + * F_prohibited (with error bit) if filesystem does not allow for removing. + * F_failure (with error bit) for any other (mknod()) error. + * F_filesystem_quota_block (with error bit) if filesystem's disk blocks or inodes are exhausted. + * F_space_not (with error bit) if filesystem is out of space (or filesystem quota is reached). + * F_file_found (with error bit) of a directory aleady exists at the path. + * F_name (with error bit) on path name error. + * F_directory (with error bit) if a supposed directory in path is not actually a directory. + * F_unsupported (with error bit) for unsupported file types. + * F_file_descriptor (with error bit) for bad file descriptor. + * + * @see f_file_create_device_at() + * @see f_file_create_node_at() + */ +#if !defined(_di_f_file_create_device_at_) || !defined(_di_f_file_create_node_at_) || !defined(_di_f_file_copy_at_) + extern f_return_status private_f_file_create_node_at(const int at_id, const f_string path, const mode_t mode, const dev_t device) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_file_create_device_at_) || !defined(_di_f_file_create_node_at_) || !defined(_di_f_file_copy_at_) + +/** * Private implementation of f_file_link(). * * Intended to be shared to each of the different implementation variations. @@ -447,7 +657,7 @@ extern "C" { * Set to 0 to not use. * @param file * The data related to the file being opened. - * This will be updated with the file descriptor and file address. + * This will be updated with the file descriptor. * * @return * F_none on success. @@ -477,7 +687,7 @@ extern "C" { * Set to 0 to not use. * @param file * The data related to the file being opened. - * This will be updated with the file descriptor and file address. + * This will be updated with the file descriptor. * * @return * F_none on success. diff --git a/level_0/f_status/c/status.h b/level_0/f_status/c/status.h index 4e49f9a..80a2caf 100644 --- a/level_0/f_status/c/status.h +++ b/level_0/f_status/c/status.h @@ -63,7 +63,7 @@ extern "C" { * 1) F_false, must always evaluate to 0. * 2) F_true, must always evaluate to 1 and will conflict with F_signal_hangup. * 3) All f_signal_*, these numbers must map directly to the standard signal codes. - * 4) f_none, this is intended to be the default return code and the return code representing the standard start code. + * 4) F_none, this is intended to be the default return code and the return code representing the standard start code. * 5) F_status_code_last, this is intended to designate the last code provided by level_0 status project. * All code sets started by another project (such as FSS status codes) must start at this number + 1 with a code start map. */ @@ -298,10 +298,12 @@ extern "C" { F_file_type_block, F_file_type_character, F_file_type_directory, + F_file_type_fifo, F_file_type_link, F_file_type_not_block, F_file_type_not_character, F_file_type_not_directory, + F_file_type_not_fifo, F_file_type_not_link, F_file_type_not_pipe, F_file_type_not_regular, diff --git a/level_1/fl_directory/c/private-directory.c b/level_1/fl_directory/c/private-directory.c index f11d35d..9ee5299 100644 --- a/level_1/fl_directory/c/private-directory.c +++ b/level_1/fl_directory/c/private-directory.c @@ -52,11 +52,11 @@ extern "C" { f_macro_string_dynamics_delete_simple(listing.character); - for (; i < listing.file.used; i++) { + for (; i < listing.regular.used; i++) { // @todo } // for - f_macro_string_dynamics_delete_simple(listing.file); + f_macro_string_dynamics_delete_simple(listing.regular); for (; i < listing.link.used; i++) { // @todo @@ -182,8 +182,8 @@ extern "C" { else if (mode == f_file_type_directory) { names = &listing->directory; } - else if (mode == f_file_type_file) { - names = &listing->file; + else if (mode == f_file_type_regular) { + names = &listing->regular; } else if (mode == f_file_type_link) { names = &listing->link; diff --git a/level_1/fl_status/c/status.c b/level_1/fl_status/c/status.c index f7023a5..8771ce7 100644 --- a/level_1/fl_status/c/status.c +++ b/level_1/fl_status/c/status.c @@ -644,6 +644,9 @@ extern "C" { case F_file_type_directory: *string = FL_status_string_file_type_directory; break; + case F_file_type_fifo: + *string = FL_status_string_file_type_fifo; + break; case F_file_type_link: *string = FL_status_string_file_type_link; break; @@ -653,6 +656,9 @@ extern "C" { case F_file_type_not_directory: *string = FL_status_string_file_type_not_directory; break; + case F_file_type_not_fifo: + *string = FL_status_string_file_type_not_fifo; + break; case F_file_type_not_link: *string = FL_status_string_file_type_not_link; break; diff --git a/level_1/fl_status/c/status.h b/level_1/fl_status/c/status.h index 71970e6..138f808 100644 --- a/level_1/fl_status/c/status.h +++ b/level_1/fl_status/c/status.h @@ -438,10 +438,12 @@ extern "C" { #define FL_status_string_file_type_block "F_file_type_block" #define FL_status_string_file_type_character "F_file_type_character" #define FL_status_string_file_type_directory "F_file_type_directory" + #define FL_status_string_file_type_fifo "F_file_type_fifo" #define FL_status_string_file_type_link "F_file_type_link" #define FL_status_string_file_type_not_block "F_file_type_not_block" #define FL_status_string_file_type_not_character "F_file_type_not_character" #define FL_status_string_file_type_not_directory "F_file_type_not_directory" + #define FL_status_string_file_type_not_fifo "F_file_type_not_fifo" #define FL_status_string_file_type_not_link "F_file_type_not_link" #define FL_status_string_file_type_not_pipe "F_file_type_not_pipe" #define FL_status_string_file_type_not_regular "F_file_type_not_regular" @@ -478,10 +480,12 @@ extern "C" { #define FL_status_string_file_type_block_length 17 #define FL_status_string_file_type_character_length 21 #define FL_status_string_file_type_directory_length 21 + #define FL_status_string_file_type_fifo_length 16 #define FL_status_string_file_type_link_length 16 #define FL_status_string_file_type_not_block_length 21 #define FL_status_string_file_type_not_character_length 25 #define FL_status_string_file_type_not_directory_length 25 + #define FL_status_string_file_type_not_fifo_length 20 #define FL_status_string_file_type_not_link_length 20 #define FL_status_string_file_type_not_pipe_length 20 #define FL_status_string_file_type_not_regular_length 23 diff --git a/level_2/fll_status/c/status.c b/level_2/fll_status/c/status.c index 8d27a96..a173598 100644 --- a/level_2/fll_status/c/status.c +++ b/level_2/fll_status/c/status.c @@ -1078,6 +1078,11 @@ extern "C" { return F_none; } + if (fl_string_compare(string, FL_status_string_file_type_not_fifo, length, FL_status_string_file_type_not_fifo_length) == F_equal_to) { + *code = F_file_type_not_fifo; + return F_none; + } + if (fl_string_compare(string, FL_status_string_file_type_not_link, length, FL_status_string_file_type_not_link_length) == F_equal_to) { *code = F_file_type_not_link; return F_none; diff --git a/level_3/fake/c/private-skeleton.c b/level_3/fake/c/private-skeleton.c index 63e8744..951e7ec 100644 --- a/level_3/fake/c/private-skeleton.c +++ b/level_3/fake/c/private-skeleton.c @@ -146,7 +146,7 @@ extern "C" { if (path.used == 0) return F_none; - status = f_file_is(path.string, f_file_type_file); + status = f_file_is(path.string, f_file_type_regular); if (status == F_true) { if (data.verbosity == fake_verbosity_verbose) { printf("File '%s' already exists.%c", path.string, f_string_eol);