root/tools/testing/selftests/proc/read.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. f_reg
  2. f_reg_write
  3. f_lnk
  4. f
  5. main

   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 <stdio.h>
  30 #include <string.h>
  31 #include <sys/stat.h>
  32 #include <sys/vfs.h>
  33 #include <fcntl.h>
  34 #include <unistd.h>
  35 
  36 #include "proc.h"
  37 
  38 static void f_reg(DIR *d, const char *filename)
  39 {
  40         char buf[4096];
  41         int fd;
  42         ssize_t rv;
  43 
  44         /* read from /proc/kmsg can block */
  45         fd = openat(dirfd(d), filename, O_RDONLY|O_NONBLOCK);
  46         if (fd == -1)
  47                 return;
  48         rv = read(fd, buf, sizeof(buf));
  49         assert((0 <= rv && rv <= sizeof(buf)) || rv == -1);
  50         close(fd);
  51 }
  52 
  53 static void f_reg_write(DIR *d, const char *filename, const char *buf, size_t len)
  54 {
  55         int fd;
  56         ssize_t rv;
  57 
  58         fd = openat(dirfd(d), filename, O_WRONLY);
  59         if (fd == -1)
  60                 return;
  61         rv = write(fd, buf, len);
  62         assert((0 <= rv && rv <= len) || rv == -1);
  63         close(fd);
  64 }
  65 
  66 static void f_lnk(DIR *d, const char *filename)
  67 {
  68         char buf[4096];
  69         ssize_t rv;
  70 
  71         rv = readlinkat(dirfd(d), filename, buf, sizeof(buf));
  72         assert((0 <= rv && rv <= sizeof(buf)) || rv == -1);
  73 }
  74 
  75 static void f(DIR *d, unsigned int level)
  76 {
  77         struct dirent *de;
  78 
  79         de = xreaddir(d);
  80         assert(de->d_type == DT_DIR);
  81         assert(streq(de->d_name, "."));
  82 
  83         de = xreaddir(d);
  84         assert(de->d_type == DT_DIR);
  85         assert(streq(de->d_name, ".."));
  86 
  87         while ((de = xreaddir(d))) {
  88                 assert(!streq(de->d_name, "."));
  89                 assert(!streq(de->d_name, ".."));
  90 
  91                 switch (de->d_type) {
  92                         DIR *dd;
  93                         int fd;
  94 
  95                 case DT_REG:
  96                         if (level == 0 && streq(de->d_name, "sysrq-trigger")) {
  97                                 f_reg_write(d, de->d_name, "h", 1);
  98                         } else if (level == 1 && streq(de->d_name, "clear_refs")) {
  99                                 f_reg_write(d, de->d_name, "1", 1);
 100                         } else if (level == 3 && streq(de->d_name, "clear_refs")) {
 101                                 f_reg_write(d, de->d_name, "1", 1);
 102                         } else {
 103                                 f_reg(d, de->d_name);
 104                         }
 105                         break;
 106                 case DT_DIR:
 107                         fd = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY);
 108                         if (fd == -1)
 109                                 continue;
 110                         dd = fdopendir(fd);
 111                         if (!dd)
 112                                 continue;
 113                         f(dd, level + 1);
 114                         closedir(dd);
 115                         break;
 116                 case DT_LNK:
 117                         f_lnk(d, de->d_name);
 118                         break;
 119                 default:
 120                         assert(0);
 121                 }
 122         }
 123 }
 124 
 125 int main(void)
 126 {
 127         DIR *d;
 128         struct statfs sfs;
 129 
 130         d = opendir("/proc");
 131         if (!d)
 132                 return 4;
 133 
 134         /* Ensure /proc is proc. */
 135         if (fstatfs(dirfd(d), &sfs) == -1) {
 136                 return 1;
 137         }
 138         if (sfs.f_type != 0x9fa0) {
 139                 fprintf(stderr, "error: unexpected f_type %lx\n", (long)sfs.f_type);
 140                 return 2;
 141         }
 142 
 143         f(d, 0);
 144 
 145         return 0;
 146 }

/* [<][>][^][v][top][bottom][index][help] */