mirror of
https://github.com/jarun/nnn.git
synced 2024-11-28 05:41:31 +00:00
noice: No need to perform so many memory allocations
The code was quite fragile. As a first pass, use buffers of size PATH_MAX and LINE_MAX accordingly until we simplify the overall logic.
This commit is contained in:
parent
6d4166f0d6
commit
65fae61bea
140
noice.c
140
noice.c
|
@ -74,7 +74,7 @@ struct key {
|
|||
#include "config.h"
|
||||
|
||||
struct entry {
|
||||
char *name;
|
||||
char name[PATH_MAX];
|
||||
mode_t mode;
|
||||
time_t t;
|
||||
};
|
||||
|
@ -82,8 +82,8 @@ struct entry {
|
|||
/* Global context */
|
||||
struct entry *dents;
|
||||
int n, cur;
|
||||
char *path, *oldpath;
|
||||
char *fltr;
|
||||
char path[PATH_MAX], oldpath[PATH_MAX];
|
||||
char fltr[LINE_MAX];
|
||||
int idle;
|
||||
|
||||
/*
|
||||
|
@ -106,7 +106,7 @@ int idle;
|
|||
void printmsg(char *);
|
||||
void printwarn(void);
|
||||
void printerr(int, char *);
|
||||
char *mkpath(char *, char *);
|
||||
char *mkpath(char *, char *, char *, size_t);
|
||||
|
||||
#undef dprintf
|
||||
int
|
||||
|
@ -155,20 +155,20 @@ xstrdup(const char *s)
|
|||
return p;
|
||||
}
|
||||
|
||||
/* Some implementations of dirname(3) may modify `path' and some
|
||||
* return a pointer inside `path'. */
|
||||
char *
|
||||
xdirname(const char *path)
|
||||
{
|
||||
static char out[PATH_MAX];
|
||||
char tmp[PATH_MAX], *p;
|
||||
|
||||
/* Some implementations of dirname(3) may modify `path' and some
|
||||
* return a pointer inside `path' and we cannot free(3) the
|
||||
* original string if we lose track of it. */
|
||||
strlcpy(tmp, path, sizeof(tmp));
|
||||
p = dirname(tmp);
|
||||
if (p == NULL)
|
||||
printerr(1, "dirname");
|
||||
/* Make sure this is a malloc(3)-ed string */
|
||||
return xstrdup(p);
|
||||
strlcpy(out, p, sizeof(out));
|
||||
return out;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -226,15 +226,17 @@ openwith(char *file)
|
|||
int
|
||||
setfilter(regex_t *regex, char *filter)
|
||||
{
|
||||
char *errbuf;
|
||||
char errbuf[LINE_MAX];
|
||||
size_t len;
|
||||
int r;
|
||||
|
||||
r = regcomp(regex, filter, REG_NOSUB | REG_EXTENDED | REG_ICASE);
|
||||
if (r != 0) {
|
||||
errbuf = xmalloc(COLS);
|
||||
regerror(r, regex, errbuf, COLS);
|
||||
len = COLS;
|
||||
if (len > sizeof(errbuf))
|
||||
len = sizeof(errbuf);
|
||||
regerror(r, regex, errbuf, len);
|
||||
printmsg(errbuf);
|
||||
free(errbuf);
|
||||
}
|
||||
|
||||
return r;
|
||||
|
@ -461,10 +463,10 @@ int
|
|||
dentfill(char *path, struct entry **dents,
|
||||
int (*filter)(regex_t *, char *), regex_t *re)
|
||||
{
|
||||
char newpath[PATH_MAX];
|
||||
DIR *dirp;
|
||||
struct dirent *dp;
|
||||
struct stat sb;
|
||||
char *newpath;
|
||||
int r, n = 0;
|
||||
|
||||
dirp = opendir(path);
|
||||
|
@ -479,13 +481,12 @@ dentfill(char *path, struct entry **dents,
|
|||
if (filter(re, dp->d_name) == 0)
|
||||
continue;
|
||||
*dents = xrealloc(*dents, (n + 1) * sizeof(**dents));
|
||||
(*dents)[n].name = xstrdup(dp->d_name);
|
||||
strlcpy((*dents)[n].name, dp->d_name, sizeof((*dents)[n].name));
|
||||
/* Get mode flags */
|
||||
newpath = mkpath(path, dp->d_name);
|
||||
mkpath(path, dp->d_name, newpath, sizeof(newpath));
|
||||
r = lstat(newpath, &sb);
|
||||
if (r == -1)
|
||||
printerr(1, "lstat");
|
||||
free(newpath);
|
||||
(*dents)[n].mode = sb.st_mode;
|
||||
(*dents)[n].t = sb.st_mtime;
|
||||
n++;
|
||||
|
@ -500,58 +501,47 @@ dentfill(char *path, struct entry **dents,
|
|||
}
|
||||
|
||||
void
|
||||
dentfree(struct entry *dents, int n)
|
||||
dentfree(struct entry *dents)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
free(dents[i].name);
|
||||
free(dents);
|
||||
}
|
||||
|
||||
char *
|
||||
mkpath(char *dir, char *name)
|
||||
mkpath(char *dir, char *name, char *out, size_t n)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
|
||||
/* Handle absolute path */
|
||||
if (name[0] == '/') {
|
||||
strlcpy(path, name, sizeof(path));
|
||||
strlcpy(out, name, n);
|
||||
} else {
|
||||
/* Handle root case */
|
||||
if (strcmp(dir, "/") == 0) {
|
||||
strlcpy(path, "/", sizeof(path));
|
||||
strlcat(path, name, sizeof(path));
|
||||
strlcpy(out, "/", n);
|
||||
strlcat(out, name, n);
|
||||
} else {
|
||||
strlcpy(path, dir, sizeof(path));
|
||||
strlcat(path, "/", sizeof(path));
|
||||
strlcat(path, name, sizeof(path));
|
||||
strlcpy(out, dir, n);
|
||||
strlcat(out, "/", n);
|
||||
strlcat(out, name, n);
|
||||
}
|
||||
}
|
||||
return xstrdup(path);
|
||||
return out;
|
||||
}
|
||||
|
||||
/* Return the position of the matching entry or 0 otherwise */
|
||||
int
|
||||
dentfind(struct entry *dents, int n, char *cwd, char *path)
|
||||
{
|
||||
char tmp[PATH_MAX];
|
||||
int i;
|
||||
char *tmp;
|
||||
|
||||
if (path == NULL)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
tmp = mkpath(cwd, dents[i].name);
|
||||
mkpath(cwd, dents[i].name, tmp, sizeof(tmp));
|
||||
DPRINTF_S(path);
|
||||
DPRINTF_S(tmp);
|
||||
if (strcmp(tmp, path) == 0) {
|
||||
free(tmp);
|
||||
if (strcmp(tmp, path) == 0)
|
||||
return i;
|
||||
}
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -570,7 +560,7 @@ populate(void)
|
|||
if (r != 0)
|
||||
return -1;
|
||||
|
||||
dentfree(dents, n);
|
||||
dentfree(dents);
|
||||
|
||||
n = 0;
|
||||
dents = NULL;
|
||||
|
@ -581,9 +571,6 @@ populate(void)
|
|||
|
||||
/* Find cur from history */
|
||||
cur = dentfind(dents, n, path, oldpath);
|
||||
free(oldpath);
|
||||
oldpath = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -638,18 +625,16 @@ redraw(void)
|
|||
void
|
||||
browse(const char *ipath, const char *ifilter)
|
||||
{
|
||||
int r, fd;
|
||||
regex_t re;
|
||||
char *newpath;
|
||||
struct stat sb;
|
||||
char newpath[PATH_MAX];
|
||||
char *name, *bin, *dir, *tmp, *run, *env;
|
||||
struct stat sb;
|
||||
regex_t re;
|
||||
int r, fd;
|
||||
int nowtyping = 0;
|
||||
|
||||
oldpath = NULL;
|
||||
path = xstrdup(ipath);
|
||||
fltr = xstrdup(ifilter);
|
||||
strlcpy(path, ipath, sizeof(path));
|
||||
strlcpy(fltr, ifilter, sizeof(fltr));
|
||||
begin:
|
||||
/* Path and filter should be malloc(3)-ed strings at all times */
|
||||
r = populate();
|
||||
if (r == -1) {
|
||||
if (!nowtyping) {
|
||||
|
@ -667,9 +652,7 @@ begin:
|
|||
nochange:
|
||||
switch (nextsel(&run, &env)) {
|
||||
case SEL_QUIT:
|
||||
free(path);
|
||||
free(fltr);
|
||||
dentfree(dents, n);
|
||||
dentfree(dents);
|
||||
return;
|
||||
case SEL_BACK:
|
||||
/* There is no going back */
|
||||
|
@ -679,16 +662,14 @@ nochange:
|
|||
goto nochange;
|
||||
dir = xdirname(path);
|
||||
if (canopendir(dir) == 0) {
|
||||
free(dir);
|
||||
printwarn();
|
||||
goto nochange;
|
||||
}
|
||||
/* Save history */
|
||||
oldpath = path;
|
||||
path = dir;
|
||||
strlcpy(oldpath, path, sizeof(path));
|
||||
strlcpy(path, dir, sizeof(path));
|
||||
/* Reset filter */
|
||||
free(fltr);
|
||||
fltr = xstrdup(ifilter);
|
||||
strlcpy(fltr, ifilter, sizeof(fltr));
|
||||
goto begin;
|
||||
case SEL_GOIN:
|
||||
/* Cannot descend in empty directories */
|
||||
|
@ -696,21 +677,19 @@ nochange:
|
|||
goto nochange;
|
||||
|
||||
name = dents[cur].name;
|
||||
newpath = mkpath(path, name);
|
||||
mkpath(path, name, newpath, sizeof(newpath));
|
||||
DPRINTF_S(newpath);
|
||||
|
||||
/* Get path info */
|
||||
fd = open(newpath, O_RDONLY | O_NONBLOCK);
|
||||
if (fd == -1) {
|
||||
printwarn();
|
||||
free(newpath);
|
||||
goto nochange;
|
||||
}
|
||||
r = fstat(fd, &sb);
|
||||
if (r == -1) {
|
||||
printwarn();
|
||||
close(fd);
|
||||
free(newpath);
|
||||
goto nochange;
|
||||
}
|
||||
close(fd);
|
||||
|
@ -720,26 +699,21 @@ nochange:
|
|||
case S_IFDIR:
|
||||
if (canopendir(newpath) == 0) {
|
||||
printwarn();
|
||||
free(newpath);
|
||||
goto nochange;
|
||||
}
|
||||
free(path);
|
||||
path = newpath;
|
||||
strlcpy(path, newpath, sizeof(path));
|
||||
/* Reset filter */
|
||||
free(fltr);
|
||||
fltr = xstrdup(ifilter);
|
||||
strlcpy(fltr, ifilter, sizeof(fltr));
|
||||
goto begin;
|
||||
case S_IFREG:
|
||||
bin = openwith(newpath);
|
||||
if (bin == NULL) {
|
||||
printmsg("No association");
|
||||
free(newpath);
|
||||
goto nochange;
|
||||
}
|
||||
exitcurses();
|
||||
spawn(bin, newpath, NULL);
|
||||
initcurses();
|
||||
free(newpath);
|
||||
continue;
|
||||
default:
|
||||
printmsg("Unsupported file");
|
||||
|
@ -757,12 +731,11 @@ nochange:
|
|||
free(tmp);
|
||||
goto nochange;
|
||||
}
|
||||
free(fltr);
|
||||
fltr = tmp;
|
||||
strlcpy(fltr, tmp, sizeof(fltr));
|
||||
DPRINTF_S(fltr);
|
||||
/* Save current */
|
||||
if (n > 0)
|
||||
oldpath = mkpath(path, dents[cur].name);
|
||||
mkpath(path, dents[cur].name, oldpath, sizeof(oldpath));
|
||||
goto begin;
|
||||
case SEL_TYPE:
|
||||
nowtyping = 1;
|
||||
|
@ -788,14 +761,13 @@ moretyping:
|
|||
}
|
||||
}
|
||||
/* Copy or reset filter */
|
||||
free(fltr);
|
||||
if (tmp != NULL)
|
||||
fltr = xstrdup(tmp);
|
||||
strlcpy(fltr, tmp, sizeof(fltr));
|
||||
else
|
||||
fltr = xstrdup(ifilter);
|
||||
strlcpy(fltr, ifilter, sizeof(fltr));
|
||||
/* Save current */
|
||||
if (n > 0)
|
||||
oldpath = mkpath(path, dents[cur].name);
|
||||
mkpath(path, dents[cur].name, oldpath, sizeof(oldpath));
|
||||
if (!nowtyping)
|
||||
free(tmp);
|
||||
goto begin;
|
||||
|
@ -829,29 +801,27 @@ moretyping:
|
|||
clearprompt();
|
||||
goto nochange;
|
||||
}
|
||||
newpath = mkpath(path, tmp);
|
||||
mkpath(path, tmp, newpath, sizeof(newpath));
|
||||
free(tmp);
|
||||
if (canopendir(newpath) == 0) {
|
||||
free(newpath);
|
||||
printwarn();
|
||||
goto nochange;
|
||||
}
|
||||
free(path);
|
||||
path = newpath;
|
||||
free(fltr);
|
||||
fltr = xstrdup(ifilter); /* Reset filter */
|
||||
strlcpy(path, newpath, sizeof(path));
|
||||
/* Reset filter */
|
||||
strlcpy(fltr, ifilter, sizeof(fltr))
|
||||
DPRINTF_S(path);
|
||||
goto begin;
|
||||
case SEL_MTIME:
|
||||
mtimeorder = !mtimeorder;
|
||||
/* Save current */
|
||||
if (n > 0)
|
||||
oldpath = mkpath(path, dents[cur].name);
|
||||
mkpath(path, dents[cur].name, oldpath, sizeof(oldpath));
|
||||
goto begin;
|
||||
case SEL_REDRAW:
|
||||
/* Save current */
|
||||
if (n > 0)
|
||||
oldpath = mkpath(path, dents[cur].name);
|
||||
mkpath(path, dents[cur].name, oldpath, sizeof(oldpath));
|
||||
goto begin;
|
||||
case SEL_RUN:
|
||||
run = xgetenv(env, run);
|
||||
|
|
Loading…
Reference in a new issue