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 @@
|
||||||
|
/* common/path.c - path string handling routines
|
||||||
/*
|
*
|
||||||
* Copyright (C) 2010 Archived
|
* Copyright (C) 2010 Hernrik Hautakoski <henrik.hautakoski@gmail.com>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* The design goal here is to not use fixed size buffers because
|
||||||
* 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 buffers because
|
|
||||||
* path's can be extremely long (slightly overexaggerated but extreme cases are extreme).
|
* path's can be extremely long (slightly overexaggerated but extreme cases are extreme).
|
||||||
* so we use funky heap memory based algorithms instead :)
|
* so we use funky heap memory based algorithms instead :)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "path.h"
|
#include "path.h"
|
||||||
|
|
||||||
|
static char defpath[2];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* allocates and initilizes a path
|
* allocates and initilizes a path
|
||||||
*/
|
*/
|
||||||
|
|
@ -38,7 +29,9 @@ static char* alloc_path(size_t s) {
|
||||||
if (s < 1)
|
if (s < 1)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if ((ptr = malloc(s+1)) == NULL)
|
ptr = malloc(s+1);
|
||||||
|
|
||||||
|
if (ptr == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
*ptr = '/';
|
*ptr = '/';
|
||||||
|
|
@ -69,7 +62,7 @@ static inline int has_delim(const char *str) {
|
||||||
*/
|
*/
|
||||||
static char* cpy_path(char *buf, const char *path) {
|
static char* cpy_path(char *buf, const char *path) {
|
||||||
|
|
||||||
if(!*path)
|
if (*path == 0)
|
||||||
return buf;
|
return buf;
|
||||||
|
|
||||||
while(*path) {
|
while(*path) {
|
||||||
|
|
@ -90,7 +83,31 @@ static char* cpy_path(char *buf, const char *path) {
|
||||||
return buf;
|
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 != '/')
|
if (*path != '/')
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -109,8 +126,8 @@ size_t pathlen(const char *path) {
|
||||||
|
|
||||||
if (*path == '/')
|
if (*path == '/')
|
||||||
path = path_clear(path);
|
path = path_clear(path);
|
||||||
else if (*(++path) == 0)
|
else
|
||||||
size++;
|
path++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
|
|
@ -121,17 +138,20 @@ char* fmt_path(const char *base, const char *name, unsigned char dir) {
|
||||||
char *ptr, *ret;
|
char *ptr, *ret;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
if (base == NULL || !abspath(base) || has_delim(name))
|
if (base == NULL || !is_abspath(base) || has_delim(name))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
size = pathlen(base);
|
size = pathlen(base);
|
||||||
|
|
||||||
if (name != NULL) {
|
if (name != NULL) {
|
||||||
size += strlen(name);
|
size += strlen(name);
|
||||||
if (dir) size++;
|
if (dir)
|
||||||
|
size++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((ptr = alloc_path(size)) == NULL)
|
ptr = alloc_path(size);
|
||||||
|
|
||||||
|
if (ptr == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ret = ptr;
|
ret = ptr;
|
||||||
|
|
@ -142,51 +162,68 @@ char* fmt_path(const char *base, const char *name, unsigned char dir) {
|
||||||
|
|
||||||
if (name != NULL) {
|
if (name != NULL) {
|
||||||
memcpy(ptr, name, strlen(name));
|
memcpy(ptr, name, strlen(name));
|
||||||
if (dir) *(ptr+strlen(name)) = '/';
|
if (dir)
|
||||||
|
*(ptr+strlen(name)) = '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* split_path(const char *path) {
|
char* basename(char *path) {
|
||||||
return NULL;
|
|
||||||
|
char *pos = path;
|
||||||
|
|
||||||
|
if (path == NULL || *path == '\0') {
|
||||||
|
defpath[0] = '.';
|
||||||
|
defpath[1] = '\0';
|
||||||
|
return defpath;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* basename(const char *path) {
|
while(*path != '\0') {
|
||||||
|
|
||||||
const char *last = path+strlen(path);
|
if (*path == '/') {
|
||||||
|
|
||||||
if (*last == '/')
|
if (*(path+1) == '\0') {
|
||||||
last--;
|
|
||||||
|
|
||||||
while(path != last) {
|
if (pos >= path)
|
||||||
if(*last == '/')
|
|
||||||
break;
|
break;
|
||||||
last--;
|
|
||||||
|
*(path--) = '\0';
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return last;
|
if (*(path+1) != '/')
|
||||||
|
pos = path+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
path++;
|
||||||
char* dirname(char *fullpath) {
|
}
|
||||||
|
|
||||||
char *dirname, *sep;
|
return pos;
|
||||||
int pos;
|
}
|
||||||
|
|
||||||
if (fullpath[strlen(fullpath)-1] == '/')
|
char* dirname(char *path) {
|
||||||
fullpath[strlen(fullpath)-1] = '\0';
|
|
||||||
|
char *last, *slash = NULL;
|
||||||
sep = strrchr(fullpath,'/');
|
size_t len;
|
||||||
pos = sep-fullpath+1;
|
|
||||||
|
if (path == NULL || *path == '\0') {
|
||||||
if(sep == NULL)
|
defpath[0] = '.';
|
||||||
return NULL;
|
defpath[1] = '\0';
|
||||||
|
return defpath;
|
||||||
dirname = malloc ( pos );
|
}
|
||||||
|
|
||||||
memset(dirname,0,pos);
|
len = split_path(path) - path;
|
||||||
memcpy (dirname, fullpath, pos-1 );
|
|
||||||
|
if (len <= 1) {
|
||||||
return dirname;
|
|
||||||
|
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 <stddef.h>
|
||||||
#include <string.h>
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
#ifndef PATH_MAX
|
int is_abspath(const char *path);
|
||||||
#define PATH_MAX 4096
|
|
||||||
#endif
|
|
||||||
|
|
||||||
size_t pathlen(const char *path);
|
size_t pathlen(const char *path);
|
||||||
|
|
||||||
char* fmt_path(const char *base, const char *name, unsigned char dir);
|
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 :
|
path :
|
||||||
$(CC) -D__DEBUG__ $(CFLAGS) ../src/common/path.c t_path.c -o test_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 :
|
rbtree :
|
||||||
$(CC) $(DEFS) $(CFLAGS) unit.c ../src/common/rbtree.c t_rbtree.c -o test_rbtree
|
$(CC) $(DEFS) $(CFLAGS) unit.c ../src/common/rbtree.c t_rbtree.c -o test_rbtree
|
||||||
|
|
||||||
|
|
|
||||||
147
test/t_path.c
147
test/t_path.c
|
|
@ -1,82 +1,95 @@
|
||||||
|
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include "unit.h"
|
||||||
#include "../src/common/path.h"
|
#include "../src/common/path.h"
|
||||||
|
|
||||||
/* test data */
|
void test_fmt_path() {
|
||||||
|
|
||||||
char string[8][128] = {
|
char *ptr;
|
||||||
"usr/include/",
|
|
||||||
"/usr/src/linux",
|
ptr = fmt_path("usr/", "include/", 0);
|
||||||
"/segment1/segment2/segment3/",
|
assert(ptr == NULL);
|
||||||
"//double///tripple",
|
|
||||||
"/stuff/with/ahell/lot/of/slashes/at/the/end/////////",
|
ptr = fmt_path("/usr/src/", "linux", 0);
|
||||||
"~/myhome/",
|
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" }
|
||||||
};
|
};
|
||||||
|
|
||||||
char split[8][2][64] = {
|
for(i=0; i < 11; i++)
|
||||||
{"usr/", "include/" },
|
assert_string(basename(data[i][0]), data[i][1]);
|
||||||
{"/usr/src/", "linux" },
|
}
|
||||||
{"/segment1/segment2/", "segment3/" },
|
|
||||||
{"//double//", "/tripple" },
|
void test_dirname() {
|
||||||
{"/stuff/with/ahell/lot/of/slashes/at/the/", "end/////////" },
|
|
||||||
{"~/", "myhome/" },
|
int i;
|
||||||
{"/mnt/cdrom", "keff" },
|
|
||||||
{"//////////////////////////////", "/////////////////////////////" }
|
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 main(int argc, char *argv[]) {
|
||||||
|
|
||||||
int i;
|
test_fmt_path();
|
||||||
char *ptr = NULL;
|
test_pathlen();
|
||||||
|
test_basename();
|
||||||
for(i=0; i < 8; i++) {
|
test_dirname();
|
||||||
//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 <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#define assert_string(a, b) \
|
#define __uexit(file, line, func, fmt, ...) \
|
||||||
assert(strcmp((char*)a, (char*)b) == 0)
|
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();
|
void utest_init_RNG();
|
||||||
|
|
||||||
|
|
|
||||||
Reference in a new issue