aboutsummaryrefslogtreecommitdiffstats
path: root/src/nnn.c
diff options
context:
space:
mode:
authorGravatar Arun Prakash Jana <engineerarun@gmail.com>2020-02-22 08:44:28 +0530
committerGravatar Arun Prakash Jana <engineerarun@gmail.com>2020-02-22 08:44:28 +0530
commit4a91df950b26660a9d6918cf97ab3f1f9cf7b97b (patch)
tree2579bdc348356beb0327efff7967261b4f6aba6e /src/nnn.c
parent0f03b41995bb614c03539b5a04647742b51c458a (diff)
downloadnnn-4a91df950b26660a9d6918cf97ab3f1f9cf7b97b.tar.gz
Ignore hard links on du
Diffstat (limited to 'src/nnn.c')
-rw-r--r--src/nnn.c78
1 files changed, 66 insertions, 12 deletions
diff --git a/src/nnn.c b/src/nnn.c
index e8b5209..8fa1c8f 100644
--- a/src/nnn.c
+++ b/src/nnn.c
@@ -164,6 +164,10 @@
#define ARCHIVE_CMD_LEN 16
#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 */
#define _SUCCESS 0
#define _FAILURE !_SUCCESS
@@ -206,6 +210,7 @@ typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef long long ll;
+typedef unsigned long long ull;
/* STRUCTURES */
@@ -348,6 +353,7 @@ static char *g_prefixpath;
static char *plugindir;
static char *sessiondir;
static char *pnamebuf, *pselbuf;
+static ull *ihashbmp;
static struct entry *dents;
static blkcnt_t ent_blocks;
static blkcnt_t dir_blocks;
@@ -690,6 +696,44 @@ static char *xitoa(uint val)
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)
{
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))
{
- 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;
++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))
{
- 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;
++num_files;
@@ -4222,6 +4268,13 @@ static int dentfill(char *path, struct entry **dents)
printwarn(NULL);
return 0;
}
+
+ if (!ihashbmp) {
+ ihashbmp = calloc(1, HASH_OCTETS << 3);
+ if (!ihashbmp)
+ return 0;
+ } else
+ clear_hash();
}
#if _POSIX_C_SOURCE >= 200112L
@@ -4266,13 +4319,13 @@ static int dentfill(char *path, struct entry **dents)
dir_blocks += dirwalk(buf, &sb);
- if (g_states & STATE_INTERRUPTED) {
- closedir(dirp);
- return n;
- }
+ if (g_states & STATE_INTERRUPTED)
+ goto exit;
}
} else {
- dir_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 += (cfg.apparentsz ? sb.st_size : sb.st_blocks);
++num_files;
}
@@ -4363,13 +4416,13 @@ static int dentfill(char *path, struct entry **dents)
else
num_files = num_saved;
- if (g_states & STATE_INTERRUPTED) {
- closedir(dirp);
- return n;
- }
+ if (g_states & STATE_INTERRUPTED)
+ goto exit;
} else {
dentp->blocks = (cfg.apparentsz ? sb.st_size : sb.st_blocks);
- dir_blocks += dentp->blocks;
+ /* Do not recount hard links */
+ if (sb.st_nlink <= 1 || test_set_bit((ull)sb.st_ino))
+ dir_blocks += dentp->blocks;
++num_files;
}
}
@@ -6446,6 +6499,7 @@ static void cleanup(void)
free(bmstr);
free(pluginstr);
free(g_prefixpath);
+ free(ihashbmp);
unlink(g_pipepath);