aboutsummaryrefslogtreecommitdiffstats
path: root/src/launcherutil.c
diff options
context:
space:
mode:
authorLibravatar bigfoot547 <[email protected]>2024-01-08 12:17:20 -0600
committerLibravatar bigfoot547 <[email protected]>2024-01-08 12:17:20 -0600
commitd38c13b2fe1293b499312bb4cfd66a56108c4b5e (patch)
tree998438c400a6b05f13d145270e95a9236ed7fb87 /src/launcherutil.c
parentadd to-do list (diff)
WIP: JRE stuff
Diffstat (limited to 'src/launcherutil.c')
-rw-r--r--src/launcherutil.c168
1 files changed, 168 insertions, 0 deletions
diff --git a/src/launcherutil.c b/src/launcherutil.c
index e1e8c40..b292df9 100644
--- a/src/launcherutil.c
+++ b/src/launcherutil.c
@@ -13,6 +13,8 @@
#include <sys/stat.h>
#include <stdarg.h>
#include <alloca.h>
+#include <ftw.h>
+#include <dirent.h>
/* handcoded string functions
*
@@ -138,6 +140,44 @@ int l2_launcher_open_config(const char *path, int flags, mode_t mode)
return instfd;
}
+int l2_launcher__rmtree_ftw_delete_with_reckless_abandon(const char *fpath, const struct stat *st, int typeflag, struct FTW *ftwbuf)
+{
+ L2_UNUSED(ftwbuf);
+ L2_UNUSED(st);
+
+ switch (typeflag) {
+ case FTW_F:
+ case FTW_SL:
+ if (unlink(fpath) < 0) {
+ CMD_WARN("l2_rm_tree: Failed to delete file or symlink %s: %s", fpath, strerror(errno));
+ return 1;
+ }
+ break;
+ case FTW_DP:
+ if (rmdir(fpath) < 0) {
+ CMD_WARN("l2_rm_tree: Failed to delete directory %s: %s", fpath, strerror(errno));
+ return 1;
+ }
+ break;
+ case FTW_DNR:
+ CMD_WARN("l2_rm_tree: Not traversing into directory I cannot read: %s", fpath);
+ break;
+ case FTW_NS:
+ CMD_WARN("l2_rm_tree: Not deleting/traversing file I cannot stat: %s", fpath);
+ break;
+ }
+ return 0;
+}
+
+int l2_launcher_rm_tree(const char *path, int nfds)
+{
+ if (nfds <= 0) nfds = 64;
+
+ int res = nftw(path, &l2_launcher__rmtree_ftw_delete_with_reckless_abandon, nfds, FTW_DEPTH | FTW_PHYS);
+ if (res != 0) return -1;
+ return 0;
+}
+
int l2_launcher_mkdir_parents(const char *path)
{
return l2_launcher_mkdir_parents_ex(path, 0);
@@ -465,3 +505,131 @@ cleanup:
if (pc) curl_easy_cleanup(pc);
return res;
}
+
+struct l2_ftw__data_int {
+ struct l2_ftw_data user;
+
+ size_t pathcap;
+ size_t pathlen;
+ int abort;
+};
+
+int l2_launcher__ftw_update_path(char **path, struct l2_ftw__data_int *ftw, const char *entname)
+{
+ size_t entlen = strlen(entname);
+ if (ftw->pathlen + entlen + 2 > ftw->pathcap) {
+ char *newpathbuf = realloc(*path, ftw->pathlen + entlen + 2);
+ if (!newpathbuf) return -1;
+ *path = newpathbuf;
+ ftw->pathcap = ftw->pathlen + entlen + 2;
+ }
+
+ (*path)[ftw->pathlen] = '/';
+ ++ftw->pathlen;
+ memcpy(*path + ftw->pathlen, entname, entlen + 1);
+ ftw->pathlen += entlen;
+ return 0;
+}
+
+int l2_launcher__ftw_internal(char **path, int depth, l2_ftw_proc_t *proc, struct l2_ftw__data_int *ftw)
+{
+ if (depth <= 0) {
+ CMD_DEBUG0("myftw: interation depth exceeded");
+ return -1;
+ }
+
+ DIR *thisdir = opendir(*path);
+ int res;
+ if (!thisdir) {
+ if (errno != ENOENT || ftw->user.depth == 0) {
+ CMD_DEBUG("myftw: could not open %s: %s", *path, strerror(errno));
+ return -1;
+ }
+ CMD_DEBUG("myftw: directory %s does not exist. (maybe it was deleted?)", *path);
+ return 0;
+ }
+
+ ++ftw->user.depth;
+
+ struct dirent *ent;
+ struct stat st;
+ size_t pathlen = ftw->pathlen;
+
+ errno = 0;
+ while ((ent = readdir(thisdir))) {
+ if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) continue;
+
+ int flags = 0;
+ if (fstatat(dirfd(thisdir), ent->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
+ CMD_DEBUG("myftw: stat failed %s: %s", *path, strerror(errno));
+ res = -1;
+ goto cleanup;
+ }
+
+ ftw->pathlen = pathlen;
+ (*path)[pathlen] = '\0';
+ l2_launcher__ftw_update_path(path, ftw, ent->d_name);
+
+ if (S_ISREG(st.st_mode)) {
+ flags |= L2_FTW_FILE;
+ }
+
+ if (S_ISDIR(st.st_mode)) {
+ flags |= L2_FTW_DIR;
+ }
+
+ if (S_ISLNK(st.st_mode)) {
+ flags |= L2_FTW_SYMLINK;
+ }
+
+ if ((res = (*proc)(*path, &st, flags, (struct l2_ftw_data *)ftw))) {
+ CMD_DEBUG("myftw: user aborted %s: %d", *path, res);
+ ftw->abort = 1;
+ goto cleanup;
+ }
+
+ if (S_ISDIR(st.st_mode)) {
+ if ((res = l2_launcher__ftw_internal(path, depth - 1, proc, ftw)) < 0 || ftw->abort) {
+ goto cleanup;
+ }
+ }
+
+ errno = 0;
+ }
+
+ if (errno) {
+ CMD_DEBUG("myftw: readdir failed on %s: %s", *path, strerror(errno));
+ res = -1;
+ goto cleanup;
+ }
+
+ --ftw->user.depth;
+ res = 0;
+
+cleanup:
+ closedir(thisdir);
+ return res;
+}
+
+int l2_launcher_ftw(const char *path, int depth, l2_ftw_proc_t *proc, void *user)
+{
+ struct l2_ftw__data_int data;
+ size_t pathlen = strlen(path);
+
+ data.user.depth = 0;
+ data.user.reloffset = pathlen + 1;
+ data.user.user = user;
+ data.abort = 0;
+
+ char *pathdup = strdup(path);
+ data.pathcap = pathlen + 1;
+ data.pathlen = pathlen;
+
+ if (!pathdup) return -1;
+
+ int res = l2_launcher__ftw_internal(&pathdup, depth, proc, &data);
+
+ free(pathdup);
+
+ return res;
+}