Commit 892f59bd authored by Rusty Russell's avatar Rusty Russell

tal/path: new module

Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>


Header from folded patch 'path-talloc-take.patch':

tal/path: accept take() for arguments.
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 1322fd33
...@@ -72,6 +72,7 @@ MODS_NORMAL_WITH_SRC := antithread \ ...@@ -72,6 +72,7 @@ MODS_NORMAL_WITH_SRC := antithread \
str_talloc \ str_talloc \
take \ take \
tal \ tal \
tal/path \
tal/str \ tal/str \
talloc \ talloc \
talloc_link \ talloc_link \
......
../../../licenses/BSD-MIT
\ No newline at end of file
#include <string.h>
#include "config.h"
/**
* tal/path - routines to manipulate paths
*
* This code helps manage paths.
*
* License: BSD-MIT
* Author: Rusty Russell <rusty@rustcorp.com.au>
*
* Example:
* // Program to print out full path names, recursively.
* #include <ccan/tal/path/path.h>
* #include <sys/types.h>
* #include <dirent.h>
* #include <stdio.h>
* #include <ccan/err/err.h>
*
* static void dump(const char *dir)
* {
* struct dirent *di;
* DIR *d = opendir(dir);
* if (!d) {
* warn("Failed to open %s", dir);
* return;
* }
* printf("%s\n", dir);
* while ((di = readdir(d)) != NULL) {
* char *path;
* if (streq(di->d_name, ".") || streq(di->d_name, ".."))
* continue;
* path = path_join(NULL, dir, di->d_name);
* if (path_is_dir(path))
* dump(path);
* tal_free(path);
* }
* closedir(d);
* }
*
* int main(void)
* {
* dump(path_cwd(NULL));
* return 0;
* }
*/
int main(int argc, char *argv[])
{
/* Expect exactly one argument */
if (argc != 2)
return 1;
if (strcmp(argv[1], "depends") == 0) {
printf("ccan/str\n");
printf("ccan/take\n");
printf("ccan/tal\n");
printf("ccan/tal/str\n");
return 0;
}
return 1;
}
This diff is collapsed.
/* Licensed under BSD-MIT - see LICENSE file for details */
#ifndef CCAN_PATH_H
#define CCAN_PATH_H
#include <ccan/tal/tal.h>
#include <stdbool.h>
/**
* path_cwd - get current directory.
* @ctx: the context to tal from
*
* Returns NULL and sets errno on error.
*/
char *path_cwd(const tal_t *ctx);
/**
* path_readlink - get a symbolic link contents
* @ctx: the context to tal the result from
* @link: the link to read (can be take())
*
* Returns NULL and sets errno on error, otherwise returns nul-terminated
* link contents.
*/
char *path_readlink(const tal_t *ctx, const char *link);
/**
* path_canon - return the canonical absolute pathname.
* @ctx: the context to tal the result from.
* @a: path to canonicalize (can be take())
*
* Returns NULL and sets errno on error, otherwise returns an absolute
* path with no symbolic links and no extra separators (ie. as per
* realpath).
*/
char *path_canon(const tal_t *ctx, const char *a);
/**
* path_simplify - remove double-/, ./ and some ../, plus trailing /.
* @ctx: the context to tal the result from
* @a: path to simplify (can be take())
*
* Unlike path_canon(), this routine does not convert a path to absolute
* terms or remove symlinks, but it does neaten it by removing extraneous
* parts.
*/
char *path_simplify(const tal_t *ctx, const char *a);
/**
* path_join - attach one path to another.
* @ctx: the context to tal the result from
* @base: the path to start at (can be take())
* @a: the path to head from there (can be take())
*
* If @a is an absolute path, return a copy of it. Otherwise, attach
* @a to @base.
*/
char *path_join(const tal_t *ctx, const char *base, const char *a);
/**
* path_pushd - save old dir and change to a new one.
* @ctx: the context to tal the result from
* @dir: the directory to return to (can be take())
*/
struct path_pushd *path_pushd(const tal_t *ctx, const char *dir);
/**
* path_popd - return to old, path_pushd dir.
* @olddir: the return from a previous path_pushd.
*
* Returns false and sets errno if it fails.
*/
bool path_popd(struct path_pushd *olddir);
/**
* path_rel - get relative path from a to b.
* @ctx: the context to tal the result from.
* @fromdir: the starting location (can be take())
* @to: the destination location (can be take())
*
* This returns a relative path which leads from @fromdir (assumed to be a
* directory) to @to. If @ctx it TAL_TAKE, frees both @fromdir and @to.
*
* Example:
* char *path = path_rel(NULL, "/tmp", "/");
* assert(strcmp(path, "..") == 0);
*/
char *path_rel(const tal_t *ctx, const char *fromdir, const char *to);
/**
* path_basename - get trailing filename part of path
* @ctx: the context to tal the result from
* @path: the path (can be take())
*
* This follows SUSv2:
* path dirname basename
* "/usr/lib" "/usr" "lib"
* "/usr/" "/" "usr"
* "usr" "." "usr"
* "/" "/" "/"
* "." "." "."
* ".." "." ".."
*
* See Also:
* path_dirname()
*/
char *path_basename(const tal_t *ctx, const char *path);
/**
* path_dirname - get the directory part of path
* @ctx: the context to tal the result from.
* @path: the path (can be take())
*
* This follows SUSv2.
*
* See Also:
* path_basename()
*/
char *path_dirname(const tal_t *ctx, const char *path);
/**
* path_is_abs - is a path absolute?
* @path: the path to examine.
*/
bool path_is_abs(const char *path);
/**
* path_is_file - is a path an existing file (or long to one)?
* @path: the path to examine.
*/
bool path_is_file(const char *path);
/**
* path_is_file - is a path an existing directory (or long to one)?
* @path: the path to examine.
*/
bool path_is_dir(const char *path);
/**
* path_split - split a path into its pathname components
* @ctx: the context to tal the result from
* @path: the path (can be take())
*
* This returns the sections of a path, such that joining them with /
* will restore the original path. This means that the resulting
* strings will never contain / unless the input path was entirely one
* or more "/" characters.
*
* The final char * in the array will be NULL.
*
* See Also:
* strjoin()
*/
char **path_split(const tal_t *ctx, const char *path);
/**
* path_ext_off - get offset of the extension within a pathname.
* @path: the path
*
* This returns the offset of the final . in the pathname (ie.
* path[path_ext_off(path)] == '.') or the length of the string
* if there is no extension.
*
* Note that if the only . in the basename is at the start
* (eg. /home/person/.bashrc), that is not considered an extension!
*/
size_t path_ext_off(const char *path);
#endif /* CCAN_PATH_H */
#include <ccan/tal/path/path.h>
#include <ccan/tal/path/path.c>
#include <ccan/tap/tap.h>
int main(void)
{
char *path, *ctx = tal_strdup(NULL, "ctx");
plan_tests(26);
path = path_basename(ctx, "/usr/lib");
ok1(streq(path, "lib"));
ok1(tal_parent(path) == ctx);
path = path_basename(ctx, "/usr/");
ok1(streq(path, "usr"));
ok1(tal_parent(path) == ctx);
path = path_basename(ctx, "/usr//");
ok1(streq(path, "usr"));
ok1(tal_parent(path) == ctx);
path = path_basename(ctx, "usr");
ok1(streq(path, "usr"));
ok1(tal_parent(path) == ctx);
path = path_basename(ctx, "/");
ok1(streq(path, "/"));
ok1(tal_parent(path) == ctx);
path = path_basename(ctx, "//");
ok1(streq(path, "/"));
ok1(tal_parent(path) == ctx);
path = path_basename(ctx, ".");
ok1(streq(path, "."));
ok1(tal_parent(path) == ctx);
path = path_basename(ctx, "./");
ok1(streq(path, "."));
ok1(tal_parent(path) == ctx);
path = path_basename(ctx, "..");
ok1(streq(path, ".."));
ok1(tal_parent(path) == ctx);
path = path_basename(ctx, "../");
ok1(streq(path, ".."));
ok1(tal_parent(path) == ctx);
tal_free(ctx);
ctx = tal_strdup(NULL, "ctx");
ok1(!tal_first(ctx));
/* Test take */
path = path_basename(ctx, take(tal_strdup(ctx, "..")));
ok1(streq(path, ".."));
ok1(tal_parent(path) == ctx);
ok1(tal_first(ctx) == path && !tal_next(ctx, path));
tal_free(path);
ok1(path_basename(ctx, take(NULL)) == NULL);
ok1(!tal_first(ctx));
tal_free(ctx);
return exit_status();
}
#include <ccan/tal/path/path.h>
#include <ccan/tal/path/path.c>
#include <ccan/tap/tap.h>
int main(void)
{
char cwd[1024], *path, *path2, *ctx = tal_strdup(NULL, "ctx");
plan_tests(15);
if (!getcwd(cwd, sizeof(cwd)))
abort();
unlink("run-canon-link");
rmdir("run-canon-foo");
if (mkdir("run-canon-foo", 0700) != 0)
abort();
if (symlink("run-canon-foo", "run-canon-link") != 0)
abort();
path = path_canon(ctx, "run-canon-foo");
ok1(tal_parent(path) == ctx);
ok1(strends(path, "run-canon-foo"));
ok1(strstarts(path, cwd));
ok1(path[strlen(cwd)] == PATH_SEP);
ok1(strlen(path) == strlen(cwd) + 1 + strlen("run-canon-foo"));
tal_free(path);
ok1(!path_canon(ctx, take(NULL)));
ok1(tal_first(ctx) == NULL);
/* Test take doesn't leak. */
ok1(tal_first(ctx) == NULL);
path = path_canon(ctx, take(tal_strdup(ctx, "run-canon-foo")));
ok1(strends(path, "run-canon-foo"));
ok1(strstarts(path, cwd));
ok1(path[strlen(cwd)] == PATH_SEP);
ok1(strlen(path) == strlen(cwd) + 1 + strlen("run-canon-foo"));
ok1(tal_first(ctx) == path && tal_next(ctx, path) == NULL);
path2 = path_canon(ctx, "run-canon-link");
ok1(streq(path2, path));
unlink("run-canon-link");
if (symlink(".", "run-canon-link") != 0)
abort();
path = path_canon(ctx, "run-canon-link");
ok1(streq(path, cwd));
tal_free(ctx);
return exit_status();
}
#include <ccan/tal/path/path.h>
#include <ccan/tal/path/path.c>
#include <ccan/tap/tap.h>
int main(void)
{
char path1[1024], *cwd, *ctx = tal_strdup(NULL, "ctx");
/* This is how many tests you plan to run */
plan_tests(5);
if (!getcwd(path1, sizeof(path1)))
abort();
cwd = path_cwd(ctx);
ok1(cwd);
ok1(tal_parent(cwd) == ctx);
tal_free(cwd);
rmdir("run-cwd-long-long-long-name/bar-long-long-long-long-name");
rmdir("run-cwd-long-long-long-name");
if (mkdir("run-cwd-long-long-long-name", 0700) != 0)
abort();
if (mkdir("run-cwd-long-long-long-name/bar-long-long-long-long-name", 0700) != 0)
abort();
if (chdir("run-cwd-long-long-long-name/bar-long-long-long-long-name") != 0)
abort();
cwd = path_cwd(ctx);
ok1(cwd);
ok1(tal_parent(cwd) == ctx);
ok1(strends(cwd,
"run-cwd-long-long-long-name/bar-long-long-long-long-name"));
tal_free(ctx);
return exit_status();
}
#include <ccan/tal/path/path.h>
#include <ccan/tal/path/path.c>
#include <ccan/tap/tap.h>
int main(void)
{
char *path, *ctx = tal_strdup(NULL, "ctx");
plan_tests(26);
path = path_dirname(ctx, "/usr/lib");
ok1(streq(path, "/usr"));
ok1(tal_parent(path) == ctx);
path = path_dirname(ctx, "/usr/");
ok1(streq(path, "/"));
ok1(tal_parent(path) == ctx);
path = path_dirname(ctx, "/usr//");
ok1(streq(path, "/"));
ok1(tal_parent(path) == ctx);
path = path_dirname(ctx, "usr");
ok1(streq(path, "."));
ok1(tal_parent(path) == ctx);
path = path_dirname(ctx, "/");
ok1(streq(path, "/"));
ok1(tal_parent(path) == ctx);
path = path_dirname(ctx, "//");
ok1(streq(path, "/"));
ok1(tal_parent(path) == ctx);
path = path_dirname(ctx, ".");
ok1(streq(path, "."));
ok1(tal_parent(path) == ctx);
path = path_dirname(ctx, "./");
ok1(streq(path, "."));
ok1(tal_parent(path) == ctx);
path = path_dirname(ctx, "..");
ok1(streq(path, "."));
ok1(tal_parent(path) == ctx);
path = path_dirname(ctx, "../");
ok1(streq(path, "."));
ok1(tal_parent(path) == ctx);
tal_free(ctx);
ctx = tal_strdup(NULL, "ctx");
ok1(!tal_first(ctx));
/* Test take */
path = path_dirname(ctx, take(tal_strdup(ctx, "..")));
ok1(streq(path, "."));
ok1(tal_parent(path) == ctx);
ok1(tal_first(ctx) == path && !tal_next(ctx, path));
tal_free(path);
ok1(path_dirname(ctx, take(NULL)) == NULL);
ok1(!tal_first(ctx));
tal_free(ctx);
return exit_status();
}
#include <ccan/tal/path/path.h>
#include <ccan/tal/path/path.c>
#include <ccan/tap/tap.h>
int main(void)
{
plan_tests(9);
ok1(path_ext_off("foo") == 3);
ok1(path_ext_off(".foo") == 4);
ok1(path_ext_off("bar.foo") == 3);
ok1(path_ext_off("bar/foo") == 7);
ok1(path_ext_off("bar/.foo") == 8);
ok1(path_ext_off(".bar/foo") == 8);
ok1(path_ext_off("foo.bar/foo") == 11);
ok1(path_ext_off("foo.bar/foo.") == 11);
ok1(path_ext_off("foo.bar/foo..") == 12);
return exit_status();
}
#include <ccan/tal/path/path.h>
#include <ccan/tal/path/path.c>
#include <ccan/tap/tap.h>
int main(void)
{
plan_tests(5);
ok1(path_is_abs(PATH_SEP_STR "foo"));
ok1(!path_is_abs("foo"));
ok1(!path_is_abs("foo" PATH_SEP_STR));
ok1(path_is_abs(PATH_SEP_STR "foo" PATH_SEP_STR));
ok1(path_is_abs(PATH_SEP_STR "."));
return exit_status();
}
#include <ccan/tal/path/path.h>
#include <ccan/tal/path/path.c>
#include <ccan/tap/tap.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void)
{
char cwd[1024], *path, *ctx = tal_strdup(NULL, "ctx");
plan_tests(6);
if (!getcwd(cwd, sizeof(cwd)))
abort();
unlink("run-is_dir-dir-link");
unlink("run-is_dir-file-link");
unlink("run-is_dir-dir/file");
rmdir("run-is_dir-dir");
if (mkdir("run-is_dir-dir", 0700) != 0)
abort();
if (symlink("run-is_dir-dir", "run-is_dir-dir-link") != 0)
abort();
if (symlink("run-is_dir-dir/file", "run-is_dir-file-link") != 0)
abort();
close(open("run-is_dir-dir/file", O_WRONLY|O_CREAT, 0600));
ok1(path_is_dir("run-is_dir-dir-link"));
ok1(!path_is_dir("run-is_dir-file-link"));
ok1(!path_is_dir("run-is_dir-dir/file"));
ok1(path_is_dir("run-is_dir-dir"));
path = path_join(ctx, cwd, "run-is_dir-dir/file");
ok1(!path_is_dir(path));
ok1(path_is_dir(cwd));
tal_free(ctx);
return exit_status();
}
#include <ccan/tal/path/path.h>
#include <ccan/tal/path/path.c>
#include <ccan/tap/tap.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void)
{
char cwd[1024], *path, *ctx = tal_strdup(NULL, "ctx");
plan_tests(7);
if (!getcwd(cwd, sizeof(cwd)))
abort();
unlink("run-is_file-dir-link");
unlink("run-is_file-file-link");
unlink("run-is_file-dir/file");
rmdir("run-is_file-dir");
if (mkdir("run-is_file-dir", 0700) != 0)
abort();
if (symlink("run-is_file-dir", "run-is_file-dir-link") != 0)
abort();
if (symlink("run-is_file-dir/file", "run-is_file-file-link") != 0)
abort();
close(open("run-is_file-dir/file", O_WRONLY|O_CREAT, 0600));
ok1(!path_is_file("run-is_file-dir-link"));
ok1(path_is_file("run-is_file-file-link"));
ok1(path_is_file("run-is_file-dir/file"));
ok1(!path_is_file("run-is_file-dir"));
ok1(!path_is_file("run-is_file-nonexist"));
path = path_join(ctx, cwd, "run-is_file-dir/file");
ok1(path_is_file(path));
ok1(!path_is_file(cwd));
tal_free(ctx);
return exit_status();
}
#include <ccan/tal/path/path.h>
#include <ccan/tal/path/path.c>
#include <ccan/tap/tap.h>
int main(void)
{
char *path, *ctx = tal_strdup(NULL, "ctx");
plan_tests(34);
path = path_join(ctx, "foo", "bar");
ok1(streq(path, "foo/bar"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_join(ctx, "foo/", "bar");
ok1(streq(path, "foo/bar"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_join(ctx, "foo/", "/bar");
ok1(streq(path, "/bar"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_join(ctx, "foo", "/bar");
ok1(streq(path, "/bar"));
ok1(tal_parent(path) == ctx);
tal_free(path);
/* Test take */
path = path_join(ctx, "foo", take(tal_strdup(ctx, "bar")));
ok1(streq(path, "foo/bar"));
ok1(tal_parent(path) == ctx);
ok1(tal_first(ctx) == path && tal_next(ctx, path) == NULL);
tal_free(path);
path = path_join(ctx, "foo", take(tal_strdup(ctx, "/bar")));
ok1(streq(path, "/bar"));
ok1(tal_parent(path) == ctx);
ok1(tal_first(ctx) == path && tal_next(ctx, path) == NULL);
tal_free(path);
path = path_join(ctx, take(tal_strdup(ctx, "foo")), "bar");
ok1(streq(path, "foo/bar"));
ok1(tal_parent(path) == ctx);
ok1(tal_first(ctx) == path && tal_next(ctx, path) == NULL);
tal_free(path);
path = path_join(ctx, take(tal_strdup(ctx, "foo")), "/bar");
ok1(streq(path, "/bar"));
ok1(tal_parent(path) == ctx);
ok1(tal_first(ctx) == path && tal_next(ctx, path) == NULL);
tal_free(path);
path = path_join(ctx, take(tal_strdup(ctx, "foo")),
take(tal_strdup(ctx, "bar")));
ok1(streq(path, "foo/bar"));
ok1(tal_parent(path) == ctx);
ok1(tal_first(ctx) == path && tal_next(ctx, path) == NULL);
tal_free(path);
path = path_join(ctx, take(tal_strdup(ctx, "foo")),
take(tal_strdup(ctx, "/bar")));
ok1(streq(path, "/bar"));
ok1(tal_parent(path) == ctx);
ok1(tal_first(ctx) == path && tal_next(ctx, path) == NULL);
tal_free(path);
path = path_join(ctx, take(NULL), "bar");
ok1(!path);
ok1(!tal_first(ctx));
/* This is allowed to succeed, as first arg unneeded. */
path = path_join(ctx, take(NULL), "/bar");
ok1(!path || streq(path, "/bar"));
tal_free(path);
ok1(!tal_first(ctx));
path = path_join(ctx, "foo", take(NULL));
ok1(!path);
ok1(!tal_first(ctx));
path = path_join(ctx, take(NULL), take(NULL));
ok1(!path);
ok1(!tal_first(ctx));
tal_free(ctx);
return exit_status();
}
#include <ccan/tal/path/path.h>
#include <ccan/tal/path/path.c>
#include <ccan/tap/tap.h>
int main(void)
{
struct path_pushd *pd;
char path1[1024], path2[1024], *ctx = tal_strdup(NULL, "ctx");
/* This is how many tests you plan to run */
plan_tests(19);
/* Test pushd/popd */
if (!getcwd(path1, sizeof(path1)))
abort();
pd = path_pushd(NULL, "non-existent-dir");
ok1(errno == ENOENT);
ok1(!pd);
errno = -100;
pd = path_pushd(ctx, take(tal_strdup(ctx, "non-existent-dir")));
ok1(errno == ENOENT);
ok1(!pd);
ok1(!tal_first(ctx));
errno = -100;
pd = path_pushd(ctx, take(NULL));
ok1(!pd);
ok1(!tal_first(ctx));
ok1(errno == -100);
pd = path_pushd(ctx, "/tmp");
ok1(pd);
ok1(tal_parent(pd) == ctx);
if (!getcwd(path2, sizeof(path2)))
abort();
ok1(streq(path2, "/tmp"));
path_popd(pd);
if (!getcwd(path2, sizeof(path2)))
abort();
ok1(streq(path2, path1));
pd = path_pushd(ctx, take(tal_strdup(ctx, "/tmp")));
ok1(pd);
ok1(tal_parent(pd) == ctx);
path_popd(pd);
if (!getcwd(path2, sizeof(path2)))
abort();
ok1(streq(path2, path1));
ok1(!tal_first(ctx));
/* Without fchdir, we can't push a path which no longer exists. */
if (mkdir("run-pushd-dir", 0700) != 0)
abort();
if (chdir("run-pushd-dir") != 0)
abort();
if (rmdir("../run-pushd-dir") != 0)
abort();
pd = path_pushd(ctx, path1);
#if HAVE_FCHDIR
ok1(pd);
ok1(path_popd(pd));
#else
ok1(errno == ENOENT);
ok1(!pd);
#endif
ok1(!tal_first(ctx));
tal_free(ctx);
return exit_status();
}
#include <ccan/tal/path/path.h>
#include <ccan/tal/path/path.c>
#include <ccan/tap/tap.h>
int main(void)
{
char *link, *ctx = tal_strdup(NULL, "ctx");
plan_tests(12);
unlink("run-readlink-link");
link = path_readlink(ctx, "run-readlink-link");
ok1(errno == ENOENT);
ok1(!link);
link = path_readlink(ctx, take(tal_strdup(ctx, "run-readlink-link")));
ok1(errno == ENOENT);
ok1(!link);
ok1(tal_first(ctx) == NULL);
if (symlink("/tmp", "run-readlink-link") != 0)
abort();
link = path_readlink(ctx, "run-readlink-link");
ok1(tal_parent(link) == ctx);
ok1(streq(link, "/tmp"));
tal_free(link);
link = path_readlink(ctx, take(tal_strdup(ctx, "run-readlink-link")));
ok1(tal_parent(link) == ctx);
ok1(streq(link, "/tmp"));
ok1(tal_first(ctx) == link && tal_next(ctx, link) == NULL);
unlink("run-readlink-link");
if (symlink("some-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-long-name", "run-readlink-link") != 0)
abort();
link = path_readlink(ctx, "run-readlink-link");
ok1(tal_parent(link) == ctx);
ok1(streq(link, "some-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-really-long-name"));
tal_free(ctx);
return exit_status();
}
#include <ccan/tal/path/path.h>
#include <ccan/tal/path/path.c>
#include <ccan/tap/tap.h>
int main(void)
{
char cwd[1024], *path, *ctx = tal_strdup(NULL, "ctx");
plan_tests(19);
if (!getcwd(cwd, sizeof(cwd)))
abort();
unlink("run-rel-link");
rmdir("run-rel-foo");
if (mkdir("run-rel-foo", 0700) != 0)
abort();
if (symlink("run-rel-foo", "run-rel-link") != 0)
abort();
path = path_rel(ctx, ".", "run-rel-foo");
ok1(streq(path, "run-rel-foo"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_rel(ctx, "run-rel-foo", ".");
ok1(streq(path, ".."));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_rel(ctx, ".", "run-rel-link");
/* This doesn't specify whether it preserves links. */
ok1(streq(path, "run-rel-link") || streq(path, "run-rel-foo"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_rel(ctx, "/", ".");
ok1(streq(path, cwd + 1));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_rel(ctx, "run-rel-foo", "run-rel-foo");
ok1(streq(path, "."));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_rel(ctx, take(tal_strdup(ctx, ".")), "run-rel-foo");
ok1(streq(path, "run-rel-foo"));
ok1(tal_parent(path) == ctx);
tal_free(path);
ok1(tal_first(ctx) == NULL);
path = path_rel(ctx, ".", take(tal_strdup(ctx, "run-rel-foo")));
ok1(streq(path, "run-rel-foo"));
ok1(tal_parent(path) == ctx);
tal_free(path);
ok1(tal_first(ctx) == NULL);
path = path_rel(ctx, take(tal_strdup(ctx, ".")),
take(tal_strdup(ctx, "run-rel-foo")));
ok1(streq(path, "run-rel-foo"));
ok1(tal_parent(path) == ctx);
tal_free(path);
ok1(tal_first(ctx) == NULL);
tal_free(ctx);
return exit_status();
}
#include <ccan/tal/path/path.h>
#include <ccan/tal/path/path.c>
#include <ccan/tap/tap.h>
int main(void)
{
char cwd[1024], *path, *ctx = tal_strdup(NULL, "ctx");
plan_tests(87);
if (!getcwd(cwd, sizeof(cwd)))
abort();
rmdir("run-simplify-foo");
unlink("run-simplify-link");
if (mkdir("run-simplify-foo", 0700) != 0)
abort();
if (symlink("run-simplify-foo", "run-simplify-link") != 0)
abort();
/* Handling of . and .. */
path = path_simplify(ctx, ".");
ok1(streq(path, "."));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "./");
ok1(streq(path, "."));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "..");
ok1(streq(path, ".."));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "../");
ok1(streq(path, ".."));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "./..");
ok1(streq(path, ".."));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "./../");
ok1(streq(path, ".."));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "./../.");
ok1(streq(path, ".."));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "./.././");
ok1(streq(path, ".."));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "./../..");
ok1(streq(path, "../.."));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "./../../");
ok1(streq(path, "../.."));
ok1(tal_parent(path) == ctx);
tal_free(path);
/* Handling of /. and /.. */
path = path_simplify(ctx, "/");
ok1(streq(path, "/"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "//");
ok1(streq(path, "/"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "/.");
ok1(streq(path, "/"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "/./");
ok1(streq(path, "/"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "/..");
ok1(streq(path, "/"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "/../");
ok1(streq(path, "/"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "/./..");
ok1(streq(path, "/"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "/./../");
ok1(streq(path, "/"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "/./../.");
ok1(streq(path, "/"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "/./.././");
ok1(streq(path, "/"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "/./../..");
ok1(streq(path, "/"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "/./../../");
ok1(streq(path, "/"));
ok1(tal_parent(path) == ctx);
tal_free(path);
/* Don't trace back over a symlink link */
path = path_simplify(ctx, "run-simplify-foo");
ok1(streq(path, "run-simplify-foo"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "./run-simplify-foo");
ok1(streq(path, "run-simplify-foo"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "./run-simplify-foo/.");
ok1(streq(path, "run-simplify-foo"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "run-simplify-link");
ok1(streq(path, "run-simplify-link"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "./run-simplify-link");
ok1(streq(path, "run-simplify-link"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "./run-simplify-link/.");
ok1(streq(path, "run-simplify-link"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "run-simplify-foo/..");
ok1(streq(path, "."));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "run-simplify-foo//..");
ok1(streq(path, "."));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "run-simplify-foo//../");
ok1(streq(path, "."));
ok1(tal_parent(path) == ctx);
tal_free(path);
/* This is expected to be a real directory. */
path = path_simplify(ctx, "/tmp");
ok1(streq(path, "/tmp"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "/tmp/");
ok1(streq(path, "/tmp"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "/tmp/.");
ok1(streq(path, "/tmp"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "/./tmp/.");
ok1(streq(path, "/tmp"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "/../tmp/.");
ok1(streq(path, "/tmp"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "/tmp/..");
ok1(streq(path, "/"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "/tmp/../");
ok1(streq(path, "/"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "/tmp/../tmp");
ok1(streq(path, "/tmp"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "/tmp/../tmp/");
ok1(streq(path, "/tmp"));
ok1(tal_parent(path) == ctx);
tal_free(path);
path = path_simplify(ctx, "/tmp/../tmp/.");
ok1(streq(path, "/tmp"));
ok1(tal_parent(path) == ctx);
tal_free(path);
/* take tests */
path = path_simplify(ctx, take(tal_strdup(ctx, "/tmp/../tmp/.")));
ok1(streq(path, "/tmp"));
ok1(tal_parent(path) == ctx);
tal_free(path);
ok1(tal_first(ctx) == NULL);
path = path_simplify(ctx, take(NULL));
ok1(!path);
ok1(tal_first(ctx) == NULL);
tal_free(ctx);
return exit_status();
}
#include <ccan/tal/path/path.h>
#include <ccan/tal/path/path.c>
#include <ccan/tap/tap.h>
int main(void)
{
char *ctx = tal_strdup(NULL, "ctx"), **split;
plan_tests(46);
split = path_split(ctx, "foo" PATH_SEP_STR "bar");
ok1(tal_parent(split) == ctx);
ok1(streq(split[0], "foo"));
ok1(streq(split[1], "bar"));
ok1(split[2] == NULL);
tal_free(split);
split = path_split(ctx, "foo" PATH_SEP_STR "bar" PATH_SEP_STR);
ok1(tal_parent(split) == ctx);
ok1(streq(split[0], "foo"));
ok1(streq(split[1], "bar"));
ok1(split[2] == NULL);
tal_free(split);
split = path_split(ctx, PATH_SEP_STR "foo"
PATH_SEP_STR "bar" PATH_SEP_STR);
ok1(tal_parent(split) == ctx);
ok1(streq(split[0], "foo"));
ok1(streq(split[1], "bar"));
ok1(split[2] == NULL);
tal_free(split);
split = path_split(ctx, PATH_SEP_STR PATH_SEP_STR "foo"
PATH_SEP_STR PATH_SEP_STR "bar"
PATH_SEP_STR PATH_SEP_STR);
ok1(tal_parent(split) == ctx);
ok1(streq(split[0], "foo"));
ok1(streq(split[1], "bar"));
ok1(split[2] == NULL);
tal_free(split);
split = path_split(ctx, "foo");
ok1(tal_parent(split) == ctx);
ok1(streq(split[0], "foo"));
ok1(split[1] == NULL);
tal_free(split);
split = path_split(ctx, PATH_SEP_STR "foo");
ok1(tal_parent(split) == ctx);
ok1(streq(split[0], "foo"));
ok1(split[1] == NULL);
tal_free(split);
split = path_split(ctx, PATH_SEP_STR PATH_SEP_STR "foo");
ok1(tal_parent(split) == ctx);
ok1(streq(split[0], "foo"));
ok1(split[1] == NULL);
tal_free(split);
split = path_split(ctx, "foo" PATH_SEP_STR);
ok1(tal_parent(split) == ctx);
ok1(streq(split[0], "foo"));
ok1(split[1] == NULL);
tal_free(split);
split = path_split(ctx, "foo" PATH_SEP_STR PATH_SEP_STR);
ok1(tal_parent(split) == ctx);
ok1(streq(split[0], "foo"));
ok1(split[1] == NULL);
tal_free(split);
split = path_split(ctx, PATH_SEP_STR "foo" PATH_SEP_STR);
ok1(tal_parent(split) == ctx);
ok1(streq(split[0], "foo"));
ok1(split[1] == NULL);
tal_free(split);
split = path_split(ctx, "");
ok1(tal_parent(split) == ctx);
ok1(split[0] == NULL);
tal_free(split);
split = path_split(ctx, PATH_SEP_STR);
ok1(tal_parent(split) == ctx);
ok1(streq(split[0], PATH_SEP_STR));
ok1(split[1] == NULL);
tal_free(split);
/* Test take */
split = path_split(ctx, take(tal_strdup(ctx, PATH_SEP_STR)));
ok1(tal_parent(split) == ctx);
ok1(streq(split[0], PATH_SEP_STR));
ok1(split[1] == NULL);
tal_free(split);
ok1(tal_first(ctx) == NULL);
split = path_split(ctx, take(NULL));
ok1(!split);
ok1(tal_first(ctx) == NULL);
ok1(tal_first(NULL) == ctx && tal_next(NULL, ctx) == NULL);
tal_free(ctx);
return exit_status();
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment