File operations
Overview
Functions to operate the files. More…
// typedefs typedef te_errno te_file_scandir_callback( const char *pattern, const char *pathname, void *data ); // global functions char* te_basename(const char* pathname); char* te_readlink_fmt(const char* path_fmt, ...); char char* te_dirname(const char* pathname); char* te_file_join_filename(te_string* dest, const char* dirname, const char* path, const char* suffix); int te_file_create_unique_fd_va(char** filename, const char* prefix_format, const char* suffix, va_list ap); int te_file_create_unique_fd(char** filename, const char* prefix_format, const char* suffix, ...); int char* te_file_create_unique(const char* prefix_format, const char* suffix, ...); int char FILE* te_fopen_fmt(const char* mode, const char* path_fmt, ...); int char FILE pid_t te_file_read_pid(const char* pid_path); te_errno te_file_resolve_pathname_vec(const char* filename, const te_vec* pathvec, int mode, char** resolved); te_errno te_file_resolve_pathname(const char* filename, const char* path, int mode, const char* basename, char** resolved); te_errno te_file_check_executable(const char* path); te_errno te_access_fmt(int mode, const char* fmt, ...); te_errno te_errno te_unlink_fmt(const char* fmt, ...); te_errno te_errno te_errno te_file_read_string(te_string* dest, bool binary, size_t maxsize, const char* path_fmt, ...); te_errno te_errno te_errno te_errno te_file_write_string(const te_string* src, size_t fitlen, int flags, mode_t mode, const char* path_fmt, ...); te_errno te_errno te_errno te_errno te_errno te_file_read_text(const char* path, char* buffer, size_t bufsize); te_errno te_file_scandir(const char* dirname, te_file_scandir_callback* callback, void* data, const char* pattern_fmt, ...); te_errno char* te_file_extract_glob(const char* filename, const char* pattern, bool basename);
Detailed Documentation
Functions to operate the files.
Copyright (C) 2018-2023 OKTET Labs Ltd. All rights reserved.
Typedefs
typedef te_errno te_file_scandir_callback( const char *pattern, const char *pathname, void *data )
Function type for callbacks for te_file_scandir().
Parameters:
pattern |
pattern used to filter pathnames |
pathname |
full pathname of a current file |
data |
user data as passed to te_file_scandir(). |
TE_EOK |
The scanning would stop, but |
Returns:
status code
Global Functions
char* te_basename(const char* pathname)
Get a basename from pathname
, and check if it is valid. Unlike system basename() it does not modify the contents of pathname
Parameters:
pathname |
File pathname |
Returns:
A heap-allocated string containing an extracted file name, or NULL
if pathname
is invalid, or allocation fails
char* te_readlink_fmt(const char* path_fmt, ...)
Get a resolved link using path
.
Parameters:
path_fmt |
Path format string. |
… |
Format string arguments. |
Returns:
A heap-allocated string containing a resolved link, or NULL
if an error has occurred.
char char* te_dirname(const char* pathname)
Get a dirname from pathname
, and check if it is valid. Unlike system dirname() it does not modify the contents of pathname
Parameters:
pathname |
File pathname |
Returns:
A heap-allocated string containing an extracted directory name, or NULL
if pathname
is invalid, or allocation fails
char* te_file_join_filename(te_string* dest, const char* dirname, const char* path, const char* suffix)
Construct a filename from components.
Unlike te_file_resolve_pathname(), the function does a purely syntactic operation, so no checks are made that a pathname exists or is accessible. Therefore it is suitable for constructing filenames on one host that will be used on another.
The constructing algorithm is as follows:
if
path
isNULL
, it is treated as an empty string;if
dirname
isNULL
orpath
is an absolute path,path
is used as is;otherwise,
dirname
andpath
are joined using/
separator;then if
suffix
is notNULL
, it is appended to the filename obtained at the previous step; if that name ends with a/
, it is first stripped; i.e. a suffix never creates a new pathname component.
If dest
is NULL
, a fresh string is allocated and returned.
The name is appended to the string contents.
If dest
is not empty upon entry and dirname
is empty, an extra slash may be added before the resulting pathname.
Parameters:
dest |
the string to hold the name or |
dirname |
directory name |
path |
pathname (relative or absolute) |
suffix |
suffix |
Returns:
the pointer to the contents of dest
or a heap-allocated buffer
int te_file_create_unique_fd_va(char** filename, const char* prefix_format, const char* suffix, va_list ap)
Create a file of unique name. It builds a template of file name in mkstemps compatible format which has the form “prefixXXXXXXsuffix”, or “prefixXXXXXX” if suffix
is NULL
Parameters:
filename |
Name of created file. On success it should be freed with free(3) when it is no longer needed |
prefix_format |
Format string of filename prefix |
suffix |
Filename suffix, can be |
ap |
List of arguments |
Returns:
File descriptor of the created file, or -1
in case of error
See also:
te_file_create_unique_fd, te_file_create_unique
int te_file_create_unique_fd(char** filename, const char* prefix_format, const char* suffix, ...)
Create a file of unique name, see details in description of te_file_create_unique_fd_va()
Parameters:
filename |
Name of created file. On success it should be freed with free(3) when it is no longer needed |
prefix_format |
Format string of filename prefix |
suffix |
Filename suffix, can be |
… |
Format string arguments |
Returns:
File descriptor of the created file, or -1
in case of error
See also:
te_file_create_unique_fd_va, te_file_create_unique
int char* te_file_create_unique(const char* prefix_format, const char* suffix, ...)
Create a file of unique name, see details in description of te_file_create_unique_fd_va()
Return value should be freed with free(3) when it is no longer needed
Parameters:
prefix_format |
Format string of filename prefix |
suffix |
Filename suffix, can be |
… |
Format string arguments |
Returns:
Name of created file, or NULL
in case of error
See also:
te_file_create_unique_fd_va, te_file_create_unique_fd
int char FILE* te_fopen_fmt(const char* mode, const char* path_fmt, ...)
Call fopen() with a path specified by a format string and arguments.
Parameters:
mode |
Opening mode string. |
path_fmt |
File path format string. |
… |
Format string arguments. |
Returns:
FILE pointer on success, NULL
on failure.
int char FILE pid_t te_file_read_pid(const char* pid_path)
Read process identifier from PID file
Parameters:
pid_path |
Path to PID file |
Returns:
Process ID or -1
in case of error
te_errno te_file_resolve_pathname_vec(const char* filename, const te_vec* pathvec, int mode, char** resolved)
Search a relative filename in a vector of directories.
If the filename is absolute (i.e. starts with /
), it is checked and no search is performed.
Parameters:
filename |
Filename to check |
pathvec |
Vector of directories |
mode |
Access mode to check (as used by system access()) |
resolved |
A location for a resolved pathname (which must be free()’d. If |
Returns:
Status code (possible values match those reported by access())
te_errno te_file_resolve_pathname(const char* filename, const char* path, int mode, const char* basename, char** resolved)
Search a relative filename in a colon-separated list of directories.
The function is like te_file_resolve_pathname_vec(), only it takes a colon-separated string for a path instead of a prepared vector.
Parameters:
filename |
Filename to check |
path |
Colon-separated list of directories |
mode |
Access mode to check (as used by system access()) |
basename |
If not |
resolved |
A location for a resolved pathname (which must be free()’d. If |
Returns:
Status code (possible values match those reported by access())
te_errno te_file_check_executable(const char* path)
Check that the file is executable
If path
does’t contains ‘/’ then path
is concatenated with the environment variable PATH. Otherwise, we are looking for a file from the current location
Parameters:
path |
Path to the file |
Returns:
Status code
te_errno te_access_fmt(int mode, const char* fmt, ...)
Check that a filename is accessible for a given mode
.
The filename is constructed from the format string and arguments.
Parameters:
mode |
access mode (see system access()) |
fmt |
format string |
… |
arguments |
TE_EACCESS |
Access to the file is denied |
TE_ENOENT |
The file or any of its parents does not exist |
Returns:
status code
te_errno te_errno te_unlink_fmt(const char* fmt, ...)
Delete a file.
The filename is constructed from the format string and arguments.
Parameters:
fmt |
format string |
… |
arguments |
TE_ENOENT |
The file or any of its parents does not exist. |
Returns:
status code
te_errno te_errno te_errno te_file_read_string(te_string* dest, bool binary, size_t maxsize, const char* path_fmt, ...)
Read the contents of the file into a dynamic string dest
.
If binary
is false
, the function ensures that there is no embedded zeroes in the file content and strips off trailing newlines if there are any.
If maxsize
is not zero, the function ensures that the file size is not greater than it. That allows to avoid crashes if dest
is a statically allocated TE string and in general to prevent memory bombs if a file comes from an untrusted source.
The function should be used with caution on non-regular files such as named FIFOs or character devices, as it may block indefinitely or return partial data. Using it with regular files on special filesystems such as /proc
is completely reliable.
Parameters:
dest |
TE string (the content of the file will be appended to it) |
binary |
reading mode (binary or text mode) |
maxsize |
the maximum allowed file size, if not zero |
path_fmt |
pathname format string |
… |
arguments |
TE_EFBIG |
The file size is larger than |
TE_EILSEQ |
The file contains embedded zeroes and |
Returns:
status code
te_errno te_errno te_errno te_errno te_file_write_string(const te_string* src, size_t fitlen, int flags, mode_t mode, const char* path_fmt, ...)
Write the contents of the file from a dynamic string src
.
The file is opened with POSIX flags
ORed with O_WRONLY
and if the file is created, then access mode
will be set on it.
If fitlen
is not zero, the resulting file will be exactly that long:
if
src
is longer thanfitlen
, it will be truncated;if
src
is shorter, it will be repeated until the length is reached.
Parameters:
src |
source TE string |
fitlen |
desired file length (ignored if zero) |
flags |
POSIX open flags, such as |
mode |
POSIX access mode for newly created files |
path_fmt |
pathname format string |
… |
arguments |
Returns:
status code
te_errno te_errno te_errno te_errno te_errno te_file_read_text(const char* path, char* buffer, size_t bufsize)
Read the contents of the file path
into buffer
.
The function ensures that the contents of the file is no larger than bufsize
minus one and that the contents contain no embedded zeroes. The resulting string will be zero-terminated. If there are trailing newlines, they are stripped off.
The file should be random-access, so the function cannot read from sockets, named FIFOs and most kinds of character devices.
Deprecated Prefer te_file_read_string().
Parameters:
path |
Pathname to read |
buffer |
Destination buffer |
bufsize |
The size of |
TE_EFBIG |
The file size is larger than |
TE_EILSEQ |
The file contains embedded zeroes |
Returns:
Status code
te_errno te_file_scandir(const char* dirname, te_file_scandir_callback* callback, void* data, const char* pattern_fmt, ...)
Call callback
for each file in dirname
matching a pattern.
Special entries ``. and ``
.. are always skipped.
The callback is passed a concatenation of a dirname
and the basename of the current file, not just the basename as scandir() would do.
If the callback returns non-zero, the scanning stop and the result value is passed upstream, but if it is TE_EOK
, zero would be returned.
pattern_fmt
may be NULL
, in which case no arguments shall be be provided and all files in dirname
will be processed.
Parameters:
dirname |
directory to scan |
callback |
the callback |
data |
user data passed to |
pattern_fmt |
glob-style pattern format |
… |
arguments |
Returns:
status code
te_errno char* te_file_extract_glob(const char* filename, const char* pattern, bool basename)
Extract a varying part of a filename
matching pattern
.
Only a limited subset of globs is supported, namely it must contain exactly one *
wildcard, otherwise a fatal error is reported.
Parameters:
filename |
filename |
pattern |
glob pattern with a single |
basename |
if |
Returns:
the varying part of the filename (must be free()’d) or NULL
if filename
does not match a pattern
.