cepheid

An Aurora 4X clone
Log | Files | Refs | README

commit fda5f458563c3fad93afcc03aec628dd94c1784f
parent 3d2eac4ae2429b93d694efda884f23e5648f104c
Author: hhvn <dev@hhvn.uk>
Date:   Sun, 27 Nov 2022 13:16:51 +0000

Save deletion

Diffstat:
Asrc/file.c | 69+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/main.h | 10+++++-----
Msrc/save.c | 8++++++++
Msrc/tree.c | 5+++++
Msrc/views/smenu.c | 46++++++++++++++++++++++++++++++++++++----------
Msrc/views/struct.h | 1+
Atests/file.test | 24++++++++++++++++++++++++
7 files changed, 148 insertions(+), 15 deletions(-)

diff --git a/src/file.c b/src/file.c @@ -0,0 +1,69 @@ +#include <stdio.h> +#include <string.h> +#include <dirent.h> +#include <unistd.h> +#include <stdlib.h> +#include <limits.h> +#include <sys/stat.h> +#include "main.h" + +int +mkdirp(char *path) { + char *dup; + char *p[64]; + int create; + int i, max; + int ret = 0; + + dup = estrdup(path); + max = strsplit(dup, "/", p, ELEMS(p)); + + for (i = 0, create = 0; i < max; i++) { + if (create || access(path, F_OK) == -1) { + if (mkdir(dup, 0777 & ~umask(0)) == -1) { + ret = -1; + goto end; + } + create = 1; + } + if (i + 1 != max) + *(p[i + 1] - 1) = '/'; + } + +end: + free(dup); + return ret; +} + +int +rmdirp(char *dir) { + struct dirent **dirent; + struct stat st; + char path[PATH_MAX]; + int ret = 0; + int n, i; + + n = scandir(dir, &dirent, NULL, alphasort); + if (n < 0) return 0; + + for (i = 0; i < n; i++) { + snprintf(path, sizeof(path), "%s/%s", dir, dirent[i]->d_name); + stat(path, &st); + if (!streq(dirent[i]->d_name, ".") && !streq(dirent[i]->d_name, "..")) { + if (S_ISDIR(st.st_mode)) { + if (rmdirp(path) == -1) + ret = -1; + } else { + if (unlink(path) == -1) + ret = -1; + } + } + free(dirent[i]); + } + free(dirent); + + if (rmdir(dir) == -1) + ret = -1; + + return ret; +} diff --git a/src/main.h b/src/main.h @@ -211,10 +211,15 @@ char * bodytype_strify(Body *body); Body * body_init(char *name); void body_free(Body *b); +/* file.c */ +int mkdirp(char *path); +int rmdirp(char *dir); + /* save.c */ void save_read(char *dir); int save_changed(void); void save_write(void); +int save_delete(char *name); int save_exists(char *name); int save_create(char *name); @@ -249,11 +254,6 @@ int dbgetf(char *dir, char *group, char *key, char *fmt, ...); int dbgettree(char *dir, Tree *t, Treegetter func); int dbsettree(char *dir, Tree *t, Treesetter func); -/* loading.c */ -Loader *loading_open(int steps, char *initstr); -void loading_update(Loader *hand, char *str); -void loading_close(Loader *hand); - /* maths.c */ float cosf_d(float x); float sinf_d(float x); diff --git a/src/save.c b/src/save.c @@ -64,6 +64,14 @@ save_write(void) { } int +save_delete(char *name) { + char dir[PATH_MAX]; + + snprintf(dir, sizeof(dir), "%s/%s", SAVEDIR, name); + return rmdirp(dir); +} + +int save_exists(char *name) { char dir[PATH_MAX]; diff --git a/src/tree.c b/src/tree.c @@ -82,6 +82,8 @@ tree_delete(Tree **t, Treefree freedata) { freedata(e); free(e); + *t = NULL; + return 0; } @@ -125,6 +127,9 @@ tree_delete_r(Tree **t, Treefree freedata) { e->n->p = e->p; tree_delete_r_sub(e, freedata); + + *t = NULL; + return 0; } diff --git a/src/views/smenu.c b/src/views/smenu.c @@ -27,6 +27,7 @@ static int loadhandler_actual(int type, void *elem); static void loadprinter(int x, int y, Treeview *tv, Tree *t); static void loadadd(char *dir, time_t mod); static void loadinit(char *sdir); +static void loadfree(Tree *t); static View_smenu *v = &view_smenu; View_smenu view_smenu = { @@ -76,6 +77,7 @@ View_smenu view_smenu = { .print = loadprinter, .dclick = loadhandler_actual, }, + .delete = {0, "Delete", loadhandler_actual, 1 }, .load = {0, "Load", loadhandler_actual, 0 }, } }; @@ -170,18 +172,30 @@ quithandler(void) { static void loadhandler(void) { v->load.disp = 1; - /* strcpy(v->cont.label, CONTCUR); */ - /* v->b[SMENU_CONT].enabled = 1; */ } static int loadhandler_actual(int type, void *elem) { struct Loadable *l; + Button *b; + int delete; + + + if (type == GUI_BUTTON) { + b = elem; + delete = b->arg == 1; + } else delete = 0; l = v->load.savelist.sel->data; - save_read(l->name); - view_tabs.sel = VIEW_MAIN; - v->load.disp = 0; + + if (delete) { + save_delete(l->name); + tree_delete(&v->load.savelist.sel, loadfree); + } else { + save_read(l->name); + view_tabs.sel = VIEW_MAIN; + v->load.disp = 0; + } return 0; } @@ -211,6 +225,14 @@ loadadd(char *dir, time_t mod) { tree_add_child(&v->load.saves, p->name, 1, p, NULL); } +static void +loadfree(Tree *t) { + struct Loadable *p = t->data; + + free(p->name); + free(p); +} + void checkbeforequit(void) { if (save_changed()) { @@ -268,9 +290,9 @@ view_smenu_handle(int nowsel) { } if (v->load.disp && v->load.savelist.sel) - v->load.load.enabled = 1; + v->load.load.enabled = v->load.delete.enabled = 1; else - v->load.load.enabled = 0; + v->load.load.enabled = v->load.delete.enabled = 0; v->b[SMENU_SAVE].enabled = save ? 1 : 0; } @@ -336,9 +358,13 @@ view_smenu_draw(void) { y += PAD; gui_treeview(x, y, LOAD_W, LOAD_H, &v->load.savelist); - gui_button(x + w - BUTTON_W - PAD * 2, - y + h - PAD * 2 - BUTTON_HEIGHT, - BUTTON_W, &v->load.load); + + x += w - BUTTON_W - PAD * 2; + y += h - PAD * 2 - BUTTON_HEIGHT; + gui_button(x, y, BUTTON_W, &v->load.load); + + x -= BUTTON_W + PAD; + gui_button(x, y, BUTTON_W, &v->load.delete); } else { ui_draw_rect(EXPLODE_RECT(v->main), bg); ui_draw_border_around(EXPLODE_RECT(v->main), 1); diff --git a/src/views/struct.h b/src/views/struct.h @@ -110,6 +110,7 @@ typedef struct { int disp; Tree saves; Treeview savelist; + Button delete; Button load; } load; } View_smenu; diff --git a/tests/file.test b/tests/file.test @@ -0,0 +1,24 @@ +/* vim: set filetype=c : */ +#include <unistd.h> +#include <stdio.h> +#include "../src/main.h" + +%{ + FILE *f; + int ret; + + mkdirp("a/b/c"); + ck_assert(access("a", F_OK) == 0); + ck_assert(access("a/b", F_OK) == 0); + ck_assert(access("a/b/c", F_OK) == 0); + + f = fopen("a/b/d", "w"); + fclose(f); + + ret = rmdirp("a"); + ck_assert(access("a", F_OK) != 0); + ck_assert(access("a/b", F_OK) != 0); + ck_assert(access("a/b/c", F_OK) != 0); + ck_assert(access("a/b/d", F_OK) != 0); + ck_assert(ret == 0); +}