updated dirname/basepath to follow a modification of IEEE standard.
This commit is contained in:
parent
304049064e
commit
654f4bff80
6 changed files with 217 additions and 194 deletions
|
|
@ -1,33 +1,24 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) 2010 Archived
|
||||
/* common/path.c - path string handling routines
|
||||
*
|
||||
* Copyright (C) 2010 Hernrik Hautakoski <henrik.hautakoski@gmail.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* 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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _COMMON_PATH_H
|
||||
#ifndef __COMMON_PATH_H
|
||||
|
||||
#define _COMMON_PATH_H
|
||||
#define __COMMON_PATH_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
153
test/t_path.c
153
test/t_path.c
|
|
@ -1,82 +1,95 @@
|
|||
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
#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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
#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;
|
||||
}
|
||||
20
test/unit.h
20
test/unit.h
|
|
@ -8,8 +8,24 @@
|
|||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#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();
|
||||
|
||||
|
|
|
|||
Reference in a new issue