Minor updates to f_file project.
Add the f_file_touch() and f_file_touch_at() functions.
Add the status code F_search (used by f_file_touch() and f_file_touch_at()).
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 == 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_false;
- if (errno == EACCES) return F_status_set_error(F_access_denied);
- if (errno == ELOOP) return F_status_set_error(F_loop);
+ status = private_f_file_stat(path, F_false, &file_stat);
- return F_status_set_error(F_file_stat);
+ if (F_status_is_error(status)) {
+ if (F_status_set_fine(status) == F_file_found_not) return F_false;
+
+ return status;
}
return F_true;
#endif // _di_f_file_exists_
#ifndef _di_f_file_exists_at_
- f_return_status f_file_exists_at(const int at_id, const f_string path, const bool follow) {
+ f_return_status f_file_exists_at(const int at_id, const f_string path, 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, follow ? 0 : AT_SYMLINK_NOFOLLOW) < 0) {
- 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_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);
+ status = private_f_file_stat_at(at_id, path, flag, &file_stat);
- return F_status_set_error(F_file_stat);
+ if (F_status_is_error(status)) {
+ if (F_status_set_fine(status) == F_file_found_not) return F_false;
+
+ return status;
}
return F_true;
#endif // _di_f_file_is_
#ifndef _di_f_file_is_at_
- f_return_status f_file_is_at(const int at_id, const f_string path, const int type, const bool follow) {
+ f_return_status f_file_is_at(const int at_id, const f_string path, const int type, 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_
memset(&file_stat, 0, sizeof(struct stat));
- if (fstatat(at_id, path, &file_stat, follow ? 0 : AT_SYMLINK_NOFOLLOW) < 0) {
+ if (fstatat(at_id, path, &file_stat, flag) < 0) {
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);
}
#endif // _di_f_file_stat_by_id_
+#ifndef _di_f_file_touch_
+ f_return_status f_file_touch(const f_string path, const mode_t mode, const bool dereference) {
+ #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));
+
+ status = private_f_file_stat(path, F_false, &file_stat);
+
+ if (F_status_set_fine(status) == F_file_found_not) {
+ return private_f_file_create(path, mode, dereference);
+ }
+ else if (F_status_is_error(status)) {
+ return status;
+ }
+
+ if (utimensat(f_file_at_current_working, path, 0, dereference ? 0 : f_file_at_symlink_follow_no) < 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_file_touch_
+
+#ifndef _di_f_file_touch_at_
+ f_return_status f_file_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));
+
+ status = private_f_file_stat_at(at_id, path, flag, &file_stat);
+
+ if (F_status_set_fine(status) == F_file_found_not) {
+ return private_f_file_create_at(at_id, path, mode, F_false);
+ }
+ else if (F_status_is_error(status)) {
+ return status;
+ }
+
+ 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_file_touch_at_
+
#ifndef _di_f_file_write_
f_return_status f_file_write(const f_file file, const f_string_dynamic buffer, f_string_length *written) {
#ifndef _di_level_0_parameter_checking_
#endif // _di_f_file_copy_
/**
- * Create a file based on the given path and file mode.
+ * Create a (regular) file based on the given path and file mode.
*
* The file will not be open after calling this.
*
#endif // _di_f_file_create_
/**
- * Create a file based on the given path and file mode.
+ * Create a (regular) file based on the given path and file mode.
*
* The file will not be open after calling this.
*
* @param path
* The path file name.
* @param flag
- * Additional flag to pass, such as AT_EACCESS or AT_SYMLINK_NOFOLLOW.
+ * Any valid flag, such as f_file_at_path_empty, f_file_at_automount_no, or f_file_at_symlink_follow_no.
*
* @return
* F_true if file exists.
* @see fstatat()
*/
#ifndef _di_f_file_exists_at_
- extern f_return_status f_file_exists_at(const int at_id, const f_string path, const bool follow);
+ extern f_return_status f_file_exists_at(const int at_id, const f_string path, const int flag);
#endif // _di_f_file_exists_at_
/**
* The path file name.
* @param type
* The type of the file
- * @param follow
- * Set to TRUE to follow symbolic links when determining if path is a file.
- * Set to FALSE to not follow.
+ * @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_true if path was found and path is type.
* @see fstatat()
*/
#ifndef _di_f_file_is_at_
- extern f_return_status f_file_is_at(const int at_id, const f_string path, const int type, const bool follow);
+ extern f_return_status f_file_is_at(const int at_id, const f_string path, const int type, const int flag);
#endif // _di_f_file_is_at_
/**
#endif // _di_f_file_write_
/**
+ * 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 regular file.
+ *
+ * @param path
+ * The path file name.
+ * @param mode
+ * The file mode to use when (regular) file is created.
+ * @param dereference
+ * Set to TRUE to dereferenc symlinks (often is what is desired).
+ * Set to FALSE to operate on the symlink itself.
+ *
+ * @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_directory_descriptor (with error bit) for bad directory descriptor for at_id.
+ * F_buffer (with error bit) if the buffer is invalid.
+ * F_loop (with error bit) on loop error.
+ * F_name (with error bit) on path name error.
+ * F_file_found (with error bit) if a file aleady exists at the path.
+ * F_directory (with error bit) if a supposed directory in path is not actually a directory.
+ * 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_memory_out (with error bit) if out of memory.
+ * 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_number_overflow (with error bit) on overflow error.
+ * F_interrupted (with error bit) when program received an interrupt signal, halting create.
+ * F_file_open_max (with error bit) when system-wide max open files is reached.
+ * F_busy (with error bit) if filesystem is too busy to perforrm write.
+ * F_failure (with error bit) for any other error.
+ *
+ * @see utimensat()
+ */
+#ifndef _di_f_file_touch_
+ extern f_return_status f_file_touch(const f_string path, const mode_t mode, const bool dereference);
+#endif // _di_f_file_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 regular 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 (regular) 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_parameter (with error bit) if a parameter is invalid.
+ * F_access_denied (with error bit) on access denied.
+ * F_directory_descriptor (with error bit) for bad directory descriptor for at_id.
+ * F_buffer (with error bit) if the buffer is invalid.
+ * F_loop (with error bit) on loop error.
+ * F_name (with error bit) on path name error.
+ * F_file_found (with error bit) if a file aleady exists at the path (when calling utimensat()).
+ * F_directory (with error bit) if a supposed directory in path is not actually a directory.
+ * 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_memory_out (with error bit) if out of memory.
+ * 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_number_overflow (with error bit) on overflow error.
+ * F_interrupted (with error bit) when program received an interrupt signal, halting create.
+ * F_file_open_max (with error bit) when system-wide max open files is reached.
+ * F_busy (with error bit) if filesystem is too busy to perforrm write.
+ * F_failure (with error bit) for any other error.
+ *
+ * @see utimensat()
+ */
+#ifndef _di_f_file_touch_at_
+ extern f_return_status f_file_touch_at(const int at_id, const f_string path, const mode_t mode, const int flag);
+#endif // _di_f_file_touch_at_
+
+/**
* Write until a single block is filled or entire buffer is written.
*
* To check how much was write into the buffer, record buffer->used before execution and compare to buffer->used after execution.
* @param gid
* The new group id to use.
* @param flag
- * Any valid flag, such as AT_EMPTY_PATH, AT_NO_AUTOMOUNT, or AT_SYMLINK_NO_FOLLOW.
+ * 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.
*
* @see f_file_copy()
* @see f_file_stat()
+ * @see f_file_exists()
+ * @see f_file_touch()
*/
-#if !defined(_di_f_file_stat_) || !defined(_di_f_file_copy_)
+#if !defined(_di_f_file_stat_) || !defined(_di_f_file_copy_) || !defined(_di_f_file_exists_) || !defined(_di_f_file_touch_)
extern f_return_status private_f_file_stat(const f_string file_name, const bool dereference, struct stat *file_stat) f_gcc_attribute_visibility_internal;
-#endif // !defined(_di_f_file_stat_) || !defined(_di_f_file_copy_)
+#endif // !defined(_di_f_file_stat_) || !defined(_di_f_file_copy_) || !defined(_di_f_file_exists_) || !defined(_di_f_file_touch_)
/**
* Private implementation of f_file_close().
* @param file_name
* The name of the file.
* @param flag
- * Any valid flag, such as AT_EMPTY_PATH, AT_NO_AUTOMOUNT, or AT_SYMLINK_NO_FOLLOW.
+ * Any valid flag, such as f_file_at_path_empty, f_file_at_automount_no, or f_file_at_symlink_follow_no.
* @param file_stat
* The statistics read.
*
- *
* @return
* F_none on success.
* F_name (with error bit) if the name is somehow invalid.
* F_parameter (with error bit) if a parameter is invalid.
*
* @see f_file_stat_at()
+ * @see f_file_exists_at()
+ * @see f_file_touch_at()
*/
-#if !defined(_di_f_file_stat_at_)
+#if !defined(_di_f_file_stat_at_) || !defined(_di_f_file_exists_at_) || !defined(_di_f_file_touch_at_)
extern f_return_status private_f_file_stat_at(const int at_id, const f_string file_name, const int flag, struct stat *file_stat) f_gcc_attribute_visibility_internal;
-#endif // !defined(_di_f_file_stat_at_)
+#endif // !defined(_di_f_file_stat_at_) || !defined(_di_f_file_exists_at_) || !defined(_di_f_file_touch_at_)
/**
* Private implementation of f_file_close().
F_process_too_many,
F_prohibited,
F_read_only,
+ F_search,
F_space_not,
F_stop,
F_syntax,
case F_read_only:
*string = FL_status_string_read_only;
break;
+ case F_search:
+ *string = FL_status_string_search;
+ break;
case F_space_not:
*string = FL_status_string_space_not;
break;
#define FL_status_string_process_too_many "F_process_too_many"
#define FL_status_string_prohibited "F_prohibited"
#define FL_status_string_read_only "F_read_only"
+ #define FL_status_string_search "F_search"
#define FL_status_string_space_not "F_space_not"
#define FL_status_string_stop "F_stop"
#define FL_status_string_syntax "F_syntax"
#define FL_status_string_process_too_many_length 18
#define FL_status_string_prohibited_length 12
#define FL_status_string_read_only_length 11
+ #define FL_status_string_search_length 8
#define FL_status_string_space_not_length 11
#define FL_status_string_stop_length 6
#define FL_status_string_syntax_length 8
return F_none;
}
+ if (fl_string_compare(string, FL_status_string_search, length, FL_status_string_search_length) == F_equal_to) {
+ *code = F_search;
+ return F_none;
+ }
+
if (fl_string_compare(string, FL_status_string_space_not, length, FL_status_string_space_not_length) == F_equal_to) {
*code = F_space_not;
return F_none;