@ -1 +1 @@ | |||||
Subproject commit bd7cda4f17855ef021c45c0a657a7e319c560349 | |||||
Subproject commit f1764a0ed33533a45c2da8251dac6b284156082d |
@ -1 +1 @@ | |||||
Subproject commit 5d530b0d8735345c28934b8b6c910f36197271d9 | |||||
Subproject commit 3c26a6fe64a782d7aba0db7ee331e646060cc095 |
@ -1,17 +0,0 @@ | |||||
/CMakeCache.txt | |||||
/CMakeFiles | |||||
/CTestTestfile.cmake | |||||
/DartConfiguration.tcl | |||||
/Makefile | |||||
/Testing | |||||
/Win32 | |||||
/cmake_install.cmake | |||||
/find | |||||
/locate | |||||
/ls | |||||
/t-compile | |||||
/t-dirent | |||||
/updatedb | |||||
/*.filters | |||||
/*.vcxproj | |||||
/*.dir |
@ -1,59 +0,0 @@ | |||||
cmake_minimum_required (VERSION 2.8.11) | |||||
project (dirent LANGUAGES C CXX) | |||||
# User options | |||||
option(DIRENT_BUILD_TESTS "Build bundled tests" ON) | |||||
message(STATUS "Build test and example programs: ${DIRENT_BUILD_TESTS}") | |||||
# Initialize C and C++ compilers | |||||
enable_language (C CXX) | |||||
# Compile in debug mode by default | |||||
if (NOT CMAKE_BUILD_TYPE) | |||||
set (CMAKE_BUILD_TYPE Debug | |||||
CACHE STRING | |||||
"Type of build: None Debug Release RelWithDebInfo MinSizeRel." | |||||
FORCE | |||||
) | |||||
endif (NOT CMAKE_BUILD_TYPE) | |||||
# Use the include directory only on Windows | |||||
if (WIN32) | |||||
include_directories (${CMAKE_SOURCE_DIR}/include) | |||||
endif (WIN32) | |||||
# Install dirent.h | |||||
if (WIN32) | |||||
install (FILES include/dirent.h DESTINATION include) | |||||
endif (WIN32) | |||||
# Add distclean target | |||||
add_custom_target (distclean | |||||
COMMAND ${CMAKE_BUILD_TOOL} clean | |||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/distclean.cmake | |||||
) | |||||
# Build example programs | |||||
if(DIRENT_BUILD_TESTS) | |||||
add_executable (find examples/find.c) | |||||
add_executable (ls examples/ls.c) | |||||
add_executable (locate examples/locate.c) | |||||
add_executable (updatedb examples/updatedb.c) | |||||
add_executable (scandir examples/scandir.c) | |||||
add_executable (cat examples/cat.c) | |||||
# Build test programs | |||||
include (CTest) | |||||
add_custom_target (check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C ${CMAKE_CFG_INTDIR}) | |||||
function (add_test_executable TEST_NAME) | |||||
add_executable (${TEST_NAME} EXCLUDE_FROM_ALL ${ARGN}) | |||||
add_test (NAME ${TEST_NAME} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND $<TARGET_FILE:${TEST_NAME}>) | |||||
add_dependencies (check ${TEST_NAME}) | |||||
endfunction (add_test_executable) | |||||
add_test_executable (t-compile tests/t-compile.c) | |||||
add_test_executable (t-dirent tests/t-dirent.c) | |||||
add_test_executable (t-scandir tests/t-scandir.c) | |||||
add_test_executable (t-unicode tests/t-unicode.c) | |||||
add_test_executable (t-cplusplus tests/t-cplusplus.cpp) | |||||
endif(DIRENT_BUILD_TESTS) |
@ -1,129 +0,0 @@ | |||||
2018-05-08 Toni Rönkkö | |||||
* Version 1.23.2: fixes bad scandir prototype. | |||||
2017-08-27 Toni Rönkkö | |||||
* Version 1.23: support readdir_r and scandir functions. | |||||
2017-07-18 Toni Rönkkö | |||||
* Created release branches v1.22 and v1.21 to Git. Published version | |||||
1.22 at softagalleria.net. | |||||
2016-09-11 Toni Rönkkö | |||||
* Version 1.22: added support for CMake. Thanks to Paul Fultz II. | |||||
2014-09-25 Toni Rönkkö | |||||
* Version 1.21: compiles correctly under Open Watcom. Thanks to | |||||
Virgil Banowetz for a patch! | |||||
2014-04-07 Toni Rönkkö | |||||
* Version 1.20.1: the zip file from the previous version did not open | |||||
correctly with Microsoft's compressed folders. Thanks to Alexandre | |||||
for info! | |||||
2014-03-17 Toni Ronkko | |||||
* Version 1.20: dirent.h compiles correctly in 64-bit architecture. | |||||
Thanks to Aaron Simmons! | |||||
2014-03-03 Toni Ronkko | |||||
* Version 1.13.2: define DT_LNK for compatibility with Unix | |||||
programs. Thanks to Joel Bruick for suggestion! | |||||
2013-01-27 Toni Ronkko | |||||
* Version 1.13.1: patch from Edward Berner fixes set_errno() on | |||||
Windows NT 4.0. | |||||
* Revised wcstombs() and mbstowcs() wrappers to make sure that they do | |||||
not write past their target string. | |||||
* PATH_MAX from windows.h includes zero terminator so there is no | |||||
need to add one extra byte to variables and structures. | |||||
2012-12-12 Toni Ronkko | |||||
* Version 1.13: use the traditional 8+3 file naming scheme if a file | |||||
name cannot be represented in the default ANSI code page. Now | |||||
compiles again with MSVC 6.0. Thanks to Konstantin Khomoutov for | |||||
testing. | |||||
2012-10-01 Toni Ronkko | |||||
* Version 1.12.1: renamed wide-character DIR structure _wDIR to | |||||
_WDIR (with capital W) in order to maintain compatibility with MingW. | |||||
2012-09-30 Toni Ronkko | |||||
* Version 1.12: define PATH_MAX and NAME_MAX. Added wide-character | |||||
variants _wDIR, _wdirent, _wopendir(), _wreaddir(), _wclosedir() and | |||||
_wrewinddir(). Thanks to Edgar Buerkle and Jan Nijtmans for ideas | |||||
and code. | |||||
* Now avoiding windows.h. This allows dirent.h to be integrated | |||||
more easily into programs using winsock. Thanks to Fernando | |||||
Azaldegui. | |||||
2011-03-15 Toni Ronkko | |||||
* Version 1.11: defined FILE_ATTRIBUTE_DEVICE for MSVC 6.0. | |||||
2010-08-11 Toni Ronkko | |||||
* Version 1.10: added d_type and d_namlen fields to dirent structure. | |||||
The former is especially useful for determining whether directory | |||||
entry represents a file or a directory. For more information, see | |||||
http://www.delorie.com/gnu/docs/glibc/libc_270.html | |||||
* Improved conformance to the standards. For example, errno is now | |||||
set properly on failure and assert() is never used. Thanks to Peter | |||||
Brockam for suggestions. | |||||
* Fixed a bug in rewinddir(): when using relative directory names, | |||||
change of working directory no longer causes rewinddir() to fail. | |||||
2009-12-15 John Cunningham | |||||
* Version 1.9: added rewinddir member function | |||||
2008-01-18 Toni Ronkko | |||||
* Version 1.8: Using FindFirstFileA and WIN32_FIND_DATAA to avoid | |||||
converting string between multi-byte and unicode representations. | |||||
This makes the code simpler and also allows the code to be compiled | |||||
under MingW. Thanks to Azriel Fasten for the suggestion. | |||||
2007-03-04 Toni Ronkko | |||||
* Bug fix: due to the strncpy_s() function this file only compiled in | |||||
Visual Studio 2005. Using the new string functions only when the | |||||
compiler version allows. | |||||
2006-11-02 Toni Ronkko | |||||
* Major update: removed support for Watcom C, MS-DOS and Turbo C to | |||||
simplify the file, updated the code to compile cleanly on Visual | |||||
Studio 2005 with both unicode and multi-byte character strings, | |||||
removed rewinddir() as it had a bug. | |||||
2006-08-20 Toni Ronkko | |||||
* Removed all remarks about MSVC 1.0, which is antiqued now. | |||||
Simplified comments by removing SGML tags. | |||||
2002-05-14 Toni Ronkko | |||||
* Embedded the function definitions directly to the header so that no | |||||
source modules need to be included in the Visual Studio project. | |||||
Removed all the dependencies to other projects so that this header | |||||
file can be used independently. | |||||
1998-05-28 Toni Ronkko | |||||
* First version. |
@ -1,21 +0,0 @@ | |||||
The MIT License (MIT) | |||||
Copyright (c) 1998-2019 Toni Ronkko | |||||
Permission is hereby granted, free of charge, to any person obtaining a copy | |||||
of this software and associated documentation files (the "Software"), to deal | |||||
in the Software without restriction, including without limitation the rights | |||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||||
copies of the Software, and to permit persons to whom the Software is | |||||
furnished to do so, subject to the following conditions: | |||||
The above copyright notice and this permission notice shall be included in all | |||||
copies or substantial portions of the Software. | |||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||||
SOFTWARE. |
@ -1,101 +0,0 @@ | |||||
# Dirent | |||||
Dirent is a C/C++ programming interface that allows programmers to retrieve | |||||
information about files and directories under Linux/UNIX. This project | |||||
provides Linux compatible Dirent interface for Microsoft Windows. | |||||
# Installation | |||||
Download the latest Dirent installation package from | |||||
[GitHub](https://github.com/tronkko/dirent/releases) and | |||||
unpack the installation file with 7-zip, for example. The installation | |||||
package contains dirent.h file as well as a few example programs and | |||||
tests. | |||||
## Install Dirent for All Programs | |||||
To make dirent.h available for all C/C++ programs, simply copy the | |||||
``include/dirent.h`` file to the system include directory. System include | |||||
directory contains header files such as assert.h and windows.h. In Visual | |||||
Studio 2008, for example, the system include may be found at | |||||
``C:\Program Files\Microsoft Visual Studio 9.0\VC\include``. | |||||
Everything you need is included in the single dirent.h file, and you can | |||||
start using Dirent immediately -- there is no need to add files to your | |||||
Visual Studio project. | |||||
## Embed Dirent into Your Own Project | |||||
If you wish to distribute dirent.h alongside with your own source code, then | |||||
copy ``include/dirent.h`` file to a new sub-directory within your project and | |||||
add that directory to include path on Windows while omitting the directory | |||||
under Linux/UNIX. This allows your project to be compiled against native | |||||
dirent.h on Linux/UNIX while substituting the functionality on Microsoft | |||||
Windows. | |||||
## Examples | |||||
The installation package contains four example programs: | |||||
Program | Purpose | |||||
-------- | ----------------------------------------------------------------- | |||||
ls | List files in a directory, e.g. ls "c:\Program Files" | |||||
find | Find files in subdirectories, e.g. find "c:\Program Files\CMake" | |||||
updatedb | Build database of files in a drive, e.g. updatedb c:\ | |||||
locate | Locate a file from database, e.g. locate notepad | |||||
scandir | Demonstrate scandir() function | |||||
cat | Print a text file to screen | |||||
To build the example programs, first install [CMake](https://cmake.org/). | |||||
Then, with CMake installed, open command prompt and create a temporary | |||||
directory ``c:\temp\dirent`` for the build files as | |||||
``` | |||||
c:\ | |||||
mkdir temp | |||||
mkdir temp\dirent | |||||
cd temp\dirent | |||||
``` | |||||
Generate build files as | |||||
``` | |||||
cmake d:\dirent | |||||
``` | |||||
where ``d:\dirent`` is the root directory of the Dirent package (containing | |||||
this README.md and LICENSE file). | |||||
Once CMake is finished, open Visual Studio, load the generated dirent.sln file | |||||
from the build directory and build the solution. Once the build completes, run | |||||
the example programs from the command prompt as | |||||
``` | |||||
cd Debug | |||||
ls . | |||||
find . | |||||
updatedb c:\ | |||||
locate cmd.exe | |||||
``` | |||||
You can omit generation of test and example programs by appending option | |||||
`-DDIRENT_BUILD_TESTS=OFF` to the CMake command line. | |||||
# Copying | |||||
Dirent may be freely distributed under the MIT license. See the | |||||
[LICENSE](LICENSE) file for details. | |||||
# Alternatives to Dirent | |||||
I ported Dirent to Microsoft Windows in 1998 when only a few alternatives | |||||
were available. However, the situation has changed since then and nowadays | |||||
both [Cygwin](http://www.cygwin.com) and [MingW](http://www.mingw.org) | |||||
allow you to compile a great number of UNIX programs in Microsoft Windows. | |||||
They both provide a full dirent API as well as many other UNIX APIs. MingW | |||||
can even be used for commercial applications! |
@ -1,62 +0,0 @@ | |||||
# Remove CMake generated temporary files | |||||
set (cmake_generated | |||||
${CMAKE_BINARY_DIR}/ALL_BUILD.vcxproj | |||||
${CMAKE_BINARY_DIR}/ALL_BUILD.vcxproj.filters | |||||
${CMAKE_BINARY_DIR}/CMakeCache.txt | |||||
${CMAKE_BINARY_DIR}/CMakeFiles | |||||
${CMAKE_BINARY_DIR}/CTestTestfile.cmake | |||||
${CMAKE_BINARY_DIR}/Continuous.vcxproj | |||||
${CMAKE_BINARY_DIR}/Continuous.vcxproj.filters | |||||
${CMAKE_BINARY_DIR}/DartConfiguration.tcl | |||||
${CMAKE_BINARY_DIR}/Debug | |||||
${CMAKE_BINARY_DIR}/Experimental.vcxproj | |||||
${CMAKE_BINARY_DIR}/Experimental.vcxproj.filters | |||||
${CMAKE_BINARY_DIR}/INSTALL.vcxproj | |||||
${CMAKE_BINARY_DIR}/INSTALL.vcxproj.filters | |||||
${CMAKE_BINARY_DIR}/Makefile | |||||
${CMAKE_BINARY_DIR}/Nightly.vcxproj | |||||
${CMAKE_BINARY_DIR}/Nightly.vcxproj.filters | |||||
${CMAKE_BINARY_DIR}/NightlyMemoryCheck.vcxproj | |||||
${CMAKE_BINARY_DIR}/NightlyMemoryCheck.vcxproj.filters | |||||
${CMAKE_BINARY_DIR}/RUN_TESTS.vcxproj | |||||
${CMAKE_BINARY_DIR}/RUN_TESTS.vcxproj.filters | |||||
${CMAKE_BINARY_DIR}/Testing | |||||
${CMAKE_BINARY_DIR}/Win32 | |||||
${CMAKE_BINARY_DIR}/ZERO_CHECK.vcxproj | |||||
${CMAKE_BINARY_DIR}/ZERO_CHECK.vcxproj.filters | |||||
${CMAKE_BINARY_DIR}/check.vcxproj | |||||
${CMAKE_BINARY_DIR}/check.vcxproj.filters | |||||
${CMAKE_BINARY_DIR}/cmake_install.cmake | |||||
${CMAKE_BINARY_DIR}/dirent.sln | |||||
${CMAKE_BINARY_DIR}/distclean.vcxproj | |||||
${CMAKE_BINARY_DIR}/distclean.vcxproj.filters | |||||
${CMAKE_BINARY_DIR}/find | |||||
${CMAKE_BINARY_DIR}/find.dir | |||||
${CMAKE_BINARY_DIR}/find.vcxproj | |||||
${CMAKE_BINARY_DIR}/find.vcxproj.filters | |||||
${CMAKE_BINARY_DIR}/locate | |||||
${CMAKE_BINARY_DIR}/locate.dir | |||||
${CMAKE_BINARY_DIR}/locate.vcxproj | |||||
${CMAKE_BINARY_DIR}/locate.vcxproj.filters | |||||
${CMAKE_BINARY_DIR}/ls | |||||
${CMAKE_BINARY_DIR}/ls.dir | |||||
${CMAKE_BINARY_DIR}/ls.vcxproj | |||||
${CMAKE_BINARY_DIR}/ls.vcxproj.filters | |||||
${CMAKE_BINARY_DIR}/t-compile | |||||
${CMAKE_BINARY_DIR}/t-compile.dir | |||||
${CMAKE_BINARY_DIR}/t-compile.vcxproj | |||||
${CMAKE_BINARY_DIR}/t-compile.vcxproj.filters | |||||
${CMAKE_BINARY_DIR}/t-dirent | |||||
${CMAKE_BINARY_DIR}/t-dirent.dir | |||||
${CMAKE_BINARY_DIR}/t-dirent.vcxproj | |||||
${CMAKE_BINARY_DIR}/t-dirent.vcxproj.filters | |||||
${CMAKE_BINARY_DIR}/updatedb | |||||
${CMAKE_BINARY_DIR}/updatedb.dir | |||||
${CMAKE_BINARY_DIR}/updatedb.vcxproj | |||||
${CMAKE_BINARY_DIR}/updatedb.vcxproj.filters | |||||
) | |||||
foreach (file ${cmake_generated}) | |||||
if (EXISTS ${file}) | |||||
file (REMOVE_RECURSE ${file}) | |||||
endif() | |||||
endforeach (file) |
@ -1,85 +0,0 @@ | |||||
/* | |||||
* Output contents of a file. | |||||
* | |||||
* Compile this file with Visual Studio and run the produced command in | |||||
* console with a file name argument. For example, command | |||||
* | |||||
* cat include\dirent.h | |||||
* | |||||
* will output the dirent.h to screen. | |||||
* | |||||
* 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 output_file (const char *fn); | |||||
int | |||||
main( | |||||
int argc, char *argv[]) | |||||
{ | |||||
int i; | |||||
/* Select default locale */ | |||||
setlocale (LC_ALL, ""); | |||||
/* Require at least one file */ | |||||
if (argc == 1) { | |||||
fprintf (stderr, "Usage: cat filename\n"); | |||||
return EXIT_FAILURE; | |||||
} | |||||
/* For each file name argument in command line */ | |||||
i = 1; | |||||
while (i < argc) { | |||||
output_file (argv[i]); | |||||
i++; | |||||
} | |||||
return EXIT_SUCCESS; | |||||
} | |||||
/* | |||||
* Output file to screen | |||||
*/ | |||||
static void | |||||
output_file( | |||||
const char *fn) | |||||
{ | |||||
FILE *fp; | |||||
/* Open file */ | |||||
fp = fopen (fn, "r"); | |||||
if (fp != NULL) { | |||||
size_t n; | |||||
char buffer[4096]; | |||||
/* Output file to screen */ | |||||
do { | |||||
/* Read some bytes from file */ | |||||
n = fread (buffer, 1, 4096, fp); | |||||
/* Output bytes to screen */ | |||||
fwrite (buffer, 1, n, stdout); | |||||
} while (n != 0); | |||||
/* Close file */ | |||||
fclose (fp); | |||||
} else { | |||||
/* Could not open directory */ | |||||
fprintf (stderr, "Cannot open %s (%s)\n", fn, strerror (errno)); | |||||
exit (EXIT_FAILURE); | |||||
} | |||||
} |
@ -1,147 +0,0 @@ | |||||
/* | |||||
* An example demonstrating recursive directory traversal. | |||||
* | |||||
* 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); | |||||
int | |||||
main( | |||||
int argc, char *argv[]) | |||||
{ | |||||
int i; | |||||
int ok; | |||||
/* Select default locale */ | |||||
setlocale (LC_ALL, ""); | |||||
/* For each directory in command line */ | |||||
i = 1; | |||||
while (i < argc) { | |||||
ok = find_directory (argv[i]); | |||||
if (!ok) { | |||||
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) | |||||
{ | |||||
DIR *dir; | |||||
char buffer[PATH_MAX + 2]; | |||||
char *p = buffer; | |||||
const char *src; | |||||
char *end = &buffer[PATH_MAX]; | |||||
int ok; | |||||
/* Copy directory name to buffer */ | |||||
src = dirname; | |||||
while (p < end && *src != '\0') { | |||||
*p++ = *src++; | |||||
} | |||||
*p = '\0'; | |||||
/* Open directory stream */ | |||||
dir = opendir (dirname); | |||||
if (dir != NULL) { | |||||
struct dirent *ent; | |||||
/* Print all files and directories within the directory */ | |||||
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); | |||||
ok = 1; | |||||
} else { | |||||
/* Could not open directory */ | |||||
fprintf (stderr, "Cannot open %s (%s)\n", dirname, strerror (errno)); | |||||
ok = 0; | |||||
} | |||||
return ok; | |||||
} |
@ -1,281 +0,0 @@ | |||||
/* | |||||
* A file look-up utility to complement updatedb | |||||
* | |||||
* Compile and run updatedb command first to create locate.db file. Then, | |||||
* compile this program with Visual Studio and run the program in console with | |||||
* a file name argument. For example, the command | |||||
* | |||||
* locate autoexec | |||||
* | |||||
* might output something like | |||||
* | |||||
* c:/AUTOEXEC.BAT | |||||
* c:/WINDOWS/repair/autoexec.nt | |||||
* c:/WINDOWS/system32/AUTOEXEC.NT | |||||
* | |||||
* Be ware that this file uses wide-character API which is not compatible | |||||
* with Linux or other major Unixes. | |||||
* | |||||
* 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 | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <wchar.h> | |||||
#ifdef WIN32 | |||||
# include <io.h> | |||||
# include <fcntl.h> | |||||
#endif | |||||
#include <dirent.h> | |||||
/* File name and location of database file */ | |||||
#define DB_LOCATION L"locate.db" | |||||
/* Forward-decl */ | |||||
static int db_locate (const wchar_t *pattern); | |||||
static int db_match (const wchar_t *fn, const wchar_t *pattern); | |||||
static void db_open (void); | |||||
static void db_close (void); | |||||
static int db_read (wchar_t *buffer, size_t max); | |||||
/* Module local variables */ | |||||
static FILE *db = NULL; | |||||
int | |||||
main( | |||||
int argc, char *argv[]) | |||||
{ | |||||
#ifdef WIN32 | |||||
int i; | |||||
/* Prepare for unicode output */ | |||||
_setmode (_fileno (stdout), _O_U16TEXT); | |||||
/* For each pattern in command line */ | |||||
i = 1; | |||||
while (i < argc) { | |||||
wchar_t buffer[PATH_MAX + 1]; | |||||
errno_t error; | |||||
size_t n; | |||||
int count = 0; | |||||
/* Convert ith argument to wide-character string */ | |||||
error = mbstowcs_s (&n, buffer, PATH_MAX, argv[i], _TRUNCATE); | |||||
if (!error) { | |||||
/* Find files matching pattern */ | |||||
count = db_locate (buffer); | |||||
/* Output warning if string is not found */ | |||||
if (count == 0) { | |||||
wprintf (L"%s not found\n", buffer); | |||||
} | |||||
} | |||||
i++; | |||||
} | |||||
if (argc < 2) { | |||||
wprintf (L"Usage: locate pattern\n"); | |||||
exit (EXIT_FAILURE); | |||||
} | |||||
#else | |||||
printf ("locate only works on Microsoft Windows\n"); | |||||
#endif | |||||
return EXIT_SUCCESS; | |||||
} | |||||
/* Match pattern against files in locate.db file */ | |||||
static int | |||||
db_locate( | |||||
const wchar_t *pattern) | |||||
{ | |||||
int count = 0; | |||||
#ifdef WIN32 | |||||
wchar_t buffer[PATH_MAX + 1]; | |||||
/* Open locate.db for read */ | |||||
db_open (); | |||||
/* Read one directory and file name at a time from database file */ | |||||
while (db_read (buffer, PATH_MAX + 1)) { | |||||
/* See if file name in buffer matches the search pattern */ | |||||
if (db_match (buffer, pattern)) { | |||||
/* Match found => output file name and path */ | |||||
wprintf (L"%s\n", buffer); | |||||
count++; | |||||
} | |||||
} | |||||
db_close (); | |||||
#endif | |||||
return count; | |||||
} | |||||
/* Match pattern against file name */ | |||||
static int | |||||
db_match( | |||||
const wchar_t *fn, const wchar_t *pattern) | |||||
{ | |||||
int found = 0; | |||||
#ifdef WIN32 | |||||
wchar_t *p; | |||||
wchar_t base[PATH_MAX + 1]; | |||||
wchar_t patt[PATH_MAX + 1]; | |||||
int i; | |||||
int done = 0; | |||||
/* Locate zero-terminator from fn */ | |||||
p = wcschr (fn, '\0'); | |||||
/* Find base name from buffer */ | |||||
while (fn < p && !done) { | |||||
switch (p[-1]) { | |||||
case ':': | |||||
case '/': | |||||
case '\\': | |||||
/* Final path separator found */ | |||||
done = 1; | |||||
break; | |||||
default: | |||||
/* No path separator yet */ | |||||
p--; | |||||
} | |||||
} | |||||
/* Convert base name to lower case */ | |||||
i = 0; | |||||
while (i < PATH_MAX && p[i] != '\0') { | |||||
base[i] = towlower (p[i]); | |||||
i++; | |||||
} | |||||
base[i] = '\0'; | |||||
/* Convert search pattern to lower case */ | |||||
i = 0; | |||||
while (i < PATH_MAX && pattern[i] != '\0') { | |||||
patt[i] = towlower (pattern[i]); | |||||
i++; | |||||
} | |||||
patt[i] = '\0'; | |||||
/* See if file name matches pattern */ | |||||
if (wcsstr (base, patt) != NULL) { | |||||
found = 1; | |||||
} else { | |||||
found = 0; | |||||
} | |||||
#endif | |||||
return found; | |||||
} | |||||
/* | |||||
* Read line from locate.db. This function is same as fgetws() except | |||||
* that new-line at the end of line is not included. | |||||
*/ | |||||
static int | |||||
db_read( | |||||
wchar_t *buffer, size_t max) | |||||
{ | |||||
int ok = 0; | |||||
#ifdef WIN32 | |||||
size_t i = 0; | |||||
wchar_t c; | |||||
int done = 0; | |||||
do { | |||||
/* Read wide-character from stream */ | |||||
if (db) { | |||||
c = fgetwc (db); | |||||
} else { | |||||
wprintf (L"Database not open\n"); | |||||
exit (EXIT_SUCCESS); | |||||
} | |||||
/* Determine how to process character */ | |||||
switch (c) { | |||||
case '\r': | |||||
/* Ignore, should be handled by run-time libraries */ | |||||
/*NOP*/; | |||||
break; | |||||
case '\n': | |||||
/* End of string => return file name and true */ | |||||
done = 1; | |||||
ok = 1; | |||||
break; | |||||
case /*EOF*/WEOF: | |||||
/* End of file */ | |||||
done = 1; | |||||
if (i == 0) { | |||||
/* No data in buffer => return false to indicate EOF */ | |||||
ok = 0; | |||||
} else { | |||||
/* Data in buffer => return true */ | |||||
ok = 1; | |||||
} | |||||
break; | |||||
default: | |||||
/* Store character */ | |||||
if (i < max - 1) { | |||||
buffer[i++] = c; | |||||
} else { | |||||
buffer[max - 1] = '\0'; | |||||
wprintf (L"Buffer too small: %s", buffer); | |||||
exit (EXIT_FAILURE); | |||||
} | |||||
} | |||||
} while (!done); | |||||
/* Zero-terminate buffer */ | |||||
buffer[i] = '\0'; | |||||
#endif | |||||
return ok; | |||||
} | |||||
/* Open database file locate.db */ | |||||
static void | |||||
db_open( | |||||
void) | |||||
{ | |||||
#ifdef WIN32 | |||||
if (db == NULL) { | |||||
errno_t error; | |||||
/* Open file for writing */ | |||||
error = _wfopen_s (&db, DB_LOCATION, L"rt, ccs=UNICODE"); | |||||
if (error) { | |||||
wprintf (L"Cannot open %s\n", DB_LOCATION); | |||||
exit (EXIT_FAILURE); | |||||
} | |||||
} | |||||
#endif | |||||
} | |||||
/* Close database file */ | |||||
static void | |||||
db_close( | |||||
void) | |||||
{ | |||||
if (db) { | |||||
fclose (db); | |||||
db = NULL; | |||||
} | |||||
} |
@ -1,103 +0,0 @@ | |||||
/* | |||||
* An example demonstrating basic directory listing. | |||||
* | |||||
* 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); | |||||
int | |||||
main( | |||||
int argc, char *argv[]) | |||||
{ | |||||
int i; | |||||
/* Select default locale */ | |||||
setlocale (LC_ALL, ""); | |||||
/* For each directory in command line */ | |||||
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) | |||||
{ | |||||
DIR *dir; | |||||
struct dirent *ent; | |||||
/* Open directory stream */ | |||||
dir = opendir (dirname); | |||||
if (dir != NULL) { | |||||
/* Print all files and directories within the directory */ | |||||
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); | |||||
} else { | |||||
/* Could not open directory */ | |||||
fprintf (stderr, "Cannot open %s (%s)\n", dirname, strerror (errno)); | |||||
exit (EXIT_FAILURE); | |||||
} | |||||
} |
@ -1,110 +0,0 @@ | |||||
/* | |||||
* Example program demonstrating the use of scandir function. | |||||
* | |||||
* Compile this file with Visual Studio and run the produced command in | |||||
* console with a directory name argument. For example, command | |||||
* | |||||
* scandir "c:\Program Files" | |||||
* | |||||
* might output something like | |||||
* | |||||
* ./ | |||||
* ../ | |||||
* 7-Zip/ | |||||
* Internet Explorer/ | |||||
* Microsoft Visual Studio 9.0/ | |||||
* Microsoft.NET/ | |||||
* Mozilla Firefox/ | |||||
* | |||||
* 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); | |||||
int | |||||
main( | |||||
int argc, char *argv[]) | |||||
{ | |||||
int i; | |||||
/* Select default locale */ | |||||
setlocale (LC_ALL, ""); | |||||
/* For each directory in command line */ | |||||
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) | |||||
{ | |||||
struct dirent **files; | |||||
int i; | |||||
int n; | |||||
/* Scan files in directory */ | |||||
n = scandir (dirname, &files, NULL, alphasort); | |||||
if (n >= 0) { | |||||
/* Loop through file names */ | |||||
for (i = 0; i < n; i++) { | |||||
struct dirent *ent; | |||||
/* Get pointer to file entry */ | |||||
ent = files[i]; | |||||
/* Output file name */ | |||||
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); | |||||
} | |||||
} | |||||
/* Release file names */ | |||||
for (i = 0; i < n; i++) { | |||||
free (files[i]); | |||||
} | |||||
free (files); | |||||
} else { | |||||
fprintf (stderr, "Cannot open %s (%s)\n", dirname, strerror (errno)); | |||||
exit (EXIT_FAILURE); | |||||
} | |||||
} |
@ -1,232 +0,0 @@ | |||||
/* | |||||
* An example demonstrating wide-character functions | |||||
* | |||||
* Compile this file with Visual Studio and run the produced command in | |||||
* console with a directory name argument. For example, command | |||||
* | |||||
* updatedb C:\ | |||||
* | |||||
* will produce the file locate.db with one file name per line 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 | |||||
* | |||||
* Be ware that this file uses wide-character API which is not compatible | |||||
* with Linux or other major Unixes. | |||||
* | |||||
* 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 | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <wchar.h> | |||||
#ifdef WIN32 | |||||
# include <io.h> | |||||
# include <fcntl.h> | |||||
#endif | |||||
#include <dirent.h> | |||||
/* File name and location of database file */ | |||||
#define DB_LOCATION L"locate.db" | |||||
/* Forward-decl */ | |||||
static int update_directory (const wchar_t *dirname); | |||||
static void db_open (void); | |||||
static void db_close (void); | |||||
static void db_store (const wchar_t *dirname); | |||||
/* Module local variables */ | |||||
static FILE *db = NULL; | |||||
int | |||||
main( | |||||
int argc, char *argv[]) | |||||
{ | |||||
#ifdef WIN32 | |||||
int i; | |||||
int ok; | |||||
/* Prepare for unicode output */ | |||||
_setmode (_fileno (stdout), _O_U16TEXT); | |||||
/* Open locate.db */ | |||||
db_open (); | |||||
/* For each directory in command line */ | |||||
i = 1; | |||||
while (i < argc) { | |||||
wchar_t buffer[PATH_MAX + 1]; | |||||
errno_t error; | |||||
size_t n; | |||||
/* Convert ith argument to wide-character string */ | |||||
error = mbstowcs_s (&n, buffer, PATH_MAX, argv[i], _TRUNCATE); | |||||
if (!error) { | |||||
/* Scan directory for files */ | |||||
ok = update_directory (buffer); | |||||
if (!ok) { | |||||
wprintf (L"Cannot open directory %s\n", buffer); | |||||
exit (EXIT_FAILURE); | |||||
} | |||||
} | |||||
i++; | |||||
} | |||||
/* Use current working directory if no arguments on command line */ | |||||
if (argc == 1) { | |||||
update_directory (L"."); | |||||
} | |||||
db_close (); | |||||
#else | |||||
printf ("updatedb only works on Microsoft Windows\n"); | |||||
#endif | |||||
return EXIT_SUCCESS; | |||||
} | |||||
/* Find files recursively */ | |||||
static int | |||||
update_directory( | |||||
const wchar_t *dirname) | |||||
{ | |||||
int ok = 0; | |||||
#ifdef WIN32 | |||||
_WDIR *dir; | |||||
wchar_t buffer[PATH_MAX + 2]; | |||||
wchar_t *p = buffer; | |||||
const wchar_t *src; | |||||
wchar_t *end = &buffer[PATH_MAX]; | |||||
/* Copy directory name to buffer */ | |||||
src = dirname; | |||||
while (p < end && *src != '\0') { | |||||
*p++ = *src++; | |||||
} | |||||
*p = '\0'; | |||||
/* Open directory stream */ | |||||
dir = _wopendir (dirname); | |||||
if (dir != NULL) { | |||||
struct _wdirent *ent; | |||||
/* Print all files and directories within the directory */ | |||||
while ((ent = _wreaddir (dir)) != NULL) { | |||||
wchar_t *q = p; | |||||
wchar_t 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_REG: | |||||
/* Store file name */ | |||||
db_store (buffer); | |||||
break; | |||||
case DT_DIR: | |||||
/* Scan sub-directory recursively */ | |||||
if (wcscmp (ent->d_name, L".") != 0 | |||||
&& wcscmp (ent->d_name, L"..") != 0) { | |||||
update_directory (buffer); | |||||
} | |||||
break; | |||||
default: | |||||
/* Do not device entries */ | |||||
/*NOP*/; | |||||
} | |||||
} | |||||
wclosedir (dir); | |||||
ok = 1; | |||||
} else { | |||||
/* Cannot open directory */ | |||||
ok = 0; | |||||
} | |||||
#endif | |||||
return ok; | |||||
} | |||||
/* Store file name to locate.db */ | |||||
static void | |||||
db_store( | |||||
const wchar_t *dirname) | |||||
{ | |||||
#ifdef WIN32 | |||||
if (db) { | |||||
/* Output line to file */ | |||||
fwprintf (db, L"%s\n", dirname); | |||||
} else { | |||||
wprintf (L"Database not open\n"); | |||||
exit (EXIT_FAILURE); | |||||
} | |||||
#endif | |||||
} | |||||
/* Open database file locate.db */ | |||||
static void | |||||
db_open( | |||||
void) | |||||
{ | |||||
#ifdef WIN32 | |||||
if (db == NULL) { | |||||
errno_t error; | |||||
/* Open file for writing */ | |||||
error = _wfopen_s (&db, DB_LOCATION, L"wt, ccs=UNICODE"); | |||||
if (error) { | |||||
wprintf (L"Cannot open %s\n", DB_LOCATION); | |||||
exit (EXIT_FAILURE); | |||||
} | |||||
} | |||||
#endif | |||||
} | |||||
/* Close database file */ | |||||
static void | |||||
db_close( | |||||
void) | |||||
{ | |||||
if (db) { | |||||
fclose (db); | |||||
db = NULL; | |||||
} | |||||
} |
@ -1,3 +0,0 @@ | |||||
This file ensures that the directory dir will be created accordingly when | |||||
you unzip dirent to your computer. The directory itself is needed by the | |||||
test program t-dirent. |
@ -1 +0,0 @@ | |||||
This dummy file is needed by the test program t-dirent. |
@ -1,2 +0,0 @@ | |||||
This directory contains some random files for the t-scandir test program. The | |||||
files are empty and only the file names matter. |
@ -1,47 +0,0 @@ | |||||
/* | |||||
* Test program to make sure that dirent compiles cleanly with winsock. | |||||
* | |||||
* 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 | |||||
*/ | |||||
#include <dirent.h> | |||||
#ifdef WIN32 | |||||
# include <winsock2.h> | |||||
# include <ws2tcpip.h> | |||||
#endif | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
int | |||||
main( | |||||
int argc, char *argv[]) | |||||
{ | |||||
struct dirent *dirp = NULL; | |||||
(void) argc; | |||||
(void) argv; | |||||
#ifdef _DIRENT_HAVE_D_TYPE | |||||
printf ("Has d_type\n"); | |||||
#endif | |||||
#ifdef _DIRENT_HAVE_D_NAMLEN | |||||
printf ("Has d_namlen\n"); | |||||
#endif | |||||
#ifdef _D_EXACT_NAMLEN | |||||
printf ("Has _D_EXACT_NAMLEN\n"); | |||||
#endif | |||||
#ifdef _D_ALLOC_NAMLEN | |||||
printf ("Has _D_ALLOC_NAMLEN\n"); | |||||
#endif | |||||
#ifdef _D_ALLOC_NAMLEN | |||||
printf ("Has _D_ALLOC_NAMLEN\n"); | |||||
#endif | |||||
printf ("Length of d_name with terminator: %d\n", | |||||
(int) sizeof (dirp->d_name)); | |||||
printf ("OK\n"); | |||||
return EXIT_SUCCESS; | |||||
} |
@ -1,160 +0,0 @@ | |||||
/* | |||||
* Test program to make sure that dirent compiles cleanly with 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 | |||||
*/ | |||||
#include <iostream> | |||||
#include <string.h> | |||||
#include <dirent.h> | |||||
#include <assert.h> | |||||
using namespace std; | |||||
/* Filter and sort functions */ | |||||
static int only_readme (const struct dirent *entry); | |||||
int | |||||
main( | |||||
int argc, char *argv[]) | |||||
{ | |||||
(void) argc; | |||||
(void) argv; | |||||
/* Basic directory retrieval */ | |||||
{ | |||||
DIR *dir; | |||||
struct dirent *ent; | |||||
int found = 0; | |||||
/* Open directory */ | |||||
dir = opendir ("tests/1"); | |||||
if (dir == NULL) { | |||||
cerr << "Directory tests/1 not found" << endl; | |||||
abort (); | |||||
} | |||||
/* Read entries */ | |||||
while ((ent = readdir (dir)) != NULL) { | |||||
/* Check each file */ | |||||
if (strcmp (ent->d_name, ".") == 0) { | |||||
/* Directory itself */ | |||||
#ifdef _DIRENT_HAVE_D_TYPE | |||||
assert (ent->d_type == DT_DIR); | |||||
#endif | |||||
#ifdef _DIRENT_HAVE_D_NAMLEN | |||||
assert (ent->d_namlen == 1); | |||||
#endif | |||||
#ifdef _D_EXACT_NAMLEN | |||||
assert (_D_EXACT_NAMLEN(ent) == 1); | |||||
#endif | |||||
#ifdef _D_ALLOC_NAMLEN | |||||
assert (_D_ALLOC_NAMLEN(ent) > 1); | |||||
#endif | |||||
found += 1; | |||||
} else if (strcmp (ent->d_name, "..") == 0) { | |||||
/* Parent directory */ | |||||
#ifdef _DIRENT_HAVE_D_TYPE | |||||
assert (ent->d_type == DT_DIR); | |||||
#endif | |||||
#ifdef _DIRENT_HAVE_D_NAMLEN | |||||
assert (ent->d_namlen == 2); | |||||
#endif | |||||
#ifdef _D_EXACT_NAMLEN | |||||
assert (_D_EXACT_NAMLEN(ent) == 2); | |||||
#endif | |||||
#ifdef _D_ALLOC_NAMLEN | |||||
assert (_D_ALLOC_NAMLEN(ent) > 2); | |||||
#endif | |||||
found += 2; | |||||
} else if (strcmp (ent->d_name, "file") == 0) { | |||||
/* Regular file */ | |||||
#ifdef _DIRENT_HAVE_D_TYPE | |||||
assert (ent->d_type == DT_REG); | |||||
#endif | |||||
#ifdef _DIRENT_HAVE_D_NAMLEN | |||||
assert (ent->d_namlen == 4); | |||||
#endif | |||||
#ifdef _D_EXACT_NAMLEN | |||||
assert (_D_EXACT_NAMLEN(ent) == 4); | |||||
#endif | |||||
#ifdef _D_ALLOC_NAMLEN | |||||
assert (_D_ALLOC_NAMLEN(ent) > 4); | |||||
#endif | |||||
found += 4; | |||||
} else if (strcmp (ent->d_name, "dir") == 0) { | |||||
/* Just a directory */ | |||||
#ifdef _DIRENT_HAVE_D_TYPE | |||||
assert (ent->d_type == DT_DIR); | |||||
#endif | |||||
#ifdef _DIRENT_HAVE_D_NAMLEN | |||||
assert (ent->d_namlen == 3); | |||||
#endif | |||||
#ifdef _D_EXACT_NAMLEN | |||||
assert (_D_EXACT_NAMLEN(ent) == 3); | |||||
#endif | |||||
#ifdef _D_ALLOC_NAMLEN | |||||
assert (_D_ALLOC_NAMLEN(ent) > 3); | |||||
#endif | |||||
found += 8; | |||||
} else { | |||||
/* Other file */ | |||||
cerr << "Unexpected file " << ent->d_name << endl; | |||||
abort (); | |||||
} | |||||
} | |||||
/* Make sure that all files were found */ | |||||
assert (found == 0xf); | |||||
closedir (dir); | |||||
} | |||||
/* Basic scan with simple filter function */ | |||||
{ | |||||
struct dirent **files; | |||||
int n; | |||||
int i; | |||||
/* Read directory entries */ | |||||
n = scandir ("tests/3", &files, only_readme, alphasort); | |||||
assert (n == 1); | |||||
/* Make sure that the filter works */ | |||||
assert (strcmp (files[0]->d_name, "README.txt") == 0); | |||||
/* Release file names */ | |||||
for (i = 0; i < n; i++) { | |||||
free (files[i]); | |||||
} | |||||
free (files); | |||||
} | |||||
cout << "OK" << endl; | |||||
return EXIT_SUCCESS; | |||||
} | |||||
/* Only pass README.txt file */ | |||||
static int | |||||
only_readme (const struct dirent *entry) | |||||
{ | |||||
int pass; | |||||
if (strcmp (entry->d_name, "README.txt") == 0) { | |||||
pass = 1; | |||||
} else { | |||||
pass = 0; | |||||
} | |||||
return pass; | |||||
} |
@ -1,633 +0,0 @@ | |||||
/* | |||||
* A test program to make sure that dirent works correctly. | |||||
* | |||||
* 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 | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#ifdef _MSC_VER | |||||
# include <direct.h> | |||||
# define chdir(x) _chdir(x) | |||||
#else | |||||
# include <unistd.h> | |||||
#endif | |||||
#include <sys/stat.h> | |||||
#include <dirent.h> | |||||
#include <errno.h> | |||||
#undef NDEBUG | |||||
#include <assert.h> | |||||
int | |||||
main( | |||||
int argc, char *argv[]) | |||||
{ | |||||
(void) argc; | |||||
(void) argv; | |||||
/* File type macros */ | |||||
{ | |||||
assert (DTTOIF(DT_REG) == S_IFREG); | |||||
assert (DTTOIF(DT_DIR) == S_IFDIR); | |||||
assert (DTTOIF(DT_FIFO) == S_IFIFO); | |||||
assert (DTTOIF(DT_SOCK) == S_IFSOCK); | |||||
assert (DTTOIF(DT_CHR) == S_IFCHR); | |||||
assert (DTTOIF(DT_BLK) == S_IFBLK); | |||||
assert (IFTODT(S_IFREG) == DT_REG); | |||||
assert (IFTODT(S_IFDIR) == DT_DIR); | |||||
assert (IFTODT(S_IFIFO) == DT_FIFO); | |||||
assert (IFTODT(S_IFSOCK) == DT_SOCK); | |||||
assert (IFTODT(S_IFCHR) == DT_CHR); | |||||
assert (IFTODT(S_IFBLK) == DT_BLK); | |||||
} | |||||
/* Basic directory retrieval */ | |||||
{ | |||||
DIR *dir; | |||||
struct dirent *ent; | |||||
int found = 0; | |||||
/* Open directory */ | |||||
dir = opendir ("tests/1"); | |||||
if (dir == NULL) { | |||||
fprintf (stderr, "Directory tests/1 not found\n"); | |||||
abort (); | |||||
} | |||||
/* Read entries */ | |||||
while ((ent = readdir (dir)) != NULL) { | |||||
/* Check each file */ | |||||
if (strcmp (ent->d_name, ".") == 0) { | |||||
/* Directory itself */ | |||||
#ifdef _DIRENT_HAVE_D_TYPE | |||||
assert (ent->d_type == DT_DIR); | |||||
#endif | |||||
#ifdef _DIRENT_HAVE_D_NAMLEN | |||||
assert (ent->d_namlen == 1); | |||||
#endif | |||||
#ifdef _D_EXACT_NAMLEN | |||||
assert (_D_EXACT_NAMLEN(ent) == 1); | |||||
#endif | |||||
#ifdef _D_ALLOC_NAMLEN | |||||
assert (_D_ALLOC_NAMLEN(ent) > 1); | |||||
#endif | |||||
found += 1; | |||||
} else if (strcmp (ent->d_name, "..") == 0) { | |||||
/* Parent directory */ | |||||
#ifdef _DIRENT_HAVE_D_TYPE | |||||
assert (ent->d_type == DT_DIR); | |||||
#endif | |||||
#ifdef _DIRENT_HAVE_D_NAMLEN | |||||
assert (ent->d_namlen == 2); | |||||
#endif | |||||
#ifdef _D_EXACT_NAMLEN | |||||
assert (_D_EXACT_NAMLEN(ent) == 2); | |||||
#endif | |||||
#ifdef _D_ALLOC_NAMLEN | |||||
assert (_D_ALLOC_NAMLEN(ent) > 2); | |||||
#endif | |||||
found += 2; | |||||
} else if (strcmp (ent->d_name, "file") == 0) { | |||||
/* Regular file */ | |||||
#ifdef _DIRENT_HAVE_D_TYPE | |||||
assert (ent->d_type == DT_REG); | |||||
#endif | |||||
#ifdef _DIRENT_HAVE_D_NAMLEN | |||||
assert (ent->d_namlen == 4); | |||||
#endif | |||||
#ifdef _D_EXACT_NAMLEN | |||||
assert (_D_EXACT_NAMLEN(ent) == 4); | |||||
#endif | |||||
#ifdef _D_ALLOC_NAMLEN | |||||
assert (_D_ALLOC_NAMLEN(ent) > 4); | |||||
#endif | |||||
found += 4; | |||||
} else if (strcmp (ent->d_name, "dir") == 0) { | |||||
/* Just a directory */ | |||||
#ifdef _DIRENT_HAVE_D_TYPE | |||||
assert (ent->d_type == DT_DIR); | |||||
#endif | |||||
#ifdef _DIRENT_HAVE_D_NAMLEN | |||||
assert (ent->d_namlen == 3); | |||||
#endif | |||||
#ifdef _D_EXACT_NAMLEN | |||||
assert (_D_EXACT_NAMLEN(ent) == 3); | |||||
#endif | |||||
#ifdef _D_ALLOC_NAMLEN | |||||
assert (_D_ALLOC_NAMLEN(ent) > 3); | |||||
#endif | |||||
found += 8; | |||||
} else { | |||||
/* Other file */ | |||||
fprintf (stderr, "Unexpected file %s\n", ent->d_name); | |||||
abort (); | |||||
} | |||||
} | |||||
/* Make sure that all files were found */ | |||||
assert (found == 0xf); | |||||
closedir (dir); | |||||
} | |||||
/* Function opendir() fails if directory doesn't exist */ | |||||
{ | |||||
DIR *dir; | |||||
/* Open directory */ | |||||
dir = opendir ("tests/invalid"); | |||||
assert (dir == NULL); | |||||
assert (errno == ENOENT); | |||||
} | |||||
/* Function opendir() fails if pathname is really a file */ | |||||
{ | |||||
DIR *dir; | |||||
/* Open directory */ | |||||
dir = opendir ("tests/1/file"); | |||||
assert (dir == NULL); | |||||
assert (errno == ENOTDIR); | |||||
} | |||||
/* Function opendir() fails if pathname is a zero-length string */ | |||||
{ | |||||
DIR *dir; | |||||
/* Open directory */ | |||||
dir = opendir (""); | |||||
assert (dir == NULL); | |||||
assert (errno == ENOENT); | |||||
} | |||||
/* Rewind of directory stream */ | |||||
{ | |||||
DIR *dir; | |||||
struct dirent *ent; | |||||
int found = 0; | |||||
/* Open directory */ | |||||
dir = opendir ("tests/1"); | |||||
assert (dir != NULL); | |||||
/* Read entries */ | |||||
while ((ent = readdir (dir)) != NULL) { | |||||
/* Check each file */ | |||||
if (strcmp (ent->d_name, ".") == 0) { | |||||
/* Directory itself */ | |||||
found += 1; | |||||
} else if (strcmp (ent->d_name, "..") == 0) { | |||||
/* Parent directory */ | |||||
found += 2; | |||||
} else if (strcmp (ent->d_name, "file") == 0) { | |||||
/* Regular file */ | |||||
found += 4; | |||||
} else if (strcmp (ent->d_name, "dir") == 0) { | |||||
/* Just a directory */ | |||||
found += 8; | |||||
} else { | |||||
/* Other file */ | |||||
fprintf (stderr, "Unexpected file %s\n", ent->d_name); | |||||
abort (); | |||||
} | |||||
} | |||||
/* Make sure that all files were found */ | |||||
assert (found == 0xf); | |||||
/* Rewind stream and read entries again */ | |||||
rewinddir (dir); | |||||
found = 0; | |||||
/* Read entries */ | |||||
while ((ent = readdir (dir)) != NULL) { | |||||
/* Check each file */ | |||||
if (strcmp (ent->d_name, ".") == 0) { | |||||
/* Directory itself */ | |||||
found += 1; | |||||
} else if (strcmp (ent->d_name, "..") == 0) { | |||||
/* Parent directory */ | |||||
found += 2; | |||||
} else if (strcmp (ent->d_name, "file") == 0) { | |||||
/* Regular file */ | |||||
found += 4; | |||||
} else if (strcmp (ent->d_name, "dir") == 0) { | |||||
/* Just a directory */ | |||||
found += 8; | |||||
} else { | |||||
/* Other file */ | |||||
fprintf (stderr, "Unexpected file %s\n", ent->d_name); | |||||
abort (); | |||||
} | |||||
} | |||||
/* Make sure that all files were found */ | |||||
assert (found == 0xf); | |||||
closedir (dir); | |||||
} | |||||
/* Rewind with intervening change of working directory */ | |||||
{ | |||||
DIR *dir; | |||||
struct dirent *ent; | |||||
int found = 0; | |||||
int errorcode; | |||||
/* Open directory */ | |||||
dir = opendir ("tests/1"); | |||||
assert (dir != NULL); | |||||
/* Read entries */ | |||||
while ((ent = readdir (dir)) != NULL) { | |||||
/* Check each file */ | |||||
if (strcmp (ent->d_name, ".") == 0) { | |||||
/* Directory itself */ | |||||
found += 1; | |||||
} else if (strcmp (ent->d_name, "..") == 0) { | |||||
/* Parent directory */ | |||||
found += 2; | |||||
} else if (strcmp (ent->d_name, "file") == 0) { | |||||
/* Regular file */ | |||||
found += 4; | |||||
} else if (strcmp (ent->d_name, "dir") == 0) { | |||||
/* Just a directory */ | |||||
found += 8; | |||||
} else { | |||||
/* Other file */ | |||||
fprintf (stderr, "Unexpected file %s\n", ent->d_name); | |||||
abort (); | |||||
} | |||||
} | |||||
/* Make sure that all files were found */ | |||||
assert (found == 0xf); | |||||
/* Change working directory */ | |||||
errorcode = chdir ("tests"); | |||||
assert (errorcode == 0); | |||||
/* Rewind stream and read entries again */ | |||||
rewinddir (dir); | |||||
found = 0; | |||||
/* Read entries */ | |||||
while ((ent = readdir (dir)) != NULL) { | |||||
/* Check each file */ | |||||
if (strcmp (ent->d_name, ".") == 0) { | |||||
/* Directory itself */ | |||||
found += 1; | |||||
} else if (strcmp (ent->d_name, "..") == 0) { | |||||
/* Parent directory */ | |||||
found += 2; | |||||
} else if (strcmp (ent->d_name, "file") == 0) { | |||||
/* Regular file */ | |||||
found += 4; | |||||
} else if (strcmp (ent->d_name, "dir") == 0) { | |||||
/* Just a directory */ | |||||
found += 8; | |||||
} else { | |||||
/* Other file */ | |||||
fprintf (stderr, "Unexpected file %s\n", ent->d_name); | |||||
abort (); | |||||
} | |||||
} | |||||
/* Make sure that all files were found */ | |||||
assert (found == 0xf); | |||||
/* Restore working directory */ | |||||
errorcode = chdir (".."); | |||||
assert (errorcode == 0); | |||||
closedir (dir); | |||||
} | |||||
/* Long file name */ | |||||
{ | |||||
DIR *dir; | |||||
struct dirent *ent; | |||||
int found = 0; | |||||
/* Open directory */ | |||||
dir = opendir ("tests/2"); | |||||
if (dir == NULL) { | |||||
fprintf (stderr, "Directory tests/2 not found\n"); | |||||
abort (); | |||||
} | |||||
/* Read entries */ | |||||
while ((ent = readdir (dir)) != NULL) { | |||||
/* Check each file */ | |||||
if (strcmp (ent->d_name, ".") == 0) { | |||||
/* Directory itself */ | |||||
found += 1; | |||||
} else if (strcmp (ent->d_name, "..") == 0) { | |||||
/* Parent directory */ | |||||
found += 2; | |||||
} else if (strcmp (ent->d_name, "file.txt") == 0) { | |||||
/* Regular 8+3 filename */ | |||||
#ifdef _DIRENT_HAVE_D_TYPE | |||||
assert (ent->d_type == DT_REG); | |||||
#endif | |||||
#ifdef _DIRENT_HAVE_D_NAMLEN | |||||
assert (ent->d_namlen == 8); | |||||
#endif | |||||
#ifdef _D_EXACT_NAMLEN | |||||
assert (_D_EXACT_NAMLEN(ent) == 8); | |||||
#endif | |||||
#ifdef _D_ALLOC_NAMLEN | |||||
assert (_D_ALLOC_NAMLEN(ent) > 8); | |||||
#endif | |||||
found += 4; | |||||
} else if (strcmp (ent->d_name, "Testfile-1.2.3.dat") == 0) { | |||||
/* Long file name with multiple dots */ | |||||
#ifdef _DIRENT_HAVE_D_TYPE | |||||
assert (ent->d_type == DT_REG); | |||||
#endif | |||||
#ifdef _DIRENT_HAVE_D_NAMLEN | |||||
assert (ent->d_namlen == 18); | |||||
#endif | |||||
#ifdef _D_EXACT_NAMLEN | |||||
assert (_D_EXACT_NAMLEN(ent) == 18); | |||||
#endif | |||||
#ifdef _D_ALLOC_NAMLEN | |||||
assert (_D_ALLOC_NAMLEN(ent) > 18); | |||||
#endif | |||||
found += 8; | |||||
} else { | |||||
/* Other file */ | |||||
fprintf (stderr, "Unexpected file %s\n", ent->d_name); | |||||
abort (); | |||||
} | |||||
} | |||||
/* Make sure that all files were found */ | |||||
assert (found == 0xf); | |||||
closedir (dir); | |||||
} | |||||
/* Basic directory retrieval with readdir_r */ | |||||
{ | |||||
DIR *dir; | |||||
struct dirent ent[10]; | |||||
struct dirent *entry; | |||||
size_t i = 0; | |||||
size_t n = 0; | |||||
int found = 0; | |||||
/* Open directory */ | |||||
dir = opendir ("tests/1"); | |||||
if (dir == NULL) { | |||||
fprintf (stderr, "Directory tests/1 not found\n"); | |||||
abort (); | |||||
} | |||||
/* Read entries to table */ | |||||
while (readdir_r (dir, &ent[n], &entry) == /*OK*/0 && entry != 0) { | |||||
n++; | |||||
assert (n <= 4); | |||||
} | |||||
/* Make sure that we got all the files from directory */ | |||||
assert (n == 4); | |||||
/* Check entries in memory */ | |||||
for (i = 0; i < 4; i++) { | |||||
entry = &ent[i]; | |||||
/* Check each file */ | |||||
if (strcmp (entry->d_name, ".") == 0) { | |||||
/* Directory itself */ | |||||
#ifdef _DIRENT_HAVE_D_TYPE | |||||
assert (entry->d_type == DT_DIR); | |||||
#endif | |||||
#ifdef _DIRENT_HAVE_D_NAMLEN | |||||
assert (entry->d_namlen == 1); | |||||
#endif | |||||
#ifdef _D_EXACT_NAMLEN | |||||
assert (_D_EXACT_NAMLEN(entry) == 1); | |||||
#endif | |||||
#ifdef _D_ALLOC_NAMLEN | |||||
assert (_D_ALLOC_NAMLEN(entry) > 1); | |||||
#endif | |||||
found += 1; | |||||
} else if (strcmp (entry->d_name, "..") == 0) { | |||||
/* Parent directory */ | |||||
#ifdef _DIRENT_HAVE_D_TYPE | |||||
assert (entry->d_type == DT_DIR); | |||||
#endif | |||||
#ifdef _DIRENT_HAVE_D_NAMLEN | |||||
assert (entry->d_namlen == 2); | |||||
#endif | |||||
#ifdef _D_EXACT_NAMLEN | |||||
assert (_D_EXACT_NAMLEN(entry) == 2); | |||||
#endif | |||||
#ifdef _D_ALLOC_NAMLEN | |||||
assert (_D_ALLOC_NAMLEN(entry) > 2); | |||||
#endif | |||||
found += 2; | |||||
} else if (strcmp (entry->d_name, "file") == 0) { | |||||
/* Regular file */ | |||||
#ifdef _DIRENT_HAVE_D_TYPE | |||||
assert (entry->d_type == DT_REG); | |||||
#endif | |||||
#ifdef _DIRENT_HAVE_D_NAMLEN | |||||
assert (entry->d_namlen == 4); | |||||
#endif | |||||
#ifdef _D_EXACT_NAMLEN | |||||
assert (_D_EXACT_NAMLEN(entry) == 4); | |||||
#endif | |||||
#ifdef _D_ALLOC_NAMLEN | |||||
assert (_D_ALLOC_NAMLEN(entry) > 4); | |||||
#endif | |||||
found += 4; | |||||
} else if (strcmp (entry->d_name, "dir") == 0) { | |||||
/* Just a directory */ | |||||
#ifdef _DIRENT_HAVE_D_TYPE | |||||
assert (entry->d_type == DT_DIR); | |||||
#endif | |||||
#ifdef _DIRENT_HAVE_D_NAMLEN | |||||
assert (entry->d_namlen == 3); | |||||
#endif | |||||
#ifdef _D_EXACT_NAMLEN | |||||
assert (_D_EXACT_NAMLEN(entry) == 3); | |||||
#endif | |||||
#ifdef _D_ALLOC_NAMLEN | |||||
assert (_D_ALLOC_NAMLEN(entry) > 3); | |||||
#endif | |||||
found += 8; | |||||
} else { | |||||
/* Other file */ | |||||
fprintf (stderr, "Unexpected file %s\n", entry->d_name); | |||||
abort (); | |||||
} | |||||
} | |||||
/* Make sure that all files were found */ | |||||
assert (found == 0xf); | |||||
closedir (dir); | |||||
} | |||||
/* Basic directory retrieval with _wreaddir_r */ | |||||
#ifdef WIN32 | |||||
{ | |||||
_WDIR *dir; | |||||
struct _wdirent ent[10]; | |||||
struct _wdirent *entry; | |||||
size_t i = 0; | |||||
size_t n = 0; | |||||
int found = 0; | |||||
/* Open directory */ | |||||
dir = _wopendir (L"tests/1"); | |||||
if (dir == NULL) { | |||||
fprintf (stderr, "Directory tests/1 not found\n"); | |||||
abort (); | |||||
} | |||||
/* Read entries to table */ | |||||
while (_wreaddir_r (dir, &ent[n], &entry) == /*OK*/0 && entry != 0) { | |||||
n++; | |||||
assert (n <= 4); | |||||
} | |||||
/* Make sure that we got all the files from directory */ | |||||
assert (n == 4); | |||||
/* Check entries in memory */ | |||||
for (i = 0; i < 4; i++) { | |||||
entry = &ent[i]; | |||||
/* Check each file */ | |||||
if (wcscmp (entry->d_name, L".") == 0) { | |||||
/* Directory itself */ | |||||
#ifdef _DIRENT_HAVE_D_TYPE | |||||
assert (entry->d_type == DT_DIR); | |||||
#endif | |||||
#ifdef _DIRENT_HAVE_D_NAMLEN | |||||
assert (entry->d_namlen == 1); | |||||
#endif | |||||
#ifdef _D_EXACT_NAMLEN | |||||
assert (_D_EXACT_NAMLEN(entry) == 1); | |||||
#endif | |||||
#ifdef _D_ALLOC_NAMLEN | |||||
assert (_D_ALLOC_NAMLEN(entry) > 1); | |||||
#endif | |||||
found += 1; | |||||
} else if (wcscmp (entry->d_name, L"..") == 0) { | |||||
/* Parent directory */ | |||||
#ifdef _DIRENT_HAVE_D_TYPE | |||||
assert (entry->d_type == DT_DIR); | |||||
#endif | |||||
#ifdef _DIRENT_HAVE_D_NAMLEN | |||||
assert (entry->d_namlen == 2); | |||||
#endif | |||||
#ifdef _D_EXACT_NAMLEN | |||||
assert (_D_EXACT_NAMLEN(entry) == 2); | |||||
#endif | |||||
#ifdef _D_ALLOC_NAMLEN | |||||
assert (_D_ALLOC_NAMLEN(entry) > 2); | |||||
#endif | |||||
found += 2; | |||||
} else if (wcscmp (entry->d_name, L"file") == 0) { | |||||
/* Regular file */ | |||||
#ifdef _DIRENT_HAVE_D_TYPE | |||||
assert (entry->d_type == DT_REG); | |||||
#endif | |||||
#ifdef _DIRENT_HAVE_D_NAMLEN | |||||
assert (entry->d_namlen == 4); | |||||
#endif | |||||
#ifdef _D_EXACT_NAMLEN | |||||
assert (_D_EXACT_NAMLEN(entry) == 4); | |||||
#endif | |||||
#ifdef _D_ALLOC_NAMLEN | |||||
assert (_D_ALLOC_NAMLEN(entry) > 4); | |||||
#endif | |||||
found += 4; | |||||
} else if (wcscmp (entry->d_name, L"dir") == 0) { | |||||
/* Just a directory */ | |||||
#ifdef _DIRENT_HAVE_D_TYPE | |||||
assert (entry->d_type == DT_DIR); | |||||
#endif | |||||
#ifdef _DIRENT_HAVE_D_NAMLEN | |||||
assert (entry->d_namlen == 3); | |||||
#endif | |||||
#ifdef _D_EXACT_NAMLEN | |||||
assert (_D_EXACT_NAMLEN(entry) == 3); | |||||
#endif | |||||
#ifdef _D_ALLOC_NAMLEN | |||||
assert (_D_ALLOC_NAMLEN(entry) > 3); | |||||
#endif | |||||
found += 8; | |||||
} else { | |||||
/* Other file */ | |||||
fprintf (stderr, "Unexpected file\n"); | |||||
abort (); | |||||
} | |||||
} | |||||
/* Make sure that all files were found */ | |||||
assert (found == 0xf); | |||||
_wclosedir (dir); | |||||
} | |||||
#endif | |||||
printf ("OK\n"); | |||||
return EXIT_SUCCESS; | |||||
} |
@ -1,264 +0,0 @@ | |||||
/* | |||||
* Make sure that scandir function works OK. | |||||
* | |||||
* 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 <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <sys/stat.h> | |||||
#include <dirent.h> | |||||
#include <errno.h> | |||||
#include <time.h> | |||||
#include <limits.h> | |||||
#undef NDEBUG | |||||
#include <assert.h> | |||||
/* Filter and sort functions */ | |||||
static int only_readme (const struct dirent *entry); | |||||
static int no_directories (const struct dirent *entry); | |||||
static int reverse_alpha (const struct dirent **a, const struct dirent **b); | |||||
int | |||||
main( | |||||
int argc, char *argv[]) | |||||
{ | |||||
struct dirent **files; | |||||
int i; | |||||
int n; | |||||
(void) argc; | |||||
(void) argv; | |||||
/* Initialize random number generator */ | |||||
srand ((unsigned) time (NULL)); | |||||
/* Basic scan with simple filter function */ | |||||
{ | |||||
/* Read directory entries */ | |||||
n = scandir ("tests/3", &files, only_readme, alphasort); | |||||
assert (n == 1); | |||||
/* Make sure that the filter works */ | |||||
assert (strcmp (files[0]->d_name, "README.txt") == 0); | |||||
/* Release file names */ | |||||
for (i = 0; i < n; i++) { | |||||
free (files[i]); | |||||
} | |||||
free (files); | |||||
} | |||||
/* Basic scan with default sorting function */ | |||||
{ | |||||
/* Read directory entries in alphabetic order */ | |||||
n = scandir ("tests/3", &files, NULL, alphasort); | |||||
assert (n == 13); | |||||
/* Make sure that we got all the file names in the proper order */ | |||||
assert (strcmp (files[0]->d_name, ".") == 0); | |||||
assert (strcmp (files[1]->d_name, "..") == 0); | |||||
assert (strcmp (files[2]->d_name, "3zero.dat") == 0); | |||||
assert (strcmp (files[3]->d_name, "666.dat") == 0); | |||||
assert (strcmp (files[4]->d_name, "Qwerty-my-aunt.dat") == 0); | |||||
assert (strcmp (files[5]->d_name, "README.txt") == 0); | |||||
assert (strcmp (files[6]->d_name, "aaa.dat") == 0); | |||||
assert (strcmp (files[7]->d_name, "dirent.dat") == 0); | |||||
assert (strcmp (files[8]->d_name, "empty.dat") == 0); | |||||
assert (strcmp (files[9]->d_name, "sane-1.12.0.dat") == 0); | |||||
assert (strcmp (files[10]->d_name, "sane-1.2.3.dat") == 0); | |||||
assert (strcmp (files[11]->d_name, "sane-1.2.4.dat") == 0); | |||||
assert (strcmp (files[12]->d_name, "zebra.dat") == 0); | |||||
/* Release file names */ | |||||
for (i = 0; i < n; i++) { | |||||
free (files[i]); | |||||
} | |||||
free (files); | |||||
} | |||||
/* Custom filter AND sort function */ | |||||
{ | |||||
/* Read directory entries in alphabetic order */ | |||||
n = scandir ("tests/3", &files, no_directories, reverse_alpha); | |||||
assert (n == 11); | |||||
/* Make sure that we got all the FILE names in the REVERSE order */ | |||||
assert (strcmp (files[0]->d_name, "zebra.dat") == 0); | |||||
assert (strcmp (files[1]->d_name, "sane-1.2.4.dat") == 0); | |||||
assert (strcmp (files[2]->d_name, "sane-1.2.3.dat") == 0); | |||||
assert (strcmp (files[3]->d_name, "sane-1.12.0.dat") == 0); | |||||
assert (strcmp (files[4]->d_name, "empty.dat") == 0); | |||||
assert (strcmp (files[5]->d_name, "dirent.dat") == 0); | |||||
assert (strcmp (files[6]->d_name, "aaa.dat") == 0); | |||||
assert (strcmp (files[7]->d_name, "README.txt") == 0); | |||||
assert (strcmp (files[8]->d_name, "Qwerty-my-aunt.dat") == 0); | |||||
assert (strcmp (files[9]->d_name, "666.dat") == 0); | |||||
assert (strcmp (files[10]->d_name, "3zero.dat") == 0); | |||||
/* Release file names */ | |||||
for (i = 0; i < n; i++) { | |||||
free (files[i]); | |||||
} | |||||
free (files); | |||||
} | |||||
/* Trying to read from non-existent directory leads to an error */ | |||||
{ | |||||
files = NULL; | |||||
n = scandir ("tests/invalid", &files, NULL, alphasort); | |||||
assert (n == -1); | |||||
assert (files == NULL); | |||||
assert (errno == ENOENT); | |||||
} | |||||
/* Trying to open file as a directory produces ENOTDIR error */ | |||||
{ | |||||
files = NULL; | |||||
n = scandir ("tests/3/666.dat", &files, NULL, alphasort); | |||||
assert (n == -1); | |||||
assert (files == NULL); | |||||
assert (errno == ENOTDIR); | |||||
} | |||||
/* Scan large directory */ | |||||
{ | |||||
char dirname[PATH_MAX+1]; | |||||
int i, j; | |||||
int ok; | |||||
/* Copy name of temporary directory to variable dirname */ | |||||
#ifdef WIN32 | |||||
i = GetTempPathA (PATH_MAX, dirname); | |||||
assert (i > 0); | |||||
#else | |||||
strcpy (dirname, "/tmp/"); | |||||
i = strlen (dirname); | |||||
#endif | |||||
/* Append random characters to dirname */ | |||||
for (j = 0; j < 10; j++) { | |||||
char c; | |||||
/* Generate random character */ | |||||
c = "abcdefghijklmnopqrstuvwxyz"[rand() % 26]; | |||||
/* Append character to dirname */ | |||||
assert (i < PATH_MAX); | |||||
dirname[i++] = c; | |||||
} | |||||
/* Terminate directory name */ | |||||
assert (i < PATH_MAX); | |||||
dirname[i] = '\0'; | |||||
/* Create directory */ | |||||
#ifdef WIN32 | |||||
ok = CreateDirectoryA (dirname, NULL); | |||||
assert (ok); | |||||
#else | |||||
ok = mkdir (dirname, 0700); | |||||
assert (ok == /*success*/0); | |||||
#endif | |||||
/* Create one thousand files */ | |||||
assert (i + 5 < PATH_MAX); | |||||
for (j = 0; j < 1000; j++) { | |||||
FILE *fp; | |||||
/* Construct file name */ | |||||
dirname[i] = '/'; | |||||
dirname[i+1] = 'z'; | |||||
dirname[i+2] = '0' + ((j / 100) % 10); | |||||
dirname[i+3] = '0' + ((j / 10) % 10); | |||||
dirname[i+4] = '0' + (j % 10); | |||||
dirname[i+5] = '\0'; | |||||
/* Create file */ | |||||
fp = fopen (dirname, "w"); | |||||
assert (fp != NULL); | |||||
fclose (fp); | |||||
} | |||||
/* Cut out the file name part */ | |||||
dirname[i] = '\0'; | |||||
/* Scan directory */ | |||||
n = scandir (dirname, &files, no_directories, alphasort); | |||||
assert (n == 1000); | |||||
/* Make sure that all 1000 files are read back */ | |||||
for (j = 0; j < n; j++) { | |||||
char match[100]; | |||||
/* Construct file name */ | |||||
match[0] = 'z'; | |||||
match[1] = '0' + ((j / 100) % 10); | |||||
match[2] = '0' + ((j / 10) % 10); | |||||
match[3] = '0' + (j % 10); | |||||
match[4] = '\0'; | |||||
/* Make sure that file name matches that on the disk */ | |||||
assert (strcmp (files[j]->d_name, match) == 0); | |||||
} | |||||
/* Release file names */ | |||||
for (j = 0; j < n; j++) { | |||||
free (files[j]); | |||||
} | |||||
free (files); | |||||
} | |||||
printf ("OK\n"); | |||||
return EXIT_SUCCESS; | |||||
} | |||||
/* Only pass README.txt file */ | |||||
static int | |||||
only_readme (const struct dirent *entry) | |||||
{ | |||||
int pass; | |||||
if (strcmp (entry->d_name, "README.txt") == 0) { | |||||
pass = 1; | |||||
} else { | |||||
pass = 0; | |||||
} | |||||
return pass; | |||||
} | |||||
/* Filter out directories */ | |||||
static int | |||||
no_directories (const struct dirent *entry) | |||||
{ | |||||
int pass; | |||||
if (entry->d_type != DT_DIR) { | |||||
pass = 1; | |||||
} else { | |||||
pass = 0; | |||||
} | |||||
return pass; | |||||
} | |||||
/* Sort in reverse direction */ | |||||
static int | |||||
reverse_alpha( | |||||
const struct dirent **a, const struct dirent **b) | |||||
{ | |||||
return strcoll ((*b)->d_name, (*a)->d_name); | |||||
} |
@ -1,401 +0,0 @@ | |||||
/* | |||||
* 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; | |||||
(void) argc; | |||||
(void) argv; | |||||
/* 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++) { | |||||
char c; | |||||
/* Generate random character */ | |||||
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 NAME 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, | |||||
/* Maximum 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; | |||||
} |