Ignore hard links on du

This commit is contained in:
Arun Prakash Jana 2020-02-22 08:44:28 +05:30
parent 0f03b41995
commit 4a91df950b
No known key found for this signature in database
GPG key ID: A75979F35C080412

View file

@ -164,6 +164,10 @@
#define ARCHIVE_CMD_LEN 16 #define ARCHIVE_CMD_LEN 16
#define BLK_SHIFT_512 9 #define BLK_SHIFT_512 9
/* Detect hardlinks in du */
#define HASH_BITS (0xFFFFFF)
#define HASH_OCTETS (HASH_BITS >> 6) /* 2^6 = 64 */
/* Program return codes */ /* Program return codes */
#define _SUCCESS 0 #define _SUCCESS 0
#define _FAILURE !_SUCCESS #define _FAILURE !_SUCCESS
@ -206,6 +210,7 @@ typedef unsigned int uint;
typedef unsigned char uchar; typedef unsigned char uchar;
typedef unsigned short ushort; typedef unsigned short ushort;
typedef long long ll; typedef long long ll;
typedef unsigned long long ull;
/* STRUCTURES */ /* STRUCTURES */
@ -348,6 +353,7 @@ static char *g_prefixpath;
static char *plugindir; static char *plugindir;
static char *sessiondir; static char *sessiondir;
static char *pnamebuf, *pselbuf; static char *pnamebuf, *pselbuf;
static ull *ihashbmp;
static struct entry *dents; static struct entry *dents;
static blkcnt_t ent_blocks; static blkcnt_t ent_blocks;
static blkcnt_t dir_blocks; static blkcnt_t dir_blocks;
@ -690,6 +696,44 @@ static char *xitoa(uint val)
return &ascbuf[++i]; return &ascbuf[++i];
} }
/*
* Source: https://elixir.bootlin.com/linux/latest/source/arch/alpha/include/asm/bitops.h
*/
static bool test_set_bit(ull nr)
{
ull *m = ((ull *)ihashbmp) + (nr >> 6);
if (*m & (1 << (nr & 63)))
return FALSE;
*m |= 1 << (nr & 63);
return TRUE;
}
#if 0
static bool test_clear_bit(ull nr)
{
ull *m = ((ull *) ihashbmp) + (nr >> 6);
if (!(*m & (1 << (nr & 63))))
return FALSE;
*m &= ~(1 << (nr & 63));
return TRUE;
}
#endif
static void clear_hash()
{
ulong i = 0;
ull *addr = ihashbmp;
for (; i < HASH_OCTETS; ++i, ++addr)
if (*addr)
*addr = 0;
}
static void clearinfoln(void) static void clearinfoln(void)
{ {
move(xlines - 2, 0); move(xlines - 2, 0);
@ -4146,7 +4190,8 @@ static void launch_app(const char *path, char *newpath)
static int sum_bsize(const char *UNUSED(fpath), const struct stat *sb, int typeflag, struct FTW *UNUSED(ftwbuf)) static int sum_bsize(const char *UNUSED(fpath), const struct stat *sb, int typeflag, struct FTW *UNUSED(ftwbuf))
{ {
if (sb->st_blocks && (typeflag == FTW_F || typeflag == FTW_D)) if (sb->st_blocks && (typeflag == FTW_F || typeflag == FTW_D)
&& (sb->st_nlink <= 1 || test_set_bit((ull)sb->st_ino)))
ent_blocks += sb->st_blocks; ent_blocks += sb->st_blocks;
++num_files; ++num_files;
@ -4155,7 +4200,8 @@ static int sum_bsize(const char *UNUSED(fpath), const struct stat *sb, int typef
static int sum_asize(const char *UNUSED(fpath), const struct stat *sb, int typeflag, struct FTW *UNUSED(ftwbuf)) static int sum_asize(const char *UNUSED(fpath), const struct stat *sb, int typeflag, struct FTW *UNUSED(ftwbuf))
{ {
if (sb->st_size && (typeflag == FTW_F || typeflag == FTW_D)) if (sb->st_size && (typeflag == FTW_F || typeflag == FTW_D)
&& (sb->st_nlink <= 1 || test_set_bit((ull)sb->st_ino)))
ent_blocks += sb->st_size; ent_blocks += sb->st_size;
++num_files; ++num_files;
@ -4222,6 +4268,13 @@ static int dentfill(char *path, struct entry **dents)
printwarn(NULL); printwarn(NULL);
return 0; return 0;
} }
if (!ihashbmp) {
ihashbmp = calloc(1, HASH_OCTETS << 3);
if (!ihashbmp)
return 0;
} else
clear_hash();
} }
#if _POSIX_C_SOURCE >= 200112L #if _POSIX_C_SOURCE >= 200112L
@ -4266,12 +4319,12 @@ static int dentfill(char *path, struct entry **dents)
dir_blocks += dirwalk(buf, &sb); dir_blocks += dirwalk(buf, &sb);
if (g_states & STATE_INTERRUPTED) { if (g_states & STATE_INTERRUPTED)
closedir(dirp); goto exit;
return n;
}
} }
} else { } else {
/* Do not recount hard links */
if (sb.st_nlink <= 1 || test_set_bit((ull)sb.st_ino))
dir_blocks += (cfg.apparentsz ? sb.st_size : sb.st_blocks); dir_blocks += (cfg.apparentsz ? sb.st_size : sb.st_blocks);
++num_files; ++num_files;
} }
@ -4363,12 +4416,12 @@ static int dentfill(char *path, struct entry **dents)
else else
num_files = num_saved; num_files = num_saved;
if (g_states & STATE_INTERRUPTED) { if (g_states & STATE_INTERRUPTED)
closedir(dirp); goto exit;
return n;
}
} else { } else {
dentp->blocks = (cfg.apparentsz ? sb.st_size : sb.st_blocks); dentp->blocks = (cfg.apparentsz ? sb.st_size : sb.st_blocks);
/* Do not recount hard links */
if (sb.st_nlink <= 1 || test_set_bit((ull)sb.st_ino))
dir_blocks += dentp->blocks; dir_blocks += dentp->blocks;
++num_files; ++num_files;
} }
@ -6446,6 +6499,7 @@ static void cleanup(void)
free(bmstr); free(bmstr);
free(pluginstr); free(pluginstr);
free(g_prefixpath); free(g_prefixpath);
free(ihashbmp);
unlink(g_pipepath); unlink(g_pipepath);