test-path-util.c revision 796beea86bcdc92e4ba2f4865414a951b1717e5c
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2016 Dovecot authors, see the included COPYING file */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "test-lib.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "path-util.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "unlink-directory.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include <unistd.h>
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include <stdlib.h>
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include <sys/stat.h>
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#define TEMP_DIRNAME ".test-path-util"
7a7d2aa11e46195e2d92d6c337d7e78052a5ce67Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic const char *tmpdir;
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainenstatic const char *cwd;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic const char *link1;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic const char *link2;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic const char *link3;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic void test_local_path() {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *expected = t_strconcat(cwd, "/README.md", NULL);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *npath = NULL, *error = NULL;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen test_assert(t_normpath_to("README.md", cwd, &npath, &error) == 0);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen test_assert_strcmp(npath, expected);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic void test_absolute_path_no_change(void) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char *npath = NULL, *error = NULL;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert(t_normpath_to("/", "/", &npath, &error) == 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert_strcmp(npath, "/");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen test_assert(t_normpath_to(cwd, cwd, &npath, &error) == 0);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen test_assert_strcmp(npath, cwd);
f5a7396b31762a1f876517e13ce9065820139f7cTimo Sirainen}
f5a7396b31762a1f876517e13ce9065820139f7cTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic int path_height(const char* p) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen int n;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen for (n = 0; *p != '\0'; ++p)
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen n += *p == '/';
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen return n;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen}
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainenstatic void test_travel_to_root(void) {
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen int l = path_height(cwd);
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen const char *npath = cwd;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen for (npath = cwd; l != 0; l--) {
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen const char *error;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen test_assert_idx(t_normpath_to("../", npath, &npath, &error) == 0, l);
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen }
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen test_assert_strcmp(npath, "/");
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen}
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainenstatic void test_extra_slashes(void) {
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen const char *npath = NULL, *error = NULL;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen test_assert(t_normpath_to(".", cwd, &npath, &error) == 0);
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen test_assert_strcmp(npath, cwd);
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen test_assert(t_normpath_to("./", cwd, &npath, &error) == 0);
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen test_assert_strcmp(npath, cwd);
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen test_assert(t_normpath_to(".////", cwd, &npath, &error) == 0);
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen test_assert_strcmp(npath, cwd);
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen}
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen
942302b0247403645394d848b3c620ead262a2a5Timo Sirainenstatic void test_nonexistent_path(void) {
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen const char *npath = NULL, *error = NULL;
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen const char *expected = t_strconcat(cwd, "/nonexistent", NULL);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert(t_normpath_to("nonexistent", cwd, &npath, &error) == 0);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen test_assert_strcmp(npath, expected);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen test_assert(t_realpath_to("nonexistent", cwd, &npath, &error) == -1);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen test_assert(error != NULL);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
cd8507179823de33d6e8242e10dbc15d136245b5Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic void test_relative_dotdot() {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *rel_path = "../"TEMP_DIRNAME;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *npath = NULL, *error = NULL;
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen test_assert(t_normpath_to(rel_path, tmpdir, &npath, &error) == 0);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen test_assert_strcmp(npath, tmpdir);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen test_assert(t_normpath_to("..", tmpdir, &npath, &error) == 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert_strcmp(npath, cwd);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert(t_normpath_to("../", tmpdir, &npath, &error) == 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert_strcmp(npath, cwd);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert(t_normpath_to("../.", tmpdir, &npath, &error) == 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert_strcmp(npath, cwd);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic void test_link1() {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const char *npath = NULL, *error = NULL;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen test_assert(t_realpath_to(link1, "/", &npath, &error) == 0);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen test_assert_strcmp(npath, tmpdir);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic void test_link_loop() {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const char *npath = NULL, *error = NULL;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen errno = 0;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen test_assert(t_realpath_to(link2, "/", &npath, &error) == -1);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen test_assert(errno == ELOOP);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen test_assert(error != NULL);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic void test_abspath_vs_normpath() {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *abs = t_abspath_to("../../bin", "/usr/lib/");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen test_assert_strcmp(abs, "/usr/lib//../../bin");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *norm = NULL, *error = NULL;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen test_assert(t_normpath_to("../../bin", "/usr///lib/", &norm, &error) == 0);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen test_assert_strcmp(norm, "/bin");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic void test_cleanup(void)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const char *error;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (unlink_directory(tmpdir, UNLINK_DIRECTORY_FLAG_RMDIR, &error) < 0)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_error("unlink_directory() failed: %s", error);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic void test_init(void) {
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen const char *error;
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen test_assert(t_get_working_dir(&cwd, &error) == 0);
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen tmpdir = t_strconcat(cwd, "/"TEMP_DIRNAME, NULL);
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen test_cleanup();
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen if (mkdir(tmpdir, 0700) < 0) {
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen i_fatal("mkdir: %m");
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen }
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen link1 = t_strconcat(tmpdir, "/link1", NULL);
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen if (symlink(tmpdir, link1) < 0) {
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen i_fatal("symlink(%s, %s) failed: %m", tmpdir, link1);
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen }
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen /* link2 and link3 point to each other to create a loop */
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen link2 = t_strconcat(tmpdir, "/link2", NULL);
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen link3 = t_strconcat(tmpdir, "/link3", NULL);
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen if (symlink(link3, link2) < 0) {
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen i_fatal("symlink(%s, %s) failed: %m", link3, link2);
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen }
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen if (symlink(link2, link3) < 0) {
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen i_fatal("symlink(%s, %s) failed: %m", link2, link3);
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen }
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen}
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainenvoid test_path_util(void) {
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen test_begin("test_path_util");
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen test_init();
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen test_local_path();
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen test_absolute_path_no_change();
8305127d1074cf9a1e25dec9be2735276462079dTimo Sirainen test_travel_to_root();
8305127d1074cf9a1e25dec9be2735276462079dTimo Sirainen test_extra_slashes();
8305127d1074cf9a1e25dec9be2735276462079dTimo Sirainen test_nonexistent_path();
8305127d1074cf9a1e25dec9be2735276462079dTimo Sirainen test_relative_dotdot();
8305127d1074cf9a1e25dec9be2735276462079dTimo Sirainen test_link1();
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen test_link_loop();
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen test_abspath_vs_normpath();
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen test_cleanup();
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen test_end();
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen}
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen