diff options
author | Rory Bradford <roryrjb@gmail.com> | 2022-11-19 11:11:26 +0000 |
---|---|---|
committer | Rory Bradford <roryrjb@gmail.com> | 2022-11-19 11:18:40 +0000 |
commit | 0f92f7352d1964a9859868439e8ded2c4de2111e (patch) | |
tree | 14c690402fa28c3b465ec00d2fe767054a1a3331 /dirent/tests/t-unicode.c | |
parent | fbb7c479de91b197c6c501c2023bf564a6a7610f (diff) | |
download | rf-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.c | 381 |
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; +} |