about summary refs log tree commit diff stats
path: root/dirent/tests/t-unicode.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/tests/t-unicode.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/tests/t-unicode.c')
-rw-r--r--dirent/tests/t-unicode.c381
1 files changed, 381 insertions, 0 deletions
diff --git a/dirent/tests/t-unicode.c b/dirent/tests/t-unicode.c
new file mode 100644
index 0000000..8239120
--- /dev/null
+++ b/dirent/tests/t-unicode.c
@@ -0,0 +1,381 @@
+/*
+ * Test program to try unicode file names.
+ *
+ * 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
+ */
+
+/* Silence warning about fopen being insecure */
+#define _CRT_SECURE_NO_WARNINGS
+
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <time.h>
+#include <locale.h>
+
+#undef NDEBUG
+#include <assert.h>
+
+int
+main(int argc, char *argv[])
+{
+#ifdef WIN32
+	wchar_t wpath[MAX_PATH+1];
+	char path[MAX_PATH+1];
+	DWORD i, j, k, x;
+	BOOL ok;
+	HANDLE fh;
+	_WDIR *wdir;
+	struct _wdirent *wentry;
+	DIR *dir;
+	struct dirent *entry;
+	char buffer[100];
+	FILE *fp;
+	int counter = 0;
+
+	/* Initialize random number generator */
+	srand(((int) time(NULL)) * 257 + ((int) GetCurrentProcessId()));
+
+	/* Set current locale */
+	if (argc > 1) {
+		printf("Locale %s\n", argv[1]);
+		setlocale(LC_ALL, argv[1]);
+	} else {
+		setlocale(LC_ALL, "");
+	}
+
+	/****** CREATE FILE WITH UNICODE FILE NAME ******/
+
+	/* Get path to temporary directory (wide-character and ascii) */
+	i = GetTempPathW(MAX_PATH, wpath);
+	assert(i > 0);
+	j = GetTempPathA(MAX_PATH, path);
+	assert(j > 0);
+
+	/* Append random directory name */
+	for (k = 0; k < 10; k++) {
+		/* Generate random character */
+		char c = "abcdefghijklmnopqrstuvwxyz"[rand() % 26];
+
+		/* Append character to paths */
+		assert(i < MAX_PATH  &&  j < MAX_PATH);
+		wpath[i++] = c;
+		path[j++] = c;
+	}
+
+	/* Terminate paths */
+	assert(i < MAX_PATH  &&  j < MAX_PATH);
+	wpath[i] = '\0';
+	path[j] = '\0';
+
+	/* Remember the end of directory name */
+	k = i;
+
+	/* Create directory using unicode */
+	ok = CreateDirectoryW(wpath, NULL);
+	if (!ok) {
+		DWORD e = GetLastError();
+		wprintf(L"Cannot create directory %ls (code %u)\n", wpath, e);
+		abort();
+	}
+
+	/* Overwrite zero terminator with path separator */
+	assert(i < MAX_PATH  &&  j < MAX_PATH);
+	wpath[i++] = '\\';
+
+	/* Append a few unicode characters */
+	assert(i < MAX_PATH);
+	wpath[i++] = 0x6d4b;
+	assert(i < MAX_PATH);
+	wpath[i++] = 0x8bd5;
+
+	/* Terminate string */
+	assert(i < MAX_PATH);
+	wpath[i] = '\0';
+
+	/* Create file with unicode */
+	fh = CreateFileW(
+		wpath,
+		/* Access */ GENERIC_READ | GENERIC_WRITE,
+		/* Share mode */ 0,
+		/* Security attributes */ NULL,
+		/* Creation disposition */ CREATE_NEW,
+		/* Attributes */ FILE_ATTRIBUTE_NORMAL,
+		/* Template files */ NULL
+		);
+	assert(fh != INVALID_HANDLE_VALUE);
+
+	/* Write some data to file */
+	ok = WriteFile(
+		/* File handle */ fh,
+		/* Pointer to data */ "hep\n",
+		/* Number of bytes to write */ 4,
+		/* Number of bytes written */ NULL,
+		/* Overlapped */ NULL
+		);
+	assert(ok);
+
+	/* Close file */
+	ok = CloseHandle(fh);
+	assert(ok);
+
+	/****** MAKE SURE THAT UNICODE FILE CAN BE READ BY _WREADDIR ******/
+
+	/* Zero terminate wide-character path and open directory stream */
+	wpath[k] = '\0';
+	wdir = _wopendir(wpath);
+	if (wdir == NULL) {
+		wprintf(L"Cannot open directory %ls\n", wpath);
+		abort();
+	}
+
+	/* Read through entries */
+	counter = 0;
+	while ((wentry = _wreaddir(wdir)) != NULL) {
+		/* Skip pseudo directories */
+		if (wcscmp(wentry->d_name, L".") == 0) {
+			continue;
+		}
+		if (wcscmp(wentry->d_name, L"..") == 0) {
+			continue;
+		}
+
+		/* Found a file */
+		counter++;
+		assert(wentry->d_type == DT_REG);
+
+		/* Append file name to path */
+		i = k;
+		assert(i < MAX_PATH);
+		wpath[i++] = '\\';
+		x = 0;
+		while (wentry->d_name[x] != '\0') {
+			assert(i < MAX_PATH);
+			wpath[i++] = wentry->d_name[x++];
+		}
+		assert(i < MAX_PATH);
+		wpath[i] = '\0';
+
+		/* Open file for read */
+		fh = CreateFileW(
+			wpath,
+			/* Access */ GENERIC_READ,
+			/* Share mode */ 0,
+			/* Security attributes */ NULL,
+			/* Creation disposition */ OPEN_EXISTING,
+			/* Attributes */ FILE_ATTRIBUTE_NORMAL,
+			/* Template files */ NULL
+			);
+		assert(fh != INVALID_HANDLE_VALUE);
+
+		/* Read data from file */
+		ok = ReadFile(
+			/* File handle */ fh,
+			/* Output buffer */ buffer,
+			/* Max number of bytes to read */ sizeof(buffer) - 1,
+			/* Number of bytes actually read */ &x,
+			/* Overlapped */ NULL
+		);
+		assert(ok);
+
+		/* Make sure that we got the file contents right */
+		assert(x == 4);
+		assert(buffer[0] == 'h');
+		assert(buffer[1] == 'e');
+		assert(buffer[2] == 'p');
+		assert(buffer[3] == '\n');
+
+		/* Close file */
+		ok = CloseHandle(fh);
+		assert(ok);
+	}
+	assert(counter == 1);
+
+	/* Close directory */
+	_wclosedir(wdir);
+
+	/****** MAKE SURE THAT UNICODE FILE NAME CAN BE READ BY READDIR *****/
+
+	/* Zero terminate ascii path and open directory stream */
+	k = j;
+	path[k] = '\0';
+	dir = opendir(path);
+	if (dir == NULL) {
+		fprintf(stderr, "Cannot open directory %s\n", path);
+		abort();
+	}
+
+	/* Read through entries */
+	counter = 0;
+	while ((entry = readdir(dir)) != NULL) {
+		/* Skip pseudo directories */
+		if (strcmp(entry->d_name, ".") == 0) {
+			continue;
+		}
+		if (strcmp(entry->d_name, "..") == 0) {
+			continue;
+		}
+
+		/* Found a file */
+		counter++;
+		assert(entry->d_type == DT_REG);
+
+		/* Append file name to path */
+		j = k;
+		assert(j < MAX_PATH);
+		path[j++] = '\\';
+		x = 0;
+		while (entry->d_name[x] != '\0') {
+			assert(j < MAX_PATH);
+			path[j++] = entry->d_name[x++];
+		}
+		assert(j < MAX_PATH);
+		path[j] = '\0';
+
+		/* Open file for read */
+		fp = fopen(path, "r");
+		if (!fp) {
+			fprintf(stderr, "Cannot open file %s\n", path);
+			abort();
+		}
+
+		/* Read data from file */
+		if (fgets(buffer, sizeof(buffer), fp) == NULL) {
+			fprintf(stderr, "Cannot read file %s\n", path);
+			abort();
+		}
+
+		/* Make sure that we got the file contents right */
+		assert(buffer[0] == 'h');
+		assert(buffer[1] == 'e');
+		assert(buffer[2] == 'p');
+		assert(buffer[3] == '\n');
+		assert(buffer[4] == '\0');
+
+		/* Close file */
+		fclose(fp);
+	}
+	assert(counter == 1);
+
+	/* Close directory */
+	closedir(dir);
+
+	/****** CREATE FILE WITH UTF-8 ******/
+
+	/* Append UTF-8 file name (åäö.txt) to path */
+	j = k;
+	path[j++] = '\\';
+	path[j++] = 0xc3;
+	path[j++] = 0xa5;
+	path[j++] = 0xc3;
+	path[j++] = 0xa4;
+	path[j++] = 0xc3;
+	path[j++] = 0xb6;
+	path[j++] = 0x2e;
+	path[j++] = 0x74;
+	path[j++] = 0x78;
+	path[j++] = 0x74;
+	assert(j < MAX_PATH);
+	path[j] = '\0';
+
+	/*
+	 * Create file.
+	 *
+	 * Be ware that the code below creates a different file depending on
+	 * the current locale!  For example, if the current locale is
+	 * english_us.65001, then the file name will be "åäö.txt" (7
+	 * characters).  However, if the current locale is english_us.1252,
+	 * then the file name will be "ÃċÃĊö.txt" (10 characters).
+	 */
+	printf("Creating %s\n", path);
+	fp = fopen(path, "w");
+	if (!fp) {
+		fprintf(stderr, "Cannot open file %s\n", path);
+		abort();
+	}
+	fputs("hep\n", fp);
+	fclose(fp);
+
+	/* Open directory again */
+	path[k] = '\0';
+	dir = opendir(path);
+	if (dir == NULL) {
+		fprintf(stderr, "Cannot open directory %s\n", path);
+		abort();
+	}
+
+	/* Read through entries */
+	counter = 0;
+	while ((entry = readdir(dir)) != NULL) {
+		/* Skip pseudo directories */
+		if (strcmp(entry->d_name, ".") == 0) {
+			continue;
+		}
+		if (strcmp(entry->d_name, "..") == 0) {
+			continue;
+		}
+
+		/* Found a file */
+		counter++;
+		assert(entry->d_type == DT_REG);
+
+		/* Append file name to path */
+		j = k;
+		assert(j < MAX_PATH);
+		path[j++] = '\\';
+		x = 0;
+		while (entry->d_name[x] != '\0') {
+			assert(j < MAX_PATH);
+			path[j++] = entry->d_name[x++];
+		}
+		assert(j < MAX_PATH);
+		path[j] = '\0';
+
+		/* Print file name for debugging */
+		printf("Opening \"%s\" hex ", path + k + 1);
+		x = 0;
+		while (entry->d_name[x] != '\0') {
+			printf("0x%02x ",
+				(unsigned) (entry->d_name[x++] & 0xff));
+		}
+		printf("\n");
+
+		/* Open file for read */
+		fp = fopen(path, "r");
+		if (!fp) {
+			fprintf(stderr, "Cannot open file %s\n", path);
+			abort();
+		}
+
+		/* Read data from file */
+		if (fgets(buffer, sizeof(buffer), fp) == NULL) {
+			fprintf(stderr, "Cannot read file %s\n", path);
+			abort();
+		}
+
+		/* Make sure that we got the file contents right */
+		assert(buffer[0] == 'h');
+		assert(buffer[1] == 'e');
+		assert(buffer[2] == 'p');
+		assert(buffer[3] == '\n');
+		assert(buffer[4] == '\0');
+
+		/* Close file */
+		fclose(fp);
+	}
+	assert(counter == 2);
+
+	/* Close directory */
+	closedir(dir);
+#else
+	/* Linux */
+	(void) argc;
+	(void) argv;
+#endif
+	return EXIT_SUCCESS;
+}