diff options
-rw-r--r-- | src/dir.h | 2 | ||||
-rw-r--r-- | src/dir_export.c | 18 | ||||
-rw-r--r-- | src/dir_import.c | 15 | ||||
-rw-r--r-- | src/dir_mem.c | 3 | ||||
-rw-r--r-- | src/dir_scan.c | 24 |
5 files changed, 39 insertions, 23 deletions
@@ -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; } |