about summary refs log tree commit diff stats
path: root/dirent/examples/find.c
diff options
context:
space:
mode:
Diffstat (limited to 'dirent/examples/find.c')
-rw-r--r--dirent/examples/find.c184
1 files changed, 184 insertions, 0 deletions
diff --git a/dirent/examples/find.c b/dirent/examples/find.c
new file mode 100644
index 0000000..3e53d49
--- /dev/null
+++ b/dirent/examples/find.c
@@ -0,0 +1,184 @@
+/*
+ * List files and directories recursively.
+ *
+ * Compile this file with Visual Studio and run the produced command in
+ * console with a directory name argument.  For example, command
+ *
+ *     find "C:\Program Files"
+ *
+ * will output thousands of file names such as
+ *
+ *     c:\Program Files/7-Zip/7-zip.chm
+ *     c:\Program Files/7-Zip/7-zip.dll
+ *     c:\Program Files/7-Zip/7z.dll
+ *     c:\Program Files/Adobe/Reader 10.0/Reader/logsession.dll
+ *     c:\Program Files/Adobe/Reader 10.0/Reader/LogTransport2.exe
+ *     c:\Program Files/Windows NT/Accessories/wordpad.exe
+ *     c:\Program Files/Windows NT/Accessories/write.wpc
+ *
+ * The find command provided by this file is only an example: the command does
+ * not provide options to restrict the output to certain files as the Linux
+ * version does.
+ *
+ * Copyright (C) 1998-2019 Toni Ronkko
+ * This file is part of dirent.  Dirent may be freely distributed
+ * under the MIT license.  For all details and documentation, see
+ * https://github.com/tronkko/dirent
+ */
+#define _CRT_SECURE_NO_WARNINGS
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <errno.h>
+#include <locale.h>
+
+static int find_directory(const char *dirname);
+static int _main(int argc, char *argv[]);
+
+int
+_main(int argc, char *argv[])
+{
+	/* For each directory in command line */
+	int i = 1;
+	while (i < argc) {
+		if (!find_directory(argv[i]))
+			exit(EXIT_FAILURE);
+		i++;
+	}
+
+	/* List current working directory if no arguments on command line */
+	if (argc == 1)
+		find_directory(".");
+
+	return EXIT_SUCCESS;
+}
+
+/* Find files and subdirectories recursively */
+static int
+find_directory(const char *dirname)
+{
+	char buffer[PATH_MAX + 2];
+	char *p = buffer;
+	char *end = &buffer[PATH_MAX];
+
+	/* Copy directory name to buffer */
+	const char *src = dirname;
+	while (p < end && *src != '\0') {
+		*p++ = *src++;
+	}
+	*p = '\0';
+
+	/* Open directory stream */
+	DIR *dir = opendir(dirname);
+	if (!dir) {
+		/* Could not open directory */
+		fprintf(stderr,
+			"Cannot open %s (%s)\n", dirname, strerror(errno));
+		return /*failure*/ 0;
+	}
+
+	/* Print all files and directories within the directory */
+	struct dirent *ent;
+	while ((ent = readdir(dir)) != NULL) {
+		char *q = p;
+		char c;
+
+		/* Get final character of directory name */
+		if (buffer < q)
+			c = q[-1];
+		else
+			c = ':';
+
+		/* Append directory separator if not already there */
+		if (c != ':' && c != '/' && c != '\\')
+			*q++ = '/';
+
+		/* Append file name */
+		src = ent->d_name;
+		while (q < end && *src != '\0') {
+			*q++ = *src++;
+		}
+		*q = '\0';
+
+		/* Decide what to do with the directory entry */
+		switch (ent->d_type) {
+		case DT_LNK:
+		case DT_REG:
+			/* Output file name with directory */
+			printf("%s\n", buffer);
+			break;
+
+		case DT_DIR:
+			/* Scan sub-directory recursively */
+			if (strcmp(ent->d_name, ".") != 0
+				&&  strcmp(ent->d_name, "..") != 0) {
+				find_directory(buffer);
+			}
+			break;
+
+		default:
+			/* Ignore device entries */
+			/*NOP*/;
+		}
+
+	}
+
+	closedir(dir);
+	return /*success*/ 1;
+}
+
+/* Stub for converting arguments to UTF-8 on Windows */
+#ifdef _MSC_VER
+int
+wmain(int argc, wchar_t *argv[])
+{
+	/* Select UTF-8 locale */
+	setlocale(LC_ALL, ".utf8");
+	SetConsoleCP(CP_UTF8);
+	SetConsoleOutputCP(CP_UTF8);
+
+	/* Allocate memory for multi-byte argv table */
+	char **mbargv;
+	mbargv = (char**) malloc(argc * sizeof(char*));
+	if (!mbargv) {
+		puts("Out of memory");
+		exit(3);
+	}
+
+	/* Convert each argument in argv to UTF-8 */
+	for (int i = 0; i < argc; i++) {
+		size_t n;
+		wcstombs_s(&n, NULL, 0, argv[i], 0);
+
+		/* Allocate room for ith argument */
+		mbargv[i] = (char*) malloc(n + 1);
+		if (!mbargv[i]) {
+			puts("Out of memory");
+			exit(3);
+		}
+
+		/* Convert ith argument to utf-8 */
+		wcstombs_s(NULL, mbargv[i], n + 1, argv[i], n);
+	}
+
+	/* Pass UTF-8 converted arguments to the main program */
+	int errorcode = _main(argc, mbargv);
+
+	/* Release UTF-8 arguments */
+	for (int i = 0; i < argc; i++) {
+		free(mbargv[i]);
+	}
+
+	/* Release the argument table */
+	free(mbargv);
+	return errorcode;
+}
+#else
+int
+main(int argc, char *argv[])
+{
+	return _main(argc, argv);
+}
+#endif
+