cregit-Linux how code gets into the kernel

Release 4.18 tools/testing/selftests/proc/read.c

/*
 * 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 of 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 <string.h>
#include <sys/stat.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; rv = read(fd, buf, sizeof(buf)); assert((0 <= rv && rv <= sizeof(buf)) || rv == -1); close(fd); }

Contributors

PersonTokensPropCommitsCommitProp
Alexey Dobriyan92100.00%1100.00%
Total92100.00%1100.00%


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); }

Contributors

PersonTokensPropCommitsCommitProp
Alexey Dobriyan85100.00%1100.00%
Total85100.00%1100.00%


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); }

Contributors

PersonTokensPropCommitsCommitProp
Alexey Dobriyan64100.00%1100.00%
Total64100.00%1100.00%


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); } } }

Contributors

PersonTokensPropCommitsCommitProp
Alexey Dobriyan313100.00%1100.00%
Total313100.00%1100.00%


int main(void) { DIR *d; d = opendir("/proc"); if (!d) return 2; f(d, 0); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Alexey Dobriyan36100.00%1100.00%
Total36100.00%1100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Alexey Dobriyan633100.00%3100.00%
Total633100.00%3100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.