feat(fs): make and delete temp directories

This commit is contained in:
maelstrom 2026-05-21 20:18:56 +02:00
commit 5afb5cd843
9 changed files with 168 additions and 12 deletions

View file

@ -1,3 +1,4 @@
add_library(onus_common INTERFACE)
add_library(onus::common ALIAS onus_common)
target_include_directories(onus_common INTERFACE include)
add_library(onuscommon)
add_library(onus::common ALIAS onuscommon)
target_sources(onuscommon PRIVATE src/str.c)
target_include_directories(onuscommon PUBLIC include)

View file

@ -17,5 +17,16 @@
#define ONUS_E_PERMISSION_ERROR -3
/* Cannot access the specified file because it does not exist */
#define ONUS_E_FILE_NOT_FOUND -4
/* Cannot copy the string to the buffer because the buffer is too short. Often
* this will still partially copy the data, do not rely on the buffer being
* unmodified in this state */
#define ONUS_E_BUFFER_TOO_SMALL -5
/* Generic file system error */
#define ONUS_E_FS_ERROR -7
/* Miscellaneous */
/* This function is not supported on the running platform */
#define ONUS_E_PLATFORM_UNSUPPORTED -6
#endif /* __LIBONUS_ERR_H */

View file

@ -0,0 +1,6 @@
#ifndef __LIBONUS_INT_H
#define __LIBONUS_INT_H
typedef unsigned long onus_size_t;
#endif /* __LIBONUS_INT_H */

View file

@ -0,0 +1,19 @@
#ifndef __LIBONUS_STR_H
#define __LIBONUS_STR_H
#include "onus/int.h"
/**
* Copies buffer src into dst with a maximum num characters. If the buffer is
* too small, it is automatically NULL-terminated
*
* @param dst: Destination string buffer
* @param src: Source string buffer
* @param num: Maximum number of characters to copy from src into dst, including
* NULL character
* @returns Size of src, excluding NULL character. This can be compared with num
* to determine whether copying was sucessful
*/
onus_size_t onus_nstrcpy(char *dst, const char *src, onus_size_t num);
#endif /* __LIBONUS_STR_H */

11
pkg/common/src/str.c Normal file
View file

@ -0,0 +1,11 @@
#include <stddef.h>
#include "onus/str.h"
onus_size_t onus_nstrcpy(char *dst, const char *src, onus_size_t num) {
onus_size_t i = 0;
while (*src != '\0' && i < num)
*dst++ = *src++, i++;
*dst = '\0';
while(*src++ != '\0') i++;
return i;
}

View file

@ -1,5 +1,5 @@
add_library(onus_fs)
add_library(onus::fs ALIAS onus_fs)
target_sources(onus_fs PRIVATE src/copymove.c)
target_include_directories(onus_fs PUBLIC include)
target_link_libraries(onus_fs PRIVATE onus::common)
add_library(onusfs)
add_library(onus::fs ALIAS onusfs)
target_sources(onusfs PRIVATE src/tmp.c)
target_include_directories(onusfs PUBLIC include)
target_link_libraries(onusfs PRIVATE onus::common)

View file

@ -1,6 +1,8 @@
#ifndef __LIBONUS_FS_H
#define __LIBONUS_FS_H
#include "onus/int.h"
/**
* Copies a file from one location to another, overwriting if necessary
* @param src: Path to original file
@ -8,7 +10,7 @@
* @throws ONUS_E_FILE_NOT_FOUND if src does not point to an existing file, or
* if dst does not point to a path within an existing directory
* @throws ONUS_E_PERMISSION_ERROR if the user does not have permission to read
* src or to write to dst
* src or to write to dst, ONUS_E_FS_ERR for unspecified file system errors
* @returns ONUS_SUCCESS on success
*/
int onus_fs_copy_file(const char *src, const char *dst);
@ -20,9 +22,43 @@ int onus_fs_copy_file(const char *src, const char *dst);
* @throws ONUS_E_FILE_NOT_FOUND if src does not point to an existing file, or
* if dst does not point to a path within an existing directory
* @throws ONUS_E_PERMISSION_ERROR if the user does not have permission to move
* src or to write to dst
* src or to write to dst, ONUS_E_FS_ERR for unspecified file system errors
* @returns ONUS_SUCCESS on success
*/
int onus_fs_move_file(const char *src, const char *dst);
/**
* Creates a temporary file directory for storing user files. Directory name is
* randomly chosen, but may be suffixed to indicate its source
*
* Not all platforms automatically clean temporary directories, so you should
* delete it using onus_fs_del_tmp
* @param path: Output buffer to store temporary file path
* @param path_sz: Size of output path buffer (including NULL character)
* @param suffix: Suffix to add to temporary directory's name. If NULL, no
* suffix will be used
* @returns ONUS_SUCCESS on success, ONUS_E_PERMISSION_ERROR if failed to create
* temporary directory, ONUS_E_FS_ERR for unspecified file system errors,
* ONUS_E_BUFFER_TOO_SMALL if path is not large enough to store the temporary
* file path (May overwrite path anyway), ONUS_E_PLATFORM_UNSUPPORTED if
* creating temporary directories is not supported on this platform
*/
int onus_fs_make_tmp(char *path, onus_size_t path_sz, const char *suffix);
/**
* Deletes a temporary directory created using onus_fs_make_tmp. Does not
* perform any checks to guarantee it was created using said function. Be
* careful when using as it could erase non-temporary directories if misused.
* (Will not delete files mounted in subdirectories, and will return
* ONUS_E_FS_ERR instead)
*
* Will still return success if the directory is missing, as the user may
* choose to delete it while the program is running
* @param path: Path to temporary directory to delete
* @returns ONUS_SUCCESS if directory was deleted successfully, or no longer
* exists, ONUS_E_PERMISSION_ERROR if failed to delete the requested path,
* ONUS_E_FS_ERR for unspecified file system errors
*/
int onus_fs_del_tmp(const char *path);
#endif /* __LIBONUS_FS_H */

View file

@ -1,2 +0,0 @@
#include "onus/err.h"
#include "onus/fs.h"

74
pkg/fs/src/tmp.c Normal file
View file

@ -0,0 +1,74 @@
#define _XOPEN_SOURCE 2008
#include "onus/err.h"
#include "onus/fs.h"
#include "onus/str.h"
#include <errno.h>
#include <ftw.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int onus_fs_make_tmp(char *path, onus_size_t path_sz, const char *suffix) {
char *npath = NULL;
char *tmpname = NULL;
int ret;
tmpname = malloc(strlen(suffix) + 1 + 6);
sprintf(tmpname, "%sXXXXXX", suffix);
npath = mkdtemp(tmpname);
if (errno == EACCES) {
ret = ONUS_E_PERMISSION_ERROR;
goto clean;
} else if (errno != 0) {
ret = ONUS_E_FS_ERROR;
goto clean;
}
if (onus_nstrcpy(path, npath, path_sz) + 1 > path_sz) {
ret = ONUS_E_BUFFER_TOO_SMALL;
goto clean;
}
ret = ONUS_SUCCESS;
clean:
if (npath)
free(npath);
if (tmpname)
free(tmpname);
return ret;
}
static int unlink_cb(const char *filename, const struct stat *status, int flag,
struct FTW *info) {
if (!remove(filename))
return ONUS_E_FS_ERROR;
return 0;
}
/**
* Deletes a temporary directory created using onus_fs_make_tmp. Does not
* perform any checks to guarantee it was created using said function. Be
* careful when using as it could erase non-temporary directories if misused.
* (Will not delete files mounted in subdirectories, and will return
* ONUS_E_FS_ERR instead)
*
* Will stilll return success if the directory is missing, as the user may
* choose to delete it while the program is running
* @param path: Path to temporary directory to delete
* @returns ONUS_SUCCESS if directory was deleted successfully, or no longer
* exists, ONUS_E_PERMISSION_ERROR if failed to delete the requested path,
* ONUS_E_FS_ERR for unspecified file system errors
*/
int onus_fs_del_tmp(const char *path) {
int err;
err = nftw(path, unlink_cb, 64, FTW_DEPTH | FTW_PHYS | FTW_MOUNT);
if (!err || err == ENOENT)
return ONUS_SUCCESS;
else if (err == EACCES)
return ONUS_E_PERMISSION_ERROR;
else
return ONUS_E_FS_ERROR;
}