1 /****************************************************************************** 2 * 3 * Copyright (c) International Business Machines Corp., 2006 4 * Author: Yi Yang <yyangcdl (at) cn.ibm.com> 5 * Copyright (c) Cyril Hrubis 2014 <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 * DESCRIPTION 22 * This test case will verify basic function of mknodat 23 * added by kernel 2.6.16 or up. 24 * 25 *****************************************************************************/ 26 27 #define _GNU_SOURCE 28 29 #include <sys/types.h> 30 #include <fcntl.h> 31 #include <sys/stat.h> 32 #include <error.h> 33 #include <stdlib.h> 34 #include <errno.h> 35 #include <string.h> 36 #include <signal.h> 37 #include "test.h" 38 #include "safe_macros.h" 39 #include "lapi/fcntl.h" 40 #include "mknodat.h" 41 42 #define PATHNAME "mknodattestdir" 43 44 static void setup(void); 45 static void cleanup(void); 46 static void clean(void); 47 48 static char testfilepath[256]; 49 static char testfile[256]; 50 static char testfile2[256]; 51 static char testfile3[256]; 52 53 static int dir_fd, fd; 54 static int fd_invalid = 100; 55 static int fd_atcwd = AT_FDCWD; 56 57 static struct test_case { 58 int *dir_fd; 59 const char *name; 60 int exp_ret; 61 int exp_errno; 62 } test_cases[] = { 63 {&dir_fd, testfile, 0, 0}, 64 {&dir_fd, testfile3, 0, 0}, 65 {&fd, testfile2, -1, ENOTDIR}, 66 {&fd_invalid, testfile, -1, EBADF}, 67 {&fd_atcwd, testfile, 0, 0} 68 }; 69 70 char *TCID = "mknodat01"; 71 int TST_TOTAL = ARRAY_SIZE(test_cases); 72 73 static dev_t dev; 74 75 static void verify_mknodat(struct test_case *test) 76 { 77 TEST(mknodat(*test->dir_fd, test->name, S_IFREG, dev)); 78 79 if (TEST_RETURN != test->exp_ret) { 80 tst_resm(TFAIL | TTERRNO, 81 "mknodat() returned %ld, expected %d", 82 TEST_RETURN, test->exp_ret); 83 return; 84 } 85 86 if (TEST_ERRNO != test->exp_errno) { 87 tst_resm(TFAIL | TTERRNO, 88 "mknodat() returned wrong errno, expected %d", 89 test->exp_errno); 90 return; 91 } 92 93 tst_resm(TPASS | TTERRNO, "mknodat() returned %ld", TEST_RETURN); 94 } 95 96 int main(int ac, char **av) 97 { 98 int lc; 99 int i; 100 101 tst_parse_opts(ac, av, NULL, NULL); 102 103 setup(); 104 105 for (lc = 0; TEST_LOOPING(lc); lc++) { 106 tst_count = 0; 107 108 for (i = 0; i < TST_TOTAL; i++) 109 verify_mknodat(test_cases + i); 110 111 /* clean created nodes before next run */ 112 clean(); 113 } 114 115 cleanup(); 116 tst_exit(); 117 } 118 119 static void setup(void) 120 { 121 char *tmpdir; 122 123 if (tst_kvercmp(2, 6, 16) < 0) 124 tst_brkm(TCONF, NULL, "This test needs kernel 2.6.16 or newer"); 125 126 tst_sig(NOFORK, DEF_HANDLER, cleanup); 127 128 TEST_PAUSE; 129 130 tst_tmpdir(); 131 132 /* Initialize test dir and file names */ 133 tmpdir = tst_get_tmpdir(); 134 sprintf(testfilepath, PATHNAME"/mknodattestfile%d", getpid()); 135 sprintf(testfile, "mknodattestfile%d", getpid()); 136 sprintf(testfile2, "mknodattestfile2%d", getpid()); 137 sprintf(testfile3, "%s/mknodattestfile3%d", tmpdir, getpid()); 138 free(tmpdir); 139 140 SAFE_MKDIR(cleanup, PATHNAME, 0700); 141 142 dir_fd = SAFE_OPEN(cleanup, PATHNAME, O_DIRECTORY); 143 fd = SAFE_OPEN(cleanup, testfile2, O_CREAT | O_RDWR, 0600); 144 } 145 146 static void clean(void) 147 { 148 SAFE_UNLINK(cleanup, testfilepath); 149 SAFE_UNLINK(cleanup, testfile3); 150 SAFE_UNLINK(cleanup, testfile); 151 } 152 153 static void cleanup(void) 154 { 155 if (dir_fd > 0 && close(dir_fd)) 156 tst_resm(TWARN | TERRNO, "Failed to close(dir_fd)"); 157 158 if (fd > 0 && close(fd)) 159 tst_resm(TWARN | TERRNO, "Failed to close(fd)"); 160 161 tst_rmdir(); 162 } 163