mirror of https://git.lain.church/x3/caniadd.git
Modify mylist entries based on size + filename
This commit is contained in:
parent
54017d0971
commit
c075609073
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
57
src/cache.c
57
src/cache.c
|
@ -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;
|
||||
}
|
||||
|
|
42
src/cache.h
42
src/cache.h
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 },
|
||||
|
|
24
src/util.c
24
src/util.c
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue