1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
|
/*
* Oracle Linux DTrace.
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
/*
* Read every .d file in the directory in which the test under execution is
* located. We assume that this directory does not change while being scanned.
*/
#define _POSIX_C_SOURCE 200112L
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/swap.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
/* We can in practice rely on PATH_MAX existing: this is pure paranoia. */
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
/* This is all rendered excessively complicated by our need to sort the list of
* dirents to ensure reproducible results (because we must read the files in the
* same order to keep the sizes passed to read() the same). */
/* The path we are working in. */
const char *path;
/* The directory entry list. */
static struct dirent **dir;
static size_t dir_count = 0;
int is_regular_test_file (const struct dirent *d);
void rw_files(const char *path, struct dirent **dir, int outfile);
int
main (void)
{
char *chop;
DIR *d;
FILE *tmp;
int writefile = -1;
/*
* Reduce the testname to a path.
*/
/*
* We leak 'path' without compunction.
*/
path = strdup(getenv("_test"));
chop = strrchr(path, '/');
*chop = '\0';
if ((d = opendir(path)) == NULL) {
fprintf(stderr, "%s opening %s\n", strerror(errno), path);
exit(1);
}
/* Read in the contents of the directory, sorted. */
dir_count = scandir(path, &dir, is_regular_test_file, alphasort);
if (dir_count < 0) {
fprintf(stderr, "%s reading directories from %s\n",
strerror(errno), path);
exit(1);
}
closedir(d);
/*
* read() as much as we can from each file, and write it out again in
* identically-sized chunks to a temporary file.
*/
if ((tmp = tmpfile()) != NULL) {
writefile = fileno(tmp);
}
if (writefile < 0) {
perror("creating temporary write-test file");
exit(1);
}
rw_files(path, dir, writefile);
fclose(tmp);
/*
* Let dtrace catch up, for ustack() tests that need a running process.
*/
if (strstr(getenv("_test"), "ustack"))
sleep(5);
return 0;
}
/* Identify regular .d files. */
int
is_regular_test_file (const struct dirent *d)
{
struct stat s;
char name[PATH_MAX];
size_t namelen = strlen (d->d_name);
/* No .d suffix. */
if ((namelen < 2) ||
(d->d_name[namelen-2] != '.') ||
(d->d_name[namelen-1] != 'd'))
return 0;
/*
* Check filetype. Don't use d_type at all, to prevent inconsistent
* results depending on the fs on which the test is run.
*/
strcpy(name, path);
strcat(name, "/");
strcat(name, d->d_name);
if (lstat(name, &s) < 0) {
/* error -> not a regular file, whatever it is */
return 0;
}
if (!S_ISREG(s.st_mode))
return 0;
return 1;
}
/*
* Read the contents of the files named in DIR, located under PATH, writing them
* out in identically-sized chunks to the OUTFILE. Any read/write/open errors
* are immediately fatal. Short writes are not diagnosed and will lead to a
* test failure.
*/
void
rw_files(const char *path, struct dirent **dir, int outfile)
{
size_t i;
struct dirent *d;
for (i = 0; i < dir_count; i++) {
char name[PATH_MAX];
char buf[4096];
int infile;
ssize_t nbytes;
d = dir[i];
strcpy(name, path);
strcat(name, "/");
strcat(name, d->d_name);
if ((infile = open(name, O_RDONLY)) < 0) {
fprintf(stderr, "Cannot open %s: %s\n", name,
strerror(errno));
exit(1);
}
while((nbytes = read(infile, buf, 4096)) > 0) {
if (write(outfile, buf, nbytes) < 0) {
fprintf(stderr, "Cannot write %li bytes: %s\n",
nbytes, strerror(errno));
exit(1);
}
}
if(nbytes < 0) {
fprintf (stderr, "Cannot read from %s: %s\n",
name, strerror(errno));
exit(1);
}
close(infile);
}
}
|