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
runs its script.
The script produces preview content and prints it to standard output.
Symbolic links are dereferenced.
.
.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 PP(e, t, s, n, o) { #n, e, t, s, PNAME(n), o, 0, LEN(PNAME(n)) }
#define PR(e, t, s, n) PP(e, t, s, n, 0)
#define PR(e, t, s, n) { #n, e, t, s, PNAME(n), 0, 0, LEN(PNAME(n)) }
Preview b_previews[] = {
PP(NULL, NULL, NULL, wrapper, INT_MAX),
PR(NULL, NULL, NULL, any),
PR("md", NULL, NULL, mdcat),
@ -31,7 +29,9 @@ Preview b_previews[] = {
PR(NULL, "application", "pdf", pdf),
PR(NULL, "application", "json", jq),
PR(NULL, "inode", "directory", ls),
PR(NULL, "inode", "symlink", symlink),
PR(NULL, "text", "html", elinks),
PR(NULL, "text", "html", lynx),

View File

@ -103,16 +103,30 @@ static const char *get_mimetype(const char *path)
return r;
}
static int check_file(const char *f)
static int check_file(char **f, char *f_link)
{
if (!f) {
print_error("file not given");
return ERR;
}
if (access(f, R_OK) != 0) {
print_errorf("failed to access '%s': %s", f, strerror(errno));
return ERR;
ssize_t f_link_len = readlink(*f, f_link, FILENAME_MAX);
if (f_link_len == -1) {
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;
@ -121,8 +135,8 @@ static int check_file(const char *f)
static int is_newer(int *resp, char *f1, char *f2)
{
struct stat stat1, stat2;
ERRCHK_RET_ERN(stat(f1, &stat1) == -1);
ERRCHK_RET_ERN(stat(f2, &stat2) == -1);
ERRCHK_RET_ERN(lstat(f1, &stat1) == -1);
ERRCHK_RET_ERN(lstat(f2, &stat2) == -1);
int sec_d = stat1.st_mtim.tv_sec - stat2.st_mtim.tv_sec;
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[])
{
char *f, *w, *h, *x, *y, *id;
char y_buf[4], h_buf[4];
GET_PARG(f, 0);
GET_PARG(w, 1);
GET_PARG(h, 2);
@ -192,7 +208,24 @@ static int preview(int argc, char *argv[])
GET_PARG(y, 4);
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());
@ -300,7 +333,9 @@ static int list(void)
static int mime(int argc, char *argv[])
{
const char *f, *mimetype;
char *f;
char f_link[FILENAME_MAX];
const char *mimetype;
if (argc <= 0) {
print_error("files are not specified");
@ -309,7 +344,7 @@ static int mime(int argc, char *argv[])
for (int i = 0; i < argc; i++) {
f = argv[i];
ERRCHK_RET_OK(check_file(f));
ERRCHK_RET_OK(check_file(&f, f_link));
ERRCHK_RET_OK(init_magic());