io: directory: implement temporary directories and delete-on-close

This commit is contained in:
2025-08-09 19:40:11 +01:00
parent 655d8b1881
commit 8bdb770ae5
5 changed files with 127 additions and 22 deletions

View File

@@ -22,6 +22,7 @@ typedef enum b_directory_iterator_flags {
typedef enum b_directory_open_flags { typedef enum b_directory_open_flags {
B_DIRECTORY_OPEN_CREATE = 0x01u, B_DIRECTORY_OPEN_CREATE = 0x01u,
B_DIRECTORY_OPEN_CREATE_INTERMEDIATE = 0x03u, B_DIRECTORY_OPEN_CREATE_INTERMEDIATE = 0x03u,
B_DIRECTORY_OPEN_DELETE_ON_CLOSE = 0x04u,
} b_directory_open_flags; } b_directory_open_flags;
typedef struct b_directory_iterator { typedef struct b_directory_iterator {
@@ -43,10 +44,12 @@ typedef struct b_directory_iterator {
BLUE_API b_result b_directory_open( BLUE_API b_result b_directory_open(
b_directory *root, const b_path *path, b_directory_open_flags flags, b_directory *root, const b_path *path, b_directory_open_flags flags,
b_directory **out); b_directory **out);
BLUE_API b_result b_directory_open_temp(b_directory **out);
BLUE_API const b_path *b_directory_get_path(const b_directory *dir); BLUE_API const b_path *b_directory_get_path(const b_directory *dir);
BLUE_API const b_path *b_directory_get_rel_path(const b_directory *dir); BLUE_API const b_path *b_directory_get_rel_path(const b_directory *dir);
BLUE_API const char *b_directory_get_path_cstr(const b_directory *dir); BLUE_API const char *b_directory_get_path_cstr(const b_directory *dir);
BLUE_API const char *b_directory_get_rel_path_cstr(const b_directory *dir); BLUE_API const char *b_directory_get_rel_path_cstr(const b_directory *dir);
BLUE_API b_result b_directory_delete(b_directory *dir);
BLUE_API bool b_directory_path_exists(const b_directory *root, const b_path *path); BLUE_API bool b_directory_path_exists(const b_directory *root, const b_path *path);
BLUE_API bool b_directory_path_is_file(const b_directory *root, const b_path *path); BLUE_API bool b_directory_path_is_file(const b_directory *root, const b_path *path);

View File

@@ -1,5 +1,7 @@
#include "misc.h"
#include "posix.h" #include "posix.h"
#include <blue/core/error.h>
#include <blue/io/directory.h> #include <blue/io/directory.h>
#include <blue/object/string.h> #include <blue/object/string.h>
#include <errno.h> #include <errno.h>
@@ -10,8 +12,13 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
enum directory_flags {
DIRECTORY_DELETE_ON_CLOSE = 0x01u,
};
struct b_directory { struct b_directory {
struct b_object base; struct b_object base;
enum directory_flags flags;
int fd; int fd;
struct b_path *rel_path; struct b_path *rel_path;
struct b_path *abs_path; struct b_path *abs_path;
@@ -34,8 +41,15 @@ static struct b_object_type directory_type = {
static b_result create_directory(struct b_directory *root, const char *path) static b_result create_directory(struct b_directory *root, const char *path)
{ {
int root_fd = root->fd; int root_fd = root ? root->fd : -1;
int err = mkdirat(root_fd, path, 0755); int err;
if (root_fd == -1) {
err = mkdir(path, 0755);
} else {
err = mkdirat(root_fd, path, 0755);
}
if (err == 0 || errno == EEXIST) { if (err == 0 || errno == EEXIST) {
return B_RESULT_SUCCESS; return B_RESULT_SUCCESS;
} }
@@ -145,11 +159,45 @@ b_result b_directory_open(
dir->rel_path = b_path_duplicate(path); dir->rel_path = b_path_duplicate(path);
dir->fd = fd; dir->fd = fd;
if (flags & B_DIRECTORY_OPEN_DELETE_ON_CLOSE) {
dir->flags = DIRECTORY_DELETE_ON_CLOSE;
}
*out = dir; *out = dir;
return B_RESULT_SUCCESS; return B_RESULT_SUCCESS;
} }
b_result b_directory_open_temp(struct b_directory **out)
{
char name[16];
char path[128];
while (1) {
z__b_io_generate_tmp_filename(name, sizeof name);
snprintf(path, sizeof path, "/tmp/%s", name);
struct b_path *rpath = b_path_create_from_cstr(path);
struct b_directory *dir = NULL;
b_result status = b_directory_open(
B_DIRECTORY_ROOT, rpath, B_DIRECTORY_OPEN_CREATE, &dir);
if (b_error_get_status_code(status) == B_ERR_NAME_EXISTS) {
b_path_release(rpath);
continue;
}
if (dir) {
dir->flags |= DIRECTORY_DELETE_ON_CLOSE;
}
b_path_unlink(rpath);
b_path_release(rpath);
return status;
}
}
const struct b_path *b_directory_get_path(const struct b_directory *dir) const struct b_path *b_directory_get_path(const struct b_directory *dir)
{ {
if (!dir) { if (!dir) {
@@ -186,6 +234,35 @@ const char *b_directory_get_rel_path_cstr(const struct b_directory *dir)
return b_path_ptr(dir->rel_path); return b_path_ptr(dir->rel_path);
} }
static b_result directory_delete(struct b_directory *dir)
{
enum b_status status = B_SUCCESS;
struct b_directory_iterator it;
b_directory_iterator_begin(dir, &it, B_DIRECTORY_ITERATE_PARENT_LAST);
while (b_directory_iterator_is_valid(&it)) {
status = b_directory_iterator_erase(&it);
if (!B_OK(status)) {
return B_RESULT_STATUS(status);
}
}
status = b_path_unlink(dir->abs_path);
if (!B_OK(status)) {
return B_RESULT_STATUS(status);
}
return B_RESULT_SUCCESS;
}
b_result b_directory_delete(struct b_directory *dir)
{
dir->flags |= DIRECTORY_DELETE_ON_CLOSE;
/* TODO allow object release functions to return a b_result value */
b_directory_release(dir);
return B_RESULT_SUCCESS;
}
bool b_directory_path_exists( bool b_directory_path_exists(
const struct b_directory *root, const struct b_path *path) const struct b_directory *root, const struct b_path *path)
{ {
@@ -478,6 +555,14 @@ bool b_directory_iterator_next(struct b_directory_iterator *it)
enum b_status b_directory_iterator_erase(struct b_directory_iterator *it) enum b_status b_directory_iterator_erase(struct b_directory_iterator *it)
{ {
b_result result = b_directory_path_unlink(it->root, it->filepath);
if (b_result_is_error(result)) {
enum b_status status = b_error_get_status_code(result);
b_error_release(result);
return status;
}
b_directory_iterator_next(it);
return B_SUCCESS; return B_SUCCESS;
} }
@@ -499,5 +584,10 @@ static void directory_release(struct b_object *obj)
struct b_directory *dir = B_DIRECTORY(obj); struct b_directory *dir = B_DIRECTORY(obj);
close(dir->fd); close(dir->fd);
if (dir->flags & DIRECTORY_DELETE_ON_CLOSE) {
directory_delete(dir);
}
b_path_release(dir->abs_path); b_path_release(dir->abs_path);
} }

View File

@@ -1,3 +1,4 @@
#include "misc.h"
#include "posix.h" #include "posix.h"
#include <blue/core/random.h> #include <blue/core/random.h>
@@ -118,24 +119,6 @@ b_result b_file_open(
return B_RESULT_SUCCESS; return B_RESULT_SUCCESS;
} }
static void generate_tmp_filename(char *out, size_t len)
{
static const char *alphabet
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
"01234567"
"89+=-_.";
static const size_t alphabet_len = 67;
b_random_ctx *ctx = b_random_global_ctx();
for (size_t i = 0; i < len; i++) {
int v = b_random_next_int64(ctx) % alphabet_len;
out[i] = alphabet[v];
}
out[len - 1] = 0;
}
b_result b_file_open_temp(enum b_file_mode mode, struct b_file **out) b_result b_file_open_temp(enum b_file_mode mode, struct b_file **out)
{ {
mode |= B_FILE_DELETE_ON_CLOSE; mode |= B_FILE_DELETE_ON_CLOSE;
@@ -144,7 +127,7 @@ b_result b_file_open_temp(enum b_file_mode mode, struct b_file **out)
char path[128]; char path[128];
while (1) { while (1) {
generate_tmp_filename(name, sizeof name); z__b_io_generate_tmp_filename(name, sizeof name);
snprintf(path, sizeof path, "/tmp/%s", name); snprintf(path, sizeof path, "/tmp/%s", name);
struct b_path *rpath = b_path_create_from_cstr(path); struct b_path *rpath = b_path_create_from_cstr(path);
@@ -423,7 +406,7 @@ enum b_status b_file_swap_shadow(struct b_file *main_file, struct b_file *shadow
while (1) { while (1) {
char tmp_name[16]; char tmp_name[16];
generate_tmp_filename(tmp_name, sizeof tmp_name); z__b_io_generate_tmp_filename(tmp_name, sizeof tmp_name);
struct b_path *tmp_name_p = b_path_create_from_cstr(tmp_name); struct b_path *tmp_name_p = b_path_create_from_cstr(tmp_name);
const struct b_path *parts[] = { const struct b_path *parts[] = {

21
io/sys/darwin/misc.c Normal file
View File

@@ -0,0 +1,21 @@
#include "misc.h"
#include <blue/core/random.h>
void z__b_io_generate_tmp_filename(char *out, size_t len)
{
static const char *alphabet
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
"01234567"
"89+=-_.";
static const size_t alphabet_len = 67;
b_random_ctx *ctx = b_random_global_ctx();
for (size_t i = 0; i < len; i++) {
int v = b_random_next_int64(ctx) % alphabet_len;
out[i] = alphabet[v];
}
out[len - 1] = 0;
}

8
io/sys/darwin/misc.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef _IO_DARWIN_MISC_H_
#define _IO_DARWIN_MISC_H_
#include <stddef.h>
extern void z__b_io_generate_tmp_filename(char *out, size_t len);
#endif