aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config.def.h8
-rw-r--r--etc/nsxiv.126
-rw-r--r--nsxiv.h12
-rw-r--r--options.c12
-rw-r--r--thumbs.c59
5 files changed, 113 insertions, 4 deletions
diff --git a/config.def.h b/config.def.h
index 7fbfb17..ead1509 100644
--- a/config.def.h
+++ b/config.def.h
@@ -70,6 +70,14 @@ static const bool ANTI_ALIAS = true;
*/
static const bool ALPHA_LAYER = false;
+/* list of whitelisted/blacklisted directory for thumbnail cache
+ * (overwritten via --cache-{allow,deny} option).
+ * see THUMBNAIL CACHING section in nsxiv(1) manpage for more details.
+ */
+static const char TNS_FILTERS[] = "";
+/* set to true to treat `TNS_FILTERS` as a blacklist instead */
+static const bool TNS_FILTERS_IS_BLACKLIST = false;
+
#endif
#ifdef INCLUDE_THUMBS_CONFIG
diff --git a/etc/nsxiv.1 b/etc/nsxiv.1
index 5edfece..2e01302 100644
--- a/etc/nsxiv.1
+++ b/etc/nsxiv.1
@@ -124,6 +124,14 @@ as an argument, disables it instead.
Enables checkerboard background for alpha layer, when given
.I no
as an argument, disables it instead.
+.TP
+.BI "\-\-cache\-allow, \-\-cache\-deny " "CACHE\-PATHS"
+List of directories to whitelist or blacklist for thumbnail caching.
+See
+.I "THUMBNAIL CACHING"
+section for more information on the argument format.
+These options are mutually exclusive, if they are specified more than once then
+only the final one takes effect.
.SH KEYBOARD COMMANDS
.SS General
The following keyboard commands are available in both image and thumbnail modes:
@@ -559,6 +567,24 @@ afterwards inside the cache directory to remove empty subdirectories:
.RS
find . \-depth \-type d \-empty ! \-name '.' \-exec rmdir {} \\;
.RE
+.P
+The option
+.BR "\-\-cache\-allow " or " \-\-cache\-deny"
+may be used to whitelists or blacklist certain directories from being cached.
+The argument is a
+.B :
+separated list of paths. A
+.B *
+at the beginning of the path indicates that path should be matched recursively.
+.P
+For example:
+.B \-\-cache\-allow \(dq/user/pictures:*/media/pictures\(dq
+whitelists \(dq/user/pictures\(dq directory non-recursively and \(dq/media/pictures\(dq
+directory recursively. Nothing outside these two directories will be cached.
+And
+.B \-\-cache\-deny \(dq*/secret\(dq
+will enable blacklist mode and will not cache anything inside \(dq/secret\(dq
+or it's subdirectories.
.SH ORIGINAL AUTHOR
.EX
Bert Muennich <ber.t at posteo.de>
diff --git a/nsxiv.h b/nsxiv.h
index ccd1796..5dfbed3 100644
--- a/nsxiv.h
+++ b/nsxiv.h
@@ -270,6 +270,8 @@ struct opt {
char *res_name;
/* misc flags: */
+ const char *tns_filters;
+ bool tns_filters_is_blacklist;
bool quiet;
bool thumb_mode;
bool clean_cache;
@@ -293,6 +295,12 @@ typedef struct {
int y;
} thumb_t;
+typedef struct {
+ const char *path;
+ int len;
+ bool recursive;
+} thumb_filter_t;
+
struct tns {
fileinfo_t *files;
thumb_t *thumbs;
@@ -312,7 +320,11 @@ struct tns {
int bw;
int dim;
+ thumb_filter_t *filters;
+ int filters_cnt;
+
bool dirty;
+ bool filters_is_blacklist;
};
void tns_clean_cache(void);
diff --git a/options.c b/options.c
index 4ae2ea5..b813244 100644
--- a/options.c
+++ b/options.c
@@ -75,7 +75,9 @@ void parse_options(int argc, char **argv)
OPT_START = UCHAR_MAX,
OPT_AA,
OPT_AL,
- OPT_BG
+ OPT_BG,
+ OPT_CA,
+ OPT_CD
};
static const struct optparse_long longopts[] = {
{ "framerate", 'A', OPTPARSE_REQUIRED },
@@ -105,6 +107,8 @@ void parse_options(int argc, char **argv)
{ "alpha-layer", OPT_AL, OPTPARSE_OPTIONAL },
/* TODO: document this when it's stable */
{ "bg-cache", OPT_BG, OPTPARSE_OPTIONAL },
+ { "cache-allow", OPT_CA, OPTPARSE_REQUIRED },
+ { "cache-deny", OPT_CD, OPTPARSE_REQUIRED },
{ 0 }, /* end */
};
@@ -137,6 +141,8 @@ void parse_options(int argc, char **argv)
_options.geometry = NULL;
_options.res_name = NULL;
+ _options.tns_filters = TNS_FILTERS;
+ _options.tns_filters_is_blacklist = TNS_FILTERS_IS_BLACKLIST;
_options.quiet = false;
_options.thumb_mode = false;
_options.clean_cache = false;
@@ -266,6 +272,10 @@ void parse_options(int argc, char **argv)
error(EXIT_FAILURE, 0, "Invalid argument for option --bg-cache: %s", op.optarg);
_options.background_cache = op.optarg == NULL;
break;
+ case OPT_CA: case OPT_CD:
+ _options.tns_filters = op.optarg;
+ _options.tns_filters_is_blacklist = (opt == OPT_CD);
+ break;
}
}
diff --git a/thumbs.c b/thumbs.c
index 9909333..f55a152 100644
--- a/thumbs.c
+++ b/thumbs.c
@@ -75,7 +75,26 @@ static Imlib_Image tns_cache_load(const char *filepath, bool *outdated)
return im;
}
-static void tns_cache_write(Imlib_Image im, const char *filepath, bool force)
+static bool tns_cache_whitelisted(tns_t *tns, const char *filepath)
+{
+ ptrdiff_t i, dir_len = strrchr(filepath, '/') - filepath;
+ dir_len = MAX(dir_len, 1); /* account for "/file" */
+
+ if (tns->filters_cnt == 0)
+ return true; /* no cache list, cache everything */
+
+ for (i = 0; i < tns->filters_cnt; ++i) {
+ thumb_filter_t *f = tns->filters + i;
+ if ((f->recursive ? (dir_len >= f->len) : (dir_len == f->len)) &&
+ memcmp(filepath, f->path, f->len) == 0)
+ { /* in blacklist mode, finding a match means we shouldn't cache */
+ return tns->filters_is_blacklist ? false : true;
+ }
+ }
+ return tns->filters_is_blacklist; /* no match */
+}
+
+static void tns_cache_write(tns_t *tns, Imlib_Image im, const char *filepath, bool force)
{
char *cfile, *dirend;
int tmpfd;
@@ -83,7 +102,7 @@ static void tns_cache_write(Imlib_Image im, const char *filepath, bool force)
struct utimbuf times;
Imlib_Load_Error err;
- if (options->private_mode)
+ if (options->private_mode || !tns_cache_whitelisted(tns, filepath))
return;
if (stat(filepath, &fstats) < 0)
@@ -167,6 +186,34 @@ void tns_init(tns_t *tns, fileinfo_t *tns_files, const int *cnt, int *sel, win_t
tns->zl = THUMB_SIZE;
tns_zoom(tns, 0);
+ tns->filters = NULL;
+ tns->filters_cnt = 0;
+ tns->filters_is_blacklist = options->tns_filters_is_blacklist;
+ if (options->tns_filters != NULL && options->tns_filters[0] != '\0') {
+ int allocated = 0;
+ char *save, *tok, *s = estrdup(options->tns_filters);
+ for (tok = strtok_r(s, ":", &save); tok != NULL;
+ tok = strtok_r(NULL, ":", &save))
+ {
+ thumb_filter_t *f;
+ if (tns->filters_cnt == allocated) {
+ allocated = allocated > 0 ? (allocated * 2) : 4;
+ tns->filters = erealloc(tns->filters,
+ allocated * sizeof(*tns->filters));
+ }
+ f = tns->filters + tns->filters_cnt++;
+ f->recursive = *tok == '*';
+ f->path = realpath(tok + f->recursive, NULL);
+ if (f->path == NULL) {
+ error(EXIT_FAILURE, errno, "--cache-%s: `%s`",
+ tns->filters_is_blacklist ? "deny" : "allow",
+ tok + f->recursive);
+ }
+ f->len = strlen(f->path);
+ }
+ free(s);
+ }
+
if ((homedir = getenv("XDG_CACHE_HOME")) == NULL || homedir[0] == '\0') {
homedir = getenv("HOME");
dsuffix = "/.cache";
@@ -196,6 +243,12 @@ CLEANUP void tns_free(tns_t *tns)
tns->thumbs = NULL;
}
+ for (i = 0; i < tns->filters_cnt; ++i)
+ free((void *)tns->filters[i].path);
+ tns->filters_cnt = 0;
+ free(tns->filters);
+ tns->filters = NULL;
+
free(cache_dir);
cache_dir = NULL;
free(cache_tmpfile);
@@ -335,7 +388,7 @@ bool tns_load(tns_t *tns, int n, bool force, bool cache_only)
im = tns_scale_down(im, maxwh);
imlib_context_set_image(im);
if (imlib_image_get_width() == maxwh || imlib_image_get_height() == maxwh)
- tns_cache_write(im, file->path, true);
+ tns_cache_write(tns, im, file->path, true);
}
if (cache_only) {