Mount archives using archivemount

This commit is contained in:
Arun Prakash Jana 2019-10-12 02:13:08 +05:30
parent c54f50cf4f
commit 19df7777db
No known key found for this signature in database
GPG Key ID: A75979F35C080412
3 changed files with 84 additions and 15 deletions

View File

@ -44,7 +44,7 @@ Add to that an awesome [Wiki](https://github.com/jarun/nnn/wiki)!
- Subtree search to open or edit files (using plugin)
- Mimes
- Open with desktop opener or specify a custom app
- Create, list, extract archives
- Create, list, extract, mount (FUSE based) archives
- Option to open all text files in EDITOR
- Information
- Detailed file information
@ -90,6 +90,7 @@ A curses library with wide char support (e.g. ncursesw), libreadline (`make O_NO
| xdg-open (Linux), open(1) (macOS), cygstart (Cygwin) | base | desktop opener |
| file, coreutils (cp, mv, rm), findutils (xargs) | base | file type, copy, move and remove |
| tar, (un)zip [atool/bsdtar for more formats] | base | create, list, extract tar, gzip, bzip2, zip |
| archivemount | optional | mount archives over FUSE |
| sshfs, fusermount(3) | optional | mount, unmount over SSHFS |
| trash-cli | optional | trash files (default action: delete) |
| vlock (Linux), bashlock (macOS), lock(1) (BSD) | optional | terminal locker (fallback: [cmatrix](https://github.com/abishekvashok/cmatrix)) |
@ -211,14 +212,14 @@ The list below is from the **dev branch**. Press <kbd>?</kbd> in `nnn` to see th
a Select all K Edit selection
P Copy selection X Delete selection
V Move selection ^X Delete entry
f Create archive C Execute entry
f Create archive T Mount archive
^F Extract archive F List archive
e Edit in EDITOR p Open in PAGER
ORDER TOGGLES
A Apparent du S du
s Size E Extn t Time
s Size E Extn t Time
MISC
! ^] Shell = Launcher
! ^] Shell = Launch C Execute entry
R ^V Pick plugin :K xK Execute plugin K
c SSHFS mount u Unmount
^P Prompt/run cmd L Lock

View File

@ -383,6 +383,7 @@ static char mv[] = "mvg -gi";
#define STR_TMPFILE 3
#define NONE_SELECTED 4
#define UTIL_MISSING 5
#define MOUNT_FAILED 6
static const char * const messages[] = {
"no traversal",
@ -391,6 +392,7 @@ static const char * const messages[] = {
"/.nnnXXXXXX",
"0 selected",
"missing dep",
"mount failed",
};
/* Supported configuration environment variables */
@ -2793,6 +2795,50 @@ static bool create_dir(const char *path)
return TRUE;
}
static bool archive_mount(char *name, char *path, char *newpath, int *presel)
{
char *dir, *cmd = "archivemount";
size_t len;
if (!getutil(cmd)) {
printwait(messages[UTIL_MISSING], presel);
return FALSE;
}
dir = strdup(name);
if (!dir)
return FALSE;
len = strlen(dir);
while (len > 1)
if (dir[--len] == '.') {
dir[len] = '\0';
break;
}
DPRINTF_S(dir);
/* Create the mount point */
mkpath(cfgdir, dir, newpath);
free(dir);
if (!create_dir(newpath)) {
printwait(strerror(errno), presel);
return FALSE;
}
/* Mount archive */
DPRINTF_S(name);
DPRINTF_S(newpath);
if (spawn(cmd, name, newpath, path, F_NORMAL)) {
printwait(messages[MOUNT_FAILED], presel);
return FALSE;
}
return TRUE;
}
static bool sshfs_mount(char *newpath, int *presel)
{
uchar flag = F_NORMAL;
@ -2828,18 +2874,23 @@ static bool sshfs_mount(char *newpath, int *presel)
/* Connect to remote */
if (spawn(env, tmp, newpath, NULL, flag)) {
printwait("mount failed", presel);
printwait(messages[MOUNT_FAILED], presel);
return FALSE;
}
return TRUE;
}
static bool sshfs_unmount(char *newpath, int *presel)
/*
* Unmounts if the directory represented by name is a mount point.
* Otherwise, asks for hostname
*/
static bool unmount(char *name, char *newpath, int *presel)
{
static char cmd[] = "fusermount3"; /* Arch Linux utility */
static bool found = FALSE;
char *tmp;
char *tmp = name;
struct stat sb, psb;
/* On Ubuntu it's fusermount */
if (!found && !getutil(cmd)) {
@ -2847,9 +2898,19 @@ static bool sshfs_unmount(char *newpath, int *presel)
found = TRUE;
}
tmp = xreadline(NULL, "host: ");
if (!tmp[0])
return FALSE;
if (tmp) {
mkpath(cfgdir, tmp, newpath);
if ((lstat(newpath, &sb) == -1) || (lstat(dirname(newpath), &psb) == -1)) {
*presel = MSGWAIT;
return FALSE;
}
}
if (!tmp || (sb.st_dev == psb.st_dev)) {
tmp = xreadline(NULL, "host: ");
if (!tmp[0])
return FALSE;
}
/* Create the mount point */
mkpath(cfgdir, tmp, newpath);
@ -2919,14 +2980,14 @@ static void show_help(const char *path)
"ca Select all K Edit selection\n"
"cP Copy selection X Delete selection\n"
"cV Move selection ^X Delete entry\n"
"cf Create archive C Execute entry\n"
"cf Create archive T Mount archive\n"
"b^F Extract archive F List archive\n"
"ce Edit in EDITOR p Open in PAGER\n"
"1ORDER TOGGLES\n"
"cA Apparent du S du\n"
"cs Size E Extn t Time\n"
"cs Size E Extn t Time\n"
"1MISC\n"
"9! ^] Shell = Launcher\n"
"9! ^] Shell = Launch C Execute entry\n"
"9R ^V Pick plugin :K xK Execute plugin K\n"
"cc SSHFS mount u Unmount\n"
"b^P Prompt/run cmd L Lock\n"};
@ -4577,8 +4638,11 @@ nochange:
/* Repopulate as directory content may have changed */
goto begin;
case SEL_ARCHIVEMNT:
if (!ndents || !archive_mount(dents[cur].name, path, newpath, &presel))
goto nochange; // fallthrough
case SEL_SSHFS:
if (!sshfs_mount(newpath, &presel))
if (sel == SEL_SSHFS && !sshfs_mount(newpath, &presel))
goto nochange;
lastname[0] = '\0';
@ -4592,7 +4656,8 @@ nochange:
setdirwatch();
goto begin;
case SEL_UMOUNT:
sshfs_unmount(newpath, &presel);
tmp = ndents ? dents[cur].name : NULL;
unmount(tmp, newpath, &presel);
goto nochange;
case SEL_QUITCD: // fallthrough
case SEL_QUIT:

View File

@ -88,6 +88,7 @@ enum action {
SEL_NEW,
SEL_RENAME,
SEL_RENAMEMUL,
SEL_ARCHIVEMNT,
SEL_SSHFS,
SEL_UMOUNT,
SEL_HELP,
@ -229,6 +230,8 @@ static struct key bindings[] = {
{ KEY_F(2), SEL_RENAME },
/* Rename contents of current dir */
{ 'r', SEL_RENAMEMUL },
/* Mount an archive */
{ 'T', SEL_ARCHIVEMNT },
/* Connect to server over SSHFS */
{ 'c', SEL_SSHFS },
/* Disconnect a SSHFS mount point */