summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dir.h2
-rw-r--r--src/dir_export.c18
-rw-r--r--src/dir_import.c15
-rw-r--r--src/dir_mem.c3
-rw-r--r--src/dir_scan.c24
5 files changed, 39 insertions, 23 deletions
diff --git a/src/dir.h b/src/dir.h
index fc33eb0..39bb41f 100644
--- a/src/dir.h
+++ b/src/dir.h
@@ -69,7 +69,7 @@ struct dir_output {
* The function should return non-zero on error, at which point errno is
* assumed to be set to something sensible.
*/
- int (*item)(struct dir *, const char *, struct dir_ext *);
+ int (*item)(struct dir *, const char *, struct dir_ext *, unsigned int);
/* Finalizes the output to go to the next program state or exit ncdu. Called
* after item(NULL) has been called for the root item or before any item()
diff --git a/src/dir_export.c b/src/dir_export.c
index dd96721..83590d4 100644
--- a/src/dir_export.c
+++ b/src/dir_export.c
@@ -74,7 +74,7 @@ static void output_int(uint64_t n) {
}
-static void output_info(struct dir *d, const char *name, struct dir_ext *e) {
+static void output_info(struct dir *d, const char *name, struct dir_ext *e, unsigned int nlink) {
if(!extended_info || !(d->flags & FF_EXT))
e = NULL;
@@ -96,8 +96,6 @@ static void output_info(struct dir *d, const char *name, struct dir_ext *e) {
fputs(",\"dev\":", stream);
output_int(d->dev);
}
- fputs(",\"ino\":", stream);
- output_int(d->ino);
if(e) {
fputs(",\"uid\":", stream);
@@ -111,8 +109,12 @@ static void output_info(struct dir *d, const char *name, struct dir_ext *e) {
}
/* TODO: Including the actual number of links would be nicer. */
- if(d->flags & FF_HLNKC)
- fputs(",\"hlnkc\":true", stream);
+ if(d->flags & FF_HLNKC) {
+ fputs(",\"ino\":", stream);
+ output_int(d->ino);
+ fputs(",\"hlnkc\":true,\"nlink\":", stream);
+ output_int(nlink);
+ }
if(d->flags & FF_ERR)
fputs(",\"read_error\":true", stream);
/* excluded/error'd files are "unknown" with respect to the "notreg" field. */
@@ -136,7 +138,7 @@ static void output_info(struct dir *d, const char *name, struct dir_ext *e) {
* item() call do we check for ferror(). This greatly simplifies the code, but
* assumes that calls to fwrite()/fput./etc don't do any weird stuff when
* called with a stream that's in an error state. */
-static int item(struct dir *item, const char *name, struct dir_ext *ext) {
+static int item(struct dir *item, const char *name, struct dir_ext *ext, unsigned int nlink) {
if(!item) {
nstack_pop(&stack);
if(!stack.top) { /* closing of the root item */
@@ -152,7 +154,7 @@ static int item(struct dir *item, const char *name, struct dir_ext *ext) {
/* File header.
* TODO: Add scan options? */
if(!stack.top) {
- fputs("[1,1,{\"progname\":\""PACKAGE"\",\"progver\":\""PACKAGE_VERSION"\",\"timestamp\":", stream);
+ fputs("[1,2,{\"progname\":\""PACKAGE"\",\"progver\":\""PACKAGE_VERSION"\",\"timestamp\":", stream);
output_int((uint64_t)time(NULL));
fputc('}', stream);
}
@@ -161,7 +163,7 @@ static int item(struct dir *item, const char *name, struct dir_ext *ext) {
if(item->flags & FF_DIR)
fputc('[', stream);
- output_info(item, name, ext);
+ output_info(item, name, ext, nlink);
if(item->flags & FF_DIR)
nstack_push(&stack, item->dev);
diff --git a/src/dir_import.c b/src/dir_import.c
index bde822c..cdb94a0 100644
--- a/src/dir_import.c
+++ b/src/dir_import.c
@@ -72,6 +72,7 @@ static struct ctx {
/* scratch space */
struct dir *buf_dir;
struct dir_ext buf_ext[1];
+ unsigned int nlink;
char buf_name[MAX_VAL];
char val[MAX_VAL];
@@ -421,7 +422,7 @@ static int itemdir(uint64_t dev) {
/* Reads a JSON object representing a struct dir/dir_ext item. Writes to
- * ctx->buf_dir, ctx->buf_ext and ctx->buf_name. */
+ * ctx->buf_dir, ctx->buf_ext, ctx->buf_name and ctx->nlink. */
static int iteminfo(void) {
uint64_t iv;
@@ -470,6 +471,11 @@ static int iteminfo(void) {
ctx->buf_dir->flags |= FF_HLNKC;
} else
C(rlit("false", 5));
+ } else if(strcmp(ctx->val, "nlink") == 0) { /* nlink */
+ C(rint64(&iv, UINT32_MAX));
+ if(iv > 1)
+ ctx->buf_dir->flags |= FF_HLNKC;
+ ctx->nlink = iv;
} else if(strcmp(ctx->val, "read_error") == 0) { /* read_error */
if(*ctx->buf == 't') {
C(rlit("true", 4));
@@ -526,6 +532,7 @@ static int item(uint64_t dev) {
memset(ctx->buf_dir, 0, offsetof(struct dir, name));
memset(ctx->buf_ext, 0, sizeof(struct dir_ext));
+ ctx->nlink = 0;
*ctx->buf_name = 0;
ctx->buf_dir->flags |= isdir ? FF_DIR : FF_FILE;
ctx->buf_dir->dev = dev;
@@ -539,16 +546,16 @@ static int item(uint64_t dev) {
dir_curpath_enter(ctx->buf_name);
if(isdir) {
- if(dir_output.item(ctx->buf_dir, ctx->buf_name, ctx->buf_ext)) {
+ if(dir_output.item(ctx->buf_dir, ctx->buf_name, ctx->buf_ext, ctx->nlink)) {
dir_seterr("Output error: %s", strerror(errno));
return 1;
}
C(itemdir(dev));
- if(dir_output.item(NULL, 0, NULL)) {
+ if(dir_output.item(NULL, 0, NULL, 0)) {
dir_seterr("Output error: %s", strerror(errno));
return 1;
}
- } else if(dir_output.item(ctx->buf_dir, ctx->buf_name, ctx->buf_ext)) {
+ } else if(dir_output.item(ctx->buf_dir, ctx->buf_name, ctx->buf_ext, ctx->nlink)) {
dir_seterr("Output error: %s", strerror(errno));
return 1;
}
diff --git a/src/dir_mem.c b/src/dir_mem.c
index d1dce8d..f513ab7 100644
--- a/src/dir_mem.c
+++ b/src/dir_mem.c
@@ -109,8 +109,9 @@ static void item_add(struct dir *item) {
}
-static int item(struct dir *dir, const char *name, struct dir_ext *ext) {
+static int item(struct dir *dir, const char *name, struct dir_ext *ext, unsigned int nlink) {
struct dir *t, *item;
+ (void)nlink;
/* Go back to parent dir */
if(!dir) {
diff --git a/src/dir_scan.c b/src/dir_scan.c
index 03a582b..9629f32 100644
--- a/src/dir_scan.c
+++ b/src/dir_scan.c
@@ -57,6 +57,7 @@ static uint64_t curdev; /* current device we're scanning on */
/* scratch space */
static struct dir *buf_dir;
static struct dir_ext buf_ext[1];
+static unsigned int buf_nlink;
#if HAVE_LINUX_MAGIC_H && HAVE_SYS_STATFS_H && HAVE_STATFS
@@ -120,8 +121,11 @@ static void stat_to_dir(struct stat *fs) {
else if(S_ISDIR(fs->st_mode))
buf_dir->flags |= FF_DIR;
- if(!S_ISDIR(fs->st_mode) && fs->st_nlink > 1)
+ if(!S_ISDIR(fs->st_mode) && fs->st_nlink > 1) {
buf_dir->flags |= FF_HLNKC;
+ buf_nlink = fs->st_nlink;
+ } else
+ buf_nlink = 0;
if(dir_scan_smfs && curdev != buf_dir->dev)
buf_dir->flags |= FF_OTHFS;
@@ -193,7 +197,7 @@ static int dir_scan_recurse(const char *name) {
if(chdir(name)) {
dir_setlasterr(dir_curpath);
buf_dir->flags |= FF_ERR;
- if(dir_output.item(buf_dir, name, buf_ext) || dir_output.item(NULL, 0, NULL)) {
+ if(dir_output.item(buf_dir, name, buf_ext, buf_nlink) || dir_output.item(NULL, 0, NULL, 0)) {
dir_seterr("Output error: %s", strerror(errno));
return 1;
}
@@ -203,7 +207,7 @@ static int dir_scan_recurse(const char *name) {
if((dir = dir_read(&fail)) == NULL) {
dir_setlasterr(dir_curpath);
buf_dir->flags |= FF_ERR;
- if(dir_output.item(buf_dir, name, buf_ext) || dir_output.item(NULL, 0, NULL)) {
+ if(dir_output.item(buf_dir, name, buf_ext, buf_nlink) || dir_output.item(NULL, 0, NULL, 0)) {
dir_seterr("Output error: %s", strerror(errno));
return 1;
}
@@ -218,12 +222,12 @@ static int dir_scan_recurse(const char *name) {
if(fail)
buf_dir->flags |= FF_ERR;
- if(dir_output.item(buf_dir, name, buf_ext)) {
+ if(dir_output.item(buf_dir, name, buf_ext, buf_nlink)) {
dir_seterr("Output error: %s", strerror(errno));
return 1;
}
fail = dir_walk(dir);
- if(dir_output.item(NULL, 0, NULL)) {
+ if(dir_output.item(NULL, 0, NULL, 0)) {
dir_seterr("Output error: %s", strerror(errno));
return 1;
}
@@ -308,11 +312,11 @@ static int dir_scan_item(const char *name) {
if(buf_dir->flags & FF_DIR && !(buf_dir->flags & (FF_ERR|FF_EXL|FF_OTHFS|FF_KERNFS|FF_FRMLNK)))
fail = dir_scan_recurse(name);
else if(buf_dir->flags & FF_DIR) {
- if(dir_output.item(buf_dir, name, buf_ext) || dir_output.item(NULL, 0, NULL)) {
+ if(dir_output.item(buf_dir, name, buf_ext, 0) || dir_output.item(NULL, 0, NULL, 0)) {
dir_seterr("Output error: %s", strerror(errno));
fail = 1;
}
- } else if(dir_output.item(buf_dir, name, buf_ext)) {
+ } else if(dir_output.item(buf_dir, name, buf_ext, buf_nlink)) {
dir_seterr("Output error: %s", strerror(errno));
fail = 1;
}
@@ -333,6 +337,7 @@ static int dir_walk(char *dir) {
dir_curpath_enter(cur);
memset(buf_dir, 0, offsetof(struct dir, name));
memset(buf_ext, 0, sizeof(struct dir_ext));
+ buf_nlink = 0;
fail = dir_scan_item(cur);
dir_curpath_leave();
}
@@ -350,6 +355,7 @@ static int process(void) {
memset(buf_dir, 0, offsetof(struct dir, name));
memset(buf_ext, 0, sizeof(struct dir_ext));
+ buf_nlink = 0;
if((path = path_real(dir_curpath)) == NULL)
dir_seterr("Error obtaining full path: %s", strerror(errno));
@@ -376,13 +382,13 @@ static int process(void) {
buf_dir->flags |= FF_ERR;
stat_to_dir(&fs);
- if(dir_output.item(buf_dir, dir_curpath, buf_ext)) {
+ if(dir_output.item(buf_dir, dir_curpath, buf_ext, buf_nlink)) {
dir_seterr("Output error: %s", strerror(errno));
fail = 1;
}
if(!fail)
fail = dir_walk(dir);
- if(!fail && dir_output.item(NULL, 0, NULL)) {
+ if(!fail && dir_output.item(NULL, 0, NULL, 0)) {
dir_seterr("Output error: %s", strerror(errno));
fail = 1;
}