blob: 61ef24cceef5e5b0e1ace175ee5eae3df2bfea47 [file] [log] [blame]
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* fcalls tests the file system calls. By providing a list of mount
* points or directories, several different file systems can be tested.
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <debug.h>
#include <eprintf.h>
#include <puny.h>
#include <style.h>
#include <timer.h>
#include "fcalls.h"
#include "main.h"
#include "util.h"
char *Scratch;
char BigFile[] = "bigfile";
char EmptyFile[] = "emptyfile";
char OneFile[] = "onefile";
bool CheckRoot;
LocalOption_s Local_option = {
.size_big_file = (1LL << 32) + (1LL << 13) + 137,
.block_size = 4096,
.exit_on_error = TRUE,
.stack_trace = TRUE,
.is_root = FALSE,
.flaky = FALSE,
.verbose = FALSE,
.seed_rand = FALSE,
.test_sparse = FALSE,
.test_direct = FALSE };
/* init_test creates a scratch directory in the specified
* test directory.
*
* It also creates some test files to help in testing. Because,
* we want to test >4 Gigfiles but it takes time to create a file
* that big, we create it here and allow its size to be set by
* the user -- use a small size when developing the tests.
*/
void init_test (char *dir)
{
char *suffix;
if (Local_option.seed_rand) srandom(nsecs());
CheckRoot = (geteuid() == 0);
chdir(dir);
chdirErr(ENOTDIR, "/etc/passwd");
suffix = RndName();
Scratch = Catstr("scratch_", suffix, 0);
free(suffix);
mkdir(Scratch, 0777);
chdir(Scratch);
CrFile(BigFile, Local_option.size_big_file);
CrFile(EmptyFile, 0);
CrFile(OneFile, 1);
}
/* cleanup deletes the scratch directory and everything under it. */
void cleanup (void)
{
char *cmd;
int rc;
chdir("..");
cmd = Catstr("rm -fr ", Scratch, NULL);
rc = system(cmd);
if (rc == -1) PrError("%s:", cmd);
free(cmd);
free(Scratch);
Scratch = NULL;
}
void all_tests (char *dir)
{
init_test(dir);
void StatTest(void); StatTest();
void FsTest(void); FsTest();
void OpenTest(void); OpenTest();
#if __linux__
void OpenatTest(void); OpenatTest();
#endif
void RwTest(void); RwTest();
void DirTest(void); DirTest();
cleanup();
}
bool myopt (int c)
{
switch (c) {
case 'b':
Local_option.block_size = strtoll(optarg, NULL, 0);
break;
case 'f':
Local_option.flaky = TRUE;
break;
case 'o':
Local_option.test_direct = TRUE;
break;
case 'r':
Local_option.seed_rand = TRUE;
break;
case 's':
Local_option.test_sparse = TRUE;
break;
case 'v':
Local_option.verbose = TRUE;
break;
default:
return FALSE;
}
return TRUE;
}
void usage (void)
{
pr_usage("[-foprsvh] [<directory>]*\n"
"\th - help\n"
"\tb - Block size [default = %ld]\n"
"\tf - Local_option.flaky - run the flaky tests (may fail)\n"
"\to - Test O_DIRECT\n"
"\tp - Print results\n"
"\tr - Don't seed random number generator\n"
"\ts - Sparse file tests\n"
"\tv - Verbose - display each file system call\n"
"\tz - Size of big file [default = 0x%llx]",
Local_option.block_size, Local_option.size_big_file);
}
int main (int argc, char *argv[])
{
int i;
Option.file_size = Local_option.size_big_file;
Option.dir = ".";
punyopt(argc, argv, myopt, "b:forsv");
Local_option.size_big_file = Option.file_size;
if (Local_option.size_big_file < 40000) {
PrError("Size of big file, %lld, should be greater than 40K",
Local_option.size_big_file);
return 2;
}
if (Local_option.size_big_file < (1LL << 32)) {
fprintf(stderr, "Size of big file only 0x%llx\n",
Local_option.size_big_file);
}
if (argc == optind) {
all_tests(Option.dir);
} else for (i = optind; i < argc; i++) {
all_tests(argv[i]);
}
if (Option.print) DumpRecords();
return 0;
}