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