memset(&stat_file, 0, sizeof(struct stat));
{
- const f_status_t status = private_f_file_stat_at(at_id, path, F_true, &stat_file);
+ const f_status_t status = private_f_file_stat_at(at_id, path, flag, &stat_file);
if (F_status_is_error(status)) return status;
}
}
#endif // _di_f_file_stream_close_
-#ifndef _di_f_file_stream_open_descriptor_
- f_status_t f_file_stream_open_descriptor(const f_string_static_t mode, f_file_t * const file) {
+#ifndef _di_f_file_stream_open_
+ f_status_t f_file_stream_open(const f_string_static_t path, const f_string_static_t mode, f_file_t * const file) {
#ifndef _di_level_0_parameter_checking_
if (!file) return F_status_set_error(F_parameter);
#endif // _di_level_0_parameter_checking_
- if (file->id == -1) {
- return F_status_set_error(F_file_descriptor);
+ if (!path.used) {
+ return F_data_not;
}
if (mode.used) {
- file->stream = fdopen(file->id, private_f_file_stream_open_mode_determine(file->flag));
+ file->stream = fopen(path.string, mode.string);
}
else {
- file->stream = fdopen(file->id, mode.string);
+ file->stream = fopen(path.string, private_f_file_stream_open_mode_determine(file->flag));
}
if (!file->stream) {
if (errno == EACCES) return F_status_set_error(F_access_denied);
- if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block);
- if (errno == EBADF) return F_status_set_error(F_file_descriptor);
- if (errno == EFBIG) return F_status_set_error(F_file_overflow);
- if (errno == EDEADLK) return F_status_set_error(F_deadlock);
- if (errno == EDESTADDRREQ) return F_status_set_error(F_socket_not);
- if (errno == EDQUOT) return F_status_set_error(F_space_not);
+ 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 == EFBIG || errno == EOVERFLOW) return F_status_set_error(F_number_overflow);
if (errno == EINTR) return F_status_set_error(F_interrupt);
if (errno == EINVAL) return F_status_set_error(F_parameter);
- if (errno == EIO) return F_status_set_error(F_input_output);
- if (errno == EMFILE) return F_status_set_error(F_file_descriptor_max);
- if (errno == ENODEV) return F_status_set_error(F_device_not);
- if (errno == ENOLCK) return F_status_set_error(F_lock);
+ if (errno == ELOOP) return F_status_set_error(F_loop);
+ if (errno == ENFILE) return F_status_set_error(F_file_open_max);
+ if (errno == ENOENT) return F_status_set_error(F_file_found_not);
+ if (errno == ENOTDIR) return F_status_set_error(F_file_type_not_directory);
if (errno == ENOMEM) return F_status_set_error(F_memory_not);
if (errno == ENOSPC) return F_status_set_error(F_space_not);
- if (errno == ENOTDIR) return F_status_set_error(F_file_type_not_directory);
if (errno == EPERM) return F_status_set_error(F_prohibited);
- if (errno == EPIPE) return F_status_set_error(F_pipe_not);
+ if (errno == EROFS) return F_status_set_error(F_read_only);
+ if (errno == ETXTBSY) return F_status_set_error(F_busy);
+ if (errno == EISDIR) return F_status_set_error(F_directory);
+ if (errno == EOPNOTSUPP) return F_status_set_error(F_supported_not);
return F_status_set_error(F_failure);
}
+ file->id = fileno(file->stream);
+
+ if (file->id == -1) {
+ return F_status_set_error(F_file_descriptor);
+ }
+
return F_none;
}
-#endif // _di_f_file_stream_open_descriptor_
+#endif // _di_f_file_stream_open_
-#ifndef _di_f_file_stream_open_
- f_status_t f_file_stream_open(const f_string_static_t path, const f_string_static_t mode, f_file_t * const file) {
+#ifndef _di_f_file_stream_open_descriptor_
+ f_status_t f_file_stream_open_descriptor(const f_string_static_t mode, f_file_t * const file) {
#ifndef _di_level_0_parameter_checking_
if (!file) return F_status_set_error(F_parameter);
#endif // _di_level_0_parameter_checking_
+ if (file->id == -1) {
+ return F_status_set_error(F_file_descriptor);
+ }
+
if (mode.used) {
- file->stream = fopen(path.string, mode.string);
+ file->stream = fdopen(file->id, private_f_file_stream_open_mode_determine(file->flag));
}
else {
- file->stream = fopen(path.string, private_f_file_stream_open_mode_determine(file->flag));
+ file->stream = fdopen(file->id, mode.string);
}
if (!file->stream) {
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 == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block);
+ if (errno == EBADF) return F_status_set_error(F_file_descriptor);
+ if (errno == EFBIG) return F_status_set_error(F_file_overflow);
+ if (errno == EDEADLK) return F_status_set_error(F_deadlock);
+ if (errno == EDESTADDRREQ) return F_status_set_error(F_socket_not);
+ if (errno == EDQUOT) return F_status_set_error(F_space_not);
if (errno == EFAULT) return F_status_set_error(F_buffer);
- if (errno == EFBIG || errno == EOVERFLOW) return F_status_set_error(F_number_overflow);
if (errno == EINTR) return F_status_set_error(F_interrupt);
if (errno == EINVAL) return F_status_set_error(F_parameter);
- if (errno == ELOOP) return F_status_set_error(F_loop);
- if (errno == ENFILE) return F_status_set_error(F_file_open_max);
- if (errno == ENOENT) return F_status_set_error(F_file_found_not);
- if (errno == ENOTDIR) return F_status_set_error(F_file_type_not_directory);
+ if (errno == EIO) return F_status_set_error(F_input_output);
+ if (errno == EMFILE) return F_status_set_error(F_file_descriptor_max);
+ if (errno == ENODEV) return F_status_set_error(F_device_not);
+ if (errno == ENOLCK) return F_status_set_error(F_lock);
if (errno == ENOMEM) return F_status_set_error(F_memory_not);
if (errno == ENOSPC) return F_status_set_error(F_space_not);
+ if (errno == ENOTDIR) return F_status_set_error(F_file_type_not_directory);
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);
- if (errno == EISDIR) return F_status_set_error(F_directory);
- if (errno == EOPNOTSUPP) return F_status_set_error(F_supported_not);
+ if (errno == EPIPE) return F_status_set_error(F_pipe_not);
return F_status_set_error(F_failure);
}
- file->id = fileno(file->stream);
-
- if (file->id == -1) {
- return F_status_set_error(F_file_descriptor);
- }
-
return F_none;
}
-#endif // _di_f_file_stream_open_
+#endif // _di_f_file_stream_open_descriptor_
#ifndef _di_f_file_stream_read_
f_status_t f_file_stream_read(const f_file_t file, f_string_dynamic_t * const buffer) {
return F_status_set_error(F_file_closed);
}
+ if (!total) {
+ return F_none_stop;
+ }
+
flockfile(file.stream);
if (feof_unlocked(file.stream)) {
if (!file) return F_status_set_error(F_parameter);
#endif // _di_level_0_parameter_checking_
- if (!path.used) {
+ if (!path.used && !mode.used) {
return F_data_not;
}
FILE *result = 0;
if (mode.used) {
- result = freopen(path.string, mode.string, file->stream);
+ result = freopen(path.used ? path.string : 0, mode.string, file->stream);
}
else {
- result = freopen(path.string, private_f_file_stream_open_mode_determine(file->flag), file->stream);
+ result = freopen(path.used ? path.string : 0, private_f_file_stream_open_mode_determine(file->flag), file->stream);
}
if (!result) {
return F_status_set_error(F_failure);
}
+ file->stream = result;
file->id = fileno(file->stream);
if (file->id == -1) {
f_status_t status = F_none;
if (written) {
- private_f_file_stream_write_until(file, buffer, buffer.used, written);
+ status = private_f_file_stream_write_until(file, buffer, buffer.used, written);
if (status == F_none && *written == buffer.used) {
return F_none_eos;
else {
f_array_length_t written_local = 0;
- private_f_file_stream_write_until(file, buffer, buffer.used, &written_local);
+ status = private_f_file_stream_write_until(file, buffer, buffer.used, &written_local);
if (status == F_none && written_local == buffer.used) {
return F_none_eos;
}
}
- if (F_status_is_error(status)) {
- return F_status_set_error(status);
- }
-
return status;
}
#endif // _di_f_file_stream_write_
f_status_t status = F_none;
if (written) {
- private_f_file_stream_write_until(file, buffer, write_max, written);
+ status = private_f_file_stream_write_until(file, buffer, write_max, written);
if (status == F_none) {
if (*written == buffer.used) {
else {
f_array_length_t written_local = 0;
- private_f_file_stream_write_until(file, buffer, write_max, &written_local);
+ status = private_f_file_stream_write_until(file, buffer, write_max, &written_local);
if (status == F_none) {
if (written_local == buffer.used) {
f_status_t status = F_none;
if (written) {
- private_f_file_stream_write_until(file, buffer, write_max, written);
+ status = private_f_file_stream_write_until(file, buffer, write_max, written);
if (status == F_none) {
if (*written == buffer.used) {
else {
f_array_length_t written_local = 0;
- private_f_file_stream_write_until(file, buffer, buffer.used, &written_local);
+ status = private_f_file_stream_write_until(file, buffer, buffer.used, &written_local);
if (status == F_none) {
if (written_local == buffer.used) {
if (written) {
const f_string_static_t buffer_adjusted = macro_f_string_static_t_initialize(buffer.string + range.start, 0, buffer.used - range.start);
- flockfile(file.stream);
-
- private_f_file_stream_write_until(file, buffer_adjusted, write_max, written);
-
- funlockfile(file.stream);
+ status = private_f_file_stream_write_until(file, buffer_adjusted, write_max, written);
if (status == F_none) {
if (range.start + *written == buffer.used) {
const f_string_static_t buffer_adjusted = macro_f_string_static_t_initialize(buffer.string + range.start, 0, buffer.used - range.start);
f_array_length_t written_local = 0;
- flockfile(file.stream);
-
- private_f_file_stream_write_until(file, buffer_adjusted, write_max, &written_local);
-
- funlockfile(file.stream);
+ status = private_f_file_stream_write_until(file, buffer_adjusted, write_max, &written_local);
if (status == F_none) {
if (range.start + written_local == buffer.used) {
memset(&stat_file, 0, sizeof(struct stat));
- status = private_f_file_stat(path, F_false, &stat_file);
+ status = private_f_file_stat(path, dereference, &stat_file);
if (F_status_set_fine(status) == F_file_found_not) {
return private_f_file_create(path, mode, dereference);
#endif // _di_f_file_touch_at_
#ifndef _di_f_file_type_
- f_status_t f_file_type(const f_string_static_t path, int * const type) {
+ f_status_t f_file_type(const f_string_static_t path, const bool dereference, int * const type) {
#ifndef _di_level_0_parameter_checking_
if (!type) return F_status_set_error(F_parameter);
#endif // _di_level_0_parameter_checking_
memset(&stat_file, 0, sizeof(struct stat));
- if (stat(path.string, &stat_file) < 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_not);
- if (errno == EOVERFLOW) return F_status_set_error(F_number_overflow);
- if (errno == ENOTDIR) return F_status_set_error(F_directory_not);
- 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);
-
- return F_status_set_error(F_file_stat);
+ {
+ const f_status_t status = private_f_file_stat(path, dereference, &stat_file);
+ if (F_status_is_error(status)) return status;
}
*type = macro_f_file_type_get(stat_file.st_mode);
memset(&stat_file, 0, sizeof(struct stat));
- if (fstatat(at_id, path.string, &stat_file, 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 == ENAMETOOLONG) return F_status_set_error(F_name);
- if (errno == ENOENT) return F_file_found_not;
- if (errno == ENOMEM) return F_status_set_error(F_memory_not);
- if (errno == ENOTDIR) return F_status_set_error(F_directory_not);
- if (errno == EOVERFLOW) return F_status_set_error(F_number_overflow);
- if (errno == ELOOP) return F_status_set_error(F_loop);
-
- return F_status_set_error(F_file_stat);
+ {
+ const f_status_t status = private_f_file_stat_at(at_id, path, flag, &stat_file);
+ if (F_status_is_error(status)) return status;
}
*type = macro_f_file_type_get(stat_file.st_mode);
#endif // _di_f_file_stream_close_
/**
- * Open a file stream from a file descriptor.
- *
- * @param mode
- * The file modes do use when opening.
- * Set mode.used to 0 to determine mode from file.flags (falling back to read only as a failsafe).
- * If neither truncate nor append are not specified in write only mode, then the failsafe is to append.
- * This should match the modes used to open the file descriptor as it relates to the stream modes.
- * @param file
- * The file with a valid file descriptor (file.id).
- * THe file stream (file.stream) is updated on success, but may be set to NULL on error.
- *
- * @return
- * F_none is returned on success.
- *
- * F_access_denied (with error bit) on access denied.
- * F_block (with error bit) if the action would block and non-blocking is set on the stream.
- * F_buffer (with error bit) if the buffer is invalid.
- * F_deadlock (with error bit) if operation would cause a deadlock.
- * 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_file_overflow (with error bit) if the write exceeds some implementation defined maximum file size.
- * F_file_type_not_directory (with error bit) if F_NOTIFY was specified and file.id is not a directory.
- * 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_pipe_not (with error bit) if the stream is a pipe or a socket but the pipe or socket is already closed.
- * F_prohibited (with error bit) if file system does not allow for making changes.
- * F_socket_not (with error bit) if socket is not connected.
- * F_space_not (with error bit) if the file system is out of space (or file system quota is reached).
- *
- * @see fdopen()
- */
-#ifndef _di_f_file_stream_open_descriptor_
- extern f_status_t f_file_stream_open_descriptor(const f_string_static_t mode, f_file_t * const file);
-#endif // _di_f_file_stream_open_descriptor_
-
-/**
* Open a file stream.
*
* The file descriptor is retrieved on success, if necessary and able.
*
+ * If the file stream is open, it is closed before re-opening.
+ *
+ * This is often used for changing the file pointed to by standard streams such as stdout.
+ *
* @param path
- * The file path
+ * The file path.
* @param mode
* The file modes do use when opening, as an fopen() file mode string.
* Set mode.used to 0 to determine mode from file.flags (falling back to read only as a failsafe).
*
* @return
* F_none is returned on success.
+ * F_data_not if both path.used is 0.
*
* F_access_denied (with error bit) on access denied.
* F_buffer (with error bit) if the buffer is invalid.
#endif // _di_f_file_stream_open_
/**
+ * Open a file stream from a file descriptor.
+ *
+ * @param mode
+ * The file modes do use when opening.
+ * Set mode.used to 0 to determine mode from file.flags (falling back to read only as a failsafe).
+ * If neither truncate nor append are not specified in write only mode, then the failsafe is to append.
+ * This should match the modes used to open the file descriptor as it relates to the stream modes.
+ * @param file
+ * The file with a valid file descriptor (file.id).
+ * THe file stream (file.stream) is updated on success, but may be set to NULL on error.
+ *
+ * @return
+ * F_none is returned on success.
+ *
+ * F_access_denied (with error bit) on access denied.
+ * F_block (with error bit) if the action would block and non-blocking is set on the stream.
+ * F_buffer (with error bit) if the buffer is invalid.
+ * F_deadlock (with error bit) if operation would cause a deadlock.
+ * 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_file_overflow (with error bit) if the write exceeds some implementation defined maximum file size.
+ * F_file_type_not_directory (with error bit) if F_NOTIFY was specified and file.id is not a directory.
+ * 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_pipe_not (with error bit) if the stream is a pipe or a socket but the pipe or socket is already closed.
+ * F_prohibited (with error bit) if file system does not allow for making changes.
+ * F_socket_not (with error bit) if socket is not connected.
+ * F_space_not (with error bit) if the file system is out of space (or file system quota is reached).
+ *
+ * @see fdopen()
+ */
+#ifndef _di_f_file_stream_open_descriptor_
+ extern f_status_t f_file_stream_open_descriptor(const f_string_static_t mode, f_file_t * const file);
+#endif // _di_f_file_stream_open_descriptor_
+
+/**
* Read until EOF is reached.
*
* To check how much was read into the buffer, record buffer->used before execution and compare to buffer->used after execution.
* The file descriptor is retrieved on success, if necessary and able.
*
* @param path
- * The file path
+ * The file path.
+ * Set path.used to 0 with a non-empty mode (mode.used > 0) to only change the mode of the existing stream.
* @param mode
* The file modes do use when opening.
* Set to 0 to determine mode from file.flags (falling back to read only as a failsafe).
*
* @return
* F_none is returned on success.
+ * F_data_not if both path.used and mode.used are 0.
*
* F_access_denied (with error bit) on access denied.
* F_buffer (with error bit) if the buffer is invalid.
* F_interrupt (with error bit) if interrupt was received.
* F_parameter (with error bit) if a parameter is invalid.
*
- * @see fwrite()
+ * F_file_write (with error bit) on any other error.
+ *
+ * @see flockfile()
+ * @see fwrite_unlocked()
+ * @see ferror_unlocked()
+ * @see funlockfile()
*/
#ifndef _di_f_file_stream_write_
extern f_status_t f_file_stream_write(const f_file_t file, const f_string_static_t buffer, f_array_length_t * const written);
* F_interrupt (with error bit) if interrupt was received.
* F_parameter (with error bit) if a parameter is invalid.
*
- * @see fwrite()
+ * F_file_write (with error bit) on any other error.
+ *
+ * @see flockfile()
+ * @see fwrite_unlocked()
+ * @see ferror_unlocked()
+ * @see funlockfile()
*/
#ifndef _di_f_file_stream_write_block_
extern f_status_t f_file_stream_write_block(const f_file_t file, const f_string_static_t buffer, f_array_length_t * const written);
* F_interrupt (with error bit) if interrupt was received.
* F_parameter (with error bit) if a parameter is invalid.
*
- * @see fwrite()
+ * F_file_write (with error bit) on any other error.
+ *
+ * @see flockfile()
+ * @see fwrite_unlocked()
+ * @see ferror_unlocked()
+ * @see funlockfile()
*/
#ifndef _di_f_file_stream_write_until_
extern f_status_t f_file_stream_write_until(const f_file_t file, const f_string_static_t buffer, const f_array_length_t total, f_array_length_t * const written);
*
* @param path
* The path file name.
+ * @param dereference
+ * Set to TRUE to dereference symlinks (often is what is desired).
+ * Set to FALSE to operate on the symlink itself.
* @param type
* The type of the file.
*
* @see stat()
*/
#ifndef _di_f_file_type_
- extern f_status_t f_file_type(const f_string_static_t path, int * const type);
+ extern f_status_t f_file_type(const f_string_static_t path, const bool dereference, int * const type);
#endif // _di_f_file_type_
/**