1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * proc01.c - Tests Linux /proc file reading. 3f08c3bdfSopenharmony_ci * 4f08c3bdfSopenharmony_ci * Copyright (C) 2001 Stephane Fillod <f4cfe@free.fr> 5f08c3bdfSopenharmony_ci * Copyright (c) 2008, 2009 Red Hat, Inc. 6f08c3bdfSopenharmony_ci * 7f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify it 8f08c3bdfSopenharmony_ci * under the terms of version 2 of the GNU General Public License as 9f08c3bdfSopenharmony_ci * published by the Free Software Foundation. 10f08c3bdfSopenharmony_ci * 11f08c3bdfSopenharmony_ci * This program is distributed in the hope that it would be useful, but 12f08c3bdfSopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of 13f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 14f08c3bdfSopenharmony_ci * 15f08c3bdfSopenharmony_ci * Further, this software is distributed without any warranty that it is 16f08c3bdfSopenharmony_ci * free of the rightful claim of any third person regarding infringement 17f08c3bdfSopenharmony_ci * or the like. Any license provided herein, whether implied or 18f08c3bdfSopenharmony_ci * otherwise, applies only to this software file. Patent licenses, if 19f08c3bdfSopenharmony_ci * any, provided herein do not apply to combinations of this program with 20f08c3bdfSopenharmony_ci * other software, or any other product whatsoever. 21f08c3bdfSopenharmony_ci * 22f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License along 23f08c3bdfSopenharmony_ci * with this program; if not, write the Free Software Foundation, Inc., 24f08c3bdfSopenharmony_ci * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 25f08c3bdfSopenharmony_ci * 26f08c3bdfSopenharmony_ci */ 27f08c3bdfSopenharmony_ci 28f08c3bdfSopenharmony_ci#include "config.h" 29f08c3bdfSopenharmony_ci 30f08c3bdfSopenharmony_ci#include <errno.h> 31f08c3bdfSopenharmony_ci#include <stdio.h> 32f08c3bdfSopenharmony_ci#include <stdlib.h> 33f08c3bdfSopenharmony_ci#include <string.h> 34f08c3bdfSopenharmony_ci#include <limits.h> 35f08c3bdfSopenharmony_ci#include <sys/types.h> 36f08c3bdfSopenharmony_ci#include <sys/stat.h> 37f08c3bdfSopenharmony_ci#include <dirent.h> 38f08c3bdfSopenharmony_ci#include <unistd.h> 39f08c3bdfSopenharmony_ci#include <fcntl.h> 40f08c3bdfSopenharmony_ci#include <fnmatch.h> 41f08c3bdfSopenharmony_ci 42f08c3bdfSopenharmony_ci#ifdef HAVE_LIBSELINUX_DEVEL 43f08c3bdfSopenharmony_ci#include <selinux/selinux.h> 44f08c3bdfSopenharmony_ci#endif 45f08c3bdfSopenharmony_ci 46f08c3bdfSopenharmony_ci#include "test.h" 47f08c3bdfSopenharmony_ci 48f08c3bdfSopenharmony_ci#define MAX_BUFF_SIZE 65536 49f08c3bdfSopenharmony_ci#define MAX_FUNC_NAME 256 50f08c3bdfSopenharmony_ci 51f08c3bdfSopenharmony_cichar *TCID = "proc01"; 52f08c3bdfSopenharmony_ciint TST_TOTAL = 1; 53f08c3bdfSopenharmony_ci 54f08c3bdfSopenharmony_cistatic int opt_verbose; 55f08c3bdfSopenharmony_cistatic int opt_procpath; 56f08c3bdfSopenharmony_cistatic char *opt_procpathstr; 57f08c3bdfSopenharmony_cistatic int opt_buffsize; 58f08c3bdfSopenharmony_cistatic int opt_readirq; 59f08c3bdfSopenharmony_cistatic char *opt_buffsizestr; 60f08c3bdfSopenharmony_cistatic int opt_maxmbytes; 61f08c3bdfSopenharmony_cistatic char *opt_maxmbytesstr; 62f08c3bdfSopenharmony_ci 63f08c3bdfSopenharmony_cistatic char *procpath = "/proc"; 64f08c3bdfSopenharmony_cistatic const char selfpath[] = "/proc/self"; 65f08c3bdfSopenharmony_cisize_t buffsize = 1024; 66f08c3bdfSopenharmony_cistatic unsigned long long maxbytes; 67f08c3bdfSopenharmony_ci 68f08c3bdfSopenharmony_ciunsigned long long total_read; 69f08c3bdfSopenharmony_ciunsigned int total_obj; 70f08c3bdfSopenharmony_ci 71f08c3bdfSopenharmony_cistruct mapping { 72f08c3bdfSopenharmony_ci char func[MAX_FUNC_NAME]; 73f08c3bdfSopenharmony_ci char file[PATH_MAX]; 74f08c3bdfSopenharmony_ci int err; 75f08c3bdfSopenharmony_ci}; 76f08c3bdfSopenharmony_ci 77f08c3bdfSopenharmony_ci/* Those are known failures for 2.6.18 baremetal kernel and Xen dom0 78f08c3bdfSopenharmony_ci kernel on i686, x86_64, ia64, ppc64 and s390x. In addition, It looks 79f08c3bdfSopenharmony_ci like if SELinux is disabled, the test may still fail on some other 80f08c3bdfSopenharmony_ci entries. */ 81f08c3bdfSopenharmony_cistatic const struct mapping known_issues[] = { 82f08c3bdfSopenharmony_ci {"open", "/proc/acpi/event", EBUSY}, 83f08c3bdfSopenharmony_ci {"open", "/proc/sal/cpe/data", EBUSY}, 84f08c3bdfSopenharmony_ci {"open", "/proc/sal/cmc/data", EBUSY}, 85f08c3bdfSopenharmony_ci {"open", "/proc/sal/init/data", EBUSY}, 86f08c3bdfSopenharmony_ci {"open", "/proc/sal/mca/data", EBUSY}, 87f08c3bdfSopenharmony_ci {"open", "/proc/fs/nfsd/pool_stats", ENODEV}, 88f08c3bdfSopenharmony_ci {"read", "/proc/fs/nfsd/clients/*/ctl", EINVAL}, 89f08c3bdfSopenharmony_ci {"read", "/proc/acpi/event", EAGAIN}, 90f08c3bdfSopenharmony_ci {"read", "/proc/kmsg", EAGAIN}, 91f08c3bdfSopenharmony_ci {"read", "/proc/sal/cpe/event", EAGAIN}, 92f08c3bdfSopenharmony_ci {"read", "/proc/sal/cmc/event", EAGAIN}, 93f08c3bdfSopenharmony_ci {"read", "/proc/sal/init/event", EAGAIN}, 94f08c3bdfSopenharmony_ci {"read", "/proc/sal/mca/event", EAGAIN}, 95f08c3bdfSopenharmony_ci {"read", "/proc/xen/privcmd", EIO}, 96f08c3bdfSopenharmony_ci {"read", "/proc/xen/privcmd", EINVAL}, 97f08c3bdfSopenharmony_ci {"read", "/proc/self/mem", EIO}, 98f08c3bdfSopenharmony_ci {"read", "/proc/self/task/[0-9]*/mem", EIO}, 99f08c3bdfSopenharmony_ci {"read", "/proc/self/attr/*", EINVAL}, 100f08c3bdfSopenharmony_ci {"read", "/proc/self/attr/selinux/*", EINVAL}, 101f08c3bdfSopenharmony_ci {"read", "/proc/self/attr/smack/*", EINVAL}, 102f08c3bdfSopenharmony_ci {"read", "/proc/self/attr/apparmor/*", EINVAL}, 103f08c3bdfSopenharmony_ci {"read", "/proc/self/task/[0-9]*/attr/*", EINVAL}, 104f08c3bdfSopenharmony_ci {"read", "/proc/self/task/[0-9]*/attr/smack/*", EINVAL}, 105f08c3bdfSopenharmony_ci {"read", "/proc/self/task/[0-9]*/attr/selinux/*", EINVAL}, 106f08c3bdfSopenharmony_ci {"read", "/proc/self/task/[0-9]*/attr/apparmor/*", EINVAL}, 107f08c3bdfSopenharmony_ci {"read", "/proc/self/ns/*", EINVAL}, 108f08c3bdfSopenharmony_ci {"read", "/proc/self/task/[0-9]*/ns/*", EINVAL}, 109f08c3bdfSopenharmony_ci {"read", "/proc/ppc64/rtas/error_log", EINVAL}, 110f08c3bdfSopenharmony_ci {"read", "/proc/powerpc/rtas/error_log", EINVAL}, 111f08c3bdfSopenharmony_ci {"read", "/proc/fs/nfsd/unlock_filesystem", EINVAL}, 112f08c3bdfSopenharmony_ci {"read", "/proc/fs/nfsd/unlock_ip", EINVAL}, 113f08c3bdfSopenharmony_ci {"read", "/proc/fs/nfsd/filehandle", EINVAL}, 114f08c3bdfSopenharmony_ci {"read", "/proc/fs/nfsd/.getfs", EINVAL}, 115f08c3bdfSopenharmony_ci {"read", "/proc/fs/nfsd/.getfd", EINVAL}, 116f08c3bdfSopenharmony_ci {"read", "/proc/self/net/rpc/use-gss-proxy", EAGAIN}, 117f08c3bdfSopenharmony_ci {"read", "/proc/sys/net/ipv6/conf/*/stable_secret", EIO}, 118f08c3bdfSopenharmony_ci {"read", "/proc/sys/vm/nr_hugepages", EOPNOTSUPP}, 119f08c3bdfSopenharmony_ci {"read", "/proc/sys/vm/nr_overcommit_hugepages", EOPNOTSUPP}, 120f08c3bdfSopenharmony_ci {"read", "/proc/sys/vm/nr_hugepages_mempolicy", EOPNOTSUPP}, 121f08c3bdfSopenharmony_ci {"read", "/proc/pressure/*", EOPNOTSUPP}, 122f08c3bdfSopenharmony_ci {"", "", 0} 123f08c3bdfSopenharmony_ci}; 124f08c3bdfSopenharmony_ci 125f08c3bdfSopenharmony_ci/* 126f08c3bdfSopenharmony_ci * If a particular LSM is enabled, it is expected that some entries can 127f08c3bdfSopenharmony_ci * be read successfully. Otherwise, those entries will retrun some 128f08c3bdfSopenharmony_ci * failures listed above. Here to add any LSM specific entries. 129f08c3bdfSopenharmony_ci */ 130f08c3bdfSopenharmony_ci 131f08c3bdfSopenharmony_ci/* 132f08c3bdfSopenharmony_ci * Test macro to indicate that SELinux libraries and headers are 133f08c3bdfSopenharmony_ci * installed. 134f08c3bdfSopenharmony_ci */ 135f08c3bdfSopenharmony_ci#ifdef HAVE_LIBSELINUX_DEVEL 136f08c3bdfSopenharmony_cistatic const char lsm_should_work[][PATH_MAX] = { 137f08c3bdfSopenharmony_ci "/proc/self/attr/*", 138f08c3bdfSopenharmony_ci "/proc/self/attr/selinux/*", 139f08c3bdfSopenharmony_ci "/proc/self/task/[0-9]*/attr/*", 140f08c3bdfSopenharmony_ci "/proc/self/task/[0-9]*/attr/selinux/*", 141f08c3bdfSopenharmony_ci "" 142f08c3bdfSopenharmony_ci}; 143f08c3bdfSopenharmony_ci#endif 144f08c3bdfSopenharmony_ci 145f08c3bdfSopenharmony_ci/* Known files that does not honor O_NONBLOCK, so they will hang 146f08c3bdfSopenharmony_ci the test while being read. */ 147f08c3bdfSopenharmony_cistatic const char error_nonblock[][PATH_MAX] = { 148f08c3bdfSopenharmony_ci "/proc/xen/xenbus", 149f08c3bdfSopenharmony_ci "" 150f08c3bdfSopenharmony_ci}; 151f08c3bdfSopenharmony_ci 152f08c3bdfSopenharmony_ci/* 153f08c3bdfSopenharmony_ci * Verify expected failures, and then let the test to continue. 154f08c3bdfSopenharmony_ci * 155f08c3bdfSopenharmony_ci * Return 0 when a problem errno is found. 156f08c3bdfSopenharmony_ci * Return 1 when a known issue is found. 157f08c3bdfSopenharmony_ci * 158f08c3bdfSopenharmony_ci */ 159f08c3bdfSopenharmony_cistatic int found_errno(const char *syscall, const char *obj, int tmperr) 160f08c3bdfSopenharmony_ci{ 161f08c3bdfSopenharmony_ci int i; 162f08c3bdfSopenharmony_ci 163f08c3bdfSopenharmony_ci /* Should not see any error for certain entries if a LSM is enabled. */ 164f08c3bdfSopenharmony_ci#ifdef HAVE_LIBSELINUX_DEVEL 165f08c3bdfSopenharmony_ci if (is_selinux_enabled()) { 166f08c3bdfSopenharmony_ci for (i = 0; lsm_should_work[i][0] != '\0'; i++) { 167f08c3bdfSopenharmony_ci if (!strcmp(obj, lsm_should_work[i]) || 168f08c3bdfSopenharmony_ci !fnmatch(lsm_should_work[i], obj, FNM_PATHNAME)) { 169f08c3bdfSopenharmony_ci return 0; 170f08c3bdfSopenharmony_ci } 171f08c3bdfSopenharmony_ci } 172f08c3bdfSopenharmony_ci } 173f08c3bdfSopenharmony_ci#endif 174f08c3bdfSopenharmony_ci for (i = 0; known_issues[i].err != 0; i++) { 175f08c3bdfSopenharmony_ci if (tmperr == known_issues[i].err && 176f08c3bdfSopenharmony_ci (!strcmp(obj, known_issues[i].file) || 177f08c3bdfSopenharmony_ci !fnmatch(known_issues[i].file, obj, FNM_PATHNAME)) && 178f08c3bdfSopenharmony_ci !strcmp(syscall, known_issues[i].func)) { 179f08c3bdfSopenharmony_ci /* Using strcmp / fnmatch could have messed up the 180f08c3bdfSopenharmony_ci * errno value. */ 181f08c3bdfSopenharmony_ci errno = tmperr; 182f08c3bdfSopenharmony_ci tst_resm(TINFO | TERRNO, "%s: known issue", obj); 183f08c3bdfSopenharmony_ci return 1; 184f08c3bdfSopenharmony_ci } 185f08c3bdfSopenharmony_ci } 186f08c3bdfSopenharmony_ci return 0; 187f08c3bdfSopenharmony_ci} 188f08c3bdfSopenharmony_ci 189f08c3bdfSopenharmony_cistatic void cleanup(void) 190f08c3bdfSopenharmony_ci{ 191f08c3bdfSopenharmony_ci tst_rmdir(); 192f08c3bdfSopenharmony_ci} 193f08c3bdfSopenharmony_ci 194f08c3bdfSopenharmony_cistatic void setup(void) 195f08c3bdfSopenharmony_ci{ 196f08c3bdfSopenharmony_ci tst_sig(FORK, DEF_HANDLER, cleanup); 197f08c3bdfSopenharmony_ci TEST_PAUSE; 198f08c3bdfSopenharmony_ci tst_tmpdir(); 199f08c3bdfSopenharmony_ci} 200f08c3bdfSopenharmony_ci 201f08c3bdfSopenharmony_civoid help(void) 202f08c3bdfSopenharmony_ci{ 203f08c3bdfSopenharmony_ci printf(" -b x read byte count\n"); 204f08c3bdfSopenharmony_ci printf(" -m x max megabytes to read from single file\n"); 205f08c3bdfSopenharmony_ci printf(" -q read .../irq/... entries\n"); 206f08c3bdfSopenharmony_ci printf(" -r x proc pathname\n"); 207f08c3bdfSopenharmony_ci printf(" -v verbose mode\n"); 208f08c3bdfSopenharmony_ci} 209f08c3bdfSopenharmony_ci 210f08c3bdfSopenharmony_ci/* 211f08c3bdfSopenharmony_ci * add the -m option whose parameter is the 212f08c3bdfSopenharmony_ci * pages that should be mapped. 213f08c3bdfSopenharmony_ci */ 214f08c3bdfSopenharmony_cistatic option_t options[] = { 215f08c3bdfSopenharmony_ci {"b:", &opt_buffsize, &opt_buffsizestr}, 216f08c3bdfSopenharmony_ci {"m:", &opt_maxmbytes, &opt_maxmbytesstr}, 217f08c3bdfSopenharmony_ci {"q", &opt_readirq, NULL}, 218f08c3bdfSopenharmony_ci {"r:", &opt_procpath, &opt_procpathstr}, 219f08c3bdfSopenharmony_ci {"v", &opt_verbose, NULL}, 220f08c3bdfSopenharmony_ci {NULL, NULL, NULL} 221f08c3bdfSopenharmony_ci}; 222f08c3bdfSopenharmony_ci 223f08c3bdfSopenharmony_ci/* 224f08c3bdfSopenharmony_ci * NB: this function is recursive 225f08c3bdfSopenharmony_ci * returns 0 if no error encountered, otherwise number of errors (objs) 226f08c3bdfSopenharmony_ci * 227f08c3bdfSopenharmony_ci * REM: Funny enough, while developing this function (actually replacing 228f08c3bdfSopenharmony_ci * streamed fopen by standard open), I hit a real /proc bug. 229f08c3bdfSopenharmony_ci * On a 2.2.13-SuSE kernel, "cat /proc/tty/driver/serial" would fail 230f08c3bdfSopenharmony_ci * with EFAULT, while "cat /proc/tty/driver/serial > somefile" wouldn't. 231f08c3bdfSopenharmony_ci * Okay, this might be due to a slight serial misconfiguration, but still. 232f08c3bdfSopenharmony_ci * Analysis with strace showed up the difference was on the count size 233f08c3bdfSopenharmony_ci * of read (1024 bytes vs 4096 bytes). So I tested further.. 234f08c3bdfSopenharmony_ci * read count of 512 bytes adds /proc/tty/drivers to the list 235f08c3bdfSopenharmony_ci * of broken proc files, while 64 bytes reads removes 236f08c3bdfSopenharmony_ci * /proc/tty/driver/serial from the list. Interesting, isn't it? 237f08c3bdfSopenharmony_ci * Now, there's a -b option to this test, so you can try your luck. --SF 238f08c3bdfSopenharmony_ci * 239f08c3bdfSopenharmony_ci * It's more fun to run this test it as root, as all the files will be accessible! 240f08c3bdfSopenharmony_ci * (however, be careful, there might be some bufferoverflow holes..) 241f08c3bdfSopenharmony_ci * reading proc files might be also a good kernel latency killer. 242f08c3bdfSopenharmony_ci */ 243f08c3bdfSopenharmony_cistatic long readproc(const char *obj) 244f08c3bdfSopenharmony_ci{ 245f08c3bdfSopenharmony_ci DIR *dir = NULL; /* pointer to a directory */ 246f08c3bdfSopenharmony_ci struct dirent *dir_ent; /* pointer to directory entries */ 247f08c3bdfSopenharmony_ci char dirobj[PATH_MAX]; /* object inside directory to modify */ 248f08c3bdfSopenharmony_ci struct stat statbuf; /* used to hold stat information */ 249f08c3bdfSopenharmony_ci int fd, tmperr, i; 250f08c3bdfSopenharmony_ci ssize_t nread; 251f08c3bdfSopenharmony_ci static char buf[MAX_BUFF_SIZE]; /* static kills reentrancy, but we don't care about the contents */ 252f08c3bdfSopenharmony_ci unsigned long long file_total_read = 0; 253f08c3bdfSopenharmony_ci 254f08c3bdfSopenharmony_ci /* Determine the file type */ 255f08c3bdfSopenharmony_ci if (lstat(obj, &statbuf) < 0) { 256f08c3bdfSopenharmony_ci 257f08c3bdfSopenharmony_ci /* permission denied is not considered as error */ 258f08c3bdfSopenharmony_ci if (errno != EACCES) { 259f08c3bdfSopenharmony_ci tst_resm(TFAIL | TERRNO, "%s: lstat", obj); 260f08c3bdfSopenharmony_ci return 1; 261f08c3bdfSopenharmony_ci } 262f08c3bdfSopenharmony_ci return 0; 263f08c3bdfSopenharmony_ci 264f08c3bdfSopenharmony_ci } 265f08c3bdfSopenharmony_ci 266f08c3bdfSopenharmony_ci /* Prevent loops, but read /proc/self. */ 267f08c3bdfSopenharmony_ci if (S_ISLNK(statbuf.st_mode) && strcmp(obj, selfpath)) 268f08c3bdfSopenharmony_ci return 0; 269f08c3bdfSopenharmony_ci 270f08c3bdfSopenharmony_ci total_obj++; 271f08c3bdfSopenharmony_ci 272f08c3bdfSopenharmony_ci /* Take appropriate action, depending on the file type */ 273f08c3bdfSopenharmony_ci if (S_ISDIR(statbuf.st_mode) || !strcmp(obj, selfpath)) { 274f08c3bdfSopenharmony_ci 275f08c3bdfSopenharmony_ci /* object is a directory */ 276f08c3bdfSopenharmony_ci 277f08c3bdfSopenharmony_ci /* 278f08c3bdfSopenharmony_ci * Skip over the /proc/irq directory, unless the user 279f08c3bdfSopenharmony_ci * requested that we read the directory because it could 280f08c3bdfSopenharmony_ci * map to a broken driver which effectively `hangs' the 281f08c3bdfSopenharmony_ci * test. 282f08c3bdfSopenharmony_ci */ 283f08c3bdfSopenharmony_ci if (!opt_readirq && !strcmp("/proc/irq", obj)) { 284f08c3bdfSopenharmony_ci return 0; 285f08c3bdfSopenharmony_ci /* Open the directory to get access to what is in it */ 286f08c3bdfSopenharmony_ci } else if ((dir = opendir(obj)) == NULL) { 287f08c3bdfSopenharmony_ci if (errno != EACCES) { 288f08c3bdfSopenharmony_ci tst_resm(TFAIL | TERRNO, "%s: opendir", obj); 289f08c3bdfSopenharmony_ci return 1; 290f08c3bdfSopenharmony_ci } 291f08c3bdfSopenharmony_ci return 0; 292f08c3bdfSopenharmony_ci } else { 293f08c3bdfSopenharmony_ci 294f08c3bdfSopenharmony_ci long ret_val = 0; 295f08c3bdfSopenharmony_ci 296f08c3bdfSopenharmony_ci /* Loop through the entries in the directory */ 297f08c3bdfSopenharmony_ci for (dir_ent = (struct dirent *)readdir(dir); 298f08c3bdfSopenharmony_ci dir_ent != NULL; 299f08c3bdfSopenharmony_ci dir_ent = (struct dirent *)readdir(dir)) { 300f08c3bdfSopenharmony_ci 301f08c3bdfSopenharmony_ci /* Ignore ".", "..", "kcore", and 302f08c3bdfSopenharmony_ci * "/proc/<pid>" (unless this is our 303f08c3bdfSopenharmony_ci * starting point as directed by the 304f08c3bdfSopenharmony_ci * user). 305f08c3bdfSopenharmony_ci */ 306f08c3bdfSopenharmony_ci if (strcmp(dir_ent->d_name, ".") && 307f08c3bdfSopenharmony_ci strcmp(dir_ent->d_name, "..") && 308f08c3bdfSopenharmony_ci strcmp(dir_ent->d_name, "kcore") && 309f08c3bdfSopenharmony_ci (fnmatch("[0-9]*", dir_ent->d_name, 310f08c3bdfSopenharmony_ci FNM_PATHNAME) || 311f08c3bdfSopenharmony_ci strcmp(obj, procpath))) { 312f08c3bdfSopenharmony_ci 313f08c3bdfSopenharmony_ci if (opt_verbose) { 314f08c3bdfSopenharmony_ci fprintf(stderr, "%s\n", 315f08c3bdfSopenharmony_ci dir_ent->d_name); 316f08c3bdfSopenharmony_ci } 317f08c3bdfSopenharmony_ci 318f08c3bdfSopenharmony_ci /* Recursively call this routine to test the 319f08c3bdfSopenharmony_ci * current entry */ 320f08c3bdfSopenharmony_ci snprintf(dirobj, PATH_MAX, 321f08c3bdfSopenharmony_ci "%s/%s", obj, dir_ent->d_name); 322f08c3bdfSopenharmony_ci ret_val += readproc(dirobj); 323f08c3bdfSopenharmony_ci 324f08c3bdfSopenharmony_ci } 325f08c3bdfSopenharmony_ci 326f08c3bdfSopenharmony_ci } 327f08c3bdfSopenharmony_ci 328f08c3bdfSopenharmony_ci /* Close the directory */ 329f08c3bdfSopenharmony_ci if (dir) 330f08c3bdfSopenharmony_ci (void)closedir(dir); 331f08c3bdfSopenharmony_ci 332f08c3bdfSopenharmony_ci return ret_val; 333f08c3bdfSopenharmony_ci 334f08c3bdfSopenharmony_ci } 335f08c3bdfSopenharmony_ci 336f08c3bdfSopenharmony_ci } else { /* if it's not a dir, read it! */ 337f08c3bdfSopenharmony_ci 338f08c3bdfSopenharmony_ci if (!S_ISREG(statbuf.st_mode)) 339f08c3bdfSopenharmony_ci return 0; 340f08c3bdfSopenharmony_ci 341f08c3bdfSopenharmony_ci#ifdef DEBUG 342f08c3bdfSopenharmony_ci fprintf(stderr, "%s", obj); 343f08c3bdfSopenharmony_ci#endif 344f08c3bdfSopenharmony_ci 345f08c3bdfSopenharmony_ci /* is O_NONBLOCK enough to escape from FIFO's ? */ 346f08c3bdfSopenharmony_ci fd = open(obj, O_RDONLY | O_NONBLOCK); 347f08c3bdfSopenharmony_ci if (fd < 0) { 348f08c3bdfSopenharmony_ci tmperr = errno; 349f08c3bdfSopenharmony_ci 350f08c3bdfSopenharmony_ci if (!found_errno("open", obj, tmperr)) { 351f08c3bdfSopenharmony_ci 352f08c3bdfSopenharmony_ci errno = tmperr; 353f08c3bdfSopenharmony_ci 354f08c3bdfSopenharmony_ci if (errno != EACCES) { 355f08c3bdfSopenharmony_ci tst_resm(TFAIL | TERRNO, 356f08c3bdfSopenharmony_ci "%s: open failed", obj); 357f08c3bdfSopenharmony_ci return 1; 358f08c3bdfSopenharmony_ci } 359f08c3bdfSopenharmony_ci 360f08c3bdfSopenharmony_ci } 361f08c3bdfSopenharmony_ci return 0; 362f08c3bdfSopenharmony_ci 363f08c3bdfSopenharmony_ci } 364f08c3bdfSopenharmony_ci 365f08c3bdfSopenharmony_ci /* Skip write-only files. */ 366f08c3bdfSopenharmony_ci if ((statbuf.st_mode & S_IRUSR) == 0 && 367f08c3bdfSopenharmony_ci (statbuf.st_mode & S_IWUSR) != 0) { 368f08c3bdfSopenharmony_ci tst_resm(TINFO, "%s: is write-only.", obj); 369f08c3bdfSopenharmony_ci (void)close(fd); 370f08c3bdfSopenharmony_ci return 0; 371f08c3bdfSopenharmony_ci } 372f08c3bdfSopenharmony_ci 373f08c3bdfSopenharmony_ci /* Skip files does not honor O_NONBLOCK. */ 374f08c3bdfSopenharmony_ci for (i = 0; error_nonblock[i][0] != '\0'; i++) { 375f08c3bdfSopenharmony_ci if (!strcmp(obj, error_nonblock[i])) { 376f08c3bdfSopenharmony_ci tst_resm(TINFO, "%s: does not honor " 377f08c3bdfSopenharmony_ci "O_NONBLOCK", obj); 378f08c3bdfSopenharmony_ci (void)close(fd); 379f08c3bdfSopenharmony_ci return 0; 380f08c3bdfSopenharmony_ci } 381f08c3bdfSopenharmony_ci } 382f08c3bdfSopenharmony_ci 383f08c3bdfSopenharmony_ci file_total_read = 0; 384f08c3bdfSopenharmony_ci do { 385f08c3bdfSopenharmony_ci 386f08c3bdfSopenharmony_ci nread = read(fd, buf, buffsize); 387f08c3bdfSopenharmony_ci 388f08c3bdfSopenharmony_ci if (nread < 0) { 389f08c3bdfSopenharmony_ci 390f08c3bdfSopenharmony_ci tmperr = errno; 391f08c3bdfSopenharmony_ci (void)close(fd); 392f08c3bdfSopenharmony_ci 393f08c3bdfSopenharmony_ci /* ignore no perm (not root) and no 394f08c3bdfSopenharmony_ci * process (terminated) errors */ 395f08c3bdfSopenharmony_ci if (!found_errno("read", obj, tmperr)) { 396f08c3bdfSopenharmony_ci 397f08c3bdfSopenharmony_ci errno = tmperr; 398f08c3bdfSopenharmony_ci 399f08c3bdfSopenharmony_ci if (errno != EACCES && errno != ESRCH) { 400f08c3bdfSopenharmony_ci tst_resm(TFAIL | TERRNO, 401f08c3bdfSopenharmony_ci "read failed: " 402f08c3bdfSopenharmony_ci "%s", obj); 403f08c3bdfSopenharmony_ci return 1; 404f08c3bdfSopenharmony_ci } 405f08c3bdfSopenharmony_ci return 0; 406f08c3bdfSopenharmony_ci 407f08c3bdfSopenharmony_ci } 408f08c3bdfSopenharmony_ci 409f08c3bdfSopenharmony_ci } else 410f08c3bdfSopenharmony_ci file_total_read += nread; 411f08c3bdfSopenharmony_ci 412f08c3bdfSopenharmony_ci if (opt_verbose) { 413f08c3bdfSopenharmony_ci#ifdef DEBUG 414f08c3bdfSopenharmony_ci fprintf(stderr, "%ld", nread); 415f08c3bdfSopenharmony_ci#endif 416f08c3bdfSopenharmony_ci fprintf(stderr, "."); 417f08c3bdfSopenharmony_ci } 418f08c3bdfSopenharmony_ci 419f08c3bdfSopenharmony_ci if ((maxbytes > 0) && (file_total_read > maxbytes)) { 420f08c3bdfSopenharmony_ci tst_resm(TINFO, "%s: reached maxmbytes (-m)", 421f08c3bdfSopenharmony_ci obj); 422f08c3bdfSopenharmony_ci break; 423f08c3bdfSopenharmony_ci } 424f08c3bdfSopenharmony_ci } while (0 < nread); 425f08c3bdfSopenharmony_ci total_read += file_total_read; 426f08c3bdfSopenharmony_ci 427f08c3bdfSopenharmony_ci if (opt_verbose) 428f08c3bdfSopenharmony_ci fprintf(stderr, "\n"); 429f08c3bdfSopenharmony_ci 430f08c3bdfSopenharmony_ci if (0 <= fd) 431f08c3bdfSopenharmony_ci (void)close(fd); 432f08c3bdfSopenharmony_ci 433f08c3bdfSopenharmony_ci } 434f08c3bdfSopenharmony_ci 435f08c3bdfSopenharmony_ci /* It's better to assume success by default rather than failure. */ 436f08c3bdfSopenharmony_ci return 0; 437f08c3bdfSopenharmony_ci 438f08c3bdfSopenharmony_ci} 439f08c3bdfSopenharmony_ci 440f08c3bdfSopenharmony_ciint main(int argc, char *argv[]) 441f08c3bdfSopenharmony_ci{ 442f08c3bdfSopenharmony_ci int lc; 443f08c3bdfSopenharmony_ci 444f08c3bdfSopenharmony_ci tst_parse_opts(argc, argv, options, help); 445f08c3bdfSopenharmony_ci 446f08c3bdfSopenharmony_ci if (opt_buffsize) { 447f08c3bdfSopenharmony_ci size_t bs; 448f08c3bdfSopenharmony_ci bs = atoi(opt_buffsizestr); 449f08c3bdfSopenharmony_ci if (bs <= MAX_BUFF_SIZE) 450f08c3bdfSopenharmony_ci buffsize = bs; 451f08c3bdfSopenharmony_ci else 452f08c3bdfSopenharmony_ci tst_brkm(TBROK, cleanup, 453f08c3bdfSopenharmony_ci "Invalid arg for -b (max: %u): %s", 454f08c3bdfSopenharmony_ci MAX_BUFF_SIZE, opt_buffsizestr); 455f08c3bdfSopenharmony_ci } 456f08c3bdfSopenharmony_ci if (opt_maxmbytes) 457f08c3bdfSopenharmony_ci maxbytes = atoi(opt_maxmbytesstr) * 1024 * 1024; 458f08c3bdfSopenharmony_ci 459f08c3bdfSopenharmony_ci if (opt_procpath) 460f08c3bdfSopenharmony_ci procpath = opt_procpathstr; 461f08c3bdfSopenharmony_ci 462f08c3bdfSopenharmony_ci setup(); 463f08c3bdfSopenharmony_ci 464f08c3bdfSopenharmony_ci for (lc = 0; TEST_LOOPING(lc); lc++) { 465f08c3bdfSopenharmony_ci tst_count = 0; 466f08c3bdfSopenharmony_ci 467f08c3bdfSopenharmony_ci TEST(readproc(procpath)); 468f08c3bdfSopenharmony_ci 469f08c3bdfSopenharmony_ci if (TEST_RETURN != 0) { 470f08c3bdfSopenharmony_ci tst_resm(TFAIL, "readproc() failed with %ld errors.", 471f08c3bdfSopenharmony_ci TEST_RETURN); 472f08c3bdfSopenharmony_ci } else { 473f08c3bdfSopenharmony_ci tst_resm(TPASS, "readproc() completed successfully, " 474f08c3bdfSopenharmony_ci "total read: %llu bytes, %u objs", total_read, 475f08c3bdfSopenharmony_ci total_obj); 476f08c3bdfSopenharmony_ci } 477f08c3bdfSopenharmony_ci } 478f08c3bdfSopenharmony_ci 479f08c3bdfSopenharmony_ci cleanup(); 480f08c3bdfSopenharmony_ci tst_exit(); 481f08c3bdfSopenharmony_ci} 482