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