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