Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 45 additions & 28 deletions dircnt.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,31 @@
#include <limits.h>
#include <sys/stat.h>

#if defined(WIN32) || defined(_WIN32)
#define PATH_SEPARATOR '\\'
#if defined(WIN32) || defined(_WIN32)
#define PATH_SEPARATOR '\\'
#else
#define PATH_SEPARATOR '/'
#define PATH_SEPARATOR '/'
#endif

// FEEDBACK_INTERVAL 0 turns off feedback.
// Low feedback intervals will impact performance. Suggest 0 or > 1000.
// Feedback is intentionally inexact (toward code simplicity), occurring on or after each feedback interval.
#define FEEDBACK_INTERVAL 10000

/* A custom structure to hold separate file and directory counts */
struct filecount {
long dirs;
long files;
long dirs;
long files;
long feedbackLimit;
};

/*
* counts the number of files and directories in the specified directory.
*
* path - relative pathname of a directory whose files should be counted
* counts - pointer to struct containing file/dir counts
* feedbackLimit - allows triggering intermittent feedback without the
* relatively high cost of the modulus operator.
*/
void count(char *path, struct filecount *counts) {
DIR *dir; /* dir structure we are reading */
Expand All @@ -61,34 +69,42 @@ void count(char *path, struct filecount *counts) {
}

while((ent = readdir(dir))) {
if (strlen(path) + 1 + strlen(ent->d_name) > PATH_MAX) {
fprintf(stdout, "path too long (%ld) %s%c%s", (strlen(path) + 1 + strlen(ent->d_name)), path, PATH_SEPARATOR, ent->d_name);
return;
}
if (strlen(path) + 1 + strlen(ent->d_name) > PATH_MAX) {
fprintf(stdout, "path too long (%ld) %s%c%s", (strlen(path) + 1 + strlen(ent->d_name)), path, PATH_SEPARATOR, ent->d_name);
return;
}

/* Use dirent.d_type if present, otherwise use stat() */
#if ( defined ( _DIRENT_HAVE_D_TYPE ) && !PREFER_STAT)
if(DT_DIR == ent->d_type) {
if(DT_DIR == ent->d_type) {
#else
sprintf(subpath, "%s%c%s", path, PATH_SEPARATOR, ent->d_name);
if(lstat(subpath, &statbuf)) {
perror(subpath);
return;
}
sprintf(subpath, "%s%c%s", path, PATH_SEPARATOR, ent->d_name);
if(lstat(subpath, &statbuf)) {
perror(subpath);
return;
}

if(S_ISDIR(statbuf.st_mode)) {
if(S_ISDIR(statbuf.st_mode)) {
#endif
/* Skip "." and ".." directory entries... they are not "real" directories */
if(0 == strcmp("..", ent->d_name) || 0 == strcmp(".", ent->d_name)) {
/* Skip "." and ".." directory entries... they are not "real" directories */
if(0 == strcmp("..", ent->d_name) || 0 == strcmp(".", ent->d_name)) {
/* fprintf(stderr, "This is %s, skipping\n", ent->d_name); */
} else {
sprintf(subpath, "%s%c%s", path, PATH_SEPARATOR, ent->d_name);
counts->dirs++;
count(subpath, counts);
}
} else {
counts->files++;
}
} else {
sprintf(subpath, "%s%c%s", path, PATH_SEPARATOR, ent->d_name);
counts->dirs++;
counts->feedbackLimit++;
count(subpath, counts);
}
} else {
counts->files++;
counts->feedbackLimit++;
}

if(FEEDBACK_INTERVAL && counts->feedbackLimit > FEEDBACK_INTERVAL) {
printf("In progress: %ld files and %ld directories so far.\r", counts->files, counts->dirs);
fflush(stdout);
counts->feedbackLimit = 0;
}
}

#ifdef DEBUG
Expand All @@ -102,13 +118,14 @@ int main(int argc, char *argv[]) {
char *dir;
counts.files = 0;
counts.dirs = 0;
counts.feedbackLimit = 0;
if(argc > 1)
dir = argv[1];
else
dir = ".";

#ifdef DEBUG
#if PREFER_STAT
#if PREFER_STAT
fprintf(stderr, "Compiled with PREFER_STAT. Using stat()\n");
#elif defined ( _DIRENT_HAVE_D_TYPE )
fprintf(stderr, "Using dirent.d_type\n");
Expand All @@ -121,7 +138,7 @@ int main(int argc, char *argv[]) {

/* If we found nothing, this is probably an error which has already been printed */
if(0 < counts.files || 0 < counts.dirs) {
printf("%s contains %ld files and %ld directories\n", dir, counts.files, counts.dirs);
printf("Complete: %s contains %ld files and %ld directories\n", dir, counts.files, counts.dirs);
}

return 0;
Expand Down