Modify mylist entries based on size + filename

This commit is contained in:
x3 2022-01-14 11:26:54 +01:00
parent 54017d0971
commit c075609073
Signed by: x3
GPG Key ID: 7E9961E8AD0E240E
9 changed files with 175 additions and 20 deletions

View File

@ -37,4 +37,7 @@ make
- Handle C-c gracefully at any time
- Rework cmd line args
- Should be multiple 'menus' like `caniadd add [paths...]`, `caniadd uptime`, `caniadd watched`...
- After some time passes between now and cache moddate and it's not watched, then query and update it
- Update cache entry is modify is used
- Pretty hashing with color and progress bars and the other fancy stuff
- Write -h page, and maybe a man page too

View File

@ -250,9 +250,9 @@ struct api_mylistmod_result {
struct api_result {
uint16_t code;
union {
struct api_version_result version;
struct api_auth_result auth;
struct api_uptime_result uptime;
e(version);
e(auth);
e(uptime);
e(mylistadd);
e(encrypt);
e(mylistmod);

View File

@ -8,6 +8,8 @@
#include "ed2k.h"
#include "util.h"
static bool cache_did_init = false;
#define sqlite_bind_goto(smt, name, type, ...) { \
int sb_idx = sqlite3_bind_parameter_index(smt, name); \
if (sb_idx == 0) { \
@ -30,11 +32,13 @@ static const char sql_create_table[] = "CREATE TABLE IF NOT EXISTS mylist ("
"fname TEXT NOT NULL,"
"fsize INTEGER NOT NULL,"
"ed2k TEXT NOT NULL,"
"watchdate INTEGER,"
"state INTEGER NOT NULL,"
"moddate INTEGER NOT NULL DEFAULT (strftime('%s')),"
"UNIQUE (fname, fsize) )";
static const char sql_mylist_add[] = "INSERT INTO mylist "
"(lid, fname, fsize, ed2k) VALUES "
//"(?, ?, ?, ?)";
"(:lid, :fname, :fsize, :ed2k)";
"(lid, fname, fsize, ed2k, watchdate, state) VALUES "
"(:lid, :fname, :fsize, :ed2k, :watchdate, :state)";
static const char sql_mylist_get[] = "SELECT * FROM mylist WHERE "
"fsize=:fsize AND fname=:fname";
@ -119,6 +123,7 @@ enum error cache_init()
if (err != NOERR)
goto fail;
cache_did_init = true;
return NOERR;
fail:
@ -126,14 +131,21 @@ fail:
return err;
}
bool cache_is_init()
{
return cache_did_init;
}
void cache_free()
{
cache_did_init = false;
sqlite3_close(cache_db);
uio_debug("Closed cache db");
}
enum error cache_add(uint64_t lid, const char *fname,
uint64_t fsize, const uint8_t *ed2k)
uint64_t fsize, const uint8_t *ed2k, uint64_t watchdate,
enum mylist_state state)
{
char ed2k_str[ED2K_HASH_SIZE * 2 + 1];
sqlite3_stmt *smt;
@ -153,6 +165,8 @@ enum error cache_add(uint64_t lid, const char *fname,
sqlite_bind_goto(smt, ":fname", text, fname, -1, SQLITE_STATIC);
sqlite_bind_goto(smt, ":fsize", int64, fsize);
sqlite_bind_goto(smt, ":ed2k", text, ed2k_str, -1, SQLITE_STATIC);
sqlite_bind_goto(smt, ":watchdate", int64, watchdate);
sqlite_bind_goto(smt, ":state", int64, state);
sret = sqlite3_step(smt);
if (sret != SQLITE_DONE) {
@ -174,7 +188,7 @@ fail:
}
enum error cache_get(const char *fname, uint64_t fsize,
enum error cache_get(const char *fname, uint64_t fsize, enum cache_select sel,
struct cache_entry *out_ce)
{
sqlite3_stmt *smt;
@ -195,14 +209,45 @@ enum error cache_get(const char *fname, uint64_t fsize,
if (sret == SQLITE_DONE) {
uio_debug("Cache entry with size (%lu) and name (%s) not found", fsize, fname);
err = ERR_CACHE_NO_EXISTS;
goto fail;
} else if (sret == SQLITE_ROW) {
uio_debug("Found Cache entry with size (%lu) and name (%s)", fsize, fname);
} else {
uio_error("sqlite_step failed: %s", sqlite3_errmsg(cache_db));
err = ERR_CACHE_SQLITE;
goto fail;
}
if (!out_ce)
goto end;
if (sel == 0)
sel = 0xFFFFFFFF;
if (sel & CACHE_S_LID)
out_ce->lid = sqlite3_column_int64(smt, 0);
if (sel & CACHE_S_FNAME)
out_ce->fname = strdup((const char *)sqlite3_column_text(smt, 1));
if (sel & CACHE_S_FSIZE)
out_ce->fsize = sqlite3_column_int64(smt, 2);
if (sel & CACHE_S_ED2K) {
const char *txt = (const char *)sqlite3_column_text(smt, 3);
util_hex2byte(txt, out_ce->ed2k);
}
if (sel & CACHE_S_WATCHDATE)
out_ce->wdate = sqlite3_column_int64(smt, 4);
if (sel & CACHE_S_STATE)
out_ce->state = sqlite3_column_int(smt, 5);
if (sel & CACHE_S_MODDATE)
out_ce->moddate = sqlite3_column_int64(smt, 6);
end:
fail:
sqlite3_finalize(smt);
return err;
}
bool cache_exists(const char *fname, uint64_t size)
{
return cache_get(fname, size, 0, NULL) == NOERR;
}

View File

@ -5,11 +5,27 @@
#include "error.h"
#include "ed2k.h"
#include "api.h"
enum cache_select {
CACHE_S_ALL = 0,
CACHE_S_LID = 1 << 0,
CACHE_S_FNAME = 1 << 1,
CACHE_S_FSIZE = 1 << 2,
CACHE_S_ED2K = 1 << 3,
CACHE_S_WATCHED = 1 << 4,
CACHE_S_WATCHDATE = 1 << 5,
CACHE_S_STATE = 1 << 6,
CACHE_S_MODDATE = 1 << 7,
};
struct cache_entry {
uint64_t lid, fsize;
uint64_t lid, fsize, wdate, moddate;
/* free() if requested */
char *fname;
uint8_t ed2k[ED2K_HASH_SIZE];
bool watched;
uint16_t state;
};
/*
@ -17,6 +33,11 @@ struct cache_entry {
*/
enum error cache_init();
/*
* Is the cache already setup or not?
*/
bool cache_is_init();
/*
* Free tha cache
*/
@ -26,15 +47,30 @@ void cache_free();
* Add a new mylist entry to the cache
*/
enum error cache_add(uint64_t lid, const char *fname,
uint64_t fsize, const uint8_t *ed2k);
uint64_t fsize, const uint8_t *ed2k, uint64_t watchdate,
enum mylist_state state);
/*
* Update an already existing cache entry
*/
enum error cache_update();
/*
* Get a cache entry
*
* sel is the columns to select
* If 0, everything is selected and returned.
* Can be ORed together
*
* out_ce can be NULL. Useful, if we only want
* to check if the entry exists or not.
*/
enum error cache_get(const char *fname, uint64_t size,
enum error cache_get(const char *fname, uint64_t fsize, enum cache_select sel,
struct cache_entry *out_ce);
/*
* Does an entry exists?
*/
bool cache_exists(const char *fname, uint64_t size);
#endif /* _CACHE_H */

View File

@ -2,6 +2,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <time.h>
#include "cmd.h"
#include "error.h"
@ -18,7 +19,7 @@ enum error cmd_add_cachecheck(const char *path, const struct stat *st,
const char *bname = util_basename(path);
enum error err;
err = cache_get(bname, st->st_size, NULL);
err = cache_get(bname, st->st_size, 0, NULL);
if (err == NOERR) {
/* We could get the entry, so it exists already */
uio_user("This file (%s) with size (%lu) already exists in cache."
@ -54,7 +55,8 @@ enum error cmd_add_apisend(const char *path, const uint8_t *hash,
x->lid, x->fid, x->eid, x->aid, x->gid, x->date, x->viewdate,
x->state, x->filestate, x->storage, x->source, x->other);
cache_add(x->lid, util_basename(path), st->st_size, hash);
cache_add(x->lid, util_basename(path), st->st_size, hash, x->viewdate,
x->state);
if (x->storage)
free(x->storage);
@ -71,7 +73,17 @@ enum error cmd_add_apisend(const char *path, const uint8_t *hash,
uio_user("Succesfully added!");
uio_debug("New mylist id is: %ld", r.mylistadd.new_id);
cache_add(r.mylistadd.new_id, util_basename(path), st->st_size, hash);
uint64_t wdate = 0;
if (mopt->watched_set && mopt->watched) {
if (mopt->wdate_set)
wdate = mopt->wdate;
else
wdate = time(NULL);
}
cache_add(r.mylistadd.new_id, util_basename(path), st->st_size, hash,
wdate, mopt->state_set ? mopt->state : MYLIST_STATE_INTERNAL);
return NOERR;
}

View File

@ -1,17 +1,42 @@
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include "cmd.h"
#include "error.h"
#include "uio.h"
#include "api.h"
#include "config.h"
#include "ed2k_util.h"
#include "cache.h"
#include "util.h"
bool did_cache_init = false;
uint64_t cmd_modify_getlid(const char *str)
{
uint64_t val;
const char *sep = strchr(str, '|');
struct cache_entry ce;
enum error err;
if (sscanf(str, "%lu", &val) != 1)
return 0;
if (!sep)
return val;
if (!cache_is_init()) {
if (cache_init() != NOERR)
return 0;
did_cache_init = true;
}
err = cache_get(sep + 1, val, CACHE_S_LID, &ce);
if (err != NOERR)
return 0;
return ce.lid;
}
enum error cmd_modify(void *data)
{
struct api_mylistadd_opts mopt = {0};
@ -44,11 +69,11 @@ enum error cmd_modify(void *data)
for (int i = 0; i < fcount; i++) {
struct api_result res;
uint64_t lid;
const char *arg = config_get_nonopt(i);
uint64_t lid = cmd_modify_getlid(arg);
if (sscanf(arg, "%lu", &lid) != 1) {
uio_error("Argument '%s' is not an integer. Skipping", arg);
if (lid == 0) {
uio_error("Argument '%s' is not valid. Skipping", arg);
continue;
}
@ -60,6 +85,11 @@ enum error cmd_modify(void *data)
uio_error("No mylist entry with id: '%lu'", lid);
}
}
if (did_cache_init) {
did_cache_init = false;
cache_free();
}
return err;
}

View File

@ -136,6 +136,9 @@ static struct conf_entry options[] = {
.has_arg = no_argument, .set_func = config_set_bool, .in_args = true,
.type = OTYPE_B, .handle_order = 1 },
/* Arguments are either mylist id's, or file sizes and names
* in the format '<size>|<filename>'. The filename can contain
* '|' characters */
{ .l_name = "modify", .s_name = 'W',
.has_arg = no_argument, .set_func = config_set_bool, .in_args = true,
.type = OTYPE_B, .handle_order = 1 },

View File

@ -16,6 +16,30 @@ void util_byte2hex(const uint8_t* bytes, size_t bytes_len,
*out = '\0';
}
void util_hex2byte(const char *str, uint8_t* out_bytes)
{
while (*str) {
if (*str >= '0' && *str <= '9')
*out_bytes = (*str - '0') << 4;
if (*str >= 'A' && *str <= 'F')
*out_bytes = (*str - ('A' - 10)) << 4;
else
*out_bytes = (*str - ('a' - 10)) << 4;
str++;
if (*str >= '0' && *str <= '9')
*out_bytes |= (*str - '0');
if (*str >= 'A' && *str <= 'F')
*out_bytes |= (*str - ('A' - 10));
else
*out_bytes |= (*str - ('a' - 10));
out_bytes++;
str++;
}
}
const char *util_get_home()
{
const char *home_env = getenv("HOME");

View File

@ -21,6 +21,8 @@
void util_byte2hex(const uint8_t* bytes, size_t bytes_len,
bool uppercase, char* out);
/* And convert it back */
void util_hex2byte(const char *str, uint8_t* out_bytes);
/*
* Return the user's home directory
*/