diff --git a/src/common/path.c b/src/common/path.c index 7eeb3d0..35ab076 100644 --- a/src/common/path.c +++ b/src/common/path.c @@ -1,33 +1,24 @@ - -/* - * Copyright (C) 2010 Archived +/* common/path.c - path string handling routines + * + * Copyright (C) 2010 Hernrik 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 - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * The design goal here is to not use fixed size buffers because + * path's can be extremely long (slightly overexaggerated but extreme cases are extreme). + * so we use funky heap memory based algorithms instead :) */ -/* - * the design goal here is to not use buffers because - * path's can be extremely long (slightly overexaggerated but extreme cases are extreme). - * so we use funky heap memory based algorithms instead :) - */ - -#include -#include +#include #include "debug.h" #include "path.h" +static char defpath[2]; + /* * allocates and initilizes a path */ @@ -37,8 +28,10 @@ static char* alloc_path(size_t s) { if (s < 1) return NULL; - - if ((ptr = malloc(s+1)) == NULL) + + ptr = malloc(s+1); + + if (ptr == NULL) return NULL; *ptr = '/'; @@ -69,7 +62,7 @@ static inline int has_delim(const char *str) { */ static char* cpy_path(char *buf, const char *path) { - if(!*path) + if (*path == 0) return buf; while(*path) { @@ -90,7 +83,31 @@ static char* cpy_path(char *buf, const char *path) { return buf; } -int abspath(const char *path) { +static char* split_path(char *path) { + + char *last = path+strlen(path)-1, *slash = NULL; + + while(*last == '/' && (last--) > path); + + while(last > path) { + + if (*last == '/') { + slash = last; + } else if (slash != NULL) { + break; + } + + last--; + } + + if (slash == NULL) + return path; + + return slash; +} + + +int is_abspath(const char *path) { if (*path != '/') return 0; @@ -109,8 +126,8 @@ size_t pathlen(const char *path) { if (*path == '/') path = path_clear(path); - else if (*(++path) == 0) - size++; + else + path++; } return size; @@ -121,17 +138,20 @@ char* fmt_path(const char *base, const char *name, unsigned char dir) { char *ptr, *ret; size_t size; - if (base == NULL || !abspath(base) || has_delim(name)) + if (base == NULL || !is_abspath(base) || has_delim(name)) return NULL; size = pathlen(base); if (name != NULL) { size += strlen(name); - if (dir) size++; + if (dir) + size++; } - - if((ptr = alloc_path(size)) == NULL) + + ptr = alloc_path(size); + + if (ptr == NULL) return NULL; ret = ptr; @@ -142,51 +162,68 @@ char* fmt_path(const char *base, const char *name, unsigned char dir) { if (name != NULL) { memcpy(ptr, name, strlen(name)); - if (dir) *(ptr+strlen(name)) = '/'; + if (dir) + *(ptr+strlen(name)) = '/'; } return ret; } -char* split_path(const char *path) { - return NULL; +char* basename(char *path) { + + char *pos = path; + + if (path == NULL || *path == '\0') { + defpath[0] = '.'; + defpath[1] = '\0'; + return defpath; + } + + while(*path != '\0') { + + if (*path == '/') { + + if (*(path+1) == '\0') { + + if (pos >= path) + break; + + *(path--) = '\0'; + continue; + } + + if (*(path+1) != '/') + pos = path+1; + } + + path++; + } + + return pos; } -const char* basename(const char *path) { - - const char *last = path+strlen(path); +char* dirname(char *path) { - if (*last == '/') - last--; - - while(path != last) { - if(*last == '/') - break; - last--; - } - - return last; -} - - -char* dirname(char *fullpath) { - - char *dirname, *sep; - int pos; - - if (fullpath[strlen(fullpath)-1] == '/') - fullpath[strlen(fullpath)-1] = '\0'; - - sep = strrchr(fullpath,'/'); - pos = sep-fullpath+1; - - if(sep == NULL) - return NULL; - - dirname = malloc ( pos ); - - memset(dirname,0,pos); - memcpy (dirname, fullpath, pos-1 ); - - return dirname; + char *last, *slash = NULL; + size_t len; + + if (path == NULL || *path == '\0') { + defpath[0] = '.'; + defpath[1] = '\0'; + return defpath; + } + + len = split_path(path) - path; + + if (len <= 1) { + + if (*path != '/') + path[0] = '.'; + + path[1] = '\0'; + } else { + path[len] = '\0'; + } + + return path; } diff --git a/src/common/path.h b/src/common/path.h index f5942ba..8f41d0a 100644 --- a/src/common/path.h +++ b/src/common/path.h @@ -1,40 +1,18 @@ -/* - * -- path.h - * - * common path handling routines - * - * Copyright (C) 2010 Archived - * - * 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 - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef _COMMON_PATH_H +#ifndef __COMMON_PATH_H -#define _COMMON_PATH_H +#define __COMMON_PATH_H -#include -#include -#include +#include -#ifndef PATH_MAX -#define PATH_MAX 4096 -#endif +int is_abspath(const char *path); size_t pathlen(const char *path); char* fmt_path(const char *base, const char *name, unsigned char dir); -const char* basename(const char *path); +char* basename(char *path); -#endif /* _COMMON_PATH_H */ +char* dirname(char *path); + +#endif /* __COMMON_PATH_H */ diff --git a/test/Makefile b/test/Makefile index a4e3792..a8ac318 100644 --- a/test/Makefile +++ b/test/Makefile @@ -14,9 +14,6 @@ raw_inotify : path : $(CC) -D__DEBUG__ $(CFLAGS) ../src/common/path.c t_path.c -o test_path -path2 : - $(CC) -D__DEBUG__ $(CFLAGS) ../src/common/path.c t_path2.c -o test_path2 - rbtree : $(CC) $(DEFS) $(CFLAGS) unit.c ../src/common/rbtree.c t_rbtree.c -o test_rbtree diff --git a/test/t_path.c b/test/t_path.c index c5a3312..ebf3e68 100644 --- a/test/t_path.c +++ b/test/t_path.c @@ -1,82 +1,95 @@ #include #include +#include "unit.h" #include "../src/common/path.h" -/* test data */ +void test_fmt_path() { -char string[8][128] = { - "usr/include/", - "/usr/src/linux", - "/segment1/segment2/segment3/", - "//double///tripple", - "/stuff/with/ahell/lot/of/slashes/at/the/end/////////", - "~/myhome/", - "/", - "///////////////////////////////////////////////////////////" -}; + char *ptr; -char split[8][2][64] = { - {"usr/", "include/" }, - {"/usr/src/", "linux" }, - {"/segment1/segment2/", "segment3/" }, - {"//double//", "/tripple" }, - {"/stuff/with/ahell/lot/of/slashes/at/the/", "end/////////" }, - {"~/", "myhome/" }, - {"/mnt/cdrom", "keff" }, - {"//////////////////////////////", "/////////////////////////////" } -}; + ptr = fmt_path("usr/", "include/", 0); + assert(ptr == NULL); + + ptr = fmt_path("/usr/src/", "linux", 0); + assert_string(ptr, "/usr/src/linux"); + free(ptr); +/* + ptr = fmt_path("/segment1/segment2/", "segment3/", 1); + assert_string(ptr, "/segment1/segment2/segment3/"); + free(ptr); + */ + +/* + ptr = fmt_path("/stuff/with/ahell/lot/of/slashes/at/the/", "end/////////", 1); + assert_string(ptr, "/stuff/with/ahell/lot/of/slashes/at/the/end/////////"); + free(ptr); + */ + + ptr = fmt_path("/mnt/cdrom", "keff", 0); + assert_string(ptr, "/mnt/cdrom/keff"); + free(ptr); +} + +void test_pathlen() { + + assert(pathlen("/usr/src/linux-2.6.30-r5/drivers") == 32); + assert(pathlen("/usr///src/") == 9); + assert(pathlen("/usr//include/sys//") == 17); + assert(pathlen("///var/lib/misc") == 13); + assert(pathlen("dir") == 3); +} + +void test_basename() { + + int i; + + char data[11][2][64] = { + { "", "." }, + { "/", "/" }, + { "///", "/" }, + { ".", "."}, + { "..", ".." }, + { "../../rel1", "rel1" }, + { "./rel2", "rel2" }, + { "justsomestring", "justsomestring" }, + { "/usr/src/", "src" }, + { "/usr/src///", "src" }, + { "/usr/src/linux-2.6.30-r5/drivers", "drivers" } + }; + + for(i=0; i < 11; i++) + assert_string(basename(data[i][0]), data[i][1]); +} + +void test_dirname() { + + int i; + + char data[11][2][64] = { + { "", "." }, + { "/", "/" }, + { "///", "/" }, + { ".", "."}, + { "..", "." }, + { "../../rel", "../.." }, + { "./rel", "." }, + { "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]); +} int main(int argc, char *argv[]) { - int i; - char *ptr = NULL; + test_fmt_path(); + test_pathlen(); + test_basename(); + test_dirname(); - for(i=0; i < 8; i++) { - //printf("adding: %s\n", string[i]); - ptr = fmt_path(string[i], NULL, 0); - printf("str %i is: %s\n", i, ptr); - - if (ptr != NULL) { - free(ptr); - ptr = NULL; - } - } - - for(i=0; i < 8; i++) { - //printf("adding: %s%s\n", split[i][0], split[i][1]); - ptr = fmt_path(split[i][0], split[i][1], 0); - printf("str %i is: %s\n", i, ptr); - - if (ptr != NULL) { - free(ptr); - ptr = NULL; - } - } - - for(i=0; i < 8; i++) { - //printf("adding: %s%s\n", split[i][0], split[i][1]); - ptr = fmt_path(split[i][0], split[i][1], 1); - printf("str %i is: %s\n", i, ptr); - - if (ptr != NULL) { - free(ptr); - ptr = NULL; - } - } - - if(argc < 2) - return 0; - else if(argc == 2) - ptr = fmt_path(argv[1], NULL, 0); - else if(argc > 2) { - ptr = fmt_path(argv[1], argv[2], 0); - } - - printf("%s\n", ptr); - - if (ptr != NULL) - free(ptr); - - return 0; + return 0; } diff --git a/test/t_path2.c b/test/t_path2.c deleted file mode 100644 index 610ca89..0000000 --- a/test/t_path2.c +++ /dev/null @@ -1,18 +0,0 @@ - -#include -#include -#include "../src/common/path.h" - - -int main(int argc, char *argv[]) { - - char fp[] = "/this/is/my/path/to/file.pdf/"; - char *d; - printf("%s\n=>\n", fp); - - d = dirname(fp); - - printf("%s\n", d); - - return 0; -} diff --git a/test/unit.h b/test/unit.h index 61fe112..119177e 100644 --- a/test/unit.h +++ b/test/unit.h @@ -8,8 +8,24 @@ #include #include -#define assert_string(a, b) \ - assert(strcmp((char*)a, (char*)b) == 0) +#define __uexit(file, line, func, fmt, ...) \ + do { \ + fprintf(stderr, "ASSERT %s in %s(%i): " fmt, func, file, line, __VA_ARGS__); \ + exit(1); \ + } while(0) + +/* internal function. assert_* macros below expands to this */ +inline void __assert_str(char *file, int line, char *func, char *a, char *b) { + + if (a == NULL || b == NULL) + __uexit(file, line, func, "a or b is null\n", NULL); + + if (strcmp(a, b) != 0) + __uexit(file, line, func, "\"%s\" != \"%s\"\n", a, b); + +} + +#define assert_string(a, b) __assert_str(__FILE__, __LINE__, __FUNCTION__, a, b) void utest_init_RNG();