Something went wrong. Try again.
(I'm so sorry!) Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149/* * Copyright © 2018 Alexey Dobriyan <adobriyan@gmail.com> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */// Test// 1) read and lseek on every file in /proc// 2) readlink of every symlink in /proc// 3) recursively (1) + (2) for every directory in /proc// 4) write to /proc/*/clear_refs and /proc/*/task/*/clear_refs// 5) write to /proc/sysrq-trigger#undef NDEBUG#include <assert.h>#include <errno.h>#include <sys/types.h>#include <dirent.h>#include <stdbool.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <sys/stat.h>#include <sys/vfs.h>#include <fcntl.h>#include <unistd.h>
#include "proc.h"
static void f_reg(DIR *d, const char *filename){ char buf[4096]; int fd; ssize_t rv;
/* read from /proc/kmsg can block */ fd = openat(dirfd(d), filename, O_RDONLY|O_NONBLOCK); if (fd == -1) return; /* struct proc_ops::proc_lseek is mandatory if file is seekable. */ (void)lseek(fd, 0, SEEK_SET); rv = read(fd, buf, sizeof(buf)); assert((0 <= rv && rv <= sizeof(buf)) || rv == -1); close(fd);}
static void f_reg_write(DIR *d, const char *filename, const char *buf, size_t len){ int fd; ssize_t rv;
fd = openat(dirfd(d), filename, O_WRONLY); if (fd == -1) return; rv = write(fd, buf, len); assert((0 <= rv && rv <= len) || rv == -1); close(fd);}
static void f_lnk(DIR *d, const char *filename){ char buf[4096]; ssize_t rv;
rv = readlinkat(dirfd(d), filename, buf, sizeof(buf)); assert((0 <= rv && rv <= sizeof(buf)) || rv == -1);}
static void f(DIR *d, unsigned int level){ struct dirent *de;
de = xreaddir(d); assert(de->d_type == DT_DIR); assert(streq(de->d_name, "."));
de = xreaddir(d); assert(de->d_type == DT_DIR); assert(streq(de->d_name, ".."));
while ((de = xreaddir(d))) { assert(!streq(de->d_name, ".")); assert(!streq(de->d_name, ".."));
switch (de->d_type) { DIR *dd; int fd;
case DT_REG: if (level == 0 && streq(de->d_name, "sysrq-trigger")) { f_reg_write(d, de->d_name, "h", 1); } else if (level == 1 && streq(de->d_name, "clear_refs")) { f_reg_write(d, de->d_name, "1", 1); } else if (level == 3 && streq(de->d_name, "clear_refs")) { f_reg_write(d, de->d_name, "1", 1); } else { f_reg(d, de->d_name); } break; case DT_DIR: fd = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY); if (fd == -1) continue; dd = fdopendir(fd); if (!dd) continue; f(dd, level + 1); closedir(dd); break; case DT_LNK: f_lnk(d, de->d_name); break; default: assert(0); } }}
int main(void){ DIR *d; struct statfs sfs;
d = opendir("/proc"); if (!d) return 4;
/* Ensure /proc is proc. */ if (fstatfs(dirfd(d), &sfs) == -1) { return 1; } if (sfs.f_type != 0x9fa0) { fprintf(stderr, "error: unexpected f_type %lx\n", (long)sfs.f_type); return 2; }
f(d, 0);
return 0;}