🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

264 lines
7.1 KiB

/*
* 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);
}