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