Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright © 2018 Alexey Dobriyan <adobriyan@gmail.com>
0003  *
0004  * Permission to use, copy, modify, and distribute this software for any
0005  * purpose with or without fee is hereby granted, provided that the above
0006  * copyright notice and this permission notice appear in all copies.
0007  *
0008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
0009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
0010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
0011  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
0012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
0013  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
0014  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0015  */
0016 // Test
0017 // 1) read and lseek on every file in /proc
0018 // 2) readlink of every symlink in /proc
0019 // 3) recursively (1) + (2) for every directory in /proc
0020 // 4) write to /proc/*/clear_refs and /proc/*/task/*/clear_refs
0021 // 5) write to /proc/sysrq-trigger
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     /* read from /proc/kmsg can block */
0045     fd = openat(dirfd(d), filename, O_RDONLY|O_NONBLOCK);
0046     if (fd == -1)
0047         return;
0048     /* struct proc_ops::proc_lseek is mandatory if file is seekable. */
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     /* Ensure /proc is proc. */
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 }