xref: /aosp_15_r20/external/ltp/testcases/kernel/fs/proc/proc01.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker /*
2*49cdfc7eSAndroid Build Coastguard Worker  * proc01.c - Tests Linux /proc file reading.
3*49cdfc7eSAndroid Build Coastguard Worker  *
4*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (C) 2001 Stephane Fillod <[email protected]>
5*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) 2008, 2009  Red Hat, Inc.
6*49cdfc7eSAndroid Build Coastguard Worker  *
7*49cdfc7eSAndroid Build Coastguard Worker  * This program is free software; you can redistribute it and/or modify it
8*49cdfc7eSAndroid Build Coastguard Worker  * under the terms of version 2 of the GNU General Public License as
9*49cdfc7eSAndroid Build Coastguard Worker  * published by the Free Software Foundation.
10*49cdfc7eSAndroid Build Coastguard Worker  *
11*49cdfc7eSAndroid Build Coastguard Worker  * This program is distributed in the hope that it would be useful, but
12*49cdfc7eSAndroid Build Coastguard Worker  * WITHOUT ANY WARRANTY; without even the implied warranty of
13*49cdfc7eSAndroid Build Coastguard Worker  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14*49cdfc7eSAndroid Build Coastguard Worker  *
15*49cdfc7eSAndroid Build Coastguard Worker  * Further, this software is distributed without any warranty that it is
16*49cdfc7eSAndroid Build Coastguard Worker  * free of the rightful claim of any third person regarding infringement
17*49cdfc7eSAndroid Build Coastguard Worker  * or the like.  Any license provided herein, whether implied or
18*49cdfc7eSAndroid Build Coastguard Worker  * otherwise, applies only to this software file.  Patent licenses, if
19*49cdfc7eSAndroid Build Coastguard Worker  * any, provided herein do not apply to combinations of this program with
20*49cdfc7eSAndroid Build Coastguard Worker  * other software, or any other product whatsoever.
21*49cdfc7eSAndroid Build Coastguard Worker  *
22*49cdfc7eSAndroid Build Coastguard Worker  * You should have received a copy of the GNU General Public License along
23*49cdfc7eSAndroid Build Coastguard Worker  * with this program; if not, write the Free Software Foundation, Inc.,
24*49cdfc7eSAndroid Build Coastguard Worker  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25*49cdfc7eSAndroid Build Coastguard Worker  *
26*49cdfc7eSAndroid Build Coastguard Worker  */
27*49cdfc7eSAndroid Build Coastguard Worker 
28*49cdfc7eSAndroid Build Coastguard Worker #include "config.h"
29*49cdfc7eSAndroid Build Coastguard Worker 
30*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
31*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
32*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
33*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
34*49cdfc7eSAndroid Build Coastguard Worker #include <limits.h>
35*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
36*49cdfc7eSAndroid Build Coastguard Worker #include <sys/stat.h>
37*49cdfc7eSAndroid Build Coastguard Worker #include <dirent.h>
38*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
39*49cdfc7eSAndroid Build Coastguard Worker #include <fcntl.h>
40*49cdfc7eSAndroid Build Coastguard Worker #include <fnmatch.h>
41*49cdfc7eSAndroid Build Coastguard Worker 
42*49cdfc7eSAndroid Build Coastguard Worker #ifdef HAVE_LIBSELINUX_DEVEL
43*49cdfc7eSAndroid Build Coastguard Worker #include <selinux/selinux.h>
44*49cdfc7eSAndroid Build Coastguard Worker #endif
45*49cdfc7eSAndroid Build Coastguard Worker 
46*49cdfc7eSAndroid Build Coastguard Worker #include "test.h"
47*49cdfc7eSAndroid Build Coastguard Worker 
48*49cdfc7eSAndroid Build Coastguard Worker #define MAX_BUFF_SIZE 65536
49*49cdfc7eSAndroid Build Coastguard Worker #define MAX_FUNC_NAME 256
50*49cdfc7eSAndroid Build Coastguard Worker 
51*49cdfc7eSAndroid Build Coastguard Worker char *TCID = "proc01";
52*49cdfc7eSAndroid Build Coastguard Worker int TST_TOTAL = 1;
53*49cdfc7eSAndroid Build Coastguard Worker 
54*49cdfc7eSAndroid Build Coastguard Worker static int opt_verbose;
55*49cdfc7eSAndroid Build Coastguard Worker static int opt_procpath;
56*49cdfc7eSAndroid Build Coastguard Worker static char *opt_procpathstr;
57*49cdfc7eSAndroid Build Coastguard Worker static int opt_buffsize;
58*49cdfc7eSAndroid Build Coastguard Worker static int opt_readirq;
59*49cdfc7eSAndroid Build Coastguard Worker static char *opt_buffsizestr;
60*49cdfc7eSAndroid Build Coastguard Worker static int opt_maxmbytes;
61*49cdfc7eSAndroid Build Coastguard Worker static char *opt_maxmbytesstr;
62*49cdfc7eSAndroid Build Coastguard Worker 
63*49cdfc7eSAndroid Build Coastguard Worker static char *procpath = "/proc";
64*49cdfc7eSAndroid Build Coastguard Worker static const char selfpath[] = "/proc/self";
65*49cdfc7eSAndroid Build Coastguard Worker size_t buffsize = 1024;
66*49cdfc7eSAndroid Build Coastguard Worker static unsigned long long maxbytes;
67*49cdfc7eSAndroid Build Coastguard Worker 
68*49cdfc7eSAndroid Build Coastguard Worker unsigned long long total_read;
69*49cdfc7eSAndroid Build Coastguard Worker unsigned int total_obj;
70*49cdfc7eSAndroid Build Coastguard Worker 
71*49cdfc7eSAndroid Build Coastguard Worker struct mapping {
72*49cdfc7eSAndroid Build Coastguard Worker 	char func[MAX_FUNC_NAME];
73*49cdfc7eSAndroid Build Coastguard Worker 	char file[PATH_MAX];
74*49cdfc7eSAndroid Build Coastguard Worker 	int err;
75*49cdfc7eSAndroid Build Coastguard Worker };
76*49cdfc7eSAndroid Build Coastguard Worker 
77*49cdfc7eSAndroid Build Coastguard Worker /* Those are known failures for 2.6.18 baremetal kernel and Xen dom0
78*49cdfc7eSAndroid Build Coastguard Worker    kernel on i686, x86_64, ia64, ppc64 and s390x. In addition, It looks
79*49cdfc7eSAndroid Build Coastguard Worker    like if SELinux is disabled, the test may still fail on some other
80*49cdfc7eSAndroid Build Coastguard Worker    entries. */
81*49cdfc7eSAndroid Build Coastguard Worker static const struct mapping known_issues[] = {
82*49cdfc7eSAndroid Build Coastguard Worker 	{"open", "/proc/acpi/event", EBUSY},
83*49cdfc7eSAndroid Build Coastguard Worker 	{"open", "/proc/sal/cpe/data", EBUSY},
84*49cdfc7eSAndroid Build Coastguard Worker 	{"open", "/proc/sal/cmc/data", EBUSY},
85*49cdfc7eSAndroid Build Coastguard Worker 	{"open", "/proc/sal/init/data", EBUSY},
86*49cdfc7eSAndroid Build Coastguard Worker 	{"open", "/proc/sal/mca/data", EBUSY},
87*49cdfc7eSAndroid Build Coastguard Worker 	{"open", "/proc/fs/nfsd/pool_stats", ENODEV},
88*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/fs/nfsd/clients/*/ctl", EINVAL},
89*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/acpi/event", EAGAIN},
90*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/kmsg", EAGAIN},
91*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/sal/cpe/event", EAGAIN},
92*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/sal/cmc/event", EAGAIN},
93*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/sal/init/event", EAGAIN},
94*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/sal/mca/event", EAGAIN},
95*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/xen/privcmd", EIO},
96*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/xen/privcmd", EINVAL},
97*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/self/mem", EIO},
98*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/self/task/[0-9]*/mem", EIO},
99*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/self/attr/*", EINVAL},
100*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/self/attr/selinux/*", EINVAL},
101*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/self/attr/smack/*", EINVAL},
102*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/self/attr/apparmor/*", EINVAL},
103*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/self/task/[0-9]*/attr/*", EINVAL},
104*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/self/task/[0-9]*/attr/smack/*", EINVAL},
105*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/self/task/[0-9]*/attr/selinux/*", EINVAL},
106*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/self/task/[0-9]*/attr/apparmor/*", EINVAL},
107*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/self/ns/*", EINVAL},
108*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/self/task/[0-9]*/ns/*", EINVAL},
109*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/ppc64/rtas/error_log", EINVAL},
110*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/powerpc/rtas/error_log", EINVAL},
111*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/fs/nfsd/unlock_filesystem", EINVAL},
112*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/fs/nfsd/unlock_ip", EINVAL},
113*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/fs/nfsd/filehandle", EINVAL},
114*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/fs/nfsd/.getfs", EINVAL},
115*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/fs/nfsd/.getfd", EINVAL},
116*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/self/net/rpc/use-gss-proxy", EAGAIN},
117*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/sys/net/ipv6/conf/*/stable_secret", EIO},
118*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/sys/vm/nr_hugepages", EOPNOTSUPP},
119*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/sys/vm/nr_overcommit_hugepages", EOPNOTSUPP},
120*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/sys/vm/nr_hugepages_mempolicy", EOPNOTSUPP},
121*49cdfc7eSAndroid Build Coastguard Worker 	/* These are added for making sure LTP runs on some of the devices that have non upstream
122*49cdfc7eSAndroid Build Coastguard Worker 	 * proc files. See following commit for more details
123*49cdfc7eSAndroid Build Coastguard Worker 	 *    d59bfa01c ("proc file fixup: This fixes some random qualcomm proc files that act odd")
124*49cdfc7eSAndroid Build Coastguard Worker 	 */
125*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/debug/fwdump", EINVAL},
126*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/cid/athdiagpfs", EIO},
127*49cdfc7eSAndroid Build Coastguard Worker 	{"read", "/proc/pressure/*", EOPNOTSUPP},
128*49cdfc7eSAndroid Build Coastguard Worker 	{"", "", 0}
129*49cdfc7eSAndroid Build Coastguard Worker };
130*49cdfc7eSAndroid Build Coastguard Worker 
131*49cdfc7eSAndroid Build Coastguard Worker /*
132*49cdfc7eSAndroid Build Coastguard Worker  * If a particular LSM is enabled, it is expected that some entries can
133*49cdfc7eSAndroid Build Coastguard Worker  * be read successfully. Otherwise, those entries will retrun some
134*49cdfc7eSAndroid Build Coastguard Worker  * failures listed above. Here to add any LSM specific entries.
135*49cdfc7eSAndroid Build Coastguard Worker  */
136*49cdfc7eSAndroid Build Coastguard Worker 
137*49cdfc7eSAndroid Build Coastguard Worker /*
138*49cdfc7eSAndroid Build Coastguard Worker  * Test macro to indicate that SELinux libraries and headers are
139*49cdfc7eSAndroid Build Coastguard Worker  * installed.
140*49cdfc7eSAndroid Build Coastguard Worker  */
141*49cdfc7eSAndroid Build Coastguard Worker #ifdef HAVE_LIBSELINUX_DEVEL
142*49cdfc7eSAndroid Build Coastguard Worker static const char lsm_should_work[][PATH_MAX] = {
143*49cdfc7eSAndroid Build Coastguard Worker 	"/proc/self/attr/*",
144*49cdfc7eSAndroid Build Coastguard Worker 	"/proc/self/attr/selinux/*",
145*49cdfc7eSAndroid Build Coastguard Worker 	"/proc/self/task/[0-9]*/attr/*",
146*49cdfc7eSAndroid Build Coastguard Worker 	"/proc/self/task/[0-9]*/attr/selinux/*",
147*49cdfc7eSAndroid Build Coastguard Worker 	""
148*49cdfc7eSAndroid Build Coastguard Worker };
149*49cdfc7eSAndroid Build Coastguard Worker #endif
150*49cdfc7eSAndroid Build Coastguard Worker 
151*49cdfc7eSAndroid Build Coastguard Worker /* Known files that does not honor O_NONBLOCK, so they will hang
152*49cdfc7eSAndroid Build Coastguard Worker    the test while being read. */
153*49cdfc7eSAndroid Build Coastguard Worker static const char error_nonblock[][PATH_MAX] = {
154*49cdfc7eSAndroid Build Coastguard Worker 	"/proc/xen/xenbus",
155*49cdfc7eSAndroid Build Coastguard Worker 	""
156*49cdfc7eSAndroid Build Coastguard Worker };
157*49cdfc7eSAndroid Build Coastguard Worker 
158*49cdfc7eSAndroid Build Coastguard Worker /*
159*49cdfc7eSAndroid Build Coastguard Worker  * Verify expected failures, and then let the test to continue.
160*49cdfc7eSAndroid Build Coastguard Worker  *
161*49cdfc7eSAndroid Build Coastguard Worker  * Return 0 when a problem errno is found.
162*49cdfc7eSAndroid Build Coastguard Worker  * Return 1 when a known issue is found.
163*49cdfc7eSAndroid Build Coastguard Worker  *
164*49cdfc7eSAndroid Build Coastguard Worker  */
found_errno(const char * syscall,const char * obj,int tmperr)165*49cdfc7eSAndroid Build Coastguard Worker static int found_errno(const char *syscall, const char *obj, int tmperr)
166*49cdfc7eSAndroid Build Coastguard Worker {
167*49cdfc7eSAndroid Build Coastguard Worker 	int i;
168*49cdfc7eSAndroid Build Coastguard Worker 
169*49cdfc7eSAndroid Build Coastguard Worker 	/* Should not see any error for certain entries if a LSM is enabled. */
170*49cdfc7eSAndroid Build Coastguard Worker #ifdef HAVE_LIBSELINUX_DEVEL
171*49cdfc7eSAndroid Build Coastguard Worker 	if (is_selinux_enabled()) {
172*49cdfc7eSAndroid Build Coastguard Worker 		for (i = 0; lsm_should_work[i][0] != '\0'; i++) {
173*49cdfc7eSAndroid Build Coastguard Worker 			if (!strcmp(obj, lsm_should_work[i]) ||
174*49cdfc7eSAndroid Build Coastguard Worker 			    !fnmatch(lsm_should_work[i], obj, FNM_PATHNAME)) {
175*49cdfc7eSAndroid Build Coastguard Worker 				return 0;
176*49cdfc7eSAndroid Build Coastguard Worker 			}
177*49cdfc7eSAndroid Build Coastguard Worker 		}
178*49cdfc7eSAndroid Build Coastguard Worker 	}
179*49cdfc7eSAndroid Build Coastguard Worker #endif
180*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; known_issues[i].err != 0; i++) {
181*49cdfc7eSAndroid Build Coastguard Worker 		if (tmperr == known_issues[i].err &&
182*49cdfc7eSAndroid Build Coastguard Worker 		    (!strcmp(obj, known_issues[i].file) ||
183*49cdfc7eSAndroid Build Coastguard Worker 		     !fnmatch(known_issues[i].file, obj, FNM_PATHNAME)) &&
184*49cdfc7eSAndroid Build Coastguard Worker 		    !strcmp(syscall, known_issues[i].func)) {
185*49cdfc7eSAndroid Build Coastguard Worker 			/* Using strcmp / fnmatch could have messed up the
186*49cdfc7eSAndroid Build Coastguard Worker 			 * errno value. */
187*49cdfc7eSAndroid Build Coastguard Worker 			errno = tmperr;
188*49cdfc7eSAndroid Build Coastguard Worker 			tst_resm(TINFO | TERRNO, "%s: known issue", obj);
189*49cdfc7eSAndroid Build Coastguard Worker 			return 1;
190*49cdfc7eSAndroid Build Coastguard Worker 		}
191*49cdfc7eSAndroid Build Coastguard Worker 	}
192*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
193*49cdfc7eSAndroid Build Coastguard Worker }
194*49cdfc7eSAndroid Build Coastguard Worker 
cleanup(void)195*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void)
196*49cdfc7eSAndroid Build Coastguard Worker {
197*49cdfc7eSAndroid Build Coastguard Worker 	tst_rmdir();
198*49cdfc7eSAndroid Build Coastguard Worker }
199*49cdfc7eSAndroid Build Coastguard Worker 
setup(void)200*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
201*49cdfc7eSAndroid Build Coastguard Worker {
202*49cdfc7eSAndroid Build Coastguard Worker 	tst_sig(FORK, DEF_HANDLER, cleanup);
203*49cdfc7eSAndroid Build Coastguard Worker 	TEST_PAUSE;
204*49cdfc7eSAndroid Build Coastguard Worker 	tst_tmpdir();
205*49cdfc7eSAndroid Build Coastguard Worker }
206*49cdfc7eSAndroid Build Coastguard Worker 
help(void)207*49cdfc7eSAndroid Build Coastguard Worker void help(void)
208*49cdfc7eSAndroid Build Coastguard Worker {
209*49cdfc7eSAndroid Build Coastguard Worker 	printf("  -b x    read byte count\n");
210*49cdfc7eSAndroid Build Coastguard Worker 	printf("  -m x    max megabytes to read from single file\n");
211*49cdfc7eSAndroid Build Coastguard Worker 	printf("  -q      read .../irq/... entries\n");
212*49cdfc7eSAndroid Build Coastguard Worker 	printf("  -r x    proc pathname\n");
213*49cdfc7eSAndroid Build Coastguard Worker 	printf("  -v      verbose mode\n");
214*49cdfc7eSAndroid Build Coastguard Worker }
215*49cdfc7eSAndroid Build Coastguard Worker 
216*49cdfc7eSAndroid Build Coastguard Worker /*
217*49cdfc7eSAndroid Build Coastguard Worker  * add the -m option whose parameter is the
218*49cdfc7eSAndroid Build Coastguard Worker  * pages that should be mapped.
219*49cdfc7eSAndroid Build Coastguard Worker  */
220*49cdfc7eSAndroid Build Coastguard Worker static option_t options[] = {
221*49cdfc7eSAndroid Build Coastguard Worker 	{"b:", &opt_buffsize, &opt_buffsizestr},
222*49cdfc7eSAndroid Build Coastguard Worker 	{"m:", &opt_maxmbytes, &opt_maxmbytesstr},
223*49cdfc7eSAndroid Build Coastguard Worker 	{"q", &opt_readirq, NULL},
224*49cdfc7eSAndroid Build Coastguard Worker 	{"r:", &opt_procpath, &opt_procpathstr},
225*49cdfc7eSAndroid Build Coastguard Worker 	{"v", &opt_verbose, NULL},
226*49cdfc7eSAndroid Build Coastguard Worker 	{NULL, NULL, NULL}
227*49cdfc7eSAndroid Build Coastguard Worker };
228*49cdfc7eSAndroid Build Coastguard Worker 
229*49cdfc7eSAndroid Build Coastguard Worker /*
230*49cdfc7eSAndroid Build Coastguard Worker  * NB: this function is recursive
231*49cdfc7eSAndroid Build Coastguard Worker  * returns 0 if no error encountered, otherwise number of errors (objs)
232*49cdfc7eSAndroid Build Coastguard Worker  *
233*49cdfc7eSAndroid Build Coastguard Worker  * REM: Funny enough, while developing this function (actually replacing
234*49cdfc7eSAndroid Build Coastguard Worker  *	streamed fopen by standard open), I hit a real /proc bug.
235*49cdfc7eSAndroid Build Coastguard Worker  *	On a 2.2.13-SuSE kernel, "cat /proc/tty/driver/serial" would fail
236*49cdfc7eSAndroid Build Coastguard Worker  *	with EFAULT, while "cat /proc/tty/driver/serial > somefile" wouldn't.
237*49cdfc7eSAndroid Build Coastguard Worker  *	Okay, this might be due to a slight serial misconfiguration, but still.
238*49cdfc7eSAndroid Build Coastguard Worker  *	Analysis with strace showed up the difference was on the count size
239*49cdfc7eSAndroid Build Coastguard Worker  *	of read (1024 bytes vs 4096 bytes). So I tested further..
240*49cdfc7eSAndroid Build Coastguard Worker  *	read count of 512 bytes adds /proc/tty/drivers to the list
241*49cdfc7eSAndroid Build Coastguard Worker  *	of broken proc files, while 64 bytes reads removes
242*49cdfc7eSAndroid Build Coastguard Worker  *	/proc/tty/driver/serial from the list. Interesting, isn't it?
243*49cdfc7eSAndroid Build Coastguard Worker  *	Now, there's a -b option to this test, so you can try your luck. --SF
244*49cdfc7eSAndroid Build Coastguard Worker  *
245*49cdfc7eSAndroid Build Coastguard Worker  * It's more fun to run this test it as root, as all the files will be accessible!
246*49cdfc7eSAndroid Build Coastguard Worker  * (however, be careful, there might be some bufferoverflow holes..)
247*49cdfc7eSAndroid Build Coastguard Worker  * reading proc files might be also a good kernel latency killer.
248*49cdfc7eSAndroid Build Coastguard Worker  */
readproc(const char * obj)249*49cdfc7eSAndroid Build Coastguard Worker static long readproc(const char *obj)
250*49cdfc7eSAndroid Build Coastguard Worker {
251*49cdfc7eSAndroid Build Coastguard Worker 	DIR *dir = NULL;	/* pointer to a directory */
252*49cdfc7eSAndroid Build Coastguard Worker 	struct dirent *dir_ent;	/* pointer to directory entries */
253*49cdfc7eSAndroid Build Coastguard Worker 	char dirobj[PATH_MAX];	/* object inside directory to modify */
254*49cdfc7eSAndroid Build Coastguard Worker 	struct stat statbuf;	/* used to hold stat information */
255*49cdfc7eSAndroid Build Coastguard Worker 	int fd, tmperr, i;
256*49cdfc7eSAndroid Build Coastguard Worker 	ssize_t nread;
257*49cdfc7eSAndroid Build Coastguard Worker 	static char buf[MAX_BUFF_SIZE];	/* static kills reentrancy, but we don't care about the contents */
258*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long long file_total_read = 0;
259*49cdfc7eSAndroid Build Coastguard Worker 
260*49cdfc7eSAndroid Build Coastguard Worker 	/* Determine the file type */
261*49cdfc7eSAndroid Build Coastguard Worker 	if (lstat(obj, &statbuf) < 0) {
262*49cdfc7eSAndroid Build Coastguard Worker 
263*49cdfc7eSAndroid Build Coastguard Worker 		/* permission denied is not considered as error */
264*49cdfc7eSAndroid Build Coastguard Worker 		if (errno != EACCES) {
265*49cdfc7eSAndroid Build Coastguard Worker 			tst_resm(TFAIL | TERRNO, "%s: lstat", obj);
266*49cdfc7eSAndroid Build Coastguard Worker 			return 1;
267*49cdfc7eSAndroid Build Coastguard Worker 		}
268*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
269*49cdfc7eSAndroid Build Coastguard Worker 
270*49cdfc7eSAndroid Build Coastguard Worker 	}
271*49cdfc7eSAndroid Build Coastguard Worker 
272*49cdfc7eSAndroid Build Coastguard Worker 	/* Prevent loops, but read /proc/self. */
273*49cdfc7eSAndroid Build Coastguard Worker 	if (S_ISLNK(statbuf.st_mode) && strcmp(obj, selfpath))
274*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
275*49cdfc7eSAndroid Build Coastguard Worker 
276*49cdfc7eSAndroid Build Coastguard Worker 	total_obj++;
277*49cdfc7eSAndroid Build Coastguard Worker 
278*49cdfc7eSAndroid Build Coastguard Worker 	/* Take appropriate action, depending on the file type */
279*49cdfc7eSAndroid Build Coastguard Worker 	if (S_ISDIR(statbuf.st_mode) || !strcmp(obj, selfpath)) {
280*49cdfc7eSAndroid Build Coastguard Worker 
281*49cdfc7eSAndroid Build Coastguard Worker 		/* object is a directory */
282*49cdfc7eSAndroid Build Coastguard Worker 
283*49cdfc7eSAndroid Build Coastguard Worker 		/*
284*49cdfc7eSAndroid Build Coastguard Worker 		 * Skip over the /proc/irq directory, unless the user
285*49cdfc7eSAndroid Build Coastguard Worker 		 * requested that we read the directory because it could
286*49cdfc7eSAndroid Build Coastguard Worker 		 * map to a broken driver which effectively `hangs' the
287*49cdfc7eSAndroid Build Coastguard Worker 		 * test.
288*49cdfc7eSAndroid Build Coastguard Worker 		 */
289*49cdfc7eSAndroid Build Coastguard Worker 		if (!opt_readirq && !strcmp("/proc/irq", obj)) {
290*49cdfc7eSAndroid Build Coastguard Worker 			return 0;
291*49cdfc7eSAndroid Build Coastguard Worker 			/* Open the directory to get access to what is in it */
292*49cdfc7eSAndroid Build Coastguard Worker 		} else if ((dir = opendir(obj)) == NULL) {
293*49cdfc7eSAndroid Build Coastguard Worker 			if (errno != EACCES) {
294*49cdfc7eSAndroid Build Coastguard Worker 				tst_resm(TFAIL | TERRNO, "%s: opendir", obj);
295*49cdfc7eSAndroid Build Coastguard Worker 				return 1;
296*49cdfc7eSAndroid Build Coastguard Worker 			}
297*49cdfc7eSAndroid Build Coastguard Worker 			return 0;
298*49cdfc7eSAndroid Build Coastguard Worker 		} else {
299*49cdfc7eSAndroid Build Coastguard Worker 
300*49cdfc7eSAndroid Build Coastguard Worker 			long ret_val = 0;
301*49cdfc7eSAndroid Build Coastguard Worker 
302*49cdfc7eSAndroid Build Coastguard Worker 			/* Loop through the entries in the directory */
303*49cdfc7eSAndroid Build Coastguard Worker 			for (dir_ent = (struct dirent *)readdir(dir);
304*49cdfc7eSAndroid Build Coastguard Worker 			     dir_ent != NULL;
305*49cdfc7eSAndroid Build Coastguard Worker 			     dir_ent = (struct dirent *)readdir(dir)) {
306*49cdfc7eSAndroid Build Coastguard Worker 
307*49cdfc7eSAndroid Build Coastguard Worker 				/* Ignore ".", "..", "kcore", and
308*49cdfc7eSAndroid Build Coastguard Worker 				 * "/proc/<pid>" (unless this is our
309*49cdfc7eSAndroid Build Coastguard Worker 				 * starting point as directed by the
310*49cdfc7eSAndroid Build Coastguard Worker 				 * user).
311*49cdfc7eSAndroid Build Coastguard Worker 				 */
312*49cdfc7eSAndroid Build Coastguard Worker 				if (strcmp(dir_ent->d_name, ".") &&
313*49cdfc7eSAndroid Build Coastguard Worker 				    strcmp(dir_ent->d_name, "..") &&
314*49cdfc7eSAndroid Build Coastguard Worker 				    strcmp(dir_ent->d_name, "kcore") &&
315*49cdfc7eSAndroid Build Coastguard Worker 				    (fnmatch("[0-9]*", dir_ent->d_name,
316*49cdfc7eSAndroid Build Coastguard Worker 					     FNM_PATHNAME) ||
317*49cdfc7eSAndroid Build Coastguard Worker 				     strcmp(obj, procpath))) {
318*49cdfc7eSAndroid Build Coastguard Worker 
319*49cdfc7eSAndroid Build Coastguard Worker 					if (opt_verbose) {
320*49cdfc7eSAndroid Build Coastguard Worker 						fprintf(stderr, "%s\n",
321*49cdfc7eSAndroid Build Coastguard Worker 							dir_ent->d_name);
322*49cdfc7eSAndroid Build Coastguard Worker 					}
323*49cdfc7eSAndroid Build Coastguard Worker 
324*49cdfc7eSAndroid Build Coastguard Worker 					/* Recursively call this routine to test the
325*49cdfc7eSAndroid Build Coastguard Worker 					 * current entry */
326*49cdfc7eSAndroid Build Coastguard Worker 					snprintf(dirobj, PATH_MAX,
327*49cdfc7eSAndroid Build Coastguard Worker 						 "%s/%s", obj, dir_ent->d_name);
328*49cdfc7eSAndroid Build Coastguard Worker 					ret_val += readproc(dirobj);
329*49cdfc7eSAndroid Build Coastguard Worker 
330*49cdfc7eSAndroid Build Coastguard Worker 				}
331*49cdfc7eSAndroid Build Coastguard Worker 
332*49cdfc7eSAndroid Build Coastguard Worker 			}
333*49cdfc7eSAndroid Build Coastguard Worker 
334*49cdfc7eSAndroid Build Coastguard Worker 			/* Close the directory */
335*49cdfc7eSAndroid Build Coastguard Worker 			if (dir)
336*49cdfc7eSAndroid Build Coastguard Worker 				(void)closedir(dir);
337*49cdfc7eSAndroid Build Coastguard Worker 
338*49cdfc7eSAndroid Build Coastguard Worker 			return ret_val;
339*49cdfc7eSAndroid Build Coastguard Worker 
340*49cdfc7eSAndroid Build Coastguard Worker 		}
341*49cdfc7eSAndroid Build Coastguard Worker 
342*49cdfc7eSAndroid Build Coastguard Worker 	} else {		/* if it's not a dir, read it! */
343*49cdfc7eSAndroid Build Coastguard Worker 
344*49cdfc7eSAndroid Build Coastguard Worker 		if (!S_ISREG(statbuf.st_mode))
345*49cdfc7eSAndroid Build Coastguard Worker 			return 0;
346*49cdfc7eSAndroid Build Coastguard Worker 
347*49cdfc7eSAndroid Build Coastguard Worker #ifdef DEBUG
348*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "%s", obj);
349*49cdfc7eSAndroid Build Coastguard Worker #endif
350*49cdfc7eSAndroid Build Coastguard Worker 
351*49cdfc7eSAndroid Build Coastguard Worker 		/* is O_NONBLOCK enough to escape from FIFO's ? */
352*49cdfc7eSAndroid Build Coastguard Worker 		fd = open(obj, O_RDONLY | O_NONBLOCK);
353*49cdfc7eSAndroid Build Coastguard Worker 		if (fd < 0) {
354*49cdfc7eSAndroid Build Coastguard Worker 			tmperr = errno;
355*49cdfc7eSAndroid Build Coastguard Worker 
356*49cdfc7eSAndroid Build Coastguard Worker 			if (!found_errno("open", obj, tmperr)) {
357*49cdfc7eSAndroid Build Coastguard Worker 
358*49cdfc7eSAndroid Build Coastguard Worker 				errno = tmperr;
359*49cdfc7eSAndroid Build Coastguard Worker 
360*49cdfc7eSAndroid Build Coastguard Worker 				if (errno != EACCES) {
361*49cdfc7eSAndroid Build Coastguard Worker 					tst_resm(TFAIL | TERRNO,
362*49cdfc7eSAndroid Build Coastguard Worker 						 "%s: open failed", obj);
363*49cdfc7eSAndroid Build Coastguard Worker 					return 1;
364*49cdfc7eSAndroid Build Coastguard Worker 				}
365*49cdfc7eSAndroid Build Coastguard Worker 
366*49cdfc7eSAndroid Build Coastguard Worker 			}
367*49cdfc7eSAndroid Build Coastguard Worker 			return 0;
368*49cdfc7eSAndroid Build Coastguard Worker 
369*49cdfc7eSAndroid Build Coastguard Worker 		}
370*49cdfc7eSAndroid Build Coastguard Worker 
371*49cdfc7eSAndroid Build Coastguard Worker 		/* Skip write-only files. */
372*49cdfc7eSAndroid Build Coastguard Worker 		if ((statbuf.st_mode & S_IRUSR) == 0 &&
373*49cdfc7eSAndroid Build Coastguard Worker 		    (statbuf.st_mode & S_IWUSR) != 0) {
374*49cdfc7eSAndroid Build Coastguard Worker 			tst_resm(TINFO, "%s: is write-only.", obj);
375*49cdfc7eSAndroid Build Coastguard Worker 			(void)close(fd);
376*49cdfc7eSAndroid Build Coastguard Worker 			return 0;
377*49cdfc7eSAndroid Build Coastguard Worker 		}
378*49cdfc7eSAndroid Build Coastguard Worker 
379*49cdfc7eSAndroid Build Coastguard Worker 		/* Skip files does not honor O_NONBLOCK. */
380*49cdfc7eSAndroid Build Coastguard Worker 		for (i = 0; error_nonblock[i][0] != '\0'; i++) {
381*49cdfc7eSAndroid Build Coastguard Worker 			if (!strcmp(obj, error_nonblock[i])) {
382*49cdfc7eSAndroid Build Coastguard Worker 				tst_resm(TINFO, "%s: does not honor "
383*49cdfc7eSAndroid Build Coastguard Worker 					 "O_NONBLOCK", obj);
384*49cdfc7eSAndroid Build Coastguard Worker 				(void)close(fd);
385*49cdfc7eSAndroid Build Coastguard Worker 				return 0;
386*49cdfc7eSAndroid Build Coastguard Worker 			}
387*49cdfc7eSAndroid Build Coastguard Worker 		}
388*49cdfc7eSAndroid Build Coastguard Worker 
389*49cdfc7eSAndroid Build Coastguard Worker 		file_total_read = 0;
390*49cdfc7eSAndroid Build Coastguard Worker 		do {
391*49cdfc7eSAndroid Build Coastguard Worker 
392*49cdfc7eSAndroid Build Coastguard Worker 			nread = read(fd, buf, buffsize);
393*49cdfc7eSAndroid Build Coastguard Worker 
394*49cdfc7eSAndroid Build Coastguard Worker 			if (nread < 0) {
395*49cdfc7eSAndroid Build Coastguard Worker 
396*49cdfc7eSAndroid Build Coastguard Worker 				tmperr = errno;
397*49cdfc7eSAndroid Build Coastguard Worker 				(void)close(fd);
398*49cdfc7eSAndroid Build Coastguard Worker 
399*49cdfc7eSAndroid Build Coastguard Worker 				/* ignore no perm (not root) and no
400*49cdfc7eSAndroid Build Coastguard Worker 				 * process (terminated) errors */
401*49cdfc7eSAndroid Build Coastguard Worker 				if (!found_errno("read", obj, tmperr)) {
402*49cdfc7eSAndroid Build Coastguard Worker 
403*49cdfc7eSAndroid Build Coastguard Worker 					errno = tmperr;
404*49cdfc7eSAndroid Build Coastguard Worker 
405*49cdfc7eSAndroid Build Coastguard Worker 					if (errno != EACCES && errno != ESRCH) {
406*49cdfc7eSAndroid Build Coastguard Worker 						tst_resm(TFAIL | TERRNO,
407*49cdfc7eSAndroid Build Coastguard Worker 							 "read failed: "
408*49cdfc7eSAndroid Build Coastguard Worker 							 "%s", obj);
409*49cdfc7eSAndroid Build Coastguard Worker 						return 1;
410*49cdfc7eSAndroid Build Coastguard Worker 					}
411*49cdfc7eSAndroid Build Coastguard Worker 					return 0;
412*49cdfc7eSAndroid Build Coastguard Worker 
413*49cdfc7eSAndroid Build Coastguard Worker 				}
414*49cdfc7eSAndroid Build Coastguard Worker 
415*49cdfc7eSAndroid Build Coastguard Worker 			} else
416*49cdfc7eSAndroid Build Coastguard Worker 				file_total_read += nread;
417*49cdfc7eSAndroid Build Coastguard Worker 
418*49cdfc7eSAndroid Build Coastguard Worker 			if (opt_verbose) {
419*49cdfc7eSAndroid Build Coastguard Worker #ifdef DEBUG
420*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr, "%ld", nread);
421*49cdfc7eSAndroid Build Coastguard Worker #endif
422*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr, ".");
423*49cdfc7eSAndroid Build Coastguard Worker 			}
424*49cdfc7eSAndroid Build Coastguard Worker 
425*49cdfc7eSAndroid Build Coastguard Worker 			if ((maxbytes > 0) && (file_total_read > maxbytes)) {
426*49cdfc7eSAndroid Build Coastguard Worker 				tst_resm(TINFO, "%s: reached maxmbytes (-m)",
427*49cdfc7eSAndroid Build Coastguard Worker 					 obj);
428*49cdfc7eSAndroid Build Coastguard Worker 				break;
429*49cdfc7eSAndroid Build Coastguard Worker 			}
430*49cdfc7eSAndroid Build Coastguard Worker 		} while (0 < nread);
431*49cdfc7eSAndroid Build Coastguard Worker 		total_read += file_total_read;
432*49cdfc7eSAndroid Build Coastguard Worker 
433*49cdfc7eSAndroid Build Coastguard Worker 		if (opt_verbose)
434*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr, "\n");
435*49cdfc7eSAndroid Build Coastguard Worker 
436*49cdfc7eSAndroid Build Coastguard Worker 		if (0 <= fd)
437*49cdfc7eSAndroid Build Coastguard Worker 			(void)close(fd);
438*49cdfc7eSAndroid Build Coastguard Worker 
439*49cdfc7eSAndroid Build Coastguard Worker 	}
440*49cdfc7eSAndroid Build Coastguard Worker 
441*49cdfc7eSAndroid Build Coastguard Worker 	/* It's better to assume success by default rather than failure. */
442*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
443*49cdfc7eSAndroid Build Coastguard Worker 
444*49cdfc7eSAndroid Build Coastguard Worker }
445*49cdfc7eSAndroid Build Coastguard Worker 
main(int argc,char * argv[])446*49cdfc7eSAndroid Build Coastguard Worker int main(int argc, char *argv[])
447*49cdfc7eSAndroid Build Coastguard Worker {
448*49cdfc7eSAndroid Build Coastguard Worker 	int lc;
449*49cdfc7eSAndroid Build Coastguard Worker 
450*49cdfc7eSAndroid Build Coastguard Worker 	tst_parse_opts(argc, argv, options, help);
451*49cdfc7eSAndroid Build Coastguard Worker 
452*49cdfc7eSAndroid Build Coastguard Worker 	if (opt_buffsize) {
453*49cdfc7eSAndroid Build Coastguard Worker 		size_t bs;
454*49cdfc7eSAndroid Build Coastguard Worker 		bs = atoi(opt_buffsizestr);
455*49cdfc7eSAndroid Build Coastguard Worker 		if (bs <= MAX_BUFF_SIZE)
456*49cdfc7eSAndroid Build Coastguard Worker 			buffsize = bs;
457*49cdfc7eSAndroid Build Coastguard Worker 		else
458*49cdfc7eSAndroid Build Coastguard Worker 			tst_brkm(TBROK, cleanup,
459*49cdfc7eSAndroid Build Coastguard Worker 				 "Invalid arg for -b (max: %u): %s",
460*49cdfc7eSAndroid Build Coastguard Worker 				 MAX_BUFF_SIZE, opt_buffsizestr);
461*49cdfc7eSAndroid Build Coastguard Worker 	}
462*49cdfc7eSAndroid Build Coastguard Worker 	if (opt_maxmbytes)
463*49cdfc7eSAndroid Build Coastguard Worker 		maxbytes = atoi(opt_maxmbytesstr) * 1024 * 1024;
464*49cdfc7eSAndroid Build Coastguard Worker 
465*49cdfc7eSAndroid Build Coastguard Worker 	if (opt_procpath)
466*49cdfc7eSAndroid Build Coastguard Worker 		procpath = opt_procpathstr;
467*49cdfc7eSAndroid Build Coastguard Worker 
468*49cdfc7eSAndroid Build Coastguard Worker 	setup();
469*49cdfc7eSAndroid Build Coastguard Worker 
470*49cdfc7eSAndroid Build Coastguard Worker 	for (lc = 0; TEST_LOOPING(lc); lc++) {
471*49cdfc7eSAndroid Build Coastguard Worker 		tst_count = 0;
472*49cdfc7eSAndroid Build Coastguard Worker 
473*49cdfc7eSAndroid Build Coastguard Worker 		TEST(readproc(procpath));
474*49cdfc7eSAndroid Build Coastguard Worker 
475*49cdfc7eSAndroid Build Coastguard Worker 		if (TEST_RETURN != 0) {
476*49cdfc7eSAndroid Build Coastguard Worker 			tst_resm(TFAIL, "readproc() failed with %ld errors.",
477*49cdfc7eSAndroid Build Coastguard Worker 				 TEST_RETURN);
478*49cdfc7eSAndroid Build Coastguard Worker 		} else {
479*49cdfc7eSAndroid Build Coastguard Worker 			tst_resm(TPASS, "readproc() completed successfully, "
480*49cdfc7eSAndroid Build Coastguard Worker 				 "total read: %llu bytes, %u objs", total_read,
481*49cdfc7eSAndroid Build Coastguard Worker 				 total_obj);
482*49cdfc7eSAndroid Build Coastguard Worker 		}
483*49cdfc7eSAndroid Build Coastguard Worker 	}
484*49cdfc7eSAndroid Build Coastguard Worker 
485*49cdfc7eSAndroid Build Coastguard Worker 	cleanup();
486*49cdfc7eSAndroid Build Coastguard Worker 	tst_exit();
487*49cdfc7eSAndroid Build Coastguard Worker }
488