1 /*
2  * Copyright (c) 2018 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdio.h>
8 #include <fcntl.h>
9 #include <zephyr/posix/unistd.h>
10 #include <zephyr/posix/dirent.h>
11 #include "test_fs.h"
12 
13 extern int test_file_write(void);
14 extern int test_file_close(void);
15 extern int file;
16 
test_mkdir(void)17 static int test_mkdir(void)
18 {
19 	int res;
20 
21 	TC_PRINT("\nmkdir tests:\n");
22 
23 	/* Verify fs_mkdir() */
24 	res = mkdir(TEST_DIR, S_IRWXG);
25 	if (res) {
26 		TC_PRINT("Error creating dir[%d]\n", res);
27 		return res;
28 	}
29 
30 	res = open(TEST_DIR_FILE, O_CREAT | O_RDWR, 0770);
31 
32 	if (res < 0) {
33 		TC_PRINT("Failed opening file [%d]\n", res);
34 		return res;
35 	}
36 	file = res;
37 
38 	res = test_file_write();
39 	if (res) {
40 		return res;
41 	}
42 
43 	res = close(file);
44 	if (res) {
45 		TC_PRINT("Error closing file [%d]\n", res);
46 		return res;
47 	}
48 
49 	TC_PRINT("Created dir %s!\n", TEST_DIR);
50 
51 	return res;
52 }
53 
readdir_wrap(DIR * dirp,bool thread_safe)54 static struct dirent *readdir_wrap(DIR *dirp, bool thread_safe)
55 {
56 	if (thread_safe) {
57 		/* cannot declare on stack otherwise this test fails for qemu_x86/atom */
58 		static struct dirent entry;
59 		struct dirent *result = NULL;
60 
61 		zassert_ok(readdir_r(dirp, &entry, &result));
62 
63 		return result;
64 	} else {
65 		return readdir(dirp);
66 	}
67 }
68 
test_lsdir(const char * path,bool thread_safe)69 static int test_lsdir(const char *path, bool thread_safe)
70 {
71 	DIR *dirp;
72 	int res = 0;
73 	struct dirent *entry;
74 
75 	TC_PRINT("\nreaddir test:\n");
76 
77 	/* Verify fs_opendir() */
78 	dirp = opendir(path);
79 	if (dirp == NULL) {
80 		TC_PRINT("Error opening dir %s\n", path);
81 		return -EIO;
82 	}
83 
84 	TC_PRINT("\nListing dir %s:\n", path);
85 	/* Verify fs_readdir() */
86 	errno = 0;
87 	while ((entry = readdir_wrap(dirp, thread_safe)) != NULL) {
88 		if (entry->d_name[0] == 0) {
89 			res = -EIO;
90 			break;
91 		}
92 
93 		TC_PRINT("[FILE] %s\n", entry->d_name);
94 	}
95 
96 	if (errno) {
97 		res = -EIO;
98 	}
99 
100 	/* Verify fs_closedir() */
101 	closedir(dirp);
102 
103 	return res;
104 }
105 
after_fn(void * unused)106 static void after_fn(void *unused)
107 {
108 	ARG_UNUSED(unused);
109 
110 	unlink(TEST_DIR_FILE);
111 	unlink(TEST_DIR);
112 }
113 
114 /* FIXME: restructure tests as per #46897 */
115 ZTEST_SUITE(posix_fs_dir_test, NULL, test_mount, NULL, after_fn,
116 	    test_unmount);
117 
118 /**
119  * @brief Test for POSIX mkdir API
120  *
121  * @details Test creates a new directory through POSIX
122  * mkdir API and open a new file under the directory and
123  * writes some data into the file.
124  */
ZTEST(posix_fs_dir_test,test_fs_mkdir)125 ZTEST(posix_fs_dir_test, test_fs_mkdir)
126 {
127 	/* FIXME: restructure tests as per #46897 */
128 	zassert_true(test_mkdir() == TC_PASS);
129 }
130 
131 /**
132  * @brief Test for POSIX opendir, readdir and closedir API
133  *
134  * @details Test opens an existing directory through POSIX
135  * opendir API, reads the contents of the directory through
136  * readdir API and closes it through closedir API.
137  */
ZTEST(posix_fs_dir_test,test_fs_readdir)138 ZTEST(posix_fs_dir_test, test_fs_readdir)
139 {
140 	/* FIXME: restructure tests as per #46897 */
141 	zassert_true(test_mkdir() == TC_PASS);
142 	zassert_true(test_lsdir(TEST_DIR, false) == TC_PASS);
143 }
144 
145 /**
146  * Same test as `test_fs_readdir`, but use thread-safe `readdir_r()` function
147  */
ZTEST(posix_fs_dir_test,test_fs_readdir_threadsafe)148 ZTEST(posix_fs_dir_test, test_fs_readdir_threadsafe)
149 {
150 	/* FIXME: restructure tests as per #46897 */
151 	zassert_true(test_mkdir() == TC_PASS);
152 	zassert_true(test_lsdir(TEST_DIR, true) == TC_PASS);
153 }
154 
155 /**
156  * @brief Test for POSIX rmdir API
157  *
158  * @details Test creates a new directory through POSIX
159  * mkdir API and remove directory using rmdir.
160  */
ZTEST(posix_fs_dir_test,test_fs_rmdir)161 ZTEST(posix_fs_dir_test, test_fs_rmdir)
162 {
163 #define IRWXG	0070
164 	/* Create and remove empty directory */
165 	zassert_ok(mkdir(TEST_DIR, IRWXG), "Error creating dir: %d", errno);
166 	zassert_ok(rmdir(TEST_DIR), "Error removing dir: %d\n", errno);
167 
168 	/* Create directory and open a file in the directory
169 	 * now removing the directory will fail, test will
170 	 * fail in removal of non empty directory
171 	 */
172 	zassert_ok(mkdir(TEST_DIR, IRWXG), "Error creating dir: %d", errno);
173 	zassert_not_equal(open(TEST_DIR_FILE, O_CREAT | O_RDWR), -1,
174 			  "Error creating file: %d", errno);
175 	zassert_not_ok(rmdir(TEST_DIR), "Error Non empty dir removed");
176 	zassert_not_ok(rmdir(""), "Error Invalid path removed");
177 	zassert_not_ok(rmdir(NULL), "Error Invalid path removed");
178 	zassert_not_ok(rmdir("TEST_DIR."), "Error Invalid path removed");
179 	zassert_not_ok(rmdir(TEST_FILE), "Error file removed");
180 }
181