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