brintos

brintos / linux-shallow public Read only

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