xref: /aosp_15_r20/external/linux-kselftest/tools/testing/selftests/proc/read.c (revision 053f45be4e351dfd5e965df293cd45b779f579ee)
1*053f45beSAndroid Build Coastguard Worker /*
2*053f45beSAndroid Build Coastguard Worker  * Copyright © 2018 Alexey Dobriyan <[email protected]>
3*053f45beSAndroid Build Coastguard Worker  *
4*053f45beSAndroid Build Coastguard Worker  * Permission to use, copy, modify, and distribute this software for any
5*053f45beSAndroid Build Coastguard Worker  * purpose with or without fee is hereby granted, provided that the above
6*053f45beSAndroid Build Coastguard Worker  * copyright notice and this permission notice appear in all copies.
7*053f45beSAndroid Build Coastguard Worker  *
8*053f45beSAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9*053f45beSAndroid Build Coastguard Worker  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10*053f45beSAndroid Build Coastguard Worker  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11*053f45beSAndroid Build Coastguard Worker  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12*053f45beSAndroid Build Coastguard Worker  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13*053f45beSAndroid Build Coastguard Worker  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14*053f45beSAndroid Build Coastguard Worker  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15*053f45beSAndroid Build Coastguard Worker  */
16*053f45beSAndroid Build Coastguard Worker // Test
17*053f45beSAndroid Build Coastguard Worker // 1) read and lseek on every file in /proc
18*053f45beSAndroid Build Coastguard Worker // 2) readlink of every symlink in /proc
19*053f45beSAndroid Build Coastguard Worker // 3) recursively (1) + (2) for every directory in /proc
20*053f45beSAndroid Build Coastguard Worker // 4) write to /proc/*/clear_refs and /proc/*/task/*/clear_refs
21*053f45beSAndroid Build Coastguard Worker // 5) write to /proc/sysrq-trigger
22*053f45beSAndroid Build Coastguard Worker #undef NDEBUG
23*053f45beSAndroid Build Coastguard Worker #include <assert.h>
24*053f45beSAndroid Build Coastguard Worker #include <errno.h>
25*053f45beSAndroid Build Coastguard Worker #include <sys/types.h>
26*053f45beSAndroid Build Coastguard Worker #include <dirent.h>
27*053f45beSAndroid Build Coastguard Worker #include <stdbool.h>
28*053f45beSAndroid Build Coastguard Worker #include <stdlib.h>
29*053f45beSAndroid Build Coastguard Worker #include <stdio.h>
30*053f45beSAndroid Build Coastguard Worker #include <string.h>
31*053f45beSAndroid Build Coastguard Worker #include <sys/stat.h>
32*053f45beSAndroid Build Coastguard Worker #include <sys/vfs.h>
33*053f45beSAndroid Build Coastguard Worker #include <fcntl.h>
34*053f45beSAndroid Build Coastguard Worker #include <unistd.h>
35*053f45beSAndroid Build Coastguard Worker 
36*053f45beSAndroid Build Coastguard Worker #include "proc.h"
37*053f45beSAndroid Build Coastguard Worker 
f_reg(DIR * d,const char * filename)38*053f45beSAndroid Build Coastguard Worker static void f_reg(DIR *d, const char *filename)
39*053f45beSAndroid Build Coastguard Worker {
40*053f45beSAndroid Build Coastguard Worker 	char buf[4096];
41*053f45beSAndroid Build Coastguard Worker 	int fd;
42*053f45beSAndroid Build Coastguard Worker 	ssize_t rv;
43*053f45beSAndroid Build Coastguard Worker 
44*053f45beSAndroid Build Coastguard Worker 	/* read from /proc/kmsg can block */
45*053f45beSAndroid Build Coastguard Worker 	fd = openat(dirfd(d), filename, O_RDONLY|O_NONBLOCK);
46*053f45beSAndroid Build Coastguard Worker 	if (fd == -1)
47*053f45beSAndroid Build Coastguard Worker 		return;
48*053f45beSAndroid Build Coastguard Worker 	/* struct proc_ops::proc_lseek is mandatory if file is seekable. */
49*053f45beSAndroid Build Coastguard Worker 	(void)lseek(fd, 0, SEEK_SET);
50*053f45beSAndroid Build Coastguard Worker 	rv = read(fd, buf, sizeof(buf));
51*053f45beSAndroid Build Coastguard Worker 	assert((0 <= rv && rv <= sizeof(buf)) || rv == -1);
52*053f45beSAndroid Build Coastguard Worker 	close(fd);
53*053f45beSAndroid Build Coastguard Worker }
54*053f45beSAndroid Build Coastguard Worker 
f_reg_write(DIR * d,const char * filename,const char * buf,size_t len)55*053f45beSAndroid Build Coastguard Worker static void f_reg_write(DIR *d, const char *filename, const char *buf, size_t len)
56*053f45beSAndroid Build Coastguard Worker {
57*053f45beSAndroid Build Coastguard Worker 	int fd;
58*053f45beSAndroid Build Coastguard Worker 	ssize_t rv;
59*053f45beSAndroid Build Coastguard Worker 
60*053f45beSAndroid Build Coastguard Worker 	fd = openat(dirfd(d), filename, O_WRONLY);
61*053f45beSAndroid Build Coastguard Worker 	if (fd == -1)
62*053f45beSAndroid Build Coastguard Worker 		return;
63*053f45beSAndroid Build Coastguard Worker 	rv = write(fd, buf, len);
64*053f45beSAndroid Build Coastguard Worker 	assert((0 <= rv && rv <= len) || rv == -1);
65*053f45beSAndroid Build Coastguard Worker 	close(fd);
66*053f45beSAndroid Build Coastguard Worker }
67*053f45beSAndroid Build Coastguard Worker 
f_lnk(DIR * d,const char * filename)68*053f45beSAndroid Build Coastguard Worker static void f_lnk(DIR *d, const char *filename)
69*053f45beSAndroid Build Coastguard Worker {
70*053f45beSAndroid Build Coastguard Worker 	char buf[4096];
71*053f45beSAndroid Build Coastguard Worker 	ssize_t rv;
72*053f45beSAndroid Build Coastguard Worker 
73*053f45beSAndroid Build Coastguard Worker 	rv = readlinkat(dirfd(d), filename, buf, sizeof(buf));
74*053f45beSAndroid Build Coastguard Worker 	assert((0 <= rv && rv <= sizeof(buf)) || rv == -1);
75*053f45beSAndroid Build Coastguard Worker }
76*053f45beSAndroid Build Coastguard Worker 
f(DIR * d,unsigned int level)77*053f45beSAndroid Build Coastguard Worker static void f(DIR *d, unsigned int level)
78*053f45beSAndroid Build Coastguard Worker {
79*053f45beSAndroid Build Coastguard Worker 	struct dirent *de;
80*053f45beSAndroid Build Coastguard Worker 
81*053f45beSAndroid Build Coastguard Worker 	de = xreaddir(d);
82*053f45beSAndroid Build Coastguard Worker 	assert(de->d_type == DT_DIR);
83*053f45beSAndroid Build Coastguard Worker 	assert(streq(de->d_name, "."));
84*053f45beSAndroid Build Coastguard Worker 
85*053f45beSAndroid Build Coastguard Worker 	de = xreaddir(d);
86*053f45beSAndroid Build Coastguard Worker 	assert(de->d_type == DT_DIR);
87*053f45beSAndroid Build Coastguard Worker 	assert(streq(de->d_name, ".."));
88*053f45beSAndroid Build Coastguard Worker 
89*053f45beSAndroid Build Coastguard Worker 	while ((de = xreaddir(d))) {
90*053f45beSAndroid Build Coastguard Worker 		assert(!streq(de->d_name, "."));
91*053f45beSAndroid Build Coastguard Worker 		assert(!streq(de->d_name, ".."));
92*053f45beSAndroid Build Coastguard Worker 
93*053f45beSAndroid Build Coastguard Worker 		switch (de->d_type) {
94*053f45beSAndroid Build Coastguard Worker 			DIR *dd;
95*053f45beSAndroid Build Coastguard Worker 			int fd;
96*053f45beSAndroid Build Coastguard Worker 
97*053f45beSAndroid Build Coastguard Worker 		case DT_REG:
98*053f45beSAndroid Build Coastguard Worker 			if (level == 0 && streq(de->d_name, "sysrq-trigger")) {
99*053f45beSAndroid Build Coastguard Worker 				f_reg_write(d, de->d_name, "h", 1);
100*053f45beSAndroid Build Coastguard Worker 			} else if (level == 1 && streq(de->d_name, "clear_refs")) {
101*053f45beSAndroid Build Coastguard Worker 				f_reg_write(d, de->d_name, "1", 1);
102*053f45beSAndroid Build Coastguard Worker 			} else if (level == 3 && streq(de->d_name, "clear_refs")) {
103*053f45beSAndroid Build Coastguard Worker 				f_reg_write(d, de->d_name, "1", 1);
104*053f45beSAndroid Build Coastguard Worker 			} else {
105*053f45beSAndroid Build Coastguard Worker 				f_reg(d, de->d_name);
106*053f45beSAndroid Build Coastguard Worker 			}
107*053f45beSAndroid Build Coastguard Worker 			break;
108*053f45beSAndroid Build Coastguard Worker 		case DT_DIR:
109*053f45beSAndroid Build Coastguard Worker 			fd = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY);
110*053f45beSAndroid Build Coastguard Worker 			if (fd == -1)
111*053f45beSAndroid Build Coastguard Worker 				continue;
112*053f45beSAndroid Build Coastguard Worker 			dd = fdopendir(fd);
113*053f45beSAndroid Build Coastguard Worker 			if (!dd)
114*053f45beSAndroid Build Coastguard Worker 				continue;
115*053f45beSAndroid Build Coastguard Worker 			f(dd, level + 1);
116*053f45beSAndroid Build Coastguard Worker 			closedir(dd);
117*053f45beSAndroid Build Coastguard Worker 			break;
118*053f45beSAndroid Build Coastguard Worker 		case DT_LNK:
119*053f45beSAndroid Build Coastguard Worker 			f_lnk(d, de->d_name);
120*053f45beSAndroid Build Coastguard Worker 			break;
121*053f45beSAndroid Build Coastguard Worker 		default:
122*053f45beSAndroid Build Coastguard Worker 			assert(0);
123*053f45beSAndroid Build Coastguard Worker 		}
124*053f45beSAndroid Build Coastguard Worker 	}
125*053f45beSAndroid Build Coastguard Worker }
126*053f45beSAndroid Build Coastguard Worker 
main(void)127*053f45beSAndroid Build Coastguard Worker int main(void)
128*053f45beSAndroid Build Coastguard Worker {
129*053f45beSAndroid Build Coastguard Worker 	DIR *d;
130*053f45beSAndroid Build Coastguard Worker 	struct statfs sfs;
131*053f45beSAndroid Build Coastguard Worker 
132*053f45beSAndroid Build Coastguard Worker 	d = opendir("/proc");
133*053f45beSAndroid Build Coastguard Worker 	if (!d)
134*053f45beSAndroid Build Coastguard Worker 		return 4;
135*053f45beSAndroid Build Coastguard Worker 
136*053f45beSAndroid Build Coastguard Worker 	/* Ensure /proc is proc. */
137*053f45beSAndroid Build Coastguard Worker 	if (fstatfs(dirfd(d), &sfs) == -1) {
138*053f45beSAndroid Build Coastguard Worker 		return 1;
139*053f45beSAndroid Build Coastguard Worker 	}
140*053f45beSAndroid Build Coastguard Worker 	if (sfs.f_type != 0x9fa0) {
141*053f45beSAndroid Build Coastguard Worker 		fprintf(stderr, "error: unexpected f_type %lx\n", (long)sfs.f_type);
142*053f45beSAndroid Build Coastguard Worker 		return 2;
143*053f45beSAndroid Build Coastguard Worker 	}
144*053f45beSAndroid Build Coastguard Worker 
145*053f45beSAndroid Build Coastguard Worker 	f(d, 0);
146*053f45beSAndroid Build Coastguard Worker 
147*053f45beSAndroid Build Coastguard Worker 	return 0;
148*053f45beSAndroid Build Coastguard Worker }
149