0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #undef NDEBUG
0023 #include <assert.h>
0024 #include <errno.h>
0025 #include <sys/types.h>
0026 #include <dirent.h>
0027 #include <stdbool.h>
0028 #include <stdlib.h>
0029 #include <stdio.h>
0030 #include <string.h>
0031 #include <sys/stat.h>
0032 #include <sys/vfs.h>
0033 #include <fcntl.h>
0034 #include <unistd.h>
0035
0036 #include "proc.h"
0037
0038 static void f_reg(DIR *d, const char *filename)
0039 {
0040 char buf[4096];
0041 int fd;
0042 ssize_t rv;
0043
0044
0045 fd = openat(dirfd(d), filename, O_RDONLY|O_NONBLOCK);
0046 if (fd == -1)
0047 return;
0048
0049 (void)lseek(fd, 0, SEEK_SET);
0050 rv = read(fd, buf, sizeof(buf));
0051 assert((0 <= rv && rv <= sizeof(buf)) || rv == -1);
0052 close(fd);
0053 }
0054
0055 static void f_reg_write(DIR *d, const char *filename, const char *buf, size_t len)
0056 {
0057 int fd;
0058 ssize_t rv;
0059
0060 fd = openat(dirfd(d), filename, O_WRONLY);
0061 if (fd == -1)
0062 return;
0063 rv = write(fd, buf, len);
0064 assert((0 <= rv && rv <= len) || rv == -1);
0065 close(fd);
0066 }
0067
0068 static void f_lnk(DIR *d, const char *filename)
0069 {
0070 char buf[4096];
0071 ssize_t rv;
0072
0073 rv = readlinkat(dirfd(d), filename, buf, sizeof(buf));
0074 assert((0 <= rv && rv <= sizeof(buf)) || rv == -1);
0075 }
0076
0077 static void f(DIR *d, unsigned int level)
0078 {
0079 struct dirent *de;
0080
0081 de = xreaddir(d);
0082 assert(de->d_type == DT_DIR);
0083 assert(streq(de->d_name, "."));
0084
0085 de = xreaddir(d);
0086 assert(de->d_type == DT_DIR);
0087 assert(streq(de->d_name, ".."));
0088
0089 while ((de = xreaddir(d))) {
0090 assert(!streq(de->d_name, "."));
0091 assert(!streq(de->d_name, ".."));
0092
0093 switch (de->d_type) {
0094 DIR *dd;
0095 int fd;
0096
0097 case DT_REG:
0098 if (level == 0 && streq(de->d_name, "sysrq-trigger")) {
0099 f_reg_write(d, de->d_name, "h", 1);
0100 } else if (level == 1 && streq(de->d_name, "clear_refs")) {
0101 f_reg_write(d, de->d_name, "1", 1);
0102 } else if (level == 3 && streq(de->d_name, "clear_refs")) {
0103 f_reg_write(d, de->d_name, "1", 1);
0104 } else {
0105 f_reg(d, de->d_name);
0106 }
0107 break;
0108 case DT_DIR:
0109 fd = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY);
0110 if (fd == -1)
0111 continue;
0112 dd = fdopendir(fd);
0113 if (!dd)
0114 continue;
0115 f(dd, level + 1);
0116 closedir(dd);
0117 break;
0118 case DT_LNK:
0119 f_lnk(d, de->d_name);
0120 break;
0121 default:
0122 assert(0);
0123 }
0124 }
0125 }
0126
0127 int main(void)
0128 {
0129 DIR *d;
0130 struct statfs sfs;
0131
0132 d = opendir("/proc");
0133 if (!d)
0134 return 4;
0135
0136
0137 if (fstatfs(dirfd(d), &sfs) == -1) {
0138 return 1;
0139 }
0140 if (sfs.f_type != 0x9fa0) {
0141 fprintf(stderr, "error: unexpected f_type %lx\n", (long)sfs.f_type);
0142 return 2;
0143 }
0144
0145 f(d, 0);
0146
0147 return 0;
0148 }