Skip to content

Commit

Permalink
wip implement delete functions
Browse files Browse the repository at this point in the history
  • Loading branch information
imaqtkatt committed Aug 22, 2024
1 parent 6542760 commit 1a31be6
Show file tree
Hide file tree
Showing 5 changed files with 344 additions and 0 deletions.
103 changes: 103 additions & 0 deletions src/run.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#include <dlfcn.h>
#include <errno.h>
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
// #include <unistd.h>
#include "hvm.c"

// Readback: λ-Encoded Ctr
Expand Down Expand Up @@ -716,6 +719,104 @@ Port io_dl_close(Net* net, Book* book, Port argm) {
return inject_ok(net, new_port(ERA, 0));
}

// Deletes a single file or an empty directory at the specified path.
// Returns Ok(None) if successful, or Err(reason) if an error occurs.
// This function attempts to remove both files and empty directories without
// first checking the type of the path.
// Returns: Result<*, IOError<i24>>
Port io_delete_file(Net* net, Book* book, Port argm) {
Str path = readback_str(net, book, argm);

int result = remove(path.buf);
free(path.buf);

if (result == 0) {
return inject_ok(net, new_port(ERA, 0));
} else {
return inject_io_err_inner(net, new_port(NUM, new_i24(errno)));
}
}

int delete_directory_recursive(const char* path) {
DIR *d = opendir(path);
size_t path_len = strlen(path);
int r = -1;

if (d) {
struct dirent *p;
r = 0;

while (!r && (p = readdir(d))) {
int r2 = -1;
char *buf;
size_t len;

if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, "..")) {
continue;
}

len = path_len + strlen(p->d_name) + 2;
buf = malloc(len);

if (buf) {
struct stat statbuf;
snprintf(buf, len, "%s/%s", path, p->d_name);

if (!stat(buf, &statbuf)) {
if (S_ISDIR(statbuf.st_mode)) {
r2 = delete_directory_recursive(buf);
} else {
r2 = remove(buf);
}
}

free(buf);
}

r = r2;
}

closedir(d);
}

if (!r) {
r = remove(path);
}

return r;
}

// Deletes a directory at the specified path. If recursive is True,
// it will delete the directory and all its contents.
// Returns Ok(None) if successful, or Err(reason) if an error occurs.
// Note: For non-recursive deletion of an empty directory,
// this function behaves the same as delete_file(path).
// Returns: Result<*, IOError<i24>>
Port io_delete_directory(Net* net, Book* book, Port argm) {
Tup tup = readback_tup(net, book, argm, 2);
if (2 != tup.elem_len) {
return inject_io_err_type(net);
}

Str path = readback_str(net, book, tup.elem_buf[0]);
u32 rec = get_u24(get_val(tup.elem_buf[1]));

int res;
if (rec) {
res = delete_directory_recursive(path.buf);
free(path.buf);
} else {
res = remove(path.buf);
free(path.buf);
}

if (0 == res) {
return inject_ok(net, new_port(ERA, 0));
} else {
return inject_io_err_inner(net, new_port(NUM, new_i24(errno)));
}
}

// Book Loader
// -----------

Expand All @@ -731,6 +832,8 @@ void book_init(Book* book) {
book->ffns_buf[book->ffns_len++] = (FFn){"DL_OPEN", io_dl_open};
book->ffns_buf[book->ffns_len++] = (FFn){"DL_CALL", io_dl_call};
book->ffns_buf[book->ffns_len++] = (FFn){"DL_CLOSE", io_dl_open};
book->ffns_buf[book->ffns_len++] = (FFn){"DELETE_FILE", io_delete_file};
book->ffns_buf[book->ffns_len++] = (FFn){"DELETE_DIRECTORY", io_delete_directory};
}

// Monadic IO Evaluator
Expand Down
11 changes: 11 additions & 0 deletions tests/programs/io_delete/delete_file.bend
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
test-io = 1

IO/FS/delete_file path =
(call "DELETE_FILE" path)

main =
use path = "./tests/programs/io_remove/files/remove_file.txt"
with IO {
ask s = (IO/FS/delete_file path)
(wrap s)
}
109 changes: 109 additions & 0 deletions tests/programs/io_delete/delete_file.hvm
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
@IO/Call = (a (b (c (d ((@IO/Call/tag (a (b (c (d e))))) e)))))

@IO/Call/tag = 1

@IO/Done = (a (b ((@IO/Done/tag (a (b c))) c)))

@IO/Done/tag = 0

@IO/FS/delete_file = l
& @call ~ (k l)
& @String/Cons ~ (68 (j k))
& @String/Cons ~ (69 (i j))
& @String/Cons ~ (76 (h i))
& @String/Cons ~ (69 (g h))
& @String/Cons ~ (84 (f g))
& @String/Cons ~ (69 (e f))
& @String/Cons ~ (95 (d e))
& @String/Cons ~ (70 (c d))
& @String/Cons ~ (73 (b c))
& @String/Cons ~ (76 (a b))
& @String/Cons ~ (69 (@String/Nil a))

@IO/MAGIC = (13683217 16719857)

@IO/bind = ((@IO/bind__C2 a) a)

@IO/bind__C0 = (* (b (a c)))
& @undefer ~ (a (b c))

@IO/bind__C1 = (* (* (a (b ((c d) (e g))))))
& @IO/Call ~ (@IO/MAGIC (a (b ((c f) g))))
& @IO/bind ~ (d (e f))

@IO/bind__C2 = (?((@IO/bind__C0 @IO/bind__C1) a) a)

@IO/wrap = a
& @IO/Done ~ (@IO/MAGIC a)

@String/Cons = (a (b ((@String/Cons/tag (a (b c))) c)))

@String/Cons/tag = 1

@String/Nil = ((@String/Nil/tag a) a)

@String/Nil/tag = 0

@call = (a (b c))
& @IO/Call ~ (@IO/MAGIC (a (b (@call__C0 c))))

@call__C0 = a
& @IO/Done ~ (@IO/MAGIC a)

@main = ac
& @IO/bind ~ (wb ((((xb xb) (@IO/wrap zb)) zb) ac))
& @IO/FS/delete_file ~ (vb wb)
& @String/Cons ~ (46 (ub vb))
& @String/Cons ~ (47 (tb ub))
& @String/Cons ~ (116 (sb tb))
& @String/Cons ~ (101 (rb sb))
& @String/Cons ~ (115 (qb rb))
& @String/Cons ~ (116 (pb qb))
& @String/Cons ~ (115 (ob pb))
& @String/Cons ~ (47 (nb ob))
& @String/Cons ~ (112 (mb nb))
& @String/Cons ~ (114 (lb mb))
& @String/Cons ~ (111 (kb lb))
& @String/Cons ~ (103 (jb kb))
& @String/Cons ~ (114 (ib jb))
& @String/Cons ~ (97 (hb ib))
& @String/Cons ~ (109 (gb hb))
& @String/Cons ~ (115 (fb gb))
& @String/Cons ~ (47 (eb fb))
& @String/Cons ~ (105 (db eb))
& @String/Cons ~ (111 (cb db))
& @String/Cons ~ (95 (bb cb))
& @String/Cons ~ (114 (ab bb))
& @String/Cons ~ (101 (z ab))
& @String/Cons ~ (109 (y z))
& @String/Cons ~ (111 (x y))
& @String/Cons ~ (118 (w x))
& @String/Cons ~ (101 (v w))
& @String/Cons ~ (47 (u v))
& @String/Cons ~ (102 (t u))
& @String/Cons ~ (105 (s t))
& @String/Cons ~ (108 (r s))
& @String/Cons ~ (101 (q r))
& @String/Cons ~ (115 (p q))
& @String/Cons ~ (47 (o p))
& @String/Cons ~ (114 (n o))
& @String/Cons ~ (101 (m n))
& @String/Cons ~ (109 (l m))
& @String/Cons ~ (111 (k l))
& @String/Cons ~ (118 (j k))
& @String/Cons ~ (101 (i j))
& @String/Cons ~ (95 (h i))
& @String/Cons ~ (102 (g h))
& @String/Cons ~ (105 (f g))
& @String/Cons ~ (108 (e f))
& @String/Cons ~ (101 (d e))
& @String/Cons ~ (46 (c d))
& @String/Cons ~ (116 (b c))
& @String/Cons ~ (120 (a b))
& @String/Cons ~ (116 (@String/Nil a))

@test-io = 1

@undefer = (((a a) b) b)


11 changes: 11 additions & 0 deletions tests/programs/io_delete/delete_non_existing_file.bend
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
test-io = 1

IO/FS/delete_file path =
(call "DELETE_FILE" path)

main =
use path = "./tests/programs/io_remove/files/non_existing.txt"
with IO {
ask s = (IO/FS/delete_file path)
(wrap s)
}
110 changes: 110 additions & 0 deletions tests/programs/io_delete/delete_non_existing_file.hvm
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
@IO/Call = (a (b (c (d ((@IO/Call/tag (a (b (c (d e))))) e)))))

@IO/Call/tag = 1

@IO/Done = (a (b ((@IO/Done/tag (a (b c))) c)))

@IO/Done/tag = 0

@IO/FS/delete_file = l
& @call ~ (k l)
& @String/Cons ~ (68 (j k))
& @String/Cons ~ (69 (i j))
& @String/Cons ~ (76 (h i))
& @String/Cons ~ (69 (g h))
& @String/Cons ~ (84 (f g))
& @String/Cons ~ (69 (e f))
& @String/Cons ~ (95 (d e))
& @String/Cons ~ (70 (c d))
& @String/Cons ~ (73 (b c))
& @String/Cons ~ (76 (a b))
& @String/Cons ~ (69 (@String/Nil a))

@IO/MAGIC = (13683217 16719857)

@IO/bind = ((@IO/bind__C2 a) a)

@IO/bind__C0 = (* (b (a c)))
& @undefer ~ (a (b c))

@IO/bind__C1 = (* (* (a (b ((c d) (e g))))))
& @IO/Call ~ (@IO/MAGIC (a (b ((c f) g))))
& @IO/bind ~ (d (e f))

@IO/bind__C2 = (?((@IO/bind__C0 @IO/bind__C1) a) a)

@IO/wrap = a
& @IO/Done ~ (@IO/MAGIC a)

@String/Cons = (a (b ((@String/Cons/tag (a (b c))) c)))

@String/Cons/tag = 1

@String/Nil = ((@String/Nil/tag a) a)

@String/Nil/tag = 0

@call = (a (b c))
& @IO/Call ~ (@IO/MAGIC (a (b (@call__C0 c))))

@call__C0 = a
& @IO/Done ~ (@IO/MAGIC a)

@main = bc
& @IO/bind ~ (xb ((((yb yb) (@IO/wrap ac)) ac) bc))
& @IO/FS/delete_file ~ (wb xb)
& @String/Cons ~ (46 (vb wb))
& @String/Cons ~ (47 (ub vb))
& @String/Cons ~ (116 (tb ub))
& @String/Cons ~ (101 (sb tb))
& @String/Cons ~ (115 (rb sb))
& @String/Cons ~ (116 (qb rb))
& @String/Cons ~ (115 (pb qb))
& @String/Cons ~ (47 (ob pb))
& @String/Cons ~ (112 (nb ob))
& @String/Cons ~ (114 (mb nb))
& @String/Cons ~ (111 (lb mb))
& @String/Cons ~ (103 (kb lb))
& @String/Cons ~ (114 (jb kb))
& @String/Cons ~ (97 (ib jb))
& @String/Cons ~ (109 (hb ib))
& @String/Cons ~ (115 (gb hb))
& @String/Cons ~ (47 (fb gb))
& @String/Cons ~ (105 (eb fb))
& @String/Cons ~ (111 (db eb))
& @String/Cons ~ (95 (cb db))
& @String/Cons ~ (114 (bb cb))
& @String/Cons ~ (101 (ab bb))
& @String/Cons ~ (109 (z ab))
& @String/Cons ~ (111 (y z))
& @String/Cons ~ (118 (x y))
& @String/Cons ~ (101 (w x))
& @String/Cons ~ (47 (v w))
& @String/Cons ~ (102 (u v))
& @String/Cons ~ (105 (t u))
& @String/Cons ~ (108 (s t))
& @String/Cons ~ (101 (r s))
& @String/Cons ~ (115 (q r))
& @String/Cons ~ (47 (p q))
& @String/Cons ~ (110 (o p))
& @String/Cons ~ (111 (n o))
& @String/Cons ~ (110 (m n))
& @String/Cons ~ (95 (l m))
& @String/Cons ~ (101 (k l))
& @String/Cons ~ (120 (j k))
& @String/Cons ~ (105 (i j))
& @String/Cons ~ (115 (h i))
& @String/Cons ~ (116 (g h))
& @String/Cons ~ (105 (f g))
& @String/Cons ~ (110 (e f))
& @String/Cons ~ (103 (d e))
& @String/Cons ~ (46 (c d))
& @String/Cons ~ (116 (b c))
& @String/Cons ~ (120 (a b))
& @String/Cons ~ (116 (@String/Nil a))

@test-io = 1

@undefer = (((a a) b) b)


0 comments on commit 1a31be6

Please sign in to comment.