android13/external/ltp/testcases/kernel/syscalls/getdents/getdents01.c

183 lines
3.2 KiB
C

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) International Business Machines Corp., 2001
* written by Wayne Boyer
* Copyright (c) 2013 Markos Chandras
* Copyright (c) 2013 Cyril Hrubis <chrubis@suse.cz>
*/
/*\
*
* [Description]
*
* Basic getdents() test that checks if directory listing is correct and
* complete.
*
*/
#define _GNU_SOURCE
#include "tst_test.h"
#include "getdents.h"
#include <stdlib.h>
static void reset_flags(void);
static void check_flags(void);
static void set_flag(const char *name);
static int fd;
enum entry_type {
ENTRY_DIR,
ENTRY_FILE,
ENTRY_SYMLINK,
};
struct testcase {
const char *name;
enum entry_type type;
int create:1;
int found:1;
};
struct testcase testcases[] = {
{.name = ".", .create = 0, .type = ENTRY_DIR},
{.name = "..", .create = 0, .type = ENTRY_DIR},
{.name = "dir", .create = 1, .type = ENTRY_DIR},
{.name = "file", .create = 1, .type = ENTRY_FILE},
{.name = "symlink", .create = 1, .type = ENTRY_SYMLINK},
};
/*
* Big enough for dirp entires + data, the current size returned
* by kernel is 128 bytes.
*/
#define BUFSIZE 512
static void *dirp;
static void run(void)
{
int rval;
fd = SAFE_OPEN(".", O_RDONLY|O_DIRECTORY);
rval = tst_getdents(fd, dirp, BUFSIZE);
if (rval < 0) {
if (errno == ENOSYS)
tst_brk(TCONF, "syscall not implemented");
else {
tst_res(TFAIL | TERRNO, "getdents failed unexpectedly");
return;
}
}
if (rval == 0) {
tst_res(TFAIL, "getdents failed - returned end of directory");
return;
}
reset_flags();
void *recp = dirp;
do {
size_t d_reclen = tst_dirp_reclen(recp);
const char *d_name = tst_dirp_name(recp);
set_flag(d_name);
tst_res(TINFO, "Found '%s'", d_name);
rval -= d_reclen;
recp += d_reclen;
} while (rval > 0);
check_flags();
SAFE_CLOSE(fd);
}
static void reset_flags(void)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(testcases); i++)
testcases[i].found = 0;
}
static void check_flags(void)
{
size_t i;
int err = 0;
for (i = 0; i < ARRAY_SIZE(testcases); i++) {
if (!testcases[i].found) {
tst_res(TINFO, "Entry '%s' not found", testcases[i].name);
err++;
}
}
if (err)
tst_res(TFAIL, "Some entries not found");
else
tst_res(TPASS, "All entries found");
}
static void set_flag(const char *name)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(testcases); i++) {
if (!strcmp(name, testcases[i].name)) {
if (testcases[i].found)
tst_res(TFAIL, "Duplicate entry %s", name);
testcases[i].found = 1;
return;
}
}
tst_res(TFAIL, "Unexpected entry '%s' found", name);
}
static void setup(void)
{
size_t i;
getdents_info();
if (!tst_variant) {
for (i = 0; i < ARRAY_SIZE(testcases); i++) {
if (!testcases[i].create)
continue;
switch (testcases[i].type) {
case ENTRY_DIR:
SAFE_MKDIR(testcases[i].name, 0777);
break;
case ENTRY_FILE:
SAFE_FILE_PRINTF(testcases[i].name, " ");
break;
case ENTRY_SYMLINK:
SAFE_SYMLINK("nonexistent", testcases[i].name);
break;
}
}
}
}
static struct tst_test test = {
.needs_tmpdir = 1,
.test_all = run,
.setup = setup,
.bufs = (struct tst_buffers []) {
{&dirp, .size = BUFSIZE},
{},
},
.test_variants = TEST_VARIANTS,
};