unistd, dirent: path manipulation, folder enumeration

This commit is contained in:
Lephenixnoir 2021-12-23 01:20:41 +01:00
parent 8280bbb919
commit 61ade4412d
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
6 changed files with 254 additions and 8 deletions

View File

@ -51,10 +51,13 @@ set(SOURCES
# time
src/time/clock.c
src/time/functions.c
# unistd
src/unistd/files.c
# dirent
src/dirent/dirent.c
# fcntl
src/fcntl/open.c
# unistd
src/unistd/files.c
)
# fx-9860G-only assets and fx-CG-50-only assets
set(ASSETS_fx

View File

@ -53,13 +53,19 @@ extern ft_test ft_string_strerror;
extern ft_test ft_time_clock;
extern ft_test ft_time_functions;
/* unistd */
extern ft_test ft_unistd_simple_write;
extern ft_test ft_unistd_write_odd;
extern ft_test ft_unistd_simple_read;
extern ft_test ft_unistd_seek_patterns;
/* dirent */
extern ft_test ft_dirent_glob;
extern ft_test ft_dirent_open_folders;
/* fcntl */
extern ft_test ft_fcntl_open;
/* unistd */
extern ft_test ft_unistd_path;
extern ft_test ft_unistd_simple_write;
extern ft_test ft_unistd_write_odd;
extern ft_test ft_unistd_simple_read;
extern ft_test ft_unistd_seek_patterns;
extern ft_test ft_unistd_folders;
#endif /* _FT_ALL_TESTS_H_ */

110
src/dirent/dirent.c Normal file
View File

@ -0,0 +1,110 @@
#include <ft/test.h>
#include <ft/all-tests.h>
#include <ft/util.h>
#include <gint/gint.h>
#include <gint/bfile.h>
#include <gint/fs.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
extern char *fc_to_utf8_alloc(uint16_t const *fc);
static void _ft_dirent_glob_switch(ft_test *t)
{
int search_handle, rc;
uint16_t found_file[256];
struct BFile_FileInfo fileinfo;
char *str;
uint16_t const *path = u"\\\\fls0\\*";
DO_E(rc, BFile_FindFirst(path, &search_handle, found_file, &fileinfo),
t, "%d");
ft_assert(t, rc == 0 || rc == BFile_EntryNotFound);
if(rc < 0) return;
str = fc_to_utf8_alloc(found_file);
ft_log(t, "Found: %s\n", str);
free(str);
while(1) {
rc = BFile_FindNext(search_handle, found_file, &fileinfo);
ft_assert(t, rc == 0 || rc == BFile_EnumerateEnd);
if(rc == BFile_EnumerateEnd)
break;
str = fc_to_utf8_alloc(found_file);
ft_log(t, "Found: %s\n", str);
free(str);
}
DO_E(rc, BFile_FindClose(search_handle), t, "%d");
ft_assert(t, rc == 0);
}
static void _ft_dirent_glob(ft_test *t)
{
gint_world_switch(GINT_CALL(_ft_dirent_glob_switch, (void *)t));
}
ft_test ft_dirent_glob = {
.name = "Glob \\\\fls0\\*",
.function = _ft_dirent_glob,
};
static struct dirent *read_ent(ft_test *t, DIR *dp)
{
int offset = telldir(dp);
struct dirent *ent = readdir(dp);
if(!ent) {
ft_log(t, "%02d <end>\n", offset);
}
else {
ft_log(t, "%02d %s%s\n", offset, ent->d_name,
ent->d_type == DT_DIR ? "/" : "");
}
return ent;
}
static void _ft_dirent_open_folders_switch(ft_test *t)
{
DIR *dp;
struct dirent *ent;
int offset;
DO_E(dp, opendir("/"), t, "%p");
ft_assert(t, dp != NULL);
if(!dp) return;
do ent = read_ent(t, dp);
while(ent);
DO_E(offset, telldir(dp), t, "%d");
if(offset > 0) offset--;
ft_log(t, "seekdir(dp, %d)\n", offset);
seekdir(dp, offset);
read_ent(t, dp);
rewinddir(dp);
ft_log(t, "rewinddir(dp)\n");
read_ent(t, dp);
closedir(dp);
}
static void _ft_dirent_open_folders(ft_test *t)
{
gint_world_switch(GINT_CALL(_ft_dirent_open_folders_switch, (void*)t));
}
ft_test ft_dirent_open_folders = {
.name = "Opening folders",
.function = _ft_dirent_open_folders,
};

View File

@ -39,4 +39,5 @@ ft_test ft_fcntl_open = {
.function = _ft_fcntl_open,
};
// TODO: Truncation
// TODO: Opening files with different access modes
// TODO: Opening files with O_TRUNC or O_APPEND

View File

@ -79,15 +79,22 @@ ft_list headers_libc[] = {
{ NULL }
};
ft_list headers_posix[] = {
{ "<dirent.h>", (ft_test*[]) {
&ft_dirent_glob,
&ft_dirent_open_folders,
NULL,
}},
{ "<fcntl.h>", (ft_test*[]){
&ft_fcntl_open,
NULL,
}},
{ "<unistd.h>", (ft_test*[]){
&ft_unistd_path,
&ft_unistd_simple_write,
&ft_unistd_write_odd,
&ft_unistd_simple_read,
&ft_unistd_seek_patterns,
&ft_unistd_folders,
NULL,
}},
{ NULL }

View File

@ -8,9 +8,68 @@
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
extern char **fs_split_components(char *path, int *count);
static void log_comps(ft_test *t, char const *path, char const *solution)
{
ft_log(t, "Splitting: %s\n", path);
char *path_dup = strdup(path);
if(!path_dup) {
ft_log(t, " ENOMEM\n");
return;
}
int count;
char **comps = fs_split_components(path_dup, &count);
for(int i = 0; i < count; i++) {
ft_log(t, " --> %s\n", comps[i]);
}
if(count == 0) {
ft_log(t, " (empty)\n");
}
free(path_dup);
free(comps);
char *norm1 = fs_path_normalize(path);
ft_log(t, "Normalized (UTF-8): %s\n", norm1);
ft_assert(t, !strcmp(norm1, solution));
free(norm1);
uint16_t *norm2 = fs_path_normalize_fc(path);
ft_log(t, "Normalized (FC): ");
for(int i = 0; norm2[i]; i++) ft_log(t, "%c", norm2[i]);
ft_log(t, "\n\n");
free(norm2);
}
static void _ft_unistd_paths(ft_test *t)
{
ft_log(t, "\nPath normalization:\n\n");
log_comps(t, ".", "/");
log_comps(t, "/", "/");
log_comps(t, "/*", "/*");
log_comps(t, "/file.txt", "/file.txt");
log_comps(t, "file.txt", "/file.txt");
log_comps(t, "folder/file", "/folder/file");
log_comps(t, "a/b/c/d", "/a/b/c/d");
log_comps(t, "/a/b//c", "/a/b/c");
log_comps(t, "folder////file", "/folder/file");
log_comps(t, "//folder///file///", "/folder/file");
log_comps(t, "./../er//e/", "/er/e");
log_comps(t, "x/../y/z/../t", "/y/t");
}
ft_test ft_unistd_path = {
.name = "Path normalization",
.function = _ft_unistd_paths,
};
static void _ft_unistd_simple_write_switch(ft_test *t)
{
int fd, rc;
@ -244,3 +303,63 @@ ft_test ft_unistd_seek_patterns = {
.name = "Seek patterns",
.function = _ft_unistd_seek_patterns,
};
static void _ft_unistd_folders_switch(ft_test *t)
{
int rc, fd, type, size;
/* Create a directory (don't fail if we already ran the test before) */
DO_E(rc, mkdir("ft_test", 0755), t, "%d");
ft_assert(t, rc == 0 || (rc == -1 && errno == EEXIST));
ft_log(t, "note: this folder might already exist\n");
/* Remove that directory */
DO_E(rc, rmdir("ft_test"), t, "%d");
ft_assert(t, rc == 0);
/* Create it anew (and empty) */
DO_E(rc, mkdir("ft_test", 0755), t, "%d");
ft_assert(t, rc == 0);
DO_E(rc, mkdir("ft_test", 0755), t, "%d");
ft_assert(t, rc == -1 && errno == EEXIST);
/* Create a file in that directory, write some stuff and close it */
DO_E(fd, open("ft_test/file.txt", O_RDWR | O_CREAT | O_TRUNC), t,"%d");
ft_assert(t, fd >= 0);
DO_E(rc, write(fd, "Some data\n", 10), t, "%d");
ft_assert(t, rc == 10);
DO_E(rc, close(fd), t, "%d");
ft_assert(t, rc == 0);
/* Stat that file */
rc = BFile_Ext_Stat(u"\\\\fls0\\ft_test\\file.txt", &type, &size);
ft_log(t, "BFile_Ext_Stat()=%d (type=%d, size=%d)\n", rc, type, size);
ft_assert(t, rc == 0 && type == BFile_Type_File && size == 10);
/* Create a subfolder */
DO_E(rc, mkdir("ft_test/subfolder", 0755), t, "%d");
ft_assert(t, rc == 0);
/* Create a file in the subfolder and stat it again */
DO_E(fd, open("ft_test/subfolder/file.txt", O_RDWR | O_CREAT
| O_TRUNC), t, "%d");
ft_assert(t, fd >= 0);
DO_E(rc, write(fd, "Some data for the subfolder\n", 28), t, "%d");
ft_assert(t, rc == 28);
DO_E(rc, close(fd), t, "%d");
ft_assert(t, rc == 0);
rc = BFile_Ext_Stat(u"\\\\fls0\\ft_test\\subfolder\\file.txt",
&type, &size);
ft_log(t, "BFile_Ext_Stat()=%d (type=%d, size=%d)\n", rc, type, size);
ft_assert(t, rc == 0 && type == BFile_Type_File && size == 28);
}
static void _ft_unistd_folders(ft_test *t)
{
gint_world_switch(GINT_CALL(_ft_unistd_folders_switch, (void *)t));
}
ft_test ft_unistd_folders = {
.name = "Using folders",
.function = _ft_unistd_folders,
};