From 4bb7d6b7c2267b517cb83359544e6b94922c0ba6 Mon Sep 17 00:00:00 2001 From: Yorhel Date: Thu, 23 Apr 2009 21:15:11 +0200 Subject: [PATCH] Removed reliance on PATH_MAX on most places ncdu already does seem to handle longer paths now, though there are still a few places where the code still relies on PATH_MAX. Will fix those later. --- src/browser.c | 15 ++++---- src/calc.c | 95 +++++++++++++++++++++++++++++++++------------------ src/delete.c | 24 ++++++------- src/util.c | 42 ++++++++++++++++------- src/util.h | 5 +-- 5 files changed, 113 insertions(+), 68 deletions(-) diff --git a/src/browser.c b/src/browser.c index 29b40c7..596f29d 100644 --- a/src/browser.c +++ b/src/browser.c @@ -134,8 +134,6 @@ struct dir *browse_sort(struct dir *list) { void browse_draw_info(struct dir *dr) { - char path[PATH_MAX]; - nccreate(11, 60, "Item info"); attron(A_BOLD); @@ -147,7 +145,7 @@ void browse_draw_info(struct dir *dr) { attroff(A_BOLD); ncaddstr(2, 9, cropstr(dr->name, 49)); - ncaddstr(3, 9, cropstr(getpath(dr, path), 49)); + ncaddstr(3, 9, cropstr(getpath(dr), 49)); ncaddstr(4, 9, dr->flags & FF_DIR ? "Directory" : dr->flags & FF_FILE ? "File" : "Other (link, device, socket, ..)"); ncprint(6, 18, "%s (%s B)", formatsize(dr->size), fullsize(dr->size)); @@ -226,7 +224,7 @@ void browse_draw_item(struct dir *n, int row, off_t max, int ispar) { int browse_draw() { struct dir *n, ref, *cur, *sel = NULL; - char tmp[PATH_MAX]; + char tmp[PATH_MAX], *tmp2; int selected, i; off_t max = 1; @@ -250,9 +248,9 @@ int browse_draw() { mvhline(1, 0, '-', wincols); if(cur) { mvaddch(1, 3, ' '); - getpath(cur, tmp); - mvaddstr(1, 4, cropstr(tmp, wincols-8)); - mvaddch(1, 4+((int)strlen(tmp) > wincols-8 ? wincols-8 : (int)strlen(tmp)), ' '); + tmp2 = getpath(cur); + mvaddstr(1, 4, cropstr(tmp2, wincols-8)); + mvaddch(1, 4+((int)strlen(tmp2) > wincols-8 ? wincols-8 : (int)strlen(tmp2)), ' '); } if(!cur) @@ -339,7 +337,6 @@ void browse_key_sel(int change) { #define toggle(x,y) if(x & y) x -=y; else x |= y int browse_key(int ch) { - char tmp[PATH_MAX]; char sort = 0, nonfo = 0; struct dir *n, *r; @@ -419,7 +416,7 @@ int browse_key(int ch) { /* refresh */ case 'r': - calc_init(getpath(browse_dir, tmp), browse_dir->parent); + calc_init(getpath(browse_dir), browse_dir->parent); nonfo++; sort++; break; diff --git a/src/calc.c b/src/calc.c index ee97de7..ae3eaec 100644 --- a/src/calc.c +++ b/src/calc.c @@ -53,28 +53,25 @@ char calc_smfs = 0; /* global vars for internal use */ char failed; /* 1 on fatal error */ -char curpath[PATH_MAX]; /* last lstat()'ed item */ -char lasterr[PATH_MAX]; /* last unreadable dir/item */ -char errmsg[128]; /* error message, when err=1 */ +char *curpath; /* last lstat()'ed item */ +char *lasterr; /* last unreadable dir/item */ +char errmsg[128]; /* error message, when failed=1 */ struct dir *root; /* root directory struct we're calculating */ struct dir *orig; /* original directory, when recalculating */ dev_t curdev; /* current device we're calculating on */ long lastupdate; /* time of the last screen update */ int anpos; /* position of the animation string */ +int curpathl = 0, lasterrl = 0; -int calc_item(struct dir *par, char *path, char *name) { - char tmp[PATH_MAX]; +int calc_item(struct dir *par, char *name) { struct dir *t, *d; struct stat fs; + char *tmp; if(name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) return 0; - /* path too long - ignore file */ - if(strlen(path)+strlen(name)+1 > PATH_MAX) - return 1; - /* allocate dir and fix references */ d = calloc(sizeof(struct dir), 1); d->parent = par; @@ -96,17 +93,22 @@ int calc_item(struct dir *par, char *path, char *name) { } #endif - /* lstat */ - strcpy(tmp, path); - strcat(tmp, name); + /* update curpath */ + tmp = getpath(d); + if((int)strlen(tmp)+1 > curpathl) { + curpathl = strlen(tmp)+1; + curpath = realloc(curpath, curpathl); + } strcpy(curpath, tmp); - if(lstat(tmp, &fs)) { + + /* lstat */ + if(lstat(d->name, &fs)) { d->flags |= FF_ERR; return 0; } /* check for excludes and same filesystem */ - if(exclude_match(tmp)) + if(exclude_match(curpath)) d->flags |= FF_EXL; if(calc_smfs && curdev != fs.st_dev) @@ -136,20 +138,26 @@ int calc_item(struct dir *par, char *path, char *name) { } -/* recursively walk through the directory tree */ -int calc_dir(struct dir *dest, char *path) { +/* recursively walk through the directory tree, + assumes path resides in the cwd */ +int calc_dir(struct dir *dest) { struct dir *t; DIR *dir; + char *tmp; struct dirent *dr; - char tmp[PATH_MAX]; - int len; + int ch; if(input_handle(1)) return 1; /* open directory */ - if((dir = opendir(path)) == NULL) { - strcpy(lasterr, path); + if((dir = opendir(dest->name)) == NULL) { + tmp = getpath(dest); + if(lasterrl < (int)strlen(tmp)+1) { + lasterrl = strlen(tmp)+1; + lasterr = realloc(lasterr, lasterrl); + } + strcpy(lasterr, tmp); dest->flags |= FF_ERR; t = dest; while((t = t->parent) != NULL) @@ -157,16 +165,15 @@ int calc_dir(struct dir *dest, char *path) { return 0; } - /* add leading slash */ - len = strlen(path); - if(path[len-1] != '/') { - path[len] = '/'; - path[++len] = '\0'; + /* chdir */ + if(chdir(dest->name) < 0) { + dest->flags |= FF_ERR; + return 0; } /* read directory */ while((dr = readdir(dir)) != NULL) { - if(calc_item(dest, path, dr->d_name)) + if(calc_item(dest, dr->d_name)) dest->flags |= FF_ERR; if(input_handle(1)) return 1; @@ -190,13 +197,18 @@ int calc_dir(struct dir *dest, char *path) { } /* calculate subdirectories */ + ch = 0; 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, t->name); - if(calc_dir(t, tmp)) + if(t->flags & FF_DIR && !(t->flags & FF_EXL || t->flags & FF_OTHFS)) + if(calc_dir(t)) return 1; - } + + /* chdir back */ + if(chdir("..") < 0) { + failed = 1; + strcpy(errmsg, "Couldn't chdir to previous directory"); + return 1; + } return 0; } @@ -295,6 +307,11 @@ void calc_process() { strcpy(errmsg, "Directory not found"); goto fail; } + if(path_chdir(tmp) < 0 || chdir("..") < 0) { + failed = 1; + strcpy(errmsg, "Couldn't chdir into directory"); + goto fail; + } /* initialize parent dir */ t = (struct dir *) calloc(1, sizeof(struct dir)); @@ -306,7 +323,7 @@ void calc_process() { curdev = fs.st_dev; /* start calculating */ - if(!calc_dir(root, tmp) && !failed) { + if(!calc_dir(root) && !failed) { browse_init(root->sub); /* update references and free original item */ @@ -344,10 +361,22 @@ fail: void calc_init(char *dir, struct dir *org) { - failed = anpos = lasterr[0] = 0; + failed = anpos = 0; lastupdate = 999; orig = org; + if(curpathl == 0) { + curpathl = strlen(dir); + curpath = malloc(curpathl); + } else if(curpathl < (int)strlen(dir)+1) { + curpathl = strlen(dir)+1; + curpath = realloc(curpath, curpathl); + } strcpy(curpath, dir); + if(lasterrl == 0) { + lasterrl = 1; + lasterr = malloc(lasterrl); + } + lasterr[0] = 0; pstate = ST_CALC; } diff --git a/src/delete.c b/src/delete.c index 98139fe..502e436 100644 --- a/src/delete.c +++ b/src/delete.c @@ -27,6 +27,7 @@ #include "ncdu.h" #include "util.h" #include "browser.h" +#include "path.h" #include #include @@ -42,10 +43,10 @@ int delete_delay = 100; long lastupdate; -struct dir *root, *nextsel; +struct dir *root, *nextsel, *curdir; char noconfirm = 0, ignoreerr = 0, - state, seloption, curfile[PATH_MAX]; + state, seloption; int lasterrno; @@ -77,7 +78,7 @@ void delete_draw_confirm() { void delete_draw_progress() { nccreate(6, 60, "Deleting..."); - ncaddstr(1, 2, cropstr(curfile, 47)); + ncaddstr(1, 2, cropstr(getpath(curdir), 47)); ncaddstr(4, 41, "Press q to abort"); } @@ -85,7 +86,7 @@ void delete_draw_progress() { void delete_draw_error() { nccreate(6, 60, "Error!"); - ncprint(1, 2, "Can't delete %s:", cropstr(curfile, 42)); + ncprint(1, 2, "Can't delete %s:", cropstr(getpath(curdir), 42)); ncaddstr(2, 4, strerror(lasterrno)); if(seloption == 0) @@ -187,15 +188,14 @@ int delete_key(int ch) { int delete_dir(struct dir *dr) { struct dir *nxt, *cur; int r; - char file[PATH_MAX]; + char *path; - getpath(dr, file); - if(file[strlen(file)-1] != '/') - strcat(file, "/"); - strcat(file, dr->name); + /* calling path_chdir() this often isn't exactly efficient... */ + path = getpath(dr->sub); + path_chdir(path); /* check for input or screen resizes */ - strcpy(curfile, file); + curdir = dr; if(input_handle(1)) return 1; @@ -210,9 +210,9 @@ int delete_dir(struct dir *dr) { return 1; } } - r = rmdir(file); + r = rmdir(dr->name); } else - r = unlink(file); + r = unlink(dr->name); /* error occured, ask user what to do */ if(r == -1 && !ignoreerr) { diff --git a/src/util.c b/src/util.c index d6002fa..76f43d7 100644 --- a/src/util.c +++ b/src/util.c @@ -35,6 +35,8 @@ int subwinr, subwinc; char cropstrdat[4096]; char formatsizedat[8]; char fullsizedat[20]; /* max: 999.999.999.999.999 */ +char *getpathdat; +int getpathdatl = 0; char *cropstr(const char *from, int s) { @@ -208,20 +210,36 @@ void freedir(struct dir *dr) { } -char *getpath(struct dir *cur, char *to) { - struct dir *d, *list[100]; - int c = 0; +char *getpath(struct dir *cur) { + struct dir *d, **list; + int c, i; - for(d = cur; (d = d->parent) != NULL; ) - list[c++] = d; - - to[0] = '\0'; - while(c--) { - if(list[c]->parent && list[c]->parent->name[strlen(list[c]->parent->name)-1] != '/') - strcat(to, "/"); - strcat(to, list[c]->name); + c = i = 1; + for(d=cur; d!=NULL; d=d->parent) { + i += strlen(d->name)+1; + c++; } - return to; + if(getpathdatl == 0) { + getpathdatl = i; + getpathdat = malloc(i); + } else if(getpathdatl < i) { + getpathdatl = i; + getpathdat = realloc(getpathdat, i); + } + list = malloc(c*sizeof(struct dir *)); + + c = 0; + for(d=cur; d!=NULL; d=d->parent) + list[c++] = d; + + getpathdat[0] = '\0'; + while(c--) { + if(list[c]->parent) + strcat(getpathdat, "/"); + strcat(getpathdat, list[c]->name); + } + free(list); + return getpathdat; } diff --git a/src/util.h b/src/util.h index 72f3038..265f6fb 100644 --- a/src/util.h +++ b/src/util.h @@ -74,8 +74,9 @@ char *fullsize(const off_t); /* recursively free()s a directory tree */ void freedir(struct dir *); -/* generates full path from a dir item */ -char *getpath(struct dir *, char *); +/* generates full path from a dir item, + returned pointer will be overwritten with a subsequent call */ +char *getpath(struct dir *); #endif