mirror of
https://github.com/jarun/nnn.git
synced 2025-01-15 13:26:37 +00:00
Improve archive, rename, new workflows
1. hover on entry created in cwd 2. check user input doesn't end with / 3. check user input len < PATH_MAX 4. support creation in ~ directory 5. handle filter mode after creation 6. ensure absolute path len < PATH_MAX
This commit is contained in:
parent
32a6a63f44
commit
e8bc59a816
105
src/nnn.c
105
src/nnn.c
|
@ -1008,6 +1008,32 @@ static inline bool is_prefix(const char *restrict str, const char *restrict pref
|
||||||
return !strncmp(str, prefix, len);
|
return !strncmp(str, prefix, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool is_bad_len_or_dir(const char *restrict path)
|
||||||
|
{
|
||||||
|
size_t len = xstrlen(path);
|
||||||
|
|
||||||
|
return ((len >= PATH_MAX) || (path[len - 1] == '/'));
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *get_cwd_entry(const char *restrict cwdpath, char *entrypath, size_t *tokenlen)
|
||||||
|
{
|
||||||
|
size_t len = xstrlen(cwdpath);
|
||||||
|
char *end;
|
||||||
|
|
||||||
|
if (!is_prefix(entrypath, cwdpath, len))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
entrypath += len + 1; /* Add 1 for trailing / */
|
||||||
|
end = strchr(entrypath, '/');
|
||||||
|
if (end)
|
||||||
|
*tokenlen = end - entrypath;
|
||||||
|
else
|
||||||
|
*tokenlen = xstrlen(entrypath);
|
||||||
|
DPRINTF_U(*tokenlen);
|
||||||
|
|
||||||
|
return entrypath;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The poor man's implementation of memrchr(3).
|
* The poor man's implementation of memrchr(3).
|
||||||
* We are only looking for '/' and '.' in this program.
|
* We are only looking for '/' and '.' in this program.
|
||||||
|
@ -1246,6 +1272,12 @@ static char *abspath(const char *filepath, char *cwd, char *buf)
|
||||||
resolved_path[1] = '\0';
|
resolved_path[1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (xstrlen(resolved_path) >= PATH_MAX) {
|
||||||
|
if (!buf)
|
||||||
|
free(resolved_path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return resolved_path;
|
return resolved_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7511,7 +7543,8 @@ nochange:
|
||||||
case SEL_NEW: // fallthrough
|
case SEL_NEW: // fallthrough
|
||||||
case SEL_RENAME:
|
case SEL_RENAME:
|
||||||
{
|
{
|
||||||
int fd, ret = 'n';
|
int ret = 'n';
|
||||||
|
size_t len;
|
||||||
|
|
||||||
if (!ndents && (sel == SEL_OPENWITH || sel == SEL_RENAME))
|
if (!ndents && (sel == SEL_OPENWITH || sel == SEL_RENAME))
|
||||||
break;
|
break;
|
||||||
|
@ -7572,7 +7605,7 @@ nochange:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tmp || !*tmp)
|
if (!tmp || !*tmp || is_bad_len_or_dir(tmp))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
switch (sel) {
|
switch (sel) {
|
||||||
|
@ -7592,15 +7625,16 @@ nochange:
|
||||||
NULL, F_CLI | F_CONFIRM);
|
NULL, F_CLI | F_CONFIRM);
|
||||||
|
|
||||||
if (tmp && (access(tmp, F_OK) == 0)) { /* File created */
|
if (tmp && (access(tmp, F_OK) == 0)) { /* File created */
|
||||||
char *base = xbasename(tmp);
|
if (r == 's')
|
||||||
char *parent = xdirname(tmp);
|
clearselection(); /* Archive operation complete */
|
||||||
|
|
||||||
/* Check if file is created in the current directory */
|
/* Check if any entry is created in the current directory */
|
||||||
if (strcmp(path, parent) == 0) {
|
tmp = get_cwd_entry(path, tmp, &len);
|
||||||
xstrsncpy(lastname, base, NAME_MAX + 1);
|
if (tmp) {
|
||||||
|
xstrsncpy(lastname, tmp, len + 1);
|
||||||
clearfilter(); /* Archive name may not match */
|
clearfilter(); /* Archive name may not match */
|
||||||
}
|
} if (cfg.filtermode)
|
||||||
clearselection(); /* Archive operation complete */
|
presel = FILTER;
|
||||||
cd = FALSE;
|
cd = FALSE;
|
||||||
goto begin;
|
goto begin;
|
||||||
}
|
}
|
||||||
|
@ -7612,10 +7646,12 @@ nochange:
|
||||||
copycurname();
|
copycurname();
|
||||||
goto nochange;
|
goto nochange;
|
||||||
case SEL_RENAME:
|
case SEL_RENAME:
|
||||||
|
r = 0;
|
||||||
/* Skip renaming to same name */
|
/* Skip renaming to same name */
|
||||||
if (strcmp(tmp, pdents[cur].name) == 0) {
|
if (strcmp(tmp, pdents[cur].name) == 0) {
|
||||||
tmp = xreadline(pdents[cur].name, messages[MSG_COPY_NAME]);
|
tmp = xreadline(pdents[cur].name, messages[MSG_COPY_NAME]);
|
||||||
if (!tmp || !tmp[0] || !strcmp(tmp, pdents[cur].name)) {
|
if (!tmp || !tmp[0] || is_bad_len_or_dir(tmp)
|
||||||
|
|| !strcmp(tmp, pdents[cur].name)) {
|
||||||
cfg.filtermode ? presel = FILTER : statusbar(path);
|
cfg.filtermode ? presel = FILTER : statusbar(path);
|
||||||
copycurname();
|
copycurname();
|
||||||
goto nochange;
|
goto nochange;
|
||||||
|
@ -7627,28 +7663,22 @@ nochange:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open the descriptor to currently open directory */
|
if (!(r == 's' || r == 'h')) {
|
||||||
#ifdef O_DIRECTORY
|
tmp = abspath(tmp, NULL, newpath);
|
||||||
fd = open(path, O_RDONLY | O_DIRECTORY);
|
if (!tmp) {
|
||||||
#else
|
printwarn(&presel);
|
||||||
fd = open(path, O_RDONLY);
|
goto nochange;
|
||||||
#endif
|
}
|
||||||
if (fd == -1) {
|
|
||||||
printwarn(&presel);
|
|
||||||
goto nochange;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if another file with same name exists */
|
/* Check if another file with same name exists */
|
||||||
if (fstatat(fd, tmp, &sb, AT_SYMLINK_NOFOLLOW) == 0) {
|
if (lstat(tmp, &sb) == 0) {
|
||||||
if ((sel == SEL_RENAME) || ((r == 'f') && (S_ISREG(sb.st_mode)))) {
|
if ((sel == SEL_RENAME) || ((r == 'f') && (S_ISREG(sb.st_mode)))) {
|
||||||
/* Overwrite file with same name? */
|
/* Overwrite file with same name? */
|
||||||
if (!xconfirm(get_input(messages[MSG_OVERWRITE]))) {
|
if (!xconfirm(get_input(messages[MSG_OVERWRITE])))
|
||||||
close(fd);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/* Do nothing for SEL_NEW if a non-regular entry exists */
|
/* Do nothing for SEL_NEW if a non-regular entry exists */
|
||||||
close(fd);
|
|
||||||
printwait(messages[MSG_EXISTS], &presel);
|
printwait(messages[MSG_EXISTS], &presel);
|
||||||
goto nochange;
|
goto nochange;
|
||||||
}
|
}
|
||||||
|
@ -7658,21 +7688,22 @@ nochange:
|
||||||
/* Rename the file */
|
/* Rename the file */
|
||||||
if (ret == 'd')
|
if (ret == 'd')
|
||||||
spawn("cp -rp", pdents[cur].name, tmp, NULL, F_SILENT);
|
spawn("cp -rp", pdents[cur].name, tmp, NULL, F_SILENT);
|
||||||
else if (renameat(fd, pdents[cur].name, fd, tmp) != 0) {
|
else if (rename(pdents[cur].name, tmp) != 0) {
|
||||||
close(fd);
|
|
||||||
printwarn(&presel);
|
printwarn(&presel);
|
||||||
goto nochange;
|
goto nochange;
|
||||||
}
|
}
|
||||||
close(fd);
|
|
||||||
xstrsncpy(lastname, tmp, NAME_MAX + 1);
|
/* Check if any entry is created in the current directory */
|
||||||
|
tmp = get_cwd_entry(path, tmp, &len);
|
||||||
|
if (tmp)
|
||||||
|
xstrsncpy(lastname, tmp, len + 1);
|
||||||
|
/* Directory must be reloeaded for rename case */
|
||||||
} else { /* SEL_NEW */
|
} else { /* SEL_NEW */
|
||||||
close(fd);
|
|
||||||
presel = 0;
|
presel = 0;
|
||||||
|
|
||||||
/* Check if it's a dir or file */
|
/* Check if it's a dir or file */
|
||||||
if (r == 'f' || r == 'd') {
|
if (r == 'f' || r == 'd') {
|
||||||
mkpath(path, tmp, newpath);
|
ret = xmktree(tmp, r == 'f' ? FALSE : TRUE);
|
||||||
ret = xmktree(newpath, r == 'f' ? FALSE : TRUE);
|
|
||||||
} else if (r == 's' || r == 'h') {
|
} else if (r == 's' || r == 'h') {
|
||||||
if (nselected > 1 && tmp[0] == '@' && tmp[1] == '\0')
|
if (nselected > 1 && tmp[0] == '@' && tmp[1] == '\0')
|
||||||
tmp[0] = '\0';
|
tmp[0] = '\0';
|
||||||
|
@ -7686,15 +7717,19 @@ nochange:
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
goto nochange;
|
goto nochange;
|
||||||
|
|
||||||
if (r == 'f' || r == 'd')
|
if (r == 'f' || r == 'd') {
|
||||||
xstrsncpy(lastname, tmp, NAME_MAX + 1);
|
tmp = get_cwd_entry(path, tmp, &len);
|
||||||
else if (ndents) {
|
if (tmp)
|
||||||
|
xstrsncpy(lastname, tmp, len + 1);
|
||||||
|
else
|
||||||
|
continue; /* No change in directory */
|
||||||
|
} else if (ndents) {
|
||||||
if (cfg.filtermode)
|
if (cfg.filtermode)
|
||||||
presel = FILTER;
|
presel = FILTER;
|
||||||
copycurname();
|
copycurname();
|
||||||
}
|
}
|
||||||
clearfilter();
|
|
||||||
}
|
}
|
||||||
|
clearfilter();
|
||||||
|
|
||||||
cd = FALSE;
|
cd = FALSE;
|
||||||
goto begin;
|
goto begin;
|
||||||
|
|
Loading…
Reference in a new issue