Add support for symlinks

Dereference symlinks
This commit is contained in:
Nikita Ivanov 2022-06-19 20:06:13 +05:00
parent 58e608bb98
commit 75796b94cc
No known key found for this signature in database
GPG Key ID: 6E656AC5B97B5133
5 changed files with 52 additions and 16 deletions

View File

@ -76,6 +76,7 @@ When
is given a file, it determines an appropriate preview for it and is given a file, it determines an appropriate preview for it and
runs its script. runs its script.
The script produces preview content and prints it to standard output. The script produces preview content and prints it to standard output.
Symbolic links are dereferenced.
. .
.SS Dependencies .SS Dependencies
. .

4
prev/symlink.sh Normal file
View File

@ -0,0 +1,4 @@
#
# do nothing because in src/ctpv.c some kind of a "preview"
# is already printed
#

View File

@ -1,4 +0,0 @@
[ -L "$f" ] && printf 'Symlink: \n%s\n\n' "$(readlink "$f")"
# Pretend that preview failed so another is run
exit 127

View File

@ -10,11 +10,9 @@
*/ */
#define PNAME(n) prev_scr_##n##_sh #define PNAME(n) prev_scr_##n##_sh
#define PP(e, t, s, n, o) { #n, e, t, s, PNAME(n), o, 0, LEN(PNAME(n)) } #define PR(e, t, s, n) { #n, e, t, s, PNAME(n), 0, 0, LEN(PNAME(n)) }
#define PR(e, t, s, n) PP(e, t, s, n, 0)
Preview b_previews[] = { Preview b_previews[] = {
PP(NULL, NULL, NULL, wrapper, INT_MAX),
PR(NULL, NULL, NULL, any), PR(NULL, NULL, NULL, any),
PR("md", NULL, NULL, mdcat), PR("md", NULL, NULL, mdcat),
@ -31,7 +29,9 @@ Preview b_previews[] = {
PR(NULL, "application", "pdf", pdf), PR(NULL, "application", "pdf", pdf),
PR(NULL, "application", "json", jq), PR(NULL, "application", "json", jq),
PR(NULL, "inode", "directory", ls), PR(NULL, "inode", "directory", ls),
PR(NULL, "inode", "symlink", symlink),
PR(NULL, "text", "html", elinks), PR(NULL, "text", "html", elinks),
PR(NULL, "text", "html", lynx), PR(NULL, "text", "html", lynx),

View File

@ -103,16 +103,30 @@ static const char *get_mimetype(const char *path)
return r; return r;
} }
static int check_file(const char *f) static int check_file(char **f, char *f_link)
{ {
if (!f) { if (!f) {
print_error("file not given"); print_error("file not given");
return ERR; return ERR;
} }
if (access(f, R_OK) != 0) { ssize_t f_link_len = readlink(*f, f_link, FILENAME_MAX);
print_errorf("failed to access '%s': %s", f, strerror(errno)); if (f_link_len == -1) {
return ERR; switch (errno) {
case ENOENT:
print_errorf("failed to access '%s': %s", *f, strerror(errno));
return ERR;
case EINVAL:
*f_link = 0;
break;
default:
FUNCFAILED("readlink", strerror(errno));
return ERR;
}
} else {
f_link[f_link_len] = '\0';
if (access(f_link, R_OK) == 0)
*f = f_link;
} }
return OK; return OK;
@ -121,8 +135,8 @@ static int check_file(const char *f)
static int is_newer(int *resp, char *f1, char *f2) static int is_newer(int *resp, char *f1, char *f2)
{ {
struct stat stat1, stat2; struct stat stat1, stat2;
ERRCHK_RET_ERN(stat(f1, &stat1) == -1); ERRCHK_RET_ERN(lstat(f1, &stat1) == -1);
ERRCHK_RET_ERN(stat(f2, &stat2) == -1); ERRCHK_RET_ERN(lstat(f2, &stat2) == -1);
int sec_d = stat1.st_mtim.tv_sec - stat2.st_mtim.tv_sec; int sec_d = stat1.st_mtim.tv_sec - stat2.st_mtim.tv_sec;
if (sec_d < 0) if (sec_d < 0)
@ -185,6 +199,8 @@ static int check_cache(int *resp, char *file, char *cache_file)
static int preview(int argc, char *argv[]) static int preview(int argc, char *argv[])
{ {
char *f, *w, *h, *x, *y, *id; char *f, *w, *h, *x, *y, *id;
char y_buf[4], h_buf[4];
GET_PARG(f, 0); GET_PARG(f, 0);
GET_PARG(w, 1); GET_PARG(w, 1);
GET_PARG(h, 2); GET_PARG(h, 2);
@ -192,7 +208,24 @@ static int preview(int argc, char *argv[])
GET_PARG(y, 4); GET_PARG(y, 4);
GET_PARG(id, 5); GET_PARG(id, 5);
ERRCHK_RET_OK(check_file(f)); char f_link[FILENAME_MAX];
ERRCHK_RET_OK(check_file(&f, f_link));
if (*f_link) {
printf("Symlink points to:\n\t%s\n\n", f_link);
fflush(stdout);
if (y && h) {
unsigned char y_i = atoi(y);
unsigned char h_i = atoi(h);
y_i += 3;
h_i -= 3;
snprintf(y_buf, LEN(y_buf), "%d", y_i);
snprintf(h_buf, LEN(h_buf), "%d", h_i);
y = y_buf;
h = h_buf;
}
}
ERRCHK_RET_OK(init_magic()); ERRCHK_RET_OK(init_magic());
@ -300,7 +333,9 @@ static int list(void)
static int mime(int argc, char *argv[]) static int mime(int argc, char *argv[])
{ {
const char *f, *mimetype; char *f;
char f_link[FILENAME_MAX];
const char *mimetype;
if (argc <= 0) { if (argc <= 0) {
print_error("files are not specified"); print_error("files are not specified");
@ -309,7 +344,7 @@ static int mime(int argc, char *argv[])
for (int i = 0; i < argc; i++) { for (int i = 0; i < argc; i++) {
f = argv[i]; f = argv[i];
ERRCHK_RET_OK(check_file(f)); ERRCHK_RET_OK(check_file(&f, f_link));
ERRCHK_RET_OK(init_magic()); ERRCHK_RET_OK(init_magic());