commit 3139342aa61d78985298d7450f97513a8aeec681
parent 8ee81f0d908bee3991248d3c86e5ce0ab2219a05
Author: Louis Burda <quent.burda@gmail.com>
Date: Wed, 7 Jul 2021 14:22:52 +0200
added .index file for upload and search
Diffstat:
4 files changed, 148 insertions(+), 100 deletions(-)
diff --git a/service/src/main.c b/service/src/main.c
@@ -4,14 +4,16 @@
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
-#include <sys/stat.h>
#include <time.h>
#include <errno.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+
#include "stlfile.h"
#include "util.h"
-#define MAXFILESIZE 50000
+#define MAXFILESIZE 1000000
struct command {
const char *name;
@@ -50,15 +52,15 @@ int echo = 0, loggedin = 0;
int
save_submission(struct parseinfo *info, char *stldata, int stlsize)
{
- char *dirpath = NULL, *infopath = NULL, *modelpath = NULL;
+ char *dirpath = NULL, *infopath = NULL, *modeldir = NULL,
+ *indexpath = NULL, *modelpath = NULL;
FILE *f = NULL;
int status = OK;
DIR *d;
- if (loggedin)
- dirpath = aprintf("%s/.%s-%i", resultdir, info->hash, time(NULL));
- else
- dirpath = aprintf("%s/%s-%i", resultdir, info->hash, time(NULL));
+ modeldir = aprintf("%s%s-%i", loggedin ? "." : "",
+ info->hash, time(NULL));
+ dirpath = aprintf("%s/%s", resultdir, modeldir);
if (mkdir(dirpath, S_IRWXU | S_IRWXG | S_IRWXO)) goto fail;
modelpath = aprintf("%s/%s", dirpath, "model");
@@ -71,12 +73,22 @@ save_submission(struct parseinfo *info, char *stldata, int stlsize)
if (save_info(info, f) != OK) goto fail;
FCLOSE(f);
+ indexpath = aprintf("%s/.index", resultdir);
+ if (!(f = fopen(indexpath, "a+"))) goto fail;
+ flock(fileno(f), LOCK_EX);
+ fwrite(modeldir, 1, strlen(modeldir), f);
+ fputc('\n', f);
+ flock(fileno(f), LOCK_UN);
+ FCLOSE(f);
+
exit:
- if (f) fclose(f);
+ FCLOSE(f);
free(dirpath);
free(modelpath);
free(infopath);
+ free(indexpath);
+ free(modeldir);
return status;
@@ -119,7 +131,7 @@ handle_download(const char *scandir)
print_info(&cached);
- if (strchr(ask("Download the model? "), 'y')) {
+ if (strchr(ask("> Download model? "), 'y')) {
modelpath = aprintf("%s/%s", scandir, "model");
if (!(f = fopen(modelpath, "r"))) {
ERR("Failed to access file!\n");
@@ -222,13 +234,13 @@ upload_cmd(const char *arg)
const char *resp;
size_t len;
- modelname = checkp(strdup(ask("Enter a model name: ")));
+ modelname = checkp(strdup(ask("> Model name: ")));
if (!strlen(modelname)) {
ERR("Empty model names are not allowed");
goto exit;
}
- resp = ask("How large is your file? ");
+ resp = ask("> File size: ");
len = strtoul(resp, &end, 10);
if (len <= 0 || len >= MAXFILESIZE || *end) {
ERR("Invalid file length!\n");
@@ -258,11 +270,10 @@ exit:
void
search_cmd(const char *arg)
{
- char *end, *scandir = NULL, **paths = NULL;
- int i, which, pathc, pathcap = 100;
- const char *hash, *name, *resp;
- struct dirent *de;
- DIR *d = NULL;
+ const char *hash, *resp = NULL;
+ char *indexpath = NULL, *seldir = NULL;
+ FILE *f;
+ int i, c, matchlen, reslen;
if (arg && !strcmp(arg, "last")) {
if (!cached.valid) {
@@ -271,53 +282,64 @@ search_cmd(const char *arg)
}
hash = cached.hash;
} else {
- hash = mhash(arg ? arg : ask("Model name: "), -1);
+ hash = mhash(arg ? arg : ask("> Model name: "), -1);
}
- if (!(d = opendir(resultdir))) {
- ERR("Unable to access upload directory!\n");
- return;
+ indexpath = aprintf("%s/.index", resultdir);
+ if (!(f = fopen(indexpath, "r"))) {
+ ERR("Sorry, no files currently available\n");
+ goto exit;
}
-
- paths = checkp(malloc(pathcap * sizeof(char*)));
- for (pathc = 0; (de = readdir(d));) {
- if (access_authorized(de->d_name)
- && !strpfcmp(hash, de->d_name + (loggedin ? 1 : 0))) {
- printf("%i : %s\n", pathc, de->d_name);
- paths[pathc++] = checkp(strdup(de->d_name));
- if (pathc == pathcap) {
- pathcap *= 2;
- paths = realloc(paths, pathcap * sizeof(char*));
- checkp(paths);
+ flock(fileno(f), LOCK_SH);
+
+ reslen = matchlen = 0;
+ while ((c = fgetc(f)) > 0) {
+ if (c == '\n') {
+ matchlen = 0;
+ } else if (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;
}
}
- closedir(d);
- if (pathc == 0) {
- ERR("Couldn't find a matching scan result!\n");
+ flock(fileno(f), LOCK_UN);
+ fclose(f);
+
+ if (!reslen) {
+ ERR("Sorry, no files matching that name\n");
goto exit;
}
while (1) {
- resp = ask("Which result [q to quit]? ");
+ resp = ask("> Enter %s [q to quit]: ",
+ resp ? "another" : "hash");
if (strchr(resp, 'q')) break;
- which = strtoul(resp, &end, 10);
- if (which >= pathc || which < 0 || *end) {
- ERR("Invalid index!\n");
+ if (checkalph(resp, "abcdef0123456789-") != OK) {
+ ERR("Invalid model id specified\n");
goto exit;
}
- scandir = aprintf("%s/%s", resultdir, paths[which]);
- if (handle_download(scandir) != OK) goto exit;
- FREE(scandir);
+ seldir = aprintf("%s/%s", resultdir, resp);
+ if (handle_download(seldir) != OK) goto exit;
+ FREE(seldir);
}
exit:
- FREE(scandir);
-
- for (i = 0; i < pathc; i++) free(paths[i]);
- free(paths);
+ free(seldir);
+ free(indexpath);
+ return;
}
void
@@ -366,7 +388,7 @@ auth_cmd(const char *arg)
return;
}
- hash = mhash(arg ? arg : ask("Enter a password: "), -1);
+ hash = mhash(arg ? arg : ask("> Enter a password: "), -1);
ndir = aprintf("%s/.%s", resultdir, hash);
ret = mkdir(ndir, S_IRWXU | S_IRWXG | S_IRWXO);
if (!ret) {
diff --git a/service/src/util.c b/service/src/util.c
@@ -64,12 +64,12 @@ mhash(const char *str, int len)
int
checkalph(const char *str, const char *alph)
{
- int i;
+ const char *c;
- for (i = 0; i < strlen(str); i++)
- if (str[i] && !strchr(alph, str[i])) return 0;
+ for (c = str; *c; c++)
+ if (!strchr(alph, *c)) return FAIL;
- return 1;
+ return OK;
}
void
diff --git a/src/main.c b/src/main.c
@@ -4,14 +4,16 @@
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
-#include <sys/stat.h>
#include <time.h>
#include <errno.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+
#include "stlfile.h"
#include "util.h"
-#define MAXFILESIZE 50000 // 20kB file limit
+#define MAXFILESIZE 1000000
struct command {
const char *name;
@@ -50,15 +52,15 @@ int echo = 0, loggedin = 0;
int
save_submission(struct parseinfo *info, char *stldata, int stlsize)
{
- char *dirpath = NULL, *infopath = NULL, *modelpath = NULL;
+ char *dirpath = NULL, *infopath = NULL, *modeldir = NULL,
+ *indexpath = NULL, *modelpath = NULL;
FILE *f = NULL;
int status = OK;
DIR *d;
- if (loggedin)
- dirpath = aprintf("%s/.%s-%i", resultdir, info->hash, time(NULL));
- else
- dirpath = aprintf("%s/%s-%i", resultdir, info->hash, time(NULL));
+ modeldir = aprintf("%s%s-%i", loggedin ? "." : "",
+ info->hash, time(NULL));
+ dirpath = aprintf("%s/%s", resultdir, modeldir);
if (mkdir(dirpath, S_IRWXU | S_IRWXG | S_IRWXO)) goto fail;
modelpath = aprintf("%s/%s", dirpath, "model");
@@ -71,12 +73,22 @@ save_submission(struct parseinfo *info, char *stldata, int stlsize)
if (save_info(info, f) != OK) goto fail;
FCLOSE(f);
+ indexpath = aprintf("%s/.index", resultdir);
+ if (!(f = fopen(indexpath, "a+"))) goto fail;
+ flock(fileno(f), LOCK_EX);
+ fwrite(modeldir, 1, strlen(modeldir), f);
+ fputc('\n', f);
+ flock(fileno(f), LOCK_UN);
+ FCLOSE(f);
+
exit:
- if (f) fclose(f);
+ FCLOSE(f);
free(dirpath);
free(modelpath);
free(infopath);
+ free(indexpath);
+ free(modeldir);
return status;
@@ -119,7 +131,7 @@ handle_download(const char *scandir)
print_info(&cached);
- if (strchr(ask("Download the model? "), 'y')) {
+ if (strchr(ask("> Download model? "), 'y')) {
modelpath = aprintf("%s/%s", scandir, "model");
if (!(f = fopen(modelpath, "r"))) {
ERR("Failed to access file!\n");
@@ -222,13 +234,13 @@ upload_cmd(const char *arg)
const char *resp;
size_t len;
- modelname = checkp(strdup(ask("Enter a model name: ")));
+ modelname = checkp(strdup(ask("> Model name: ")));
if (!strlen(modelname)) {
ERR("Empty model names are not allowed");
goto exit;
}
- resp = ask("How large is your file? ");
+ resp = ask("> File size: ");
len = strtoul(resp, &end, 10);
if (len <= 0 || len >= MAXFILESIZE || *end) {
ERR("Invalid file length!\n");
@@ -258,12 +270,12 @@ exit:
void
search_cmd(const char *arg)
{
- char *end, *scandir = NULL, **paths = NULL;
- int i, which, pathc, pathcap = 100;
- const char *hash, *name, *resp;
- struct dirent *de;
- DIR *d = NULL;
+ const char *hash, *resp = NULL;
+ char *indexpath = NULL, *seldir = NULL;
+ FILE *f;
+ int i, c, matchlen, reslen;
+ /* either choose cached or request new entry */
if (arg && !strcmp(arg, "last")) {
if (!cached.valid) {
ERR("No cached info report available\n");
@@ -271,53 +283,67 @@ search_cmd(const char *arg)
}
hash = cached.hash;
} else {
- hash = mhash(arg ? arg : ask("Model name: "), -1);
+ hash = mhash(arg ? arg : ask("> Model name: "), -1);
}
- if (!(d = opendir(resultdir))) {
- ERR("Unable to access upload directory!\n");
- return;
+ /* open and lock index file access */
+ indexpath = aprintf("%s/.index", resultdir);
+ if (!(f = fopen(indexpath, "r"))) {
+ ERR("Sorry, no files currently available\n");
+ goto exit;
}
-
- paths = checkp(malloc(pathcap * sizeof(char*)));
- for (pathc = 0; (de = readdir(d));) {
- if (access_authorized(de->d_name)
- && !strpfcmp(hash, de->d_name + (loggedin ? 1 : 0))) {
- printf("%i : %s\n", pathc, de->d_name);
- paths[pathc++] = checkp(strdup(de->d_name));
- if (pathc == pathcap) {
- pathcap *= 2;
- paths = realloc(paths, pathcap * sizeof(char*));
- checkp(paths);
+ flock(fileno(f), LOCK_SH);
+
+ /* output lines that have hash as prefix */
+ reslen = matchlen = 0;
+ while ((c = fgetc(f)) > 0) {
+ if (c == '\n') {
+ matchlen = 0;
+ } else if (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;
}
}
- closedir(d);
- if (pathc == 0) {
- ERR("Couldn't find a matching scan result!\n");
+ flock(fileno(f), LOCK_UN);
+ fclose(f);
+
+ if (!reslen) {
+ ERR("Sorry, no files matching that name\n");
goto exit;
}
+ /* allow user to choose files to access */
while (1) {
- resp = ask("Which result [q to quit]? ");
+ resp = ask("> Enter %s [q to quit]: ",
+ resp ? "another" : "hash");
if (strchr(resp, 'q')) break;
- which = strtoul(resp, &end, 10);
- if (which >= pathc || which < 0 || *end) {
- ERR("Invalid index!\n");
+ if (checkalph(resp, "abcdef0123456789-") != OK) {
+ ERR("Invalid model id specified\n");
goto exit;
}
- scandir = aprintf("%s/%s", resultdir, paths[which]);
- if (handle_download(scandir) != OK) goto exit;
- FREE(scandir);
+ seldir = aprintf("%s/%s", resultdir, resp);
+ if (handle_download(seldir) != OK) goto exit;
+ FREE(seldir);
}
exit:
- FREE(scandir);
-
- for (i = 0; i < pathc; i++) free(paths[i]);
- free(paths);
+ free(seldir);
+ free(indexpath);
+ return;
}
void
@@ -366,7 +392,7 @@ auth_cmd(const char *arg)
return;
}
- hash = mhash(arg ? arg : ask("Enter a password: "), -1);
+ hash = mhash(arg ? arg : ask("> Enter a password: "), -1);
ndir = aprintf("%s/.%s", resultdir, hash);
ret = mkdir(ndir, S_IRWXU | S_IRWXG | S_IRWXO);
if (!ret) {
diff --git a/src/util.c b/src/util.c
@@ -67,12 +67,12 @@ mhash(const char *str, int len)
int
checkalph(const char *str, const char *alph)
{
- int i;
+ const char *c;
- for (i = 0; i < strlen(str); i++)
- if (str[i] && !strchr(alph, str[i])) return 0;
+ for (c = str; *c; c++)
+ if (!strchr(alph, *c)) return FAIL;
- return 1;
+ return OK;
}
void