Skip to content
Snippets Groups Projects
Commit f392bf3e authored by Yorhel's avatar Yorhel
Browse files

Rewrote calc.c in the new style & framework

ncdu is currently pretty much in a non-working state, but things will
get fixed eventually after porting the other source files to the new
framework.
parent 02705d2c
No related branches found
No related tags found
No related merge requests found
......@@ -428,12 +428,12 @@ void showBrowser(void) {
}
break;
/* refresh */
/* refresh *
case 'r':
hideinfo;
drawBrowser(0);
if((n = showCalc(getpath(bcur, tmp))) != NULL) {
/* free current items */
* free current items *
d = bcur;
bcur = bcur->parent;
while(d != NULL) {
......@@ -442,7 +442,7 @@ void showBrowser(void) {
freedir(t);
}
/* update parent dir */
* update parent dir *
bcur->sub = n->sub;
bcur->items = n->items;
bcur->size = n->size;
......@@ -450,7 +450,7 @@ void showBrowser(void) {
for(t = bcur->sub; t != NULL; t = t->next)
t->parent = bcur;
/* update sizes of parent dirs */
* update sizes of parent dirs *
for(t = bcur; (t = t->parent) != NULL; ) {
t->size += bcur->size;
t->asize += bcur->asize;
......@@ -462,6 +462,7 @@ void showBrowser(void) {
free(n);
}
break;
*/
/* and other stuff */
case KEY_RESIZE:
......
......@@ -26,18 +26,6 @@
#include "ncdu.h"
/* parent dir we are calculating */
struct dir *parent;
/* current device we are on */
dev_t curdev;
/* path of the last dir we couldn't read */
char lasterr[PATH_MAX];
/* and for the animation... */
int anpos;
char antext[15] = "Calculating...";
suseconds_t lastupdate;
/* My own implementation of realpath()
- assumes that *every* possible path fits in PATH_MAX bytes
......@@ -140,173 +128,52 @@ char *rpath(const char *from, char *to) {
}
/* the progress window */
static void drawProgress(char *cdir) {
char ani[15];
int i;
nccreate(10, 60, dat == NULL ? "Calculating..." : "Recalculating...");
ncprint(2, 2, "Total items: %-8d size: %s",
parent->items, cropsize(parent->size));
ncprint(3, 2, "Current dir: %s", cropdir(cdir, 43));
ncaddstr(8, 43, "Press q to quit");
/* show warning if we couldn't open a dir */
if(lasterr[0] != '\0') {
attron(A_BOLD);
ncaddstr(5, 2, "Warning:");
attroff(A_BOLD);
ncprint(5, 11, "could not open %-32s", cropdir(lasterr, 32));
ncaddstr(6, 3, "some directory sizes may not be correct");
}
/* animation - but only if the screen refreshes more than or once every second */
if(sdelay <= 1000) {
if(++anpos == 28) anpos = 0;
strcpy(ani, " ");
if(anpos < 14)
for(i=0; i<=anpos; i++)
ani[i] = antext[i];
else
for(i=13; i>anpos-14; i--)
ani[i] = antext[i];
} else
strcpy(ani, antext);
ncaddstr(8, 3, ani);
refresh();
}
/* show error if can't open parent dir */
static void drawError(char *dir) {
nccreate(10, 60, "Error!");
attron(A_BOLD);
ncaddstr(5, 2, "Error:");
attroff(A_BOLD);
ncprint(5, 9, "could not open %s", cropdir(dir, 34));
ncaddstr(6, 3, "press any key to continue...");
refresh();
}
/* checks for input and calls drawProgress */
int updateProgress(char *path) {
struct timeval tv;
int ch;
/* check for input or screen resizes */
nodelay(stdscr, 1);
while((ch = getch()) != ERR) {
if(ch == 'q')
return(0);
if(ch == KEY_RESIZE) {
ncresize();
if(dat != NULL)
drawBrowser(0);
drawProgress(path);
}
}
nodelay(stdscr, 0);
/* don't update the screen with shorter intervals than sdelay */
gettimeofday(&tv, (void *)NULL);
tv.tv_usec = (1000*(tv.tv_sec % 1000) + (tv.tv_usec / 1000)) / sdelay;
if(lastupdate != tv.tv_usec) {
drawProgress(path);
lastupdate = tv.tv_usec;
}
return(1);
}
/* recursive */
int calcDir(struct dir *dest, char *path) {
struct dir *d, *t, *last;
int calc_item(struct dir *par, char *path, char *name) {
char tmp[PATH_MAX];
struct dir *t, *d;
struct stat fs;
DIR *dir;
struct dirent *dr;
char *f, tmp[PATH_MAX];
int len, derr = 0, serr = 0;
if(!updateProgress(path))
return(0);
/* open directory */
if((dir = opendir(path)) == NULL) {
strcpy(lasterr, path);
dest->flags |= FF_ERR;
t = dest;
while((t = t->parent) != NULL)
t->flags |= FF_SERR;
return(1);
}
len = strlen(path);
/* add leading slash */
if(path[len-1] != '/') {
path[len] = '/';
path[++len] = '\0';
}
/* read directory */
last = NULL;
while((dr = readdir(dir)) != NULL) {
f = dr->d_name;
if(f[0] == '.' && (f[1] == '\0' || (f[1] == '.' && f[2] == '\0')))
continue;
if(name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
return 0;
/* path too long - ignore file */
if(len+strlen(f)+1 > PATH_MAX) {
derr = 1;
errno = 0;
continue;
}
if(strlen(path)+strlen(name)+1 > PATH_MAX)
return 1;
/* allocate dir and fix references */
d = calloc(sizeof(struct dir), 1);
d->parent = dest;
if(dest->sub == NULL)
dest->sub = d;
if(last != NULL)
last->next = d;
last = d;
/* set d->name */
d->name = malloc(strlen(f)+1);
strcpy(d->name, f);
d->parent = par;
if(par->sub == NULL)
par->sub = d;
else {
for(t=par->sub; t->next!=NULL; t=t->next)
;
t->next = d;
}
d->name = malloc(strlen(name)+1);
strcpy(d->name, name);
#ifdef __CYGWIN__
/* /proc/registry names may contain slashes */
if(strchr(d->name, '/') || strchr(d->name, '\\')) {
serr = 1;
errno = 0;
d->flags |= FF_ERR;
continue;
return 0;
}
#endif
/* get full path */
strcpy(tmp, path);
strcat(tmp, f);
/* lstat */
strcpy(tmp, path);
strcat(tmp, name);
if(lstat(tmp, &fs)) {
serr = 1;
errno = 0;
d->flags |= FF_ERR;
continue;
return 0;
}
/* check for excludes and same filesystem */
if(matchExclude(tmp))
d->flags |= FF_EXL;
if(sflags & SF_SMFS && curdev != fs.st_dev)
if(sflags & SF_SMFS && pstate.calc.curdev != fs.st_dev)
d->flags |= FF_OTHFS;
/* determine type of this item */
......@@ -317,91 +184,208 @@ int calcDir(struct dir *dest, char *path) {
/* update parent dirs */
if(!(d->flags & FF_EXL))
for(t = dest; t != NULL; t = t->parent)
for(t=d; t!=NULL; t=t->parent)
t->items++;
/* count the size */
if(!(d->flags & FF_EXL || d->flags & FF_OTHFS)) {
d->size = fs.st_blocks * S_BLKSIZE;
d->asize = fs.st_size;
for(t = dest; t != NULL; t = t->parent) {
for(t=d; t!=NULL; t=t->parent) {
t->size += d->size;
t->asize += d->asize;
}
}
return 0;
}
/* show status */
if(!updateProgress(tmp))
return(0);
/* recursively walk through the directory tree */
int calc_dir(struct dir *dest, char *path) {
struct dir *t;
DIR *dir;
struct dirent *dr;
char tmp[PATH_MAX];
int len;
if(input_handle(1))
return 1;
/* open directory */
if((dir = opendir(path)) == NULL) {
strcpy(pstate.calc.lasterr, path);
dest->flags |= FF_ERR;
t = dest;
while((t = t->parent) != NULL)
t->flags |= FF_SERR;
return 0;
}
/* add leading slash */
len = strlen(path);
if(path[len-1] != '/') {
path[len] = '/';
path[++len] = '\0';
}
/* read directory */
while((dr = readdir(dir)) != NULL) {
if(calc_item(dest, path, dr->d_name))
dest->flags |= FF_ERR;
if(input_handle(1))
return 1;
errno = 0;
}
derr = derr || errno;
if(errno) {
if(dest->flags & FF_SERR)
dest->flags -= FF_SERR;
dest->flags |= FF_ERR;
}
closedir(dir);
/* error occured while reading this dir, update parent dirs */
if(derr || serr) {
dest->flags |= derr ? FF_ERR : FF_SERR;
for(t=dest->sub; t!=NULL; t=t->next)
if(t->flags & FF_ERR || t->flags & FF_SERR)
dest->flags |= FF_SERR;
if(dest->flags & FF_ERR || dest->flags & FF_SERR) {
for(t = dest; (t = t->parent) != NULL; )
t->flags |= FF_SERR;
}
if(dest->sub) {
/* calculate subdirectories */
for(d = dest->sub; d != NULL; d = d->next)
if(d->flags & FF_DIR && !(d->flags & FF_EXL || d->flags & FF_OTHFS)) {
for(t=dest->sub; t!=NULL; t=t->next)
if(t->flags & FF_DIR && !(t->flags & FF_EXL || t->flags & FF_OTHFS)) {
strcpy(tmp, path);
strcat(tmp, d->name);
if(!calcDir(d, tmp))
return(0);
strcat(tmp, t->name);
if(calc_dir(t, tmp))
return 1;
}
return 0;
}
void calc_draw_progress() {
static char antext[15] = "Calculating...";
char ani[15];
int i;
nccreate(10, 60, dat == NULL ? "Calculating..." : "Recalculating...");
ncprint(2, 2, "Total items: %-8d size: %s",
pstate.calc.parent->items, cropsize(pstate.calc.parent->size));
ncprint(3, 2, "Current dir: %s", cropdir(pstate.calc.cur, 43));
ncaddstr(8, 43, "Press q to quit");
/* show warning if we couldn't open a dir */
if(pstate.calc.lasterr[0] != '\0') {
attron(A_BOLD);
ncaddstr(5, 2, "Warning:");
attroff(A_BOLD);
ncprint(5, 11, "could not open %-32s", cropdir(pstate.calc.lasterr, 32));
ncaddstr(6, 3, "some directory sizes may not be correct");
}
return(1);
/* animation - but only if the screen refreshes more than or once every second */
if(sdelay <= 1000) {
if(++pstate.calc.anpos == 28)
pstate.calc.anpos = 0;
strcpy(ani, " ");
if(pstate.calc.anpos < 14)
for(i=0; i<=pstate.calc.anpos; i++)
ani[i] = antext[i];
else
for(i=13; i>pstate.calc.anpos-14; i--)
ani[i] = antext[i];
} else
strcpy(ani, antext);
ncaddstr(8, 3, ani);
}
struct dir *showCalc(char *path) {
char tmp[PATH_MAX];
struct stat fs;
struct dir *t;
void calc_draw_error(char *cur, char *msg) {
nccreate(7, 60, "Error!");
/* init/reset global vars */
*lasterr = '\0';
anpos = 0;
lastupdate = 999;
memset(tmp, 0, PATH_MAX);
/* init parent dir */
if(rpath(path, tmp) == NULL || lstat(tmp, &fs) != 0 || !S_ISDIR(fs.st_mode)) {
do {
ncresize();
if(dat != NULL)
drawBrowser(0);
drawError(path);
} while (getch() == KEY_RESIZE);
return(NULL);
attron(A_BOLD);
ncaddstr(2, 2, "Error:");
attroff(A_BOLD);
ncprint(2, 9, "could not open %s", cropdir(cur, 34));
ncprint(3, 4, "%s", cropdir(msg, 52));
ncaddstr(5, 30, "press any key to continue...");
}
parent = calloc(sizeof(struct dir), 1);
parent->size = fs.st_blocks * S_BLKSIZE;
parent->asize = fs.st_size;
parent->flags |= FF_DIR;
curdev = fs.st_dev;
parent->name = malloc(strlen(tmp)+1);
strcpy(parent->name, tmp);
/* start calculating */
if(!calcDir(parent, tmp)) {
freedir(parent);
return(NULL);
int calc_draw() {
struct timeval tv;
if(pstate.calc.err) {
calc_draw_error(pstate.calc.cur, pstate.calc.errmsg);
return 0;
}
return(parent);
/* should we really draw the screen again? */
gettimeofday(&tv, (void *)NULL);
tv.tv_usec = (1000*(tv.tv_sec % 1000) + (tv.tv_usec / 1000)) / sdelay;
if(pstate.calc.lastupdate != tv.tv_usec) {
calc_draw_progress();
pstate.calc.lastupdate = tv.tv_usec;
return 0;
}
return 1;
}
int calc_key(int ch) {
if(pstate.calc.err)
return 1;
if(ch == 'q')
return 1;
return 0;
}
void calc_process() {
char tmp[PATH_MAX];
struct stat fs;
struct dir *t;
/* init/reset global vars */
pstate.calc.err = 0;
pstate.calc.lastupdate = 999;
pstate.calc.lasterr[0] = 0;
pstate.calc.anpos = 0;
/* check root directory */
if(rpath(pstate.calc.cur, tmp) == NULL || lstat(tmp, &fs) != 0 || !S_ISDIR(fs.st_mode)) {
pstate.calc.err = 1;
strcpy(pstate.calc.errmsg, "Directory not found");
goto fail;
}
/* initialize parent dir */
t = (struct dir *) calloc(1, sizeof(struct dir));
t->size = fs.st_blocks * S_BLKSIZE;
t->asize = fs.st_size;
t->flags |= FF_DIR;
t->name = (char *) malloc(strlen(tmp)+1);
strcpy(t->name, tmp);
pstate.calc.parent = t;
pstate.calc.curdev = fs.st_dev;
/* start calculating */
if(!calc_dir(pstate.calc.parent, tmp) && !pstate.calc.err) {
pstate.st = ST_BROWSE;
return;
}
/* something went wrong... */
freedir(pstate.calc.parent);
fail:
while(pstate.calc.err && !input_handle(0))
;
pstate.st = dat != NULL ? ST_BROWSE : ST_QUIT;
return;
}
......@@ -28,14 +28,44 @@
/* check ncdu.h what these are for */
struct dir *dat;
int winrows, wincols;
char sdir[PATH_MAX];
int sflags, bflags, sdelay, bgraph;
int subwinc, subwinr;
struct state pstate;
void screen_draw() {
int n = 1;
switch(pstate.st) {
case ST_CALC: n = calc_draw();
}
if(!n)
refresh();
}
int input_handle(int wait) {
int ch;
nodelay(stdscr, wait);
screen_draw();
while((ch = getch()) != ERR) {
if(ch == KEY_RESIZE) {
ncresize();
screen_draw();
continue;
}
switch(pstate.st) {
case ST_CALC: return calc_key(ch);
}
}
return 0;
}
/* parse command line */
void argv_parse(int argc, char **argv, char *dir) {
int i, j;
int i, j, len;
/* load defaults */
memset(dir, 0, PATH_MAX);
......@@ -63,7 +93,8 @@ void argv_parse(int argc, char **argv, char *dir) {
continue;
}
/* small flags */
for(j=1; j < strlen(argv[i]); j++)
len = strlen(argv[i]);
for(j=1; j<len; j++)
switch(argv[i][j]) {
case 'x': sflags |= SF_SMFS; break;
case 'q': sdelay = 2000; break;
......@@ -85,12 +116,12 @@ void argv_parse(int argc, char **argv, char *dir) {
exit(1);
}
} else {
dir[PATH_MAX - 1] = 0;
strncpy(dir, argv[i], PATH_MAX);
if(dir[PATH_MAX - 1] != 0) {
printf("Error: path length exceeds PATH_MAX\n");
exit(1);
}
dir[PATH_MAX - 1] = 0;
}
}
}
......@@ -100,7 +131,8 @@ void argv_parse(int argc, char **argv, char *dir) {
int main(int argc, char **argv) {
dat = NULL;
argv_parse(argc, argv, pstate.calc.root);
memset((void *)&pstate, 0, sizeof(struct state));
argv_parse(argc, argv, pstate.calc.cur);
pstate.st = ST_CALC;
initscr();
......@@ -110,8 +142,16 @@ int main(int argc, char **argv) {
keypad(stdscr, TRUE);
ncresize();
while(pstate.st != ST_QUIT) {
if(pstate.st == ST_CALC)
calc_process();
/*else
wait_for_input() */
}
/*
if((dat = showCalc(pstate.calc.root)) != NULL)
showBrowser();
showBrowser();*/
erase();
refresh();
......
......@@ -121,6 +121,7 @@
#define ST_BROWSE 1
#define ST_DEL 2
#define ST_HELP 3
#define ST_QUIT 4
......@@ -129,7 +130,7 @@
*/
struct dir {
struct dir *parent, *next, *sub;
unsigned char *name;
char *name;
off_t size, asize;
unsigned long items;
unsigned char flags;
......@@ -138,7 +139,14 @@ struct dir {
struct state {
int st; /* SC_x */
struct {
char root[PATH_MAX];
char err;
char cur[PATH_MAX];
char lasterr[PATH_MAX];
char errmsg[128];
struct dir *parent;
dev_t curdev;
suseconds_t lastupdate;
int anpos;
} calc;
/* TODO: information structs for the other states */
};
......@@ -166,6 +174,8 @@ extern struct state pstate;
/*
* G L O B A L F U N C T I O N S
*/
/* main.c */
int input_handle(int);
/* util.c */
char *cropdir(const char *, int);
char *cropsize(const off_t);
......@@ -176,7 +186,9 @@ void ncprint(int, int, char *, ...);
struct dir *freedir(struct dir *);
char *getpath(struct dir *, char *);
/* calc.c */
struct dir *showCalc(char *);
void calc_process(void);
int calc_key(int);
int calc_draw(void);
/* browser.c */
void drawBrowser(int);
void showBrowser(void);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment