From 546e7c50f1cb9f764eb3dd2af72693c0ac21c58d Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 11 Feb 2011 19:17:38 +0100 Subject: [PATCH] path.c: added dirname_s function. --- docs/technical/path.txt | 8 ++++++++ src/path.c | 26 +++++++++++++++++++++++++- src/path.h | 4 +++- test/t_path.c | 8 +++++--- 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/docs/technical/path.txt b/docs/technical/path.txt index 36db655..6d14051 100644 --- a/docs/technical/path.txt +++ b/docs/technical/path.txt @@ -38,3 +38,11 @@ The function performs this type of checks/manipulation: + Returns `NULL` if 'base' is not an absolute path or 'name' contains a delimiter. +`dirname_s`:: + + Safe dirname implementation. works like POSIX dirname with some modifications: + ++ +-- + * 'slash' may be used to terminate the string with a \'/' character. + + * The function will never modify 'path' instead the function will *always* return a static buffer that will be overwritten by subsequent calls. +-- diff --git a/src/path.c b/src/path.c index 7ca8bad..ff2031a 100644 --- a/src/path.c +++ b/src/path.c @@ -1,6 +1,6 @@ /* path.c - path handling routines * - * Copyright (C) 2010 Henrik Hautakoski + * Copyright (C) 2010-2011 Henrik Hautakoski * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -12,6 +12,7 @@ * so we use funky heap memory based algorithms instead :) */ +#include #include #include #include @@ -67,6 +68,29 @@ int is_dir(const char *path) { return 0; } +const char* dirname_s(const char *path, int slash) { + + static strbuf_t sb = STRBUF_INIT; + + strbuf_reduce(&sb, sb.len); + strbuf_append_str(&sb, path); + strbuf_squeeze(&sb, '/'); + + if (sb.len > 1) { + if (sb.buf[sb.len-1] == '/') + strbuf_reduce(&sb, 1); + + if (!strbuf_rchop(&sb, '/')) + strbuf_reduce(&sb, sb.len-1); + } + + if (sb.buf[0] != '/') + sb.buf[0] = '.'; + if (slash) + strbuf_term(&sb, '/'); + return sb.buf; +} + const char *mkpath(const char *fmt, ...) { static strbuf_t sb = STRBUF_INIT; diff --git a/src/path.h b/src/path.h index 054147f..89fe809 100644 --- a/src/path.h +++ b/src/path.h @@ -1,6 +1,6 @@ /* path.h - path handling routines * - * Copyright (C) 2010 Henrik Hautakoski + * Copyright (C) 2010-2011 Henrik Hautakoski * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,6 +20,8 @@ int is_file(const char *path); int is_dir(const char *path); +const char* dirname_s(const char *path, int slash); + const char* mkpath(const char *fmt, ...); char* path_normalize(const char *base, const char *name, unsigned dir); diff --git a/test/t_path.c b/test/t_path.c index 51fda72..3601b18 100644 --- a/test/t_path.c +++ b/test/t_path.c @@ -97,22 +97,24 @@ void test_dirname() { int i; - char data[11][2][64] = { + char data[13][2][64] = { { "", "." }, { "/", "/" }, { "///", "/" }, { ".", "."}, { "..", "." }, + { "../", "." }, { "../../rel", "../.." }, { "./rel", "." }, + { "x", "." }, { "justsomestring", "." }, { "/usr/src/", "/usr" }, { "/usr/src///", "/usr" }, { "/usr/src/linux-2.6.30-r5/drivers", "/usr/src/linux-2.6.30-r5" } }; - for(i=0; i < 11; i++) - assert_string(dirname(data[i][0]), data[i][1]); + for(i=0; i < 12; i++) + assert_string(dirname_s(data[i][0], 0), data[i][1]); } int main(int argc, char *argv[]) {