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 0 would be returned by te_file_scandir().

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 is NULL, it is treated as an empty string;

  • if dirname is NULL or path is an absolute path, path is used as is;

  • otherwise, dirname and path are joined using / separator;

  • then if suffix is not NULL, 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 NULL.

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 NULL

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 NULL

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 NULL

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 NULL, the function just checks the presence of filename somewhere in the path.

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 NULL, filename is first looked up in a directory part of basename (i.e. if basename points to a directory, it is used, otherwise the result of dirname() is used).

resolved

A location for a resolved pathname (which must be free()’d. If NULL, the function just checks the presence of filename somewhere in the path.

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 maxsize.

TE_EILSEQ

The file contains embedded zeroes and binary is false.

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 than fitlen, 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 O_CREAT

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 buffer including terminating zero.

TE_EFBIG

The file size is larger than bufsize

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 callback

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 true, only the basename of filename is used for matching.

Returns:

the varying part of the filename (must be free()’d) or NULL if filename does not match a pattern.