2012-08-27 11:51:08 -08:00
|
|
|
/* ncdu - NCurses Disk Usage
|
|
|
|
|
|
2021-07-02 03:30:55 -08:00
|
|
|
Copyright (c) 2007-2021 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:
|
2012-08-27 11:51:08 -08:00
|
|
|
|
2007-07-20 03:15:46 -08:00
|
|
|
The above copyright notice and this permission notice shall be included
|
|
|
|
|
in all copies or substantial portions of the Software.
|
2012-08-27 11:51:08 -08:00
|
|
|
|
2007-07-20 03:15:46 -08:00
|
|
|
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>
|
2013-08-23 03:52:39 -08:00
|
|
|
#include <stdarg.h>
|
2019-07-23 01:01:48 -08:00
|
|
|
#include <unistd.h>
|
2014-04-12 22:34:32 -08:00
|
|
|
#ifdef HAVE_LOCALE_H
|
2013-01-13 03:35:25 -09:00
|
|
|
#include <locale.h>
|
2014-04-12 22:34:32 -08:00
|
|
|
#endif
|
2009-04-11 01:37:45 -08:00
|
|
|
|
2018-01-21 05:38:36 -09:00
|
|
|
int uic_theme;
|
2009-04-11 01:37:45 -08:00
|
|
|
int winrows, wincols;
|
|
|
|
|
int subwinr, subwinc;
|
2013-07-23 00:33:24 -08:00
|
|
|
int si;
|
2020-04-07 11:47:01 -08:00
|
|
|
static char thou_sep;
|
2009-04-11 01:37:45 -08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
char *cropstr(const char *from, int s) {
|
2011-10-31 06:09:12 -08:00
|
|
|
static char dat[4096];
|
2007-07-20 03:15:46 -08:00
|
|
|
int i, j, o = strlen(from);
|
|
|
|
|
if(o < s) {
|
2011-10-31 06:09:12 -08:00
|
|
|
strcpy(dat, from);
|
|
|
|
|
return dat;
|
2007-07-20 03:15:46 -08:00
|
|
|
}
|
|
|
|
|
j=s/2-3;
|
|
|
|
|
for(i=0; i<j; i++)
|
2011-10-31 06:09:12 -08:00
|
|
|
dat[i] = from[i];
|
|
|
|
|
dat[i] = '.';
|
|
|
|
|
dat[++i] = '.';
|
|
|
|
|
dat[++i] = '.';
|
2007-07-20 03:15:46 -08:00
|
|
|
j=o-s;
|
|
|
|
|
while(++i<s)
|
2011-10-31 06:09:12 -08:00
|
|
|
dat[i] = from[j+i];
|
|
|
|
|
dat[s] = '\0';
|
|
|
|
|
return dat;
|
2007-07-20 03:15:46 -08:00
|
|
|
}
|
|
|
|
|
|
2009-04-11 01:37:45 -08:00
|
|
|
|
2020-04-07 11:46:47 -08:00
|
|
|
float formatsize(int64_t from, const char **unit) {
|
2012-08-27 11:51:08 -08:00
|
|
|
float r = from;
|
2013-07-23 00:33:24 -08:00
|
|
|
if (si) {
|
2017-07-08 06:29:31 -08:00
|
|
|
if(r < 1000.0f) { *unit = " B"; }
|
|
|
|
|
else if(r < 1e6f) { *unit = "KB"; r/=1e3f; }
|
|
|
|
|
else if(r < 1e9f) { *unit = "MB"; r/=1e6f; }
|
|
|
|
|
else if(r < 1e12f){ *unit = "GB"; r/=1e9f; }
|
|
|
|
|
else if(r < 1e15f){ *unit = "TB"; r/=1e12f; }
|
|
|
|
|
else if(r < 1e18f){ *unit = "PB"; r/=1e15f; }
|
|
|
|
|
else { *unit = "EB"; r/=1e18f; }
|
2013-07-23 00:33:24 -08:00
|
|
|
}
|
|
|
|
|
else {
|
2017-07-08 06:29:31 -08:00
|
|
|
if(r < 1000.0f) { *unit = " B"; }
|
|
|
|
|
else if(r < 1023e3f) { *unit = "KiB"; r/=1024.0f; }
|
|
|
|
|
else if(r < 1023e6f) { *unit = "MiB"; r/=1048576.0f; }
|
|
|
|
|
else if(r < 1023e9f) { *unit = "GiB"; r/=1073741824.0f; }
|
|
|
|
|
else if(r < 1023e12f){ *unit = "TiB"; r/=1099511627776.0f; }
|
|
|
|
|
else if(r < 1023e15f){ *unit = "PiB"; r/=1125899906842624.0f; }
|
|
|
|
|
else { *unit = "EiB"; r/=1152921504606846976.0f; }
|
2013-07-23 00:33:24 -08:00
|
|
|
}
|
2017-07-08 06:29:31 -08:00
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void printsize(enum ui_coltype t, int64_t from) {
|
2020-04-07 11:46:47 -08:00
|
|
|
const char *unit;
|
2017-07-08 06:29:31 -08:00
|
|
|
float r = formatsize(from, &unit);
|
2018-01-21 05:38:36 -09:00
|
|
|
uic_set(t == UIC_HD ? UIC_NUM_HD : t == UIC_SEL ? UIC_NUM_SEL : UIC_NUM);
|
2017-07-08 06:29:31 -08:00
|
|
|
printw("%5.1f", r);
|
|
|
|
|
addchc(t, ' ');
|
|
|
|
|
addstrc(t, unit);
|
2007-07-20 03:15:46 -08:00
|
|
|
}
|
|
|
|
|
|
2009-04-11 01:37:45 -08:00
|
|
|
|
2012-08-27 07:20:24 -08:00
|
|
|
char *fullsize(int64_t from) {
|
2012-11-22 02:42:57 -09:00
|
|
|
static char dat[26]; /* max: 9.223.372.036.854.775.807 (= 2^63-1) */
|
|
|
|
|
char tmp[26];
|
2012-08-27 07:20:24 -08:00
|
|
|
int64_t n = from;
|
2007-08-16 00:36:58 -08:00
|
|
|
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';
|
|
|
|
|
|
2020-05-30 09:26:00 -08:00
|
|
|
/* reverse and add thousand separators */
|
2007-08-16 00:36:58 -08:00
|
|
|
j = 0;
|
|
|
|
|
while(i--) {
|
2011-10-31 06:09:12 -08:00
|
|
|
dat[j++] = tmp[i];
|
2007-08-16 00:36:58 -08:00
|
|
|
if(i != 0 && i%3 == 0)
|
2013-01-13 03:35:25 -09:00
|
|
|
dat[j++] = thou_sep;
|
2007-08-01 07:01:42 -08:00
|
|
|
}
|
2011-10-31 06:09:12 -08:00
|
|
|
dat[j] = '\0';
|
2007-08-16 00:36:58 -08:00
|
|
|
|
2011-10-31 06:09:12 -08:00
|
|
|
return dat;
|
2007-08-01 07:01:42 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2018-01-23 04:59:38 -09:00
|
|
|
char *fmtmode(unsigned short mode) {
|
|
|
|
|
static char buf[11];
|
|
|
|
|
unsigned short ft = mode & S_IFMT;
|
|
|
|
|
buf[0] = ft == S_IFDIR ? 'd'
|
|
|
|
|
: ft == S_IFREG ? '-'
|
|
|
|
|
: ft == S_IFLNK ? 'l'
|
|
|
|
|
: ft == S_IFIFO ? 'p'
|
|
|
|
|
: ft == S_IFSOCK ? 's'
|
|
|
|
|
: ft == S_IFCHR ? 'c'
|
|
|
|
|
: ft == S_IFBLK ? 'b' : '?';
|
|
|
|
|
buf[1] = mode & 0400 ? 'r' : '-';
|
|
|
|
|
buf[2] = mode & 0200 ? 'w' : '-';
|
2021-06-11 01:04:50 -08:00
|
|
|
buf[3] = mode &04000 ? 's' : mode & 0100 ? 'x' : '-';
|
2018-01-23 04:59:38 -09:00
|
|
|
buf[4] = mode & 0040 ? 'r' : '-';
|
|
|
|
|
buf[5] = mode & 0020 ? 'w' : '-';
|
2021-06-11 01:04:50 -08:00
|
|
|
buf[6] = mode &02000 ? 's' : mode & 0010 ? 'x' : '-';
|
2018-01-23 04:59:38 -09:00
|
|
|
buf[7] = mode & 0004 ? 'r' : '-';
|
|
|
|
|
buf[8] = mode & 0002 ? 'w' : '-';
|
2021-06-11 01:04:50 -08:00
|
|
|
buf[9] = mode &01000 ? (S_ISDIR(mode) ? 't' : 'T') : mode & 0001 ? 'x' : '-';
|
2018-01-23 04:59:38 -09:00
|
|
|
buf[10] = 0;
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-01-13 03:35:25 -09:00
|
|
|
void read_locale() {
|
2022-02-07 08:36:35 -09:00
|
|
|
#ifdef HAVE_LOCALE_H
|
|
|
|
|
char *locale_thou_sep;
|
|
|
|
|
#endif
|
2014-04-12 22:34:32 -08:00
|
|
|
thou_sep = '.';
|
|
|
|
|
#ifdef HAVE_LOCALE_H
|
|
|
|
|
setlocale(LC_ALL, "");
|
2022-02-07 08:36:35 -09:00
|
|
|
locale_thou_sep = localeconv()->thousands_sep;
|
2014-04-12 22:34:32 -08:00
|
|
|
if(locale_thou_sep && 1 == strlen(locale_thou_sep))
|
2013-01-13 03:35:25 -09:00
|
|
|
thou_sep = locale_thou_sep[0];
|
2014-04-12 22:34:32 -08:00
|
|
|
#endif
|
2013-01-13 03:35:25 -09: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();
|
2012-08-27 11:51:08 -08:00
|
|
|
exit(0);
|
2007-07-20 03:15:46 -08:00
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-09-05 23:45:52 -08:00
|
|
|
void nccreate(int height, int width, const char *title) {
|
2007-08-16 00:36:58 -08:00
|
|
|
int i;
|
|
|
|
|
|
2018-01-23 04:20:06 -09:00
|
|
|
uic_set(UIC_DEFAULT);
|
2007-08-16 00:36:58 -08:00
|
|
|
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 */
|
2017-07-08 06:29:31 -08:00
|
|
|
uic_set(UIC_BOX_TITLE);
|
2007-08-16 00:36:58 -08:00
|
|
|
mvaddstr(subwinr, subwinc+4, title);
|
2017-07-08 06:29:31 -08:00
|
|
|
uic_set(UIC_DEFAULT);
|
2007-08-16 00:36:58 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-04-07 11:46:47 -08:00
|
|
|
void ncprint(int r, int c, const char *fmt, ...) {
|
2007-08-16 00:36:58 -08:00
|
|
|
va_list arg;
|
|
|
|
|
va_start(arg, fmt);
|
|
|
|
|
move(subwinr+r, subwinc+c);
|
|
|
|
|
vw_printw(stdscr, fmt, arg);
|
|
|
|
|
va_end(arg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-04-07 11:46:47 -08:00
|
|
|
void nctab(int c, int sel, int num, const char *str) {
|
2018-01-21 05:38:36 -09:00
|
|
|
uic_set(sel ? UIC_KEY_HD : UIC_KEY);
|
2017-07-08 06:29:31 -08:00
|
|
|
ncprint(0, c, "%d", num);
|
|
|
|
|
uic_set(sel ? UIC_HD : UIC_DEFAULT);
|
|
|
|
|
addch(':');
|
|
|
|
|
addstr(str);
|
|
|
|
|
uic_set(UIC_DEFAULT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int colors[] = {
|
2018-01-21 05:38:36 -09:00
|
|
|
#define C(name, ...) 0,
|
2017-07-08 06:29:31 -08:00
|
|
|
UI_COLORS
|
|
|
|
|
#undef C
|
|
|
|
|
0
|
|
|
|
|
};
|
|
|
|
|
static int lastcolor = 0;
|
|
|
|
|
|
|
|
|
|
|
2018-01-21 05:38:36 -09:00
|
|
|
static const struct {
|
|
|
|
|
short fg, bg;
|
|
|
|
|
int attr;
|
|
|
|
|
} color_defs[] = {
|
2021-08-16 06:07:47 -08:00
|
|
|
#define COLOR__ -1
|
|
|
|
|
#define B A_BOLD
|
|
|
|
|
#define R A_REVERSE
|
|
|
|
|
#define C(name, off_fg, off_bg, off_a, dark_fg, dark_bg, dark_a, darkbg_fg, darkbg_bg, darkbg_a) \
|
|
|
|
|
{COLOR_##off_fg, COLOR_##off_bg, off_a}, \
|
|
|
|
|
{COLOR_##dark_fg, COLOR_##dark_bg, dark_a}, \
|
|
|
|
|
{COLOR_##darkbg_fg, COLOR_##darkbg_bg, darkbg_a},
|
2017-07-08 06:29:31 -08:00
|
|
|
UI_COLORS
|
2021-08-16 06:07:47 -08:00
|
|
|
#undef B
|
|
|
|
|
#undef R
|
2017-07-08 06:29:31 -08:00
|
|
|
#undef C
|
2018-01-21 05:38:36 -09:00
|
|
|
{0,0,0}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void uic_init() {
|
|
|
|
|
size_t i, j;
|
|
|
|
|
|
|
|
|
|
start_color();
|
|
|
|
|
use_default_colors();
|
|
|
|
|
for(i=0; i<sizeof(colors)/sizeof(*colors)-1; i++) {
|
2021-08-16 06:07:47 -08:00
|
|
|
j = i*3 + uic_theme;
|
2018-01-21 05:38:36 -09:00
|
|
|
init_pair(i+1, color_defs[j].fg, color_defs[j].bg);
|
|
|
|
|
colors[i] = color_defs[j].attr | COLOR_PAIR(i+1);
|
|
|
|
|
}
|
2017-07-08 06:29:31 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void uic_set(enum ui_coltype c) {
|
|
|
|
|
attroff(lastcolor);
|
|
|
|
|
lastcolor = colors[(int)c];
|
|
|
|
|
attron(lastcolor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-03-03 04:40:56 -09:00
|
|
|
/* removes item from the hlnk circular linked list and size counts of the parents */
|
2011-10-31 06:09:12 -08:00
|
|
|
static void freedir_hlnk(struct dir *d) {
|
2010-03-03 04:40:56 -09:00
|
|
|
struct dir *t, *par, *pt;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if(!(d->flags & FF_HLNKC))
|
2010-02-27 01:29:36 -09:00
|
|
|
return;
|
2010-03-03 04:40:56 -09:00
|
|
|
|
|
|
|
|
/* remove size from parents.
|
|
|
|
|
* This works the same as with adding: only the parents in which THIS is the
|
2020-05-30 09:26:00 -08:00
|
|
|
* only occurrence of the hard link will be modified, if the same file still
|
2010-03-03 04:40:56 -09:00
|
|
|
* exists within the parent it shouldn't get removed from the count.
|
2012-08-26 04:41:25 -08:00
|
|
|
* XXX: Same note as for dir_mem.c / hlink_check():
|
2010-03-03 04:40:56 -09:00
|
|
|
* this is probably not the most efficient algorithm */
|
|
|
|
|
for(i=1,par=d->parent; i&∥ par=par->parent) {
|
|
|
|
|
if(d->hlnk)
|
|
|
|
|
for(t=d->hlnk; i&&t!=d; t=t->hlnk)
|
|
|
|
|
for(pt=t->parent; i&&pt; pt=pt->parent)
|
|
|
|
|
if(pt==par)
|
|
|
|
|
i=0;
|
|
|
|
|
if(i) {
|
2012-11-22 03:47:10 -09:00
|
|
|
par->size = adds64(par->size, -d->size);
|
|
|
|
|
par->asize = adds64(par->size, -d->asize);
|
2010-03-03 04:40:56 -09:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* remove from hlnk */
|
|
|
|
|
if(d->hlnk) {
|
|
|
|
|
for(t=d->hlnk; t->hlnk!=d; t=t->hlnk)
|
|
|
|
|
;
|
|
|
|
|
t->hlnk = d->hlnk;
|
|
|
|
|
}
|
2010-02-27 01:29:36 -09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-10-31 06:09:12 -08:00
|
|
|
static void freedir_rec(struct dir *dr) {
|
2007-07-20 03:15:46 -08:00
|
|
|
struct dir *tmp, *tmp2;
|
|
|
|
|
tmp2 = dr;
|
|
|
|
|
while((tmp = tmp2) != NULL) {
|
2010-02-27 01:29:36 -09:00
|
|
|
freedir_hlnk(tmp);
|
|
|
|
|
/* remove item */
|
2007-07-20 03:15:46 -08:00
|
|
|
if(tmp->sub) freedir_rec(tmp->sub);
|
|
|
|
|
tmp2 = tmp->next;
|
|
|
|
|
free(tmp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-11 01:37:45 -08:00
|
|
|
|
2009-04-19 02:47:22 -08:00
|
|
|
void freedir(struct dir *dr) {
|
2012-08-26 04:41:25 -08:00
|
|
|
if(!dr)
|
|
|
|
|
return;
|
2007-07-20 03:15:46 -08:00
|
|
|
|
2009-04-19 02:47:22 -08:00
|
|
|
/* free dr->sub recursively */
|
|
|
|
|
if(dr->sub)
|
|
|
|
|
freedir_rec(dr->sub);
|
2012-08-27 11:51:08 -08:00
|
|
|
|
2009-04-11 01:37:45 -08:00
|
|
|
/* update references */
|
2010-04-27 07:01:43 -08:00
|
|
|
if(dr->parent && dr->parent->sub == dr)
|
|
|
|
|
dr->parent->sub = dr->next;
|
|
|
|
|
if(dr->prev)
|
|
|
|
|
dr->prev->next = dr->next;
|
|
|
|
|
if(dr->next)
|
|
|
|
|
dr->next->prev = dr->prev;
|
2007-07-20 03:15:46 -08:00
|
|
|
|
2010-02-27 01:29:36 -09:00
|
|
|
freedir_hlnk(dr);
|
2010-03-03 04:40:56 -09:00
|
|
|
|
|
|
|
|
/* update sizes of parent directories if this isn't a hard link.
|
2019-01-20 11:03:38 -09:00
|
|
|
* If this is a hard link, freedir_hlnk() would have done so already
|
|
|
|
|
*
|
|
|
|
|
* mtime is 0 here because recalculating the maximum at every parent
|
|
|
|
|
* dir is expensive, but might be good feature to add later if desired */
|
|
|
|
|
addparentstats(dr->parent, dr->flags & FF_HLNKC ? 0 : -dr->size, dr->flags & FF_HLNKC ? 0 : -dr->asize, 0, -(dr->items+1));
|
2010-03-03 04:40:56 -09:00
|
|
|
|
2007-07-20 03:15:46 -08:00
|
|
|
free(dr);
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-11 01:37:45 -08:00
|
|
|
|
2020-04-07 11:46:47 -08:00
|
|
|
const char *getpath(struct dir *cur) {
|
2011-10-31 06:09:12 -08:00
|
|
|
static char *dat;
|
|
|
|
|
static int datl = 0;
|
2009-04-23 11:15:11 -08:00
|
|
|
struct dir *d, **list;
|
|
|
|
|
int c, i;
|
2007-07-26 08:37:33 -08:00
|
|
|
|
2009-04-26 03:10:00 -08:00
|
|
|
if(!cur->name[0])
|
|
|
|
|
return "/";
|
|
|
|
|
|
2009-04-23 11:15:11 -08:00
|
|
|
c = i = 1;
|
|
|
|
|
for(d=cur; d!=NULL; d=d->parent) {
|
|
|
|
|
i += strlen(d->name)+1;
|
|
|
|
|
c++;
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-31 06:09:12 -08:00
|
|
|
if(datl == 0) {
|
|
|
|
|
datl = i;
|
2019-07-23 01:01:48 -08:00
|
|
|
dat = xmalloc(i);
|
2011-10-31 06:09:12 -08:00
|
|
|
} else if(datl < i) {
|
|
|
|
|
datl = i;
|
2019-07-23 01:01:48 -08:00
|
|
|
dat = xrealloc(dat, i);
|
2009-04-23 11:15:11 -08:00
|
|
|
}
|
2019-07-23 01:01:48 -08:00
|
|
|
list = xmalloc(c*sizeof(struct dir *));
|
2009-04-23 11:15:11 -08:00
|
|
|
|
|
|
|
|
c = 0;
|
|
|
|
|
for(d=cur; d!=NULL; d=d->parent)
|
2007-07-26 08:37:33 -08:00
|
|
|
list[c++] = d;
|
|
|
|
|
|
2011-10-31 06:09:12 -08:00
|
|
|
dat[0] = '\0';
|
2007-07-26 08:37:33 -08:00
|
|
|
while(c--) {
|
2009-04-23 11:15:11 -08:00
|
|
|
if(list[c]->parent)
|
2011-10-31 06:09:12 -08:00
|
|
|
strcat(dat, "/");
|
|
|
|
|
strcat(dat, list[c]->name);
|
2007-07-20 03:15:46 -08:00
|
|
|
}
|
2009-04-23 11:15:11 -08:00
|
|
|
free(list);
|
2011-10-31 06:09:12 -08:00
|
|
|
return dat;
|
2007-07-20 03:15:46 -08:00
|
|
|
}
|
2009-04-11 01:37:45 -08:00
|
|
|
|
2012-08-26 04:41:25 -08:00
|
|
|
|
|
|
|
|
struct dir *getroot(struct dir *d) {
|
|
|
|
|
while(d && d->parent)
|
|
|
|
|
d = d->parent;
|
|
|
|
|
return d;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2019-01-20 11:03:38 -09:00
|
|
|
void addparentstats(struct dir *d, int64_t size, int64_t asize, uint64_t mtime, int items) {
|
|
|
|
|
struct dir_ext *e;
|
2012-08-26 04:41:25 -08:00
|
|
|
while(d) {
|
2012-11-22 03:33:32 -09:00
|
|
|
d->size = adds64(d->size, size);
|
|
|
|
|
d->asize = adds64(d->asize, asize);
|
2012-08-26 04:41:25 -08:00
|
|
|
d->items += items;
|
2019-01-20 11:03:38 -09:00
|
|
|
if (d->flags & FF_EXT) {
|
|
|
|
|
e = dir_ext_ptr(d);
|
|
|
|
|
e->mtime = (e->mtime > mtime) ? e->mtime : mtime;
|
|
|
|
|
}
|
2012-08-26 04:41:25 -08:00
|
|
|
d = d->parent;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-07-23 01:01:48 -08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Apparently we can just resume drawing after endwin() and ncurses will pick
|
|
|
|
|
* up where it left. Probably not very portable... */
|
|
|
|
|
#define oom_msg "\nOut of memory, press enter to try again or Ctrl-C to give up.\n"
|
|
|
|
|
#define wrap_oom(f) \
|
|
|
|
|
void *ptr;\
|
|
|
|
|
char buf[128];\
|
|
|
|
|
while((ptr = f) == NULL) {\
|
|
|
|
|
close_nc();\
|
|
|
|
|
write(2, oom_msg, sizeof(oom_msg));\
|
|
|
|
|
read(0, buf, sizeof(buf));\
|
|
|
|
|
}\
|
|
|
|
|
return ptr;
|
|
|
|
|
|
|
|
|
|
void *xmalloc(size_t size) { wrap_oom(malloc(size)) }
|
|
|
|
|
void *xcalloc(size_t n, size_t size) { wrap_oom(calloc(n, size)) }
|
|
|
|
|
void *xrealloc(void *mem, size_t size) { wrap_oom(realloc(mem, size)) }
|