2007-07-20 03:15:46 -08:00
|
|
|
/* ncdu - NCurses Disk Usage
|
|
|
|
|
|
2009-01-11 00:34:19 -09:00
|
|
|
Copyright (c) 2007-2009 Yoran Heling
|
2007-07-20 03:15:46 -08:00
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
|
|
|
a copy of this software and associated documentation files (the
|
|
|
|
|
"Software"), to deal in the Software without restriction, including
|
|
|
|
|
without limitation the rights to use, copy, modify, merge, publish,
|
|
|
|
|
distribute, sublicense, and/or sell copies of the Software, and to
|
|
|
|
|
permit persons to whom the Software is furnished to do so, subject to
|
|
|
|
|
the following conditions:
|
|
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included
|
|
|
|
|
in all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
|
|
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
|
|
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
|
|
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
|
|
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
|
|
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
2009-04-11 01:37:45 -08:00
|
|
|
#include "util.h"
|
2007-07-20 03:15:46 -08:00
|
|
|
|
2009-04-11 01:37:45 -08:00
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <ncurses.h>
|
|
|
|
|
|
|
|
|
|
int winrows, wincols;
|
|
|
|
|
int subwinr, subwinc;
|
|
|
|
|
|
|
|
|
|
char cropstrdat[4096];
|
|
|
|
|
char formatsizedat[8];
|
2007-08-01 07:01:42 -08:00
|
|
|
char fullsizedat[20]; /* max: 999.999.999.999.999 */
|
2007-07-20 03:15:46 -08:00
|
|
|
|
2009-04-11 01:37:45 -08:00
|
|
|
|
|
|
|
|
char *cropstr(const char *from, int s) {
|
2007-07-20 03:15:46 -08:00
|
|
|
int i, j, o = strlen(from);
|
|
|
|
|
if(o < s) {
|
2009-04-11 01:37:45 -08:00
|
|
|
strcpy(cropstrdat, from);
|
|
|
|
|
return cropstrdat;
|
2007-07-20 03:15:46 -08:00
|
|
|
}
|
|
|
|
|
j=s/2-3;
|
|
|
|
|
for(i=0; i<j; i++)
|
2009-04-11 01:37:45 -08:00
|
|
|
cropstrdat[i] = from[i];
|
|
|
|
|
cropstrdat[i] = '.';
|
|
|
|
|
cropstrdat[++i] = '.';
|
|
|
|
|
cropstrdat[++i] = '.';
|
2007-07-20 03:15:46 -08:00
|
|
|
j=o-s;
|
|
|
|
|
while(++i<s)
|
2009-04-11 01:37:45 -08:00
|
|
|
cropstrdat[i] = from[j+i];
|
|
|
|
|
cropstrdat[s] = '\0';
|
|
|
|
|
return cropstrdat;
|
2007-07-20 03:15:46 -08:00
|
|
|
}
|
|
|
|
|
|
2009-04-11 01:37:45 -08:00
|
|
|
|
2009-04-18 04:05:45 -08:00
|
|
|
char *formatsize(const off_t from) {
|
2007-07-20 03:15:46 -08:00
|
|
|
float r = from;
|
|
|
|
|
char c = ' ';
|
2009-04-18 04:05:45 -08:00
|
|
|
if(r < 1000.0f) { }
|
|
|
|
|
else if(r < 1023e3f) { c = 'k'; r/=1024.0f; }
|
|
|
|
|
else if(r < 1023e6f) { c = 'M'; r/=1048576.0f; }
|
|
|
|
|
else if(r < 1023e9f) { c = 'G'; r/=1073741824.0f; }
|
|
|
|
|
else { c = 'T'; r/=1099511627776.0f; }
|
2009-04-11 01:37:45 -08:00
|
|
|
sprintf(formatsizedat, "%5.1f%cB", r, c);
|
|
|
|
|
return formatsizedat;
|
2007-07-20 03:15:46 -08:00
|
|
|
}
|
|
|
|
|
|
2009-04-11 01:37:45 -08:00
|
|
|
|
2007-08-01 07:01:42 -08:00
|
|
|
char *fullsize(const off_t from) {
|
|
|
|
|
char tmp[20];
|
2007-08-16 00:36:58 -08:00
|
|
|
off_t n = from;
|
|
|
|
|
int i, j;
|
|
|
|
|
|
2009-04-11 01:37:45 -08:00
|
|
|
/* the K&R method - more portable than sprintf with %lld */
|
2007-08-16 00:36:58 -08:00
|
|
|
i = 0;
|
|
|
|
|
do {
|
|
|
|
|
tmp[i++] = n % 10 + '0';
|
|
|
|
|
} while((n /= 10) > 0);
|
|
|
|
|
tmp[i] = '\0';
|
|
|
|
|
|
2009-04-11 01:37:45 -08:00
|
|
|
/* reverse and add thousand seperators */
|
2007-08-16 00:36:58 -08:00
|
|
|
j = 0;
|
|
|
|
|
while(i--) {
|
|
|
|
|
fullsizedat[j++] = tmp[i];
|
|
|
|
|
if(i != 0 && i%3 == 0)
|
|
|
|
|
fullsizedat[j++] = '.';
|
2007-08-01 07:01:42 -08:00
|
|
|
}
|
2007-08-16 00:36:58 -08:00
|
|
|
fullsizedat[j] = '\0';
|
|
|
|
|
|
2009-04-11 01:37:45 -08:00
|
|
|
return fullsizedat;
|
2007-08-01 07:01:42 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2009-04-11 01:37:45 -08:00
|
|
|
int ncresize(int minrows, int mincols) {
|
2007-07-20 03:15:46 -08:00
|
|
|
int ch;
|
2009-04-11 01:37:45 -08:00
|
|
|
|
2007-07-20 03:15:46 -08:00
|
|
|
getmaxyx(stdscr, winrows, wincols);
|
2009-04-11 01:37:45 -08:00
|
|
|
while((minrows && winrows < minrows) || (mincols && wincols < mincols)) {
|
2007-07-20 03:15:46 -08:00
|
|
|
erase();
|
|
|
|
|
mvaddstr(0, 0, "Warning: terminal too small,");
|
|
|
|
|
mvaddstr(1, 1, "please either resize your terminal,");
|
|
|
|
|
mvaddstr(2, 1, "press i to ignore, or press q to quit.");
|
|
|
|
|
refresh();
|
|
|
|
|
nodelay(stdscr, 0);
|
|
|
|
|
ch = getch();
|
|
|
|
|
getmaxyx(stdscr, winrows, wincols);
|
|
|
|
|
if(ch == 'q') {
|
|
|
|
|
erase();
|
|
|
|
|
refresh();
|
|
|
|
|
endwin();
|
|
|
|
|
exit(0);
|
|
|
|
|
}
|
|
|
|
|
if(ch == 'i')
|
2009-04-11 01:37:45 -08:00
|
|
|
return 1;
|
2007-07-20 03:15:46 -08:00
|
|
|
}
|
2007-07-26 04:56:24 -08:00
|
|
|
erase();
|
2009-04-11 01:37:45 -08:00
|
|
|
return 0;
|
2007-07-20 03:15:46 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-08-16 00:36:58 -08:00
|
|
|
void nccreate(int height, int width, char *title) {
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
subwinr = winrows/2-height/2;
|
|
|
|
|
subwinc = wincols/2-width/2;
|
|
|
|
|
|
2009-04-11 01:37:45 -08:00
|
|
|
/* clear window */
|
2007-08-16 00:36:58 -08:00
|
|
|
for(i=0; i<height; i++)
|
|
|
|
|
mvhline(subwinr+i, subwinc, ' ', width);
|
|
|
|
|
|
2009-04-11 01:37:45 -08:00
|
|
|
/* box() only works around curses windows, so create our own */
|
2007-08-16 00:36:58 -08:00
|
|
|
move(subwinr, subwinc);
|
|
|
|
|
addch(ACS_ULCORNER);
|
|
|
|
|
for(i=0; i<width-2; i++)
|
|
|
|
|
addch(ACS_HLINE);
|
|
|
|
|
addch(ACS_URCORNER);
|
|
|
|
|
|
|
|
|
|
move(subwinr+height-1, subwinc);
|
|
|
|
|
addch(ACS_LLCORNER);
|
|
|
|
|
for(i=0; i<width-2; i++)
|
|
|
|
|
addch(ACS_HLINE);
|
|
|
|
|
addch(ACS_LRCORNER);
|
|
|
|
|
|
|
|
|
|
mvvline(subwinr+1, subwinc, ACS_VLINE, height-2);
|
|
|
|
|
mvvline(subwinr+1, subwinc+width-1, ACS_VLINE, height-2);
|
|
|
|
|
|
2009-04-11 01:37:45 -08:00
|
|
|
/* title */
|
2007-08-16 00:36:58 -08:00
|
|
|
attron(A_BOLD);
|
|
|
|
|
mvaddstr(subwinr, subwinc+4, title);
|
|
|
|
|
attroff(A_BOLD);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ncprint(int r, int c, char *fmt, ...) {
|
|
|
|
|
va_list arg;
|
|
|
|
|
va_start(arg, fmt);
|
|
|
|
|
move(subwinr+r, subwinc+c);
|
|
|
|
|
vw_printw(stdscr, fmt, arg);
|
|
|
|
|
va_end(arg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-07-20 03:15:46 -08:00
|
|
|
void freedir_rec(struct dir *dr) {
|
|
|
|
|
struct dir *tmp, *tmp2;
|
|
|
|
|
tmp2 = dr;
|
|
|
|
|
while((tmp = tmp2) != NULL) {
|
|
|
|
|
if(tmp->sub) freedir_rec(tmp->sub);
|
|
|
|
|
free(tmp->name);
|
|
|
|
|
tmp2 = tmp->next;
|
|
|
|
|
free(tmp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-11 01:37:45 -08:00
|
|
|
|
2007-07-20 03:15:46 -08:00
|
|
|
struct dir *freedir(struct dir *dr) {
|
|
|
|
|
struct dir *tmp, *cur;
|
|
|
|
|
|
2009-04-11 01:37:45 -08:00
|
|
|
/* update sizes of parent directories */
|
2007-07-20 03:15:46 -08:00
|
|
|
tmp = dr;
|
|
|
|
|
while((tmp = tmp->parent) != NULL) {
|
|
|
|
|
tmp->size -= dr->size;
|
2007-08-12 01:52:24 -08:00
|
|
|
tmp->asize -= dr->asize;
|
2007-08-01 05:17:26 -08:00
|
|
|
tmp->items -= dr->items+1;
|
2007-07-20 03:15:46 -08:00
|
|
|
}
|
|
|
|
|
|
2009-04-11 01:37:45 -08:00
|
|
|
/* free dr->sub recursive */
|
2007-07-20 03:15:46 -08:00
|
|
|
if(dr->sub) freedir_rec(dr->sub);
|
|
|
|
|
|
2009-04-11 01:37:45 -08:00
|
|
|
/* update references */
|
2007-07-20 03:15:46 -08:00
|
|
|
cur = NULL;
|
2007-07-26 08:37:33 -08:00
|
|
|
if(dr->parent) {
|
2009-04-11 01:37:45 -08:00
|
|
|
/* item is at the top of the dir, refer to next item */
|
2007-07-26 08:37:33 -08:00
|
|
|
if(dr->parent->sub == dr) {
|
2007-07-20 03:15:46 -08:00
|
|
|
dr->parent->sub = dr->next;
|
2007-07-26 08:37:33 -08:00
|
|
|
cur = dr->next;
|
2007-07-20 03:15:46 -08:00
|
|
|
}
|
2009-04-11 01:37:45 -08:00
|
|
|
/* else, get the previous item and update it's "next"-reference */
|
2007-07-26 08:37:33 -08:00
|
|
|
else
|
|
|
|
|
for(tmp = dr->parent->sub; tmp != NULL; tmp = tmp->next)
|
|
|
|
|
if(tmp->next == dr) {
|
|
|
|
|
tmp->next = dr->next;
|
|
|
|
|
cur = tmp;
|
|
|
|
|
}
|
2009-04-11 01:37:45 -08:00
|
|
|
/* no previous item, refer to parent dir */
|
2007-08-12 01:52:24 -08:00
|
|
|
if(cur == NULL && dr->parent->parent)
|
|
|
|
|
cur = dr->parent;
|
2007-07-20 03:15:46 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(dr->name);
|
|
|
|
|
free(dr);
|
|
|
|
|
|
2009-04-11 04:16:51 -08:00
|
|
|
return cur;
|
2007-07-20 03:15:46 -08:00
|
|
|
}
|
|
|
|
|
|
2009-04-11 01:37:45 -08:00
|
|
|
|
2007-07-20 03:15:46 -08:00
|
|
|
char *getpath(struct dir *cur, char *to) {
|
2007-07-26 08:37:33 -08:00
|
|
|
struct dir *d, *list[100];
|
|
|
|
|
int c = 0;
|
|
|
|
|
|
|
|
|
|
for(d = cur; (d = d->parent) != NULL; )
|
|
|
|
|
list[c++] = d;
|
|
|
|
|
|
2007-07-20 03:15:46 -08:00
|
|
|
to[0] = '\0';
|
2007-07-26 08:37:33 -08:00
|
|
|
while(c--) {
|
2007-08-05 03:12:40 -08:00
|
|
|
if(list[c]->parent && list[c]->parent->name[strlen(list[c]->parent->name)-1] != '/')
|
2007-07-20 03:15:46 -08:00
|
|
|
strcat(to, "/");
|
2007-07-26 08:37:33 -08:00
|
|
|
strcat(to, list[c]->name);
|
2007-07-20 03:15:46 -08:00
|
|
|
}
|
2007-07-26 08:37:33 -08:00
|
|
|
|
2007-07-20 03:15:46 -08:00
|
|
|
return to;
|
|
|
|
|
}
|
2009-04-11 01:37:45 -08:00
|
|
|
|