Home | History | Annotate | Download | only in getdents
      1 /*
      2  * Copyright (c) International Business Machines  Corp., 2001
      3  *	         written by Wayne Boyer
      4  * Copyright (c) 2013 Markos Chandras
      5  * Copyright (c) 2013 Cyril Hrubis <chrubis (at) suse.cz>
      6  *
      7  * This program is free software;  you can redistribute it and/or modify
      8  * it under the terms of the GNU General Public License as published by
      9  * the Free Software Foundation; either version 2 of the License, or
     10  * (at your option) any later version.
     11  *
     12  * This program is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY;  without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
     15  * the GNU General Public License for more details.
     16  *
     17  * You should have received a copy of the GNU General Public License
     18  * along with this program;  if not, write to the Free Software
     19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     20  */
     21 
     22 /*
     23  * Test Description:
     24  *  Verify that,
     25  *   1. getdents() fails with -1 return value and sets errno to EBADF
     26  *      if file descriptor fd is invalid.
     27  *   2. getdents() fails with -1 return value and sets errno to EINVAL
     28  *      if result buffer is too small.
     29  *   3. getdents() fails with -1 return value and sets errno to ENOTDIR
     30  *      if file descriptor does not refer to a directory.
     31  *   4. getdents() fails with -1 return value and sets errno to ENOENT
     32  *      if there is no such directory.
     33  *
     34  */
     35 
     36 #define _GNU_SOURCE
     37 #include <stdio.h>
     38 #include <errno.h>
     39 #include <sys/types.h>
     40 #include <sys/stat.h>
     41 #include <fcntl.h>
     42 
     43 #include "test.h"
     44 #include "getdents.h"
     45 #include "safe_macros.h"
     46 
     47 #define DIR_MODE	(S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \
     48 			 S_IXGRP|S_IROTH|S_IXOTH)
     49 #define TEST_DIR	"test_dir"
     50 
     51 static void cleanup(void);
     52 static void setup(void);
     53 static void print_test_result(int err, int exp_errno);
     54 
     55 char *TCID = "getdents02";
     56 
     57 static void test_ebadf(void);
     58 static void test_einval(void);
     59 static void test_enotdir(void);
     60 static void test_enoent(void);
     61 
     62 static void (*testfunc[])(void) = { test_ebadf, test_einval,
     63 				    test_enotdir, test_enoent };
     64 
     65 int TST_TOTAL = ARRAY_SIZE(testfunc);
     66 
     67 static int longsyscall;
     68 
     69 option_t options[] = {
     70 		/* -l long option. Tests getdents64 */
     71 		{"l", &longsyscall, NULL},
     72 		{NULL, NULL, NULL}
     73 };
     74 
     75 static void help(void)
     76 {
     77 	printf("  -l      Test the getdents64 system call\n");
     78 }
     79 
     80 int main(int ac, char **av)
     81 {
     82 	int lc, i;
     83 
     84 	tst_parse_opts(ac, av, options, &help);
     85 
     86 	setup();
     87 
     88 	for (lc = 0; TEST_LOOPING(lc); lc++) {
     89 		tst_count = 0;
     90 
     91 		for (i = 0; i < TST_TOTAL; i++)
     92 			(*testfunc[i])();
     93 	}
     94 
     95 	cleanup();
     96 	tst_exit();
     97 }
     98 
     99 static void setup(void)
    100 {
    101 	tst_sig(NOFORK, DEF_HANDLER, cleanup);
    102 
    103 	tst_tmpdir();
    104 
    105 	TEST_PAUSE;
    106 }
    107 
    108 static void print_test_result(int err, int exp_errno)
    109 {
    110 	if (err == 0) {
    111 		tst_resm(TFAIL, "call succeeded unexpectedly");
    112 	} else if  (err == exp_errno) {
    113 		tst_resm(TPASS, "getdents failed as expected: %s",
    114 			 strerror(err));
    115 	} else if (err == ENOSYS) {
    116 		tst_resm(TCONF, "syscall not implemented");
    117 	} else {
    118 		tst_resm(TFAIL, "getdents failed unexpectedly: %s",
    119 			 strerror(err));
    120 	}
    121 }
    122 
    123 static void test_ebadf(void)
    124 {
    125 	int fd = -5;
    126 	struct linux_dirent64 dirp64;
    127 	struct linux_dirent dirp;
    128 
    129 	if (longsyscall)
    130 		getdents64(fd, &dirp64, sizeof(dirp64));
    131 	else
    132 		getdents(fd, &dirp, sizeof(dirp));
    133 
    134 	print_test_result(errno, EBADF);
    135 }
    136 
    137 static void test_einval(void)
    138 {
    139 	int fd;
    140 	char buf[1];
    141 
    142 	fd = SAFE_OPEN(cleanup, ".", O_RDONLY);
    143 
    144 	/* Pass one byte long buffer. The result should be EINVAL */
    145 	if (longsyscall)
    146 		getdents64(fd, (void *)buf, sizeof(buf));
    147 	else
    148 		getdents(fd, (void *)buf, sizeof(buf));
    149 
    150 	print_test_result(errno, EINVAL);
    151 
    152 	SAFE_CLOSE(cleanup, fd);
    153 }
    154 
    155 static void test_enotdir(void)
    156 {
    157 	int fd;
    158 	struct linux_dirent64 dir64;
    159 	struct linux_dirent dir;
    160 
    161 	fd = SAFE_OPEN(cleanup, "test", O_CREAT | O_RDWR);
    162 
    163 	if (longsyscall)
    164 		getdents64(fd, &dir64, sizeof(dir64));
    165 	else
    166 		getdents(fd, &dir, sizeof(dir));
    167 
    168 	print_test_result(errno, ENOTDIR);
    169 
    170 	SAFE_CLOSE(cleanup, fd);
    171 }
    172 
    173 static void test_enoent(void)
    174 {
    175 	int fd;
    176 	struct linux_dirent64 dir64;
    177 	struct linux_dirent dir;
    178 
    179 	SAFE_MKDIR(cleanup, TEST_DIR, DIR_MODE);
    180 
    181 	fd = SAFE_OPEN(cleanup, TEST_DIR, O_DIRECTORY);
    182 	SAFE_RMDIR(cleanup, TEST_DIR);
    183 
    184 	if (longsyscall)
    185 		getdents64(fd, &dir64, sizeof(dir64));
    186 	else
    187 		getdents(fd, &dir, sizeof(dir));
    188 
    189 	print_test_result(errno, ENOENT);
    190 
    191 	SAFE_CLOSE(cleanup, fd);
    192 }
    193 
    194 static void cleanup(void)
    195 {
    196 	tst_rmdir();
    197 }
    198