mirror of
https://github.com/jarun/nnn.git
synced 2024-11-28 05:41:31 +00:00
Mount archives using archivemount
This commit is contained in:
parent
c54f50cf4f
commit
19df7777db
|
@ -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
|
||||
|
|
87
src/nnn.c
87
src/nnn.c
|
@ -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:
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue