
Although not required to address bad code generation in some versions of gcc 9 and 10, a coding style that requires explicit comparison of the result to zero before use is both clearer and would have avoided the generation of bad code. This change converts all use of cmp function usage from ``` if (strcmp(a, b) || !strcmp(c, d)) ... ``` to ``` if (strcmp(a, b) != 0 || strcmp(c, d)) == 0 ``` for all C library cmp functions and related: - strcmp(), strncmp() - strcasecmp(), strncasecmp() - stricmp(), strnicmp() - memcmp() Change-Id: Ic60c15e1e3a07e4faaf10648eefe3adae2543188
279 lines
6.6 KiB
C
279 lines
6.6 KiB
C
/***********************************************************************
|
|
* Copyright (c) 2009, Secure Endpoints Inc.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* - Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* - Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in
|
|
* the documentation and/or other materials provided with the
|
|
* distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
**********************************************************************/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <direct.h>
|
|
#include <errno.h>
|
|
#include <io.h>
|
|
#include <fcntl.h>
|
|
#include <sys/stat.h>
|
|
#include <string.h>
|
|
#include "dirent.h"
|
|
|
|
/* Note that we create a known directory structure in a subdirectory
|
|
of the current directory to run our tests. */
|
|
|
|
#define TESTDIR "dirent-test-dir"
|
|
|
|
const char * dir_entries[] = {
|
|
"A",
|
|
"B",
|
|
"C",
|
|
"CAA",
|
|
"CAAA",
|
|
"CABBBB",
|
|
"CAABBB.txt",
|
|
"A filename with spaces"
|
|
};
|
|
|
|
const char * entries_begin_with_C[] = {
|
|
"C",
|
|
"CAA",
|
|
"CAAA",
|
|
"CABBBB",
|
|
"CAABBB.txt"
|
|
};
|
|
|
|
const char * entries_end_with_A[] = {
|
|
"A",
|
|
"CAA",
|
|
"CAAA"
|
|
};
|
|
|
|
const int n_dir_entries = sizeof(dir_entries)/sizeof(dir_entries[0]);
|
|
|
|
int teardown_test(void);
|
|
|
|
void fail_test(const char * reason, ...)
|
|
{
|
|
va_list args;
|
|
|
|
va_start(args, reason);
|
|
vfprintf(stderr, reason, args);
|
|
va_end(args);
|
|
|
|
fprintf(stderr, " : errno = %d (%s)\n", errno, strerror(errno));
|
|
teardown_test();
|
|
abort();
|
|
}
|
|
|
|
void fail_test_nf(const char * format, ...)
|
|
{
|
|
va_list args;
|
|
|
|
fprintf(stderr, "FAIL:");
|
|
|
|
va_start(args, format);
|
|
vfprintf(stderr, format, args);
|
|
va_end(args);
|
|
|
|
fprintf(stderr, " : errno = %d (%s)\n", errno, strerror(errno));
|
|
}
|
|
|
|
int touch(const char * filename)
|
|
{
|
|
int fd;
|
|
|
|
fd = _open(filename, _O_CREAT, _S_IREAD| _S_IWRITE);
|
|
|
|
if (fd == -1)
|
|
return -1;
|
|
|
|
return _close(fd);
|
|
}
|
|
|
|
int setup_test(void)
|
|
{
|
|
int i;
|
|
|
|
fprintf(stderr, "Creating test directory %s ...\n", TESTDIR);
|
|
|
|
if (_mkdir(TESTDIR))
|
|
fail_test("Can't create test directory \"" TESTDIR "\"");
|
|
|
|
if (_chdir(TESTDIR))
|
|
fail_test("Can't change to test directory");
|
|
|
|
for (i=0; i < n_dir_entries; i++) {
|
|
if (touch(dir_entries[i]))
|
|
fail_test("Can't create test file '%s'", dir_entries[i]);
|
|
}
|
|
|
|
fprintf(stderr, "Done with test setup.\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int teardown_test(void)
|
|
{
|
|
char dirname[_MAX_PATH];
|
|
size_t len;
|
|
int i;
|
|
|
|
printf ("Begin cleanup...\n");
|
|
|
|
if (_getcwd(dirname, sizeof(dirname)/sizeof(char)) != NULL &&
|
|
|
|
(len = strlen(dirname)) > sizeof(TESTDIR)/sizeof(char) &&
|
|
|
|
strcmp(dirname + len + 1 - sizeof(TESTDIR)/sizeof(char), TESTDIR) == 0) {
|
|
|
|
/* fallthrough */
|
|
|
|
} else {
|
|
/* did we create the directory? */
|
|
|
|
if (!_rmdir( TESTDIR )) {
|
|
fprintf(stderr, "Removed test directory\n");
|
|
return 0;
|
|
} else {
|
|
if (errno == ENOTEMPTY) {
|
|
if (_chdir(TESTDIR)) {
|
|
fprintf(stderr, "Can't change to test directory. Aborting cleanup.\n");
|
|
return -1;
|
|
} else {
|
|
/* fallthrough */
|
|
}
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
fprintf(stderr, "Cleaning up test directory %s ...\n", TESTDIR);
|
|
|
|
for (i=0; i < n_dir_entries; i++) {
|
|
if (_unlink(dir_entries[i])) {
|
|
/* if the test setup failed, we expect this to happen for
|
|
at least some files */
|
|
}
|
|
}
|
|
|
|
if (_chdir("..")) {
|
|
fprintf(stderr, "Can't escape test directory. Giving in.\n");
|
|
return -1;
|
|
}
|
|
|
|
if (_rmdir( TESTDIR )) {
|
|
fprintf(stderr, "Can't remove test directory.\n");
|
|
return -1;
|
|
}
|
|
|
|
printf("Cleaned up test directory\n");
|
|
return 0;
|
|
}
|
|
|
|
int check_list(const char * filespec, const char ** list, int n, int expect_dot_and_dotdot)
|
|
{
|
|
DIR * d;
|
|
struct dirent * e;
|
|
int n_found = 0;
|
|
int i;
|
|
int rv = 0;
|
|
int retry = 1;
|
|
|
|
d = opendir(filespec);
|
|
if (d == NULL) {
|
|
fail_test_nf("opendir failed for [%s]", filespec);
|
|
return -1;
|
|
}
|
|
|
|
printf("Checking filespec [%s]... ", filespec);
|
|
|
|
retry:
|
|
while ((e = readdir(d)) != NULL) {
|
|
n_found ++;
|
|
|
|
if (expect_dot_and_dotdot &&
|
|
(strcmp(e->d_name, ".") == 0 ||
|
|
strcmp(e->d_name, "..") == 0))
|
|
continue;
|
|
|
|
for (i=0; i < n; i++) {
|
|
if (strcmp(list[i], e->d_name) == 0)
|
|
break;
|
|
}
|
|
|
|
if (i == n) {
|
|
fail_test_nf("Found unexpected entry [%s]", e->d_name);
|
|
rv = -1;
|
|
}
|
|
}
|
|
|
|
if (n_found != n) {
|
|
fail_test_nf("Unexpected number of entries [%d]. Expected %d", n_found, n);
|
|
rv = -1;
|
|
}
|
|
|
|
if (retry) {
|
|
retry = 0;
|
|
n_found = 0;
|
|
|
|
rewinddir(d);
|
|
goto retry;
|
|
}
|
|
|
|
if (closedir(d)) {
|
|
fail_test_nf("closedir() failed");
|
|
}
|
|
|
|
printf("done\n");
|
|
|
|
return rv;
|
|
}
|
|
|
|
int run_tests()
|
|
{
|
|
/* assumes that the test directory has been set up and we have
|
|
changed into the test directory. */
|
|
|
|
check_list("*", dir_entries, n_dir_entries + 2, 1);
|
|
check_list("*.*", dir_entries, n_dir_entries + 2, 1);
|
|
check_list("C*", entries_begin_with_C, sizeof(entries_begin_with_C)/sizeof(entries_begin_with_C[0]), 0);
|
|
check_list("*A", entries_end_with_A, sizeof(entries_end_with_A)/sizeof(entries_end_with_A[0]), 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char ** argv)
|
|
{
|
|
if (setup_test())
|
|
return 1;
|
|
|
|
run_tests();
|
|
|
|
teardown_test();
|
|
|
|
return 0;
|
|
}
|