Skip to content

Commit 87dc1a0

Browse files
committed
fincore: add recursive directory scanning
Add a --recursive flag to fincore which allows to recursively scan directories.
1 parent ab89f21 commit 87dc1a0

File tree

4 files changed

+80
-26
lines changed

4 files changed

+80
-26
lines changed

bash-completion/fincore

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ _fincore_module()
3232
--output
3333
--output-all
3434
--raw
35+
--recursive
3536
--help
3637
--version
3738
"

configure.ac

+4
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,10 @@ AS_IF([test x"$have_dirfd" = xno], [
822822

823823
AM_CONDITIONAL([HAVE_DIRFD], [test "x$have_dirfd" = xyes || test "x$have_ddfd" = xyes])
824824

825+
have_fts_open=no
826+
AC_CHECK_FUNCS([fts_open], [have_fts_open=yes], [have_fts_open=no])
827+
AM_CONDITIONAL([HAVE_FTS_OPEN], [test "x$have_fts_open" = xyes])
828+
825829
MQ_LIBS=
826830
AC_CHECK_LIB([rt], [mq_open], [MQ_LIBS="-lrt"])
827831
AC_SUBST([MQ_LIBS])

misc-utils/fincore.1.adoc

+3
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ Produce output in raw format. All potentially unsafe characters are hex-escaped
4747
*-J*, *--json*::
4848
Use JSON output format.
4949

50+
*-R*, *--recursive*::
51+
recursively check all files in directories.
52+
5053
include::man-common/help-version.adoc[]
5154

5255
== AUTHORS

misc-utils/fincore.c

+72-26
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@
2626
#include <stdio.h>
2727
#include <string.h>
2828

29+
#ifdef HAVE_FTS_OPEN
30+
#include <fts.h>
31+
#endif
32+
2933
#include "c.h"
3034
#include "cctype.h"
3135
#include "nls.h"
@@ -125,12 +129,13 @@ struct fincore_control {
125129
unsigned int bytes : 1,
126130
noheadings : 1,
127131
raw : 1,
128-
json : 1;
132+
json : 1,
133+
recursive : 1;
129134

130135
};
131136

132137
struct fincore_state {
133-
const char * const name;
138+
const char * name;
134139
long long unsigned int file_size;
135140

136141
struct cachestat cstat;
@@ -356,40 +361,50 @@ static int fincore_fd (struct fincore_control *ctl,
356361
/*
357362
* Returns: <0 on error, 0 success, 1 ignore.
358363
*/
359-
static int fincore_name(struct fincore_control *ctl, const char *name)
364+
static int fincore_name(struct fincore_control *ctl,
365+
const char *filename,
366+
const char *showname,
367+
struct stat *statp)
360368
{
361369
int fd;
362370
int rc = 0;
363-
struct stat sb;
364-
struct fincore_state _st = { .name = name }, *st = &_st;
371+
struct stat sb, *stp = statp ?: &sb;
372+
struct fincore_state st = { .name = filename };
365373

366-
if ((fd = open (st->name, O_RDONLY)) < 0) {
367-
warn(_("failed to open: %s"), st->name);
374+
if ((fd = open(filename, O_RDONLY)) < 0) {
375+
warn(_("failed to open: %s"), showname);
368376
return -errno;
369377
}
370378

371-
if (fstat (fd, &sb) < 0) {
372-
warn(_("failed to do fstat: %s"), st->name);
373-
close (fd);
374-
return -errno;
379+
if (!statp) {
380+
if (fstat (fd, &sb) < 0) {
381+
warn(_("failed to do fstat: %s"), showname);
382+
close (fd);
383+
return -errno;
384+
}
375385
}
376-
st->file_size = sb.st_size;
377386

378-
if (S_ISBLK(sb.st_mode)) {
379-
rc = blkdev_get_size(fd, &st->file_size);
387+
if (S_ISBLK(stp->st_mode)) {
388+
rc = blkdev_get_size(fd, &st.file_size);
380389
if (rc)
381-
warn(_("failed ioctl to get size: %s"), st->name);
382-
} else if (S_ISREG(sb.st_mode)) {
383-
st->file_size = sb.st_size;
390+
warn(_("failed ioctl to get size: %s"), showname);
391+
} else if (S_ISREG(stp->st_mode)) {
392+
st.file_size = stp->st_size;
393+
} else {
394+
rc = 1; /* ignore things like symlinks
395+
* and directories*/
384396
}
385397

386-
if (!rc)
387-
rc = fincore_fd(ctl, fd, st);
398+
if (!rc) {
399+
rc = fincore_fd(ctl, fd, &st);
400+
}
388401

389402
close(fd);
390403

391-
if (!rc)
392-
rc = add_output_data(ctl, st);
404+
if (!rc) {
405+
st.name = showname;
406+
rc = add_output_data(ctl, &st);
407+
}
393408

394409
return rc;
395410
}
@@ -409,6 +424,7 @@ static void __attribute__((__noreturn__)) usage(void)
409424
fputs(_(" -o, --output <list> output columns\n"), out);
410425
fputs(_(" --output-all output all columns\n"), out);
411426
fputs(_(" -r, --raw use raw output format\n"), out);
427+
fputs(_(" -R, --recursive recursively check all files in directories\n"), out);
412428

413429
fputs(USAGE_SEPARATOR, out);
414430
fprintf(out, USAGE_HELP_OPTIONS(23));
@@ -446,6 +462,7 @@ int main(int argc, char ** argv)
446462
{ "help", no_argument, NULL, 'h' },
447463
{ "json", no_argument, NULL, 'J' },
448464
{ "raw", no_argument, NULL, 'r' },
465+
{ "recursive", no_argument, NULL, 'R' },
449466
{ NULL, 0, NULL, 0 },
450467
};
451468

@@ -454,7 +471,7 @@ int main(int argc, char ** argv)
454471
textdomain(PACKAGE);
455472
close_stdout_atexit();
456473

457-
while ((c = getopt_long (argc, argv, "bno:JrVh", longopts, NULL)) != -1) {
474+
while ((c = getopt_long (argc, argv, "bno:JrRVh", longopts, NULL)) != -1) {
458475
switch (c) {
459476
case 'b':
460477
ctl.bytes = 1;
@@ -475,6 +492,12 @@ int main(int argc, char ** argv)
475492
case 'r':
476493
ctl.raw = 1;
477494
break;
495+
case 'R':
496+
#ifndef HAVE_FTS_OPEN
497+
errx(0, _("recursive option is not supported"));
498+
#endif
499+
ctl.recursive = 1;
500+
break;
478501
case 'V':
479502
print_version(EXIT_SUCCESS);
480503
case 'h':
@@ -538,10 +561,33 @@ int main(int argc, char ** argv)
538561
}
539562
}
540563

541-
for(; optind < argc; optind++) {
542-
rc = fincore_name(&ctl, argv[optind]);
543-
if (rc)
544-
break;
564+
if (ctl.recursive) {
565+
#ifdef HAVE_FTS_OPEN
566+
FTS *fts = fts_open(argv + optind, FTS_PHYSICAL, NULL);
567+
FTSENT *ent;
568+
569+
if (!fts) {
570+
warn(_("failed to iterate tree"));
571+
rc = EXIT_FAILURE;
572+
} else {
573+
while ((ent = fts_read(fts)) != NULL) {
574+
if (ent->fts_info == FTS_F || ent->fts_info == FTS_DEFAULT) {
575+
/* fts changes directory when iterating,
576+
* so we need to use .fts_accpath to access
577+
* the file named .fts_path */
578+
rc = fincore_name(&ctl, ent->fts_accpath, ent->fts_path, ent->fts_statp);
579+
if (rc)
580+
break;
581+
}
582+
}
583+
}
584+
#endif
585+
} else {
586+
for(; optind < argc; optind++) {
587+
rc = fincore_name(&ctl, argv[optind], argv[optind], NULL);
588+
if (rc)
589+
break;
590+
}
545591
}
546592

547593
if (rc == 0)

0 commit comments

Comments
 (0)