File: readwholedir.c

package info (click to toggle)
dtrace 2.0.5-1
  • links: PTS
  • area: main
  • in suites: sid
  • size: 24,408 kB
  • sloc: ansic: 61,247; sh: 17,997; asm: 1,717; lex: 947; awk: 754; yacc: 695; perl: 37; sed: 17; makefile: 15
file content (187 lines) | stat: -rw-r--r-- 4,019 bytes parent folder | download
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);
	}
}