This also adds the unit tests.
The unit tests includes additional fixes where several of the wrapped functions are not being setup properly.
The fact that has not triggered an error in the past is concerning.
}
#endif // _di_f_file_link_read_at_
+#ifndef _di_f_file_manipulate_
+ f_status_t f_file_manipulate(const f_file_t file, const int command, const long argument) {
+
+ if (file.id == -1) return F_file_descriptor_not;
+
+ if (fcntl(file.id, command, argument) == -1) {
+ if (errno == EACCES) return F_status_set_error(F_access_denied);
+ if (errno == EAGAIN) return F_status_set_error(F_again);
+ if (errno == EBADF) return F_status_set_error(F_file_descriptor);
+ if (errno == EBUSY) return F_status_set_error(F_busy);
+ if (errno == EDEADLK) return F_status_set_error(F_deadlock);
+ if (errno == EFAULT) return F_status_set_error(F_buffer);
+ if (errno == EINTR) return F_status_set_error(F_interrupt);
+ if (errno == EINVAL) return F_status_set_error(F_parameter);
+ if (errno == EMFILE) return F_status_set_error(F_file_descriptor_max);
+ if (errno == ENOLCK) return F_status_set_error(F_lock);
+ if (errno == ENOTDIR) return F_status_set_error(F_directory_not);
+ if (errno == EPERM) return F_status_set_error(F_prohibited);
+
+ return F_status_set_error(F_failure);
+ }
+
+ return F_none;
+ }
+#endif // _di_f_file_manipulate_
+
#ifndef _di_f_file_mode_determine_
f_status_t f_file_mode_determine(const mode_t mode_file, const f_file_mode_t mode_change, const uint8_t mode_replace, const bool directory_is, mode_t *mode) {
#ifndef _di_level_0_parameter_checking_
#endif // _di_f_file_link_read_at_
/**
+ * Manipulate the file by the file descriptor.
+ *
+ * @param file
+ * The data related to the file containing the file descriptor.
+ * The file descriptor is required to be valid.
+ * @param command
+ * The command to perform.
+ * See fcntl() for details.
+ * @param argument
+ * An argument associated with the command.
+ * See fcntl() for details.
+ *
+ * @return
+ * F_none on success.
+ *
+ * F_access_denied (with error bit) on access denied (due to locks being held by other processes).
+ * F_again (with error bit) on operation on file is prohibited (often due to file being memory mapped by another process).
+ * F_buffer (with error bit) if the buffer is invalid.
+ * F_busy (with error bit) if system is too busy to perform operation.
+ * F_deadlock (with error bit) if operation would cause a deadlock.
+ * F_directory_not (with error bit) on invalid directory.
+ * F_file_descriptor (with error bit) if file descriptor is invalid.
+ * F_file_descriptor_max (with error bit) if max file descriptors is reached.
+ * F_interrupt (with error bit) when program received an interrupt signal, halting operation.
+ * F_lock (with error bit) if failed to lock, such as lock table is full or too many open segments.
+ * F_parameter (with error bit) if a parameter is invalid.
+ * F_prohibited (with error bit) if operation is prohibited (maps to EPERM).
+ * F_failure (with error bit) for any other error.
+ *
+ * @see fcntl()
+ */
+#ifndef _di_f_file_manipulate_
+ extern f_status_t f_file_manipulate(const f_file_t file, const int command, const long argument);
+#endif // _di_f_file_manipulate_
+
+/**
* Determine how the mode should be applied based on different file properties and the given mode properties.
*
* This does not set mode based on umask(), which is already applied if f_file_mode_from_string() was used to create mode_change.
flags -Wl,--wrap=chown
flags -Wl,--wrap=close
flags -Wl,--wrap=faccessat
+flags -Wl,--wrap=fchmod
flags -Wl,--wrap=fchmodat
+flags -Wl,--wrap=fchown
flags -Wl,--wrap=fchownat
flags -Wl,--wrap=fclose
+flags -Wl,--wrap=fopen
flags -Wl,--wrap=fdopen
+flags -Wl,--wrap=freopen
flags -Wl,--wrap=feof_unlocked
flags -Wl,--wrap=ferror_unlocked
flags -Wl,--wrap=fflush
flags -Wl,--wrap=fileno
flags -Wl,--wrap=flockfile
-flags -Wl,--wrap=fopen
+flags -Wl,--wrap=fcntl
flags -Wl,--wrap=fread_unlocked
-flags -Wl,--wrap=freopen
flags -Wl,--wrap=fstat
flags -Wl,--wrap=fstatat
flags -Wl,--wrap=fsync
flags -Wl,--wrap=linkat
flags -Wl,--wrap=lseek
flags -Wl,--wrap=lstat
-flags -Wl,--wrap=makedev
flags -Wl,--wrap=mkdir
flags -Wl,--wrap=mkdirat
flags -Wl,--wrap=mkfifo
flags -Wl,--wrap=rename
flags -Wl,--wrap=renameat
flags -Wl,--wrap=renameat2
-flags -Wl,--wrap=remove
flags -Wl,--wrap=stat
flags -Wl,--wrap=symlink
flags -Wl,--wrap=symlinkat
flags -Wl,--wrap=unlink
flags -Wl,--wrap=unlinkat
-flags -Wl,--wrap=utimensat
flags -Wl,--wrap=umask
+flags -Wl,--wrap=utimensat
flags -Wl,--wrap=write
build_libraries -lc -lcmocka
build_libraries-individual -lf_memory -lf_string -lf_file
-build_sources_program test-file-access.c test-file-access_at.c test-file-clone.c test-file-close.c test-file-copy.c test-file-create.c test-file-create_at.c test-file-create_device.c test-file-create_device_at.c test-file-create_fifo.c test-file-create_fifo_at.c test-file-create_node.c test-file-create_node_at.c test-file-descriptor.c test-file-exists.c test-file-exists_at.c test-file-flush.c test-file-group_read.c test-file-is.c test-file-is_at.c test-file-is_stat.c test-file-link.c test-file-link_at.c test-file-link_hard.c test-file-link_hard_at.c test-file-link_read.c test-file-link_read_at.c test-file-mode_determine.c test-file-mode_from_string.c test-file-mode_read.c test-file-mode_read_at.c test-file-mode_set.c test-file-mode_set_at.c test-file-mode_to_mode.c test-file-name_base.c test-file-name_directory.c test-file-open.c test-file-open_at.c test-file-owner_read.c test-file-read.c test-file-read_block.c test-file-read_until.c test-file-remove.c test-file-remove_at.c test-file-rename.c test-file-rename_at.c test-file-role_change.c test-file-role_change_at.c test-file-seek.c test-file-size.c test-file-size_at.c test-file-size_by_id.c test-file-stat.c test-file-stat_at.c test-file-stat_by_id.c test-file-stream_close.c test-file-stream_open_descriptor.c test-file-stream_open.c test-file-stream_read.c test-file-stream_read_block.c test-file-stream_read_until.c test-file-stream_reopen.c test-file-stream_write.c test-file-stream_write_block.c test-file-stream_write_until.c test-file-stream_write_range.c test-file-touch.c test-file-touch_at.c test-file-type.c test-file-type_at.c test-file-umask_get.c test-file-umask_set.c test-file-write.c test-file-write_block.c test-file-write_until.c test-file-write_range.c
+build_sources_program test-file-access.c test-file-access_at.c test-file-clone.c test-file-close.c test-file-copy.c test-file-create.c test-file-create_at.c test-file-create_device.c test-file-create_device_at.c test-file-create_fifo.c test-file-create_fifo_at.c test-file-create_node.c test-file-create_node_at.c test-file-descriptor.c test-file-exists.c test-file-exists_at.c test-file-flush.c test-file-group_read.c test-file-is.c test-file-is_at.c test-file-is_stat.c test-file-link.c test-file-link_at.c test-file-link_hard.c test-file-link_hard_at.c test-file-link_read.c test-file-link_read_at.c test-file-manipulate.c test-file-mode_determine.c test-file-mode_from_string.c test-file-mode_read.c test-file-mode_read_at.c test-file-mode_set.c test-file-mode_set_at.c test-file-mode_to_mode.c test-file-name_base.c test-file-name_directory.c test-file-open.c test-file-open_at.c test-file-owner_read.c test-file-read.c test-file-read_block.c test-file-read_until.c test-file-remove.c test-file-remove_at.c test-file-rename.c test-file-rename_at.c test-file-role_change.c test-file-role_change_at.c test-file-seek.c test-file-size.c test-file-size_at.c test-file-size_by_id.c test-file-stat.c test-file-stat_at.c test-file-stat_by_id.c test-file-stream_close.c test-file-stream_open_descriptor.c test-file-stream_open.c test-file-stream_read.c test-file-stream_read_block.c test-file-stream_read_until.c test-file-stream_reopen.c test-file-stream_write.c test-file-stream_write_block.c test-file-stream_write_until.c test-file-stream_write_range.c test-file-touch.c test-file-touch_at.c test-file-type.c test-file-type_at.c test-file-umask_get.c test-file-umask_set.c test-file-write.c test-file-write_block.c test-file-write_until.c test-file-write_range.c
build_sources_program test-file.c
build_script no
}
+int __wrap_fcntl(int fd, int cmd, ...) {
+
+ const bool failure = mock_type(bool);
+
+ if (failure) {
+ errno = mock_type(int);
+
+ return -1;
+ }
+
+ return 0;
+}
+
size_t __wrap_fread_unlocked(void *ptr, size_t size, size_t nmemb, FILE *stream) {
return mock_type(int);
extern int __wrap_fflush(FILE *stream);
extern int __wrap_fileno(FILE *stream);
extern void __wrap_flockfile(FILE *filehandle);
+extern int __wrap_fcntl(int fd, int cmd, ...);
extern size_t __wrap_fread_unlocked(void *ptr, size_t size, size_t nmemb, FILE *stream);
extern int __wrap_fstat(int fd, struct stat *statbuf);
extern int __wrap_fstatat(int dirfd, const char *pathname, struct stat *statbuf, int flags);
--- /dev/null
+#include "test-file.h"
+#include "test-file-manipulate.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_file_manipulate__fails(void **state) {
+
+ const f_file_t file = macro_f_file_t_initialize_2(F_type_output_d, F_type_descriptor_output_d, F_file_flag_write_only_d);
+
+ {
+ int errnos[] = {
+ EACCES,
+ EAGAIN,
+ EBADF,
+ EBUSY,
+ EDEADLK,
+ EFAULT,
+ EINTR,
+ EINVAL,
+ EMFILE,
+ ENOLCK,
+ ENOTDIR,
+ EPERM,
+ mock_errno_generic,
+ };
+
+ f_status_t statuss[] = {
+ F_access_denied,
+ F_again,
+ F_file_descriptor,
+ F_busy,
+ F_deadlock,
+ F_buffer,
+ F_interrupt,
+ F_parameter,
+ F_file_descriptor_max,
+ F_lock,
+ F_directory_not,
+ F_prohibited,
+ F_failure,
+ };
+
+ for (int i = 0; i < 13; ++i) {
+
+ will_return(__wrap_fcntl, true);
+ will_return(__wrap_fcntl, errnos[i]);
+
+ const f_status_t status = f_file_manipulate(file, 0, 0);
+
+ assert_int_equal(status, F_status_set_error(statuss[i]));
+ } // for
+ }
+}
+
+void test__f_file_manipulate__returns_file_descriptor_not(void **state) {
+
+ const f_file_t file = macro_f_file_t_initialize_2(F_type_output_d, -1, F_file_flag_write_only_d);
+
+ {
+ const f_status_t status = f_file_manipulate(file, 0, 0);
+
+ assert_int_equal(status, F_file_descriptor_not);
+ }
+}
+
+void test__f_file_manipulate__works(void **state) {
+
+ const f_file_t file = macro_f_file_t_initialize_2(F_type_output_d, F_type_descriptor_output_d, F_file_flag_write_only_d);
+
+ {
+
+ will_return(__wrap_fcntl, false);
+
+ const f_status_t status = f_file_manipulate(file, 0, 0);
+
+ assert_int_equal(status, F_none);
+ }
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * FLL - Level 0
+ *
+ * Project: File
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the file project.
+ */
+#ifndef _TEST__F_file_manipulate_h
+#define _TEST__F_file_manipulate_h
+
+/**
+ * Test that function fails.
+ *
+ * @see f_file_manipulate()
+ */
+extern void test__f_file_manipulate__fails(void **state);
+
+/**
+ * Test that function works but the descriptor is not valid.
+ *
+ * @see f_file_manipulate()
+ */
+extern void test__f_file_manipulate__returns_file_descriptor_not(void **state);
+
+/**
+ * Test that function works.
+ *
+ * @see f_file_manipulate()
+ */
+extern void test__f_file_manipulate__works(void **state);
+
+#endif // _TEST__F_file_manipulate_h
cmocka_unit_test(test__f_file_link_read_at__returns_file_descriptor_not),
cmocka_unit_test(test__f_file_link_read_at__works),
+ cmocka_unit_test(test__f_file_manipulate__fails),
+ cmocka_unit_test(test__f_file_manipulate__returns_file_descriptor_not),
+ cmocka_unit_test(test__f_file_manipulate__works),
+
cmocka_unit_test(test__f_file_mode_determine__works_basic),
cmocka_unit_test(test__f_file_mode_determine__works_basic_replace),
// f_file_link_hard_at() doesn't use parameter checking.
cmocka_unit_test(test__f_file_link_read__parameter_checking),
cmocka_unit_test(test__f_file_link_read_at__parameter_checking),
+ // f_file_manipulate() doesn't use parameter checking.
cmocka_unit_test(test__f_file_mode_determine__parameter_checking),
cmocka_unit_test(test__f_file_mode_from_string__parameter_checking),
cmocka_unit_test(test__f_file_mode_read__parameter_checking),
#include "test-file-link_hard_at.h"
#include "test-file-link_read.h"
#include "test-file-link_read_at.h"
+#include "test-file-manipulate.h"
#include "test-file-mode_determine.h"
#include "test-file-mode_from_string.h"
#include "test-file-mode_read.h"