mirror of https://gitea.it/1414codeforge/ubgpsuite
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
254 lines
8.8 KiB
C
254 lines
8.8 KiB
C
3 years ago
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||
|
|
||
|
/**
|
||
|
* \file sys/fs.h
|
||
|
*
|
||
|
* Portable low-level filesystem layer
|
||
|
*
|
||
|
* \copyright The DoubleFourteen Code Forge (C) All Rights Reserved
|
||
|
* \author Lorenzo Cogotti
|
||
|
*
|
||
|
* Achieves portable low-level, close to operating system, filesystem
|
||
|
* functionality. Functionality includes:
|
||
|
* - file I/O
|
||
|
* - file usage hints
|
||
|
* - file creation and removal
|
||
|
* - directory listing, creation and removal
|
||
|
* - path utilities.
|
||
|
*
|
||
|
* No library file buffering is attempted, nor any kind of text-based I/O.
|
||
|
* Paths are UTF-8.
|
||
|
*/
|
||
|
|
||
|
#ifndef DF_SYS_FS_H_
|
||
|
#define DF_SYS_FS_H_
|
||
|
|
||
|
#include "sys/fsdef.h" // platform-specific defs, including `Fildes`
|
||
|
|
||
|
/// File access mode for `Sys_Fopen()`.
|
||
|
typedef enum {
|
||
|
FM_READ, ///< Read-only access
|
||
|
FM_WRITE, ///< Write-only access
|
||
|
FM_APPEND, ///< File-append access
|
||
|
FM_EXCL, ///< Exclusive creation access
|
||
|
FM_TEMP ///< Temporary scratch file creation
|
||
|
} FopenMode;
|
||
|
|
||
|
/// Access pattern is sequential.
|
||
|
#define FH_SEQ BIT(0)
|
||
|
/// Access pattern is random.
|
||
|
#define FH_RAND BIT(1)
|
||
|
/// Avoid filesystem cache buffers with this file.
|
||
|
#define FH_UNBUF BIT(2)
|
||
|
/// File data is accessed once and never reused.
|
||
|
#define FH_NOREUSE BIT(3)
|
||
|
|
||
|
/**
|
||
|
* \brief Open a descriptor handle to a regular or special file.
|
||
|
*
|
||
|
* Every successfully opened file descriptor must be closed using
|
||
|
* `Sys_Fclose()` when no longer necessary.
|
||
|
*
|
||
|
* \param [in] filename Path to file, must not be `NULL`
|
||
|
* \param [in] mode File access mode
|
||
|
* \param [in] hints File access hints (`FH_*` bit mask)
|
||
|
*
|
||
|
* \return Opened file descriptor on success, `FILDES_BAD` on failure.
|
||
|
*/
|
||
|
Fildes Sys_Fopen(const char *filename, FopenMode mode, unsigned hints);
|
||
|
/**
|
||
|
* \brief Move file's cursor to the specified offset.
|
||
|
*
|
||
|
* \param [in] fd Opened file descriptor
|
||
|
* \param [in] offset Offset to move the cursor to, according to `whence`, in bytes
|
||
|
* \param [in] whence Seek mode
|
||
|
*
|
||
|
* \return New cursor position on success, -1 on failure or non-seekable file.
|
||
|
*/
|
||
|
Sint64 Sys_Fseek(Fildes fd, Sint64 offset, SeekMode whence);
|
||
|
/// Retrieve current file cursor position, returns -1 on failure or non-seekable file.
|
||
|
Sint64 Sys_Ftell(Fildes fd);
|
||
|
/// Get current file size, in bytes, -1 on error.
|
||
|
Sint64 Sys_FileSize(Fildes fd);
|
||
|
/**
|
||
|
* \brief Write raw bytes to file.
|
||
|
*
|
||
|
* \param [in] fd Opened, writable, file descriptor
|
||
|
* \param [in] buf Containing at least `nbytes` bytes of data
|
||
|
* \param [in] nbytes Bytes count in `buf` to be written to `fd`
|
||
|
*
|
||
|
* \return Number of bytes actually written on `fd`, possibly less
|
||
|
* than `nbytes` on short-write. -1 on failure.
|
||
|
*/
|
||
|
Sint64 Sys_Fwrite(Fildes fd, const void *buf, size_t nbytes);
|
||
|
/**
|
||
|
* \brief Read raw bytes from file.
|
||
|
*
|
||
|
* \param [in] fd Opened, readable, file descriptor
|
||
|
* \param [out] buf Destination buffer for the read operation
|
||
|
* \param [in] nbytes Bytes count to read from `fd` inside `buf`
|
||
|
*
|
||
|
* \return Number of bytes actually read from `fd`, possibly less than `nbytes`,
|
||
|
* 0 is returned on `EOF` condition. -1 on failure.
|
||
|
*/
|
||
|
Sint64 Sys_Fread(Fildes fd, void *buf, size_t nbytes);
|
||
|
/**
|
||
|
* \brief Truncate or grow file size to its current cursor position.
|
||
|
*
|
||
|
* \return `OK` on success, and file is altered as follows,
|
||
|
* - if file size has been truncated excess data is lost;
|
||
|
* - if file has grown in size (file cursor was beyond the original size),
|
||
|
* new content is unspecified.
|
||
|
* On failure returns `NG` and file is unaltered.
|
||
|
*/
|
||
|
Judgement Sys_SetEof(Fildes fd);
|
||
|
/**
|
||
|
* \brief Synchronize file data to disk, flushing buffers.
|
||
|
*
|
||
|
* Some systems require `fd` to be writable, whether `Sys_Fsync()` supports
|
||
|
* a read-only descriptor is system specific.
|
||
|
* Some systems allow optimized syncs that only guarantee read operations
|
||
|
* consistency afterwards, this optimization is used on such systems when
|
||
|
* `fullSync` is `FALSE`. otherwise `fullSync` is ignored (as if always `TRUE`).
|
||
|
* A call to `Sys_Fsync()` with `fullSync` to `TRUE` causes the system
|
||
|
* to sync disk data with `fd` in its entirety.
|
||
|
*
|
||
|
* \param [in] fd Opened file descriptor
|
||
|
* \param [in] fullSync Whether a full sync should occur
|
||
|
*
|
||
|
* \return `OK` on success, `NG` on failure or on systems where
|
||
|
* there is no mean to force file data sync with disk.
|
||
|
*/
|
||
|
Judgement Sys_Fsync(Fildes fd, Boolean fullSync);
|
||
|
/// Close opened file descriptor.
|
||
|
void Sys_Fclose(Fildes fd);
|
||
|
|
||
|
/**
|
||
|
* \brief List directory contents.
|
||
|
*
|
||
|
* `pat` | Meaning
|
||
|
* ---------|------------------------------------------
|
||
|
* __NULL__ | Equivalent to `""`
|
||
|
* "" | No filtering
|
||
|
* / | Only return subdirectories
|
||
|
* .* | Only return files whose extension matches
|
||
|
*
|
||
|
* \param [in] path Path to directory, must not be `NULL`
|
||
|
* \param [out] nfiles Location to store returned file count, may be `NULL` if unimportant
|
||
|
* \param [in] pat Optional pattern to filter directory files, may be `NULL`
|
||
|
*
|
||
|
* \return `malloc()`ed string list containing matching files,
|
||
|
* must be `free()`d by the caller when no longer necessary.
|
||
|
* A single `free()` on the returned list is sufficient to
|
||
|
* release it entirely.
|
||
|
*/
|
||
|
char **Sys_ListFiles(const char *path, unsigned *nfiles, const char *pat);
|
||
|
|
||
|
/**
|
||
|
* \brief Create directory.
|
||
|
*
|
||
|
* \param [in] path Directory creation path, must not be `NULL`
|
||
|
*
|
||
|
* \return `OK` on success, and directory is created.
|
||
|
* Creating already existing directories is a success.
|
||
|
* `NG` on failure.
|
||
|
*/
|
||
|
Judgement Sys_Mkdir(const char *path);
|
||
|
|
||
|
/**
|
||
|
* \brief Rename a file.
|
||
|
*
|
||
|
* Different systems may impose different restrictions on
|
||
|
* rename operations, in particular when the operation crosses
|
||
|
* different devices in the filesystem.
|
||
|
* The only portable and safe way to rename a file (or, in this
|
||
|
* specific scenario, *move* it) is copying it over `newPath`,
|
||
|
* and remove `path` on success, but the basic `rename` operation is
|
||
|
* usually safe, unexpensive and atomic under the same device.
|
||
|
* `Sys_Rename()` works on directories as well.
|
||
|
*
|
||
|
* \param [in] path Path to the file to be renamed, must not be `NULL`
|
||
|
* \param [in] newPath New name for the file, destination directory must exist
|
||
|
*
|
||
|
* \return `OK` on success, `NG` otherwise.
|
||
|
*/
|
||
|
Judgement Sys_Rename(const char *path, const char *newPath);
|
||
|
/**
|
||
|
* \brief Remove a file or empty directory.
|
||
|
*
|
||
|
* \param [in] path Path to file or directory to be removed, must not be `NULL`
|
||
|
*
|
||
|
* \return `OK` on success, `NG` otherwise.
|
||
|
*/
|
||
|
Judgement Sys_Remove(const char *path);
|
||
|
|
||
|
// Path utilities
|
||
|
|
||
|
/// Retrieve the absolute file extension (leftmost not leading dot in basename).
|
||
|
char *Sys_GetAbsoluteFileExtension(const char *path);
|
||
|
/// Retrieve the file extension (rightmost not leading dot in basename).
|
||
|
char *Sys_GetFileExtension(const char *path);
|
||
|
/**
|
||
|
* \brief Set `path` file extension to `ext`.
|
||
|
*
|
||
|
* \param [in,out] path UTF-8 path, must not be `NULL`
|
||
|
* \param [in] ext File extension, including dot, must not be `NULL`
|
||
|
*
|
||
|
* \return Pointer to the extension inside `path`.
|
||
|
*
|
||
|
* \note Assumes `path` is is large enough to hold the result.
|
||
|
*/
|
||
|
char *Sys_SetFileExtension(char *path, const char *ext);
|
||
|
/**
|
||
|
* \brief Removes extension from `path` if it matches `ext`.
|
||
|
*
|
||
|
* \param [in,out] path UTF-8 path, must not be `NULL`
|
||
|
* \param [in] ext File extension, including dot, leave to `""` or `NULL`
|
||
|
* to remove any extension
|
||
|
*
|
||
|
* \return Length of the resulting path, in chars.
|
||
|
*/
|
||
|
size_t Sys_StripFileExtension(char *path, const char *ext);
|
||
|
/**
|
||
|
* \brief If file in `path` has no extension yet, set it to `ext`.
|
||
|
*
|
||
|
* \param [in,out] path UTF-8 path, must not be `NULL`
|
||
|
* \param [in] ext Default extension to be set, including dot, must not be `NULL`
|
||
|
*
|
||
|
* \return Pointer to the extension inside `path`
|
||
|
*
|
||
|
* \note Assums `path` is large enough to hold the result.
|
||
|
*/
|
||
|
char *Sys_DefaultFileExtension(char *path, const char *ext);
|
||
|
/**
|
||
|
* Strip initial portion of `path` if it matches `basePath`.
|
||
|
*
|
||
|
* \param [in,out] path UTF-8 path, must not be `NULL`
|
||
|
* \param [in] basePath Initial path to be removed, use `""` or `NULL` to strip the entire path and leave only file (Unix `basename()`)
|
||
|
*
|
||
|
* \return Length of the resulting path, in chars.
|
||
|
*/
|
||
|
size_t Sys_StripPath(char *path, const char *basePath);
|
||
|
/// Return `path` depth (number of path components).
|
||
|
size_t Sys_PathDepth(const char *path);
|
||
|
|
||
|
/**
|
||
|
* \brief Strip leading slashes and change any path separator to `/`.
|
||
|
*
|
||
|
* \return Resulting path length, in chars.
|
||
|
*/
|
||
|
size_t Sys_ConvertPath(char *path);
|
||
|
/**
|
||
|
* \brief Change any path separator to a single `PATH_SEP`.
|
||
|
*
|
||
|
* \return Resulting path length, in chars.
|
||
|
*/
|
||
|
size_t Sys_ReplaceSeps(char *path);
|
||
|
|
||
|
/// Case-sensitive UTF-8 path comparison, regardless of separators.
|
||
|
int Sys_PathCompare(const char *a, const char *b);
|
||
|
// XXX int Sys_PathCompareNoCase(const char *a, const char *b);
|
||
|
// XXX int Sys_PathCompareNoCaseAscii(const char *a, const char *b);
|
||
|
|
||
|
#endif
|