xref: /netbsd-src/external/bsd/ntp/dist/tests/libntp/realpath.c (revision eabc0478de71e4e011a5b4e0392741e01d491794)
1*eabc0478Schristos /*	$NetBSD: realpath.c,v 1.2 2024/08/18 20:47:27 christos Exp $	*/
2897be3a4Schristos 
3897be3a4Schristos #include "config.h"
4897be3a4Schristos 
5897be3a4Schristos #include "ntp_stdlib.h"
6897be3a4Schristos #include "unity.h"
7897be3a4Schristos 
8897be3a4Schristos #include <sys/types.h>
9897be3a4Schristos #include <sys/stat.h>
10897be3a4Schristos #include <unistd.h>
11897be3a4Schristos #include <dirent.h>
12897be3a4Schristos #include <stdarg.h>
13897be3a4Schristos 
14897be3a4Schristos static char * resolved;
15897be3a4Schristos 
16897be3a4Schristos void setUp(void);
17897be3a4Schristos void setUp(void) {
18897be3a4Schristos 	resolved = NULL;
19897be3a4Schristos }
20897be3a4Schristos 
21897be3a4Schristos void tearDown(void);
22897be3a4Schristos void tearDown(void) {
23897be3a4Schristos 	free(resolved);
24897be3a4Schristos 	resolved = NULL;
25897be3a4Schristos }
26897be3a4Schristos 
27897be3a4Schristos static int/*BOOL*/ isValidAbsPath(const char * path)
28897be3a4Schristos {
29897be3a4Schristos 	int retv = FALSE;
30897be3a4Schristos 	/* this needs some elaboration: */
31897be3a4Schristos 	if (path && path[0] == '/') {
32897be3a4Schristos 		struct stat sb;
33897be3a4Schristos 		if (0 == lstat(path, &sb)) {
34897be3a4Schristos 			retv = (sb.st_mode & S_IFMT) != S_IFLNK;
35897be3a4Schristos 		}
36897be3a4Schristos 	}
37897be3a4Schristos 	return retv;
38897be3a4Schristos }
39897be3a4Schristos 
40897be3a4Schristos static const char * errMsg(const char *fmt, ...)
41897be3a4Schristos {
42897be3a4Schristos 	static char buf[256];
43897be3a4Schristos 	va_list va;
44897be3a4Schristos 	va_start(va, fmt);
45897be3a4Schristos 	vsnprintf(buf, sizeof(buf), fmt, va);
46897be3a4Schristos 	va_end(va);
47897be3a4Schristos 	return buf;
48897be3a4Schristos }
49897be3a4Schristos 
50897be3a4Schristos void test_CurrentWorkingDir(void);
51897be3a4Schristos void test_CurrentWorkingDir(void) {
52897be3a4Schristos #   ifdef SYS_WINNT
53897be3a4Schristos 	TEST_IGNORE_MESSAGE("not applicable to windows so far");
54897be3a4Schristos #   else
55897be3a4Schristos 	resolved = ntp_realpath(".");
56897be3a4Schristos 	TEST_ASSERT_NOT_NULL_MESSAGE(resolved, "failed to resolve '.'");
57897be3a4Schristos 	TEST_ASSERT_TRUE_MESSAGE(isValidAbsPath(resolved), "'.' not resolved to absolute path");
58897be3a4Schristos #   endif
59897be3a4Schristos }
60897be3a4Schristos 
61897be3a4Schristos void test_DevLinks(void);
62897be3a4Schristos void test_DevLinks(void) {
63897be3a4Schristos #   ifdef SYS_WINNT
64897be3a4Schristos 	TEST_IGNORE_MESSAGE("not applicable to windows so far");
65897be3a4Schristos #   else
66897be3a4Schristos 	char            nam[512];
67897be3a4Schristos 	char            abs[512];
68897be3a4Schristos 	struct dirent * ent;
69897be3a4Schristos 	DIR           * dfs = opendir("/dev");
70897be3a4Schristos 
71897be3a4Schristos 	TEST_ASSERT_NOT_NULL_MESSAGE(dfs, "failed to open '/dev' !?!");
72897be3a4Schristos 	while (NULL != (ent = readdir(dfs))) {
73897be3a4Schristos 		/* the /dev/std{in,out,err} symlinks are prone to some
74897be3a4Schristos 		 * kind of race condition under Linux, so we better skip
75897be3a4Schristos 		 * them here; running tests in parallel can fail mysteriously
76897be3a4Schristos 		 * otherwise. (Dunno *how* this could happen, but it
77897be3a4Schristos 		 * did at some point in time, quite reliably...)
78897be3a4Schristos 		 */
79897be3a4Schristos 		if (!strncmp(ent->d_name, "std", 3))
80897be3a4Schristos 			continue;
81897be3a4Schristos 		/* otherwise build the full name & try to resolve: */
82897be3a4Schristos 		snprintf(nam, sizeof(nam), "/dev/%s", ent->d_name);
83897be3a4Schristos 		resolved = ntp_realpath(nam);
84897be3a4Schristos 		TEST_ASSERT_NOT_NULL_MESSAGE(resolved, errMsg("could not resolve '%s'", nam));
85897be3a4Schristos 		strlcpy(abs, resolved, sizeof(abs));
86897be3a4Schristos 		free(resolved);
87897be3a4Schristos 		resolved = NULL;
88897be3a4Schristos 		/* test/development code:
89897be3a4Schristos 		if (strcmp(nam, abs))
90897be3a4Schristos 			printf(" '%s' --> '%s'\n", nam, abs);
91897be3a4Schristos 		*/
92897be3a4Schristos 		TEST_ASSERT_TRUE_MESSAGE(isValidAbsPath(abs), errMsg("could not validate '%s'", abs));
93897be3a4Schristos 	}
94897be3a4Schristos 	closedir(dfs);
95897be3a4Schristos #   endif
96897be3a4Schristos }
97