fs: stat(), proper unlink(), rmdir()

This commit is contained in:
Lephe 2021-12-30 18:17:13 +01:00
parent ed30895a49
commit b549fd68ba
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
10 changed files with 159 additions and 25 deletions

View File

@ -52,6 +52,7 @@ set(SOURCES_COMMON
src/fs/rewinddir.c
src/fs/rmdir.c
src/fs/seekdir.c
src/fs/stat.c
src/fs/telldir.c
src/fs/unlink.c
src/fs/write.c
@ -61,6 +62,8 @@ set(SOURCES_COMMON
src/fs/fugue/fugue_dir.c
src/fs/fugue/fugue_open.c
src/fs/fugue/fugue_mkdir.c
src/fs/fugue/fugue_stat.c
src/fs/fugue/fugue_rmdir.c
src/fs/fugue/fugue_unlink.c
src/fs/fugue/util.c
# Interrupt Controller driver

3
TODO
View File

@ -2,7 +2,8 @@ Extensions on existing code:
* usb: add PC->calc reading, and interrupt pipes
* fs: support RAM files
* fs: support USB streams as generic file descriptors
* fugue: support glob() and stat() to abstract away BFile entirely
* fugue: support glob() to abstract away BFile entirely
* fugue/fs: offer a primitive to remove recursively, which is native in Fugue
* bfile: implement the optimization-restart as realized by Kbd2
* kernel: better restore to userspace before panic (ensure BL=0 IMASK=0)
* project: add license file

View File

@ -5,6 +5,7 @@
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
/* File descriptor type */
extern const fs_descriptor_type_t fugue_descriptor_type;
@ -21,6 +22,8 @@ int fugue_mkdir(char const *path, mode_t mode);
int fugue_rmdir(char const *path);
int fugue_stat(char const * restrict path, struct stat * restrict statbuf);
/* Other functions */
void *fugue_dir_explore(char const *path);

View File

@ -145,20 +145,8 @@ void *fugue_dir_explore(char const *path)
if(!ent) goto alloc_failure;
ent->d_ino = 0;
ent->d_type = DT_UNKNOWN;
ent->d_type = bfile_type_to_dirent(info.type);
fc_to_utf8(ent->d_name, fc_path, name_length + 1);
if(info.type == BFile_Type_File)
ent->d_type = DT_REG;
if(info.type == BFile_Type_Archived)
ent->d_type = DT_REG;
if(info.type == BFile_Type_Directory)
ent->d_type = DT_DIR;
if(info.type == BFile_Type_Dot)
ent->d_type = DT_DIR;
if(info.type == BFile_Type_DotDot)
ent->d_type = DT_DIR;
dp->entries[dp->count++] = ent;
rc = BFile_FindNext(sd, fc_path, &info);

View File

@ -0,0 +1,51 @@
#include <gint/hardware.h>
#include <gint/bfile.h>
#include <gint/fs.h>
#include <errno.h>
#include <dirent.h>
#include <string.h>
#include "util.h"
#include "fugue.h"
int fugue_rmdir(char const *path)
{
ENOTSUP_IF_NOT_FUGUE(-1);
/* Check if the folder is empty */
DIR *dp = opendir(path);
if(!dp) return -1;
bool empty = true;
struct dirent *ent;
while((ent = readdir(dp))) {
if(strcmp(ent->d_name, ".") != 0 &&
strcmp(ent->d_name, "..") != 0) {
empty = false;
break;
}
}
closedir(dp);
if(!empty) {
errno = ENOTEMPTY;
return -1;
}
uint16_t *fcpath = fs_path_normalize_fc(path);
if(!fcpath) {
errno = ENOMEM;
return -1;
}
int rc = BFile_Remove(fcpath);
if(rc < 0) {
errno = bfile_error_to_errno(rc);
rc = -1;
}
else rc = 0;
free(fcpath);
return rc;
}

36
src/fs/fugue/fugue_stat.c Normal file
View File

@ -0,0 +1,36 @@
#include <sys/stat.h>
#include <gint/fs.h>
#include <gint/bfile.h>
#include "fugue.h"
#include <errno.h>
#include <stdlib.h>
#include "util.h"
int fugue_stat(char const * restrict path, struct stat * restrict statbuf)
{
ENOTSUP_IF_NOT_FUGUE(-1);
uint16_t *fcpath = fs_path_normalize_fc(path);
if(!fcpath) {
errno = ENOMEM;
return -1;
}
int type, size, rc;
rc = BFile_Ext_Stat(fcpath, &type, &size);
free(fcpath);
if(rc < 0) {
errno = bfile_error_to_errno(rc);
return -1;
}
statbuf->st_mode = bfile_type_to_mode_t(type) | 0777;
statbuf->st_size = -1;
if(S_ISREG(statbuf->st_mode)) {
statbuf->st_size = size;
}
return 0;
}

View File

@ -2,6 +2,7 @@
#include <gint/bfile.h>
#include <gint/fs.h>
#include <errno.h>
#include <sys/stat.h>
#include "util.h"
int fugue_unlink(char const *path)
@ -14,18 +15,27 @@ int fugue_unlink(char const *path)
return -1;
}
int err = BFile_Remove(fcpath);
if(err < 0) {
errno = bfile_error_to_errno(err);
free(fcpath);
return -1;
int type, size, rc;
rc = BFile_Ext_Stat(fcpath, &type, &size);
if(rc < 0) {
errno = bfile_error_to_errno(rc);
rc = -1;
goto end;
}
if(bfile_type_to_mode_t(type) != S_IFREG) {
errno = ENOTDIR;
rc = -1;
goto end;
}
free(fcpath);
return 0;
}
rc = BFile_Remove(fcpath);
if(rc < 0) {
errno = bfile_error_to_errno(rc);
rc = -1;
}
else rc = 0;
int fugue_rmdir(char const *path)
{
return fugue_unlink(path);
end:
free(fcpath);
return rc;
}

View File

@ -4,6 +4,8 @@
#include <errno.h>
#include <stdarg.h>
#include <gint/bfile.h>
#include <dirent.h>
#include <sys/stat.h>
int bfile_error_to_errno(int e)
{
@ -26,6 +28,32 @@ int bfile_error_to_errno(int e)
}
}
int bfile_type_to_mode_t(int bfile_type)
{
switch(bfile_type) {
case BFile_Type_Directory: return S_IFDIR;
case BFile_Type_Dot: return S_IFDIR;
case BFile_Type_DotDot: return S_IFDIR;
case BFile_Type_MainMem: return S_IFBLK;
case BFile_Type_File: return S_IFREG;
case BFile_Type_Archived: return S_IFREG;
default: return S_IFREG;
}
}
int bfile_type_to_dirent(int bfile_type)
{
switch(bfile_type) {
case BFile_Type_Directory: return DT_DIR;
case BFile_Type_Dot: return DT_DIR;
case BFile_Type_DotDot: return DT_DIR;
case BFile_Type_MainMem: return DT_BLK;
case BFile_Type_File: return DT_REG;
case BFile_Type_Archived: return DT_REG;
default: return DT_UNKNOWN;
}
}
/* Length of FONTCHARACTER and UTF-8 strings, counting only ASCII characters */
size_t utf8_len(char const *utf8)
{

View File

@ -16,6 +16,12 @@ extern "C" {
/* Translate common BFile error codes to errno values. */
int bfile_error_to_errno(int bfile_error_code);
/* Translate BFile file types to st_mode values. */
int bfile_type_to_mode_t(int bfile_type);
/* Translate BFile file types to struct dirent values. */
int bfile_type_to_dirent(int bfile_type);
/* TODO: These functions do not actually translate special characters between
encodings, they simply strip them. */

8
src/fs/stat.c Normal file
View File

@ -0,0 +1,8 @@
#include <sys/stat.h>
#include "fugue/fugue.h"
int stat(char const * restrict path, struct stat * restrict statbuf)
{
/* Standard stat() is the Fugue filesystem only */
return fugue_stat(path, statbuf);
}