aboutsummaryrefslogtreecommitdiffstats
path: root/service
diff options
context:
space:
mode:
Diffstat (limited to 'service')
-rw-r--r--service/Dockerfile13
-rw-r--r--service/cleaner.sh24
-rw-r--r--service/cleaner/.gitignore1
-rw-r--r--service/cleaner/Makefile7
-rw-r--r--service/cleaner/main.c155
-rwxr-xr-xservice/entrypoint.sh15
-rw-r--r--service/src/main.c93
7 files changed, 243 insertions, 65 deletions
diff --git a/service/Dockerfile b/service/Dockerfile
index 66952dc..c49190e 100644
--- a/service/Dockerfile
+++ b/service/Dockerfile
@@ -8,16 +8,19 @@ RUN adduser --system --ingroup service --uid 1000 service
COPY entrypoint.sh /
RUN chmod 755 /entrypoint.sh
-COPY cleaner.sh /
-RUN chmod 755 /cleaner.sh
+COPY cleaner /cleaner
+RUN make -C /cleaner clean && make -C /cleaner
+RUN cp /cleaner/cleaner /usr/bin/cleaner
+run chmod +x /usr/bin/cleaner
COPY src/ /service/
+RUN make -C /service clean && make -C /service
+RUN chmod +x /service/build/stldoctor
WORKDIR /service/
-RUN make clean && make
-
-EXPOSE 9000
ENV RESULTDIR=/data/uploads
+EXPOSE 9000
+
ENTRYPOINT ["/entrypoint.sh"]
diff --git a/service/cleaner.sh b/service/cleaner.sh
deleted file mode 100644
index bd67705..0000000
--- a/service/cleaner.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/sh
-
-timeref="/data/lastclean"
-
-if [ -z "$RESULTDIR" ]; then
- echo "RESULTDIR is undefined! skipping cleanup.."
- exit 1
-fi
-
-if [ -f "$timeref" ]; then
- files="$(find "$RESULTDIR" -mindepth 1 \! -newer "$timeref")"
- echo "$files" | while read path; do
- rm -rf "$path"
- done
- if [ -z "$files" ]; then
- filecount=0
- else
- filecount=$(echo "$files" | wc -l)
- fi
- echo "[ $(date +%T) ] Removed $filecount old files!"
-fi
-
-touch "$timeref"
-
diff --git a/service/cleaner/.gitignore b/service/cleaner/.gitignore
new file mode 100644
index 0000000..021c4e8
--- /dev/null
+++ b/service/cleaner/.gitignore
@@ -0,0 +1 @@
+cleaner
diff --git a/service/cleaner/Makefile b/service/cleaner/Makefile
new file mode 100644
index 0000000..1589c27
--- /dev/null
+++ b/service/cleaner/Makefile
@@ -0,0 +1,7 @@
+all: cleaner
+
+clean:
+ rm cleaner
+
+cleaner: main.c
+ $(CC) -o $@ $<
diff --git a/service/cleaner/main.c b/service/cleaner/main.c
new file mode 100644
index 0000000..ef48dfa
--- /dev/null
+++ b/service/cleaner/main.c
@@ -0,0 +1,155 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include <unistd.h>
+#include <dirent.h>
+#include <time.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+
+void
+die(const char *fmtstr, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "CLEANER: ");
+ va_start(ap, fmtstr);
+ vfprintf(stderr, fmtstr, ap);
+ va_end(ap);
+
+ exit(EXIT_FAILURE);
+}
+
+int
+creation_time(const char *path)
+{
+ struct stat attrib;
+
+ stat(path, &attrib);
+ return attrib.st_ctim.tv_sec;
+}
+
+char*
+aprintf(const char *fmtstr, ...)
+{
+ va_list ap, cpy;
+ size_t nb;
+ char *str;
+
+ va_copy(cpy, ap);
+
+ va_start(cpy, fmtstr);
+ nb = vsnprintf(NULL, 0, fmtstr, cpy);
+ va_end(cpy);
+
+ if (nb <= 0) die("Invalid fmtstr!\n");
+ str = malloc(nb+1);
+ if (!str) die("Alloc of fmtstr failed\n");
+
+ va_start(ap, fmtstr);
+ nb = vsnprintf(str, nb+1, fmtstr, ap);
+ va_end(ap);
+
+ return str;
+}
+
+void
+recdel(const char *path)
+{
+ struct stat attrib;
+ struct dirent *de;
+ char *subpath;
+ DIR *d;
+
+ stat(path, &attrib);
+ if (S_ISDIR(attrib.st_mode)) {
+ d = opendir(path);
+ while ((de = readdir(d))) {
+ if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
+ continue;
+ subpath = aprintf("%s/%s", path, de->d_name);
+ recdel(subpath);
+ free(subpath);
+ }
+ closedir(d);
+ rmdir(path);
+ } else {
+ remove(path);
+ }
+}
+
+int
+main(int argc, const char **argv)
+{
+ char buf[256], *end, *path,
+ **paths, *oldpath, *newpath;
+ unsigned long reftime;
+ int i, pathc, pathcap, nread;
+ const char *dirpath;
+ FILE *f, *fn;
+
+ if (argc != 3) die("USAGE: cleaner DIR REFTIME\n");
+
+ dirpath = argv[1];
+
+ reftime = strtoul(argv[2], &end, 10);
+ if (end && *end) die("Invalid unix time reference\n");
+
+ oldpath = aprintf("%s/.index", dirpath);
+ if (!(f = fopen(oldpath, "r+")))
+ die("Missing index file: %s\n", oldpath);
+ flock(fileno(f), LOCK_EX);
+
+ newpath = aprintf("%s/.index.next", dirpath);
+ if (!(fn = fopen(newpath, "w+")))
+ die("Failed to create index file: %s\n", newpath);
+
+ pathc = 0;
+ pathcap = 1024;
+ paths = malloc(pathcap * sizeof(char*));
+ if (!paths) die("OOM - allocating initial path array\n");
+
+ while (fgets(buf, sizeof(buf), f)) {
+ if (*buf && buf[strlen(buf)-1] == '\n')
+ buf[strlen(buf)-1] = '\0';
+
+ path = aprintf("%s/%s", dirpath, buf);
+ if (creation_time(path) < reftime) {
+ paths[pathc] = strdup(path);
+ if (!paths[pathc++]) die("OOM - during path str alloc\n");
+ if (pathc == pathcap) {
+ pathcap *= 2;
+ paths = realloc(paths, pathcap * sizeof(char*));
+ if (!paths) die("OOM - too many paths to alloc\n");
+ }
+ } else {
+ fwrite(buf, 1, strlen(buf), fn);
+ putc('\n', fn);
+ }
+ free(path);
+ }
+
+ fseek(f, 0, SEEK_SET);
+ fseek(fn, 0, SEEK_SET);
+ while ((nread = fread(buf, 1, sizeof(buf), fn)) > 0)
+ fwrite(buf, 1, nread, f);
+ ftruncate(fileno(f), ftell(f));
+
+ nread = ftell(f);
+
+ flock(fileno(f), LOCK_UN);
+ fclose(f);
+ fclose(fn);
+
+ if (!nread && getenv("DELROOT")) {
+ remove(oldpath);
+ remove(newpath);
+ }
+
+ for (i = 0; i < pathc; i++) {
+ printf("CLEANER: REMOVED %s\n", paths[i]);
+ recdel(paths[i]);
+ }
+}
diff --git a/service/entrypoint.sh b/service/entrypoint.sh
index 614b251..f266474 100755
--- a/service/entrypoint.sh
+++ b/service/entrypoint.sh
@@ -3,10 +3,19 @@
mkdir -p "$RESULTDIR"
chown -R service:service "$RESULTDIR"
+expiry=$((13*60))
while [ 1 ]; do
- /cleaner.sh
- sleep $((60*13)) # data persistence for atleast 11 rounds
+ reftime="$(($(date +%s)-$expiry))"
+ echo "[FILE CLEANUP] @ $(date +%T)"
+ cleaner "$RESULTDIR" "$reftime"
+ DELROOT=1 find "$RESULTDIR" -maxdepth 1 -regextype posix-extended \
+ -regex '.*/\.[^/]+$' ! -name .index ! -name .index.next \
+ -exec cleaner {} "$reftime" \;
+ find "$RESULTDIR" -regextype posix-extended \
+ -regex '.*/\.[^/]+$' -type d -empty -delete
+ sleep 70
done &
-CMD="socat -T180 -s TCP-LISTEN:9000,nodelay,reuseaddr,fork EXEC:/service/build/stldoctor,raw,pty,echo=0,stderr"
+CMD="socat -T180 -s TCP-LISTEN:9000,nodelay,reuseaddr,fork \
+EXEC:/service/build/stldoctor,raw,pty,echo=0,stderr"
su -s /bin/sh -c "$CMD" service
diff --git a/service/src/main.c b/service/src/main.c
index 5f3282d..cc92cf5 100644
--- a/service/src/main.c
+++ b/service/src/main.c
@@ -2,7 +2,6 @@
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
-#include <dirent.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>
@@ -56,7 +55,6 @@ save_submission(struct parseinfo *info, char *stldata, int stlsize)
*indexpath = NULL, *modelpath = NULL;
FILE *f = NULL;
int status = OK;
- DIR *d;
modeldir = aprintf("%s%s-%i", loggedin ? "." : "",
info->hash, time(NULL));
@@ -296,22 +294,28 @@ search_cmd(const char *arg)
while ((c = fgetc(f)) > 0) {
if (c == '\n') {
matchlen = 0;
+ continue;
} else if (matchlen == -1) {
continue;
+ } else if (!matchlen && c == '.') {
+ if (!loggedin) matchlen = -1;
+ continue;
} else if (c == hash[matchlen]) {
matchlen += 1;
- if (matchlen == strlen(hash)) {
- fseek(f, -matchlen, SEEK_CUR);
- putchar(' ');
- while ((c = fgetc(f)) > 0 && c != '\n')
- putchar(c);
- putchar('\n');
- matchlen = 0;
- reslen += 1;
- }
} else {
matchlen = -1;
}
+
+ if (matchlen == strlen(hash)) {
+ fseek(f, -matchlen, SEEK_CUR);
+ putchar(' ');
+ if (loggedin) putchar('.');
+ while ((c = fgetc(f)) > 0 && c != '\n')
+ putchar(c);
+ putchar('\n');
+ matchlen = 0;
+ reslen += 1;
+ }
}
flock(fileno(f), LOCK_UN);
@@ -326,7 +330,7 @@ search_cmd(const char *arg)
resp = ask("> Enter %s [q to quit]: ",
resp ? "another" : "hash");
if (strchr(resp, 'q')) break;
- if (checkalph(resp, "abcdef0123456789-") != OK) {
+ if (checkalph(resp, ".abcdef0123456789-") != OK) {
ERR("Invalid model id specified\n");
goto exit;
}
@@ -345,43 +349,50 @@ exit:
void
list_cmd(const char *arg)
{
- struct dirent *de;
struct parseinfo info;
- char *path;
- FILE *f;
- DIR *d;
+ char buf[256], *path;
+ FILE *f, *fn;
if (!loggedin) {
ERR("Not logged in!\n");
return;
}
- if (!(d = opendir(resultdir))) return;
-
- while ((de = readdir(d))) {
- if (*de->d_name == '.' && !strchr(".", de->d_name[1])) {
- printf(">> %s\n", de->d_name);
- path = aprintf("%s/%s/info", resultdir, de->d_name);
- if ((f = fopen(path, "r")) && load_info(&info, f) == OK) {
- print_info(&info);
- free_info(&info);
- } else {
- ERR("Failed to read file info!\n");
- }
- if (f) fclose(f);
- free(path);
- }
+ path = aprintf("%s/.index", resultdir);
+ if (!(f = fopen(path, "r"))) {
+ ERR("Failed to get files index\n");
+ free(path);
+ return;
}
+ free(path);
- closedir(d);
+ flock(fileno(f), LOCK_SH);
+ while (fgets(buf, sizeof(buf), f)) {
+ if (*buf && buf[strlen(buf)-1] == '\n')
+ buf[strlen(buf)-1] = '\0';
+
+ printf(">> %s\n", buf);
+ path = aprintf("%s/%s/info", resultdir, buf);
+ if ((fn = fopen(path, "r")) && load_info(&info, fn) == OK) {
+ print_info(&info);
+ free_info(&info);
+ } else {
+ ERR("Failed to read file info!\n");
+ }
+ if (fn) fclose(f);
+ free(path);
+ }
+ flock(fileno(f), LOCK_UN);
+ fclose(f);
}
void
auth_cmd(const char *arg)
{
const char *hash;
- char *ndir;
+ char *ndir, *indexpath;
int ret;
+ FILE *f;
if (loggedin) {
ERR("Already logged in!\n");
@@ -400,6 +411,22 @@ auth_cmd(const char *arg)
return;
}
+ if (errno != EEXIST) {
+ indexpath = aprintf("%s/.index", resultdir);
+ if (!(f = fopen(indexpath, "a+"))) {
+ free(indexpath);
+ ERR("Auth failed!\n");
+ return;
+ }
+ flock(fileno(f), LOCK_EX);
+ fputc('.', f);
+ fwrite(hash, 1, strlen(hash), f);
+ fputc('\n', f);
+ flock(fileno(f), LOCK_UN);
+ fclose(f);
+ free(indexpath);
+ }
+
free(resultdir);
resultdir = ndir;
loggedin = 1;