about summary refs log tree commit diff stats
path: root/dirent/examples/ls.c
diff options
context:
space:
mode:
authorRory Bradford <roryrjb@gmail.com>2022-11-19 11:11:26 +0000
committerRory Bradford <roryrjb@gmail.com>2022-11-19 11:18:40 +0000
commit0f92f7352d1964a9859868439e8ded2c4de2111e (patch)
tree14c690402fa28c3b465ec00d2fe767054a1a3331 /dirent/examples/ls.c
parentfbb7c479de91b197c6c501c2023bf564a6a7610f (diff)
downloadrf-0f92f7352d1964a9859868439e8ded2c4de2111e.tar.gz
Full native win32 support
This will now compile with MSVC using the make.bat batch file. It does
however bring in some additional third party dependencies: ports of
dirent and getopt (something I'd ideally like to work on in the future).

Signed-off-by: Rory Bradford <roryrjb@gmail.com>
Diffstat (limited to 'dirent/examples/ls.c')
-rw-r--r--dirent/examples/ls.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/dirent/examples/ls.c b/dirent/examples/ls.c
new file mode 100644
index 0000000..3fb627e
--- /dev/null
+++ b/dirent/examples/ls.c
@@ -0,0 +1,148 @@
+/*
+ * List contents of a directory.
+ *
+ * Compile this file with Visual Studio and run the produced command in
+ * console with a directory name argument.  For example, command
+ *
+ *     ls "c:\Program Files"
+ *
+ * might output something like
+ *
+ *     ./
+ *     ../
+ *     7-Zip/
+ *     Internet Explorer/
+ *     Microsoft Visual Studio 9.0/
+ *     Microsoft.NET/
+ *     Mozilla Firefox/
+ *
+ * The ls command provided by this file is only an example: the command does
+ * not have any fancy options like "ls -al" in Linux and the command does not
+ * support file name matching like "ls *.c".
+ *
+ * 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 void list_directory(const char *dirname);
+static int _main(int argc, char *argv[]);
+
+static int
+_main(int argc, char *argv[])
+{
+	/* For each directory in command line */
+	int i = 1;
+	while (i < argc) {
+		list_directory(argv[i]);
+		i++;
+	}
+
+	/* List current working directory if no arguments on command line */
+	if (argc == 1)
+		list_directory(".");
+
+	return EXIT_SUCCESS;
+}
+
+/*
+ * List files and directories within a directory.
+ */
+static void
+list_directory(const char *dirname)
+{
+	/* Open directory stream */
+	DIR *dir = opendir(dirname);
+	if (!dir) {
+		/* Could not open directory */
+		fprintf(stderr,
+			"Cannot open %s (%s)\n", dirname, strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+
+	/* Print all files and directories within the directory */
+	struct dirent *ent;
+	while ((ent = readdir(dir)) != NULL) {
+		switch (ent->d_type) {
+		case DT_REG:
+			printf("%s\n", ent->d_name);
+			break;
+
+		case DT_DIR:
+			printf("%s/\n", ent->d_name);
+			break;
+
+		case DT_LNK:
+			printf("%s@\n", ent->d_name);
+			break;
+
+		default:
+			printf("%s*\n", ent->d_name);
+		}
+	}
+
+	closedir(dir);
+}
+
+/* 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
+