summaryrefslogtreecommitdiff
path: root/src/util.c
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2013-07-02 11:56:52 +0200
committerantirez <antirez@gmail.com>2013-07-02 11:56:52 +0200
commit0781ad68991171360becfc472c492861ba119c01 (patch)
tree08de1c1f8ff0d0f464da9431f19f3588c12d9fa9 /src/util.c
parentde9a221749b10af3a408385056bb51255ca860f6 (diff)
downloadredis-0781ad68991171360becfc472c492861ba119c01.tar.gz
getAbsolutePath() moved into utils.c
Diffstat (limited to 'src/util.c')
-rw-r--r--src/util.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/src/util.c b/src/util.c
index 24f936b66..4b77e9fef 100644
--- a/src/util.c
+++ b/src/util.c
@@ -405,6 +405,58 @@ void getRandomHexChars(char *p, unsigned int len) {
fclose(fp);
}
+/* Given the filename, return the absolute path as an SDS string, or NULL
+ * if it fails for some reason. Note that "filename" may be an absolute path
+ * already, this will be detected and handled correctly.
+ *
+ * The function does not try to normalize everything, but only the obvious
+ * case of one or more "../" appearning at the start of "filename"
+ * relative path. */
+sds getAbsolutePath(char *filename) {
+ char cwd[1024];
+ sds abspath;
+ sds relpath = sdsnew(filename);
+
+ relpath = sdstrim(relpath," \r\n\t");
+ if (relpath[0] == '/') return relpath; /* Path is already absolute. */
+
+ /* If path is relative, join cwd and relative path. */
+ if (getcwd(cwd,sizeof(cwd)) == NULL) {
+ sdsfree(relpath);
+ return NULL;
+ }
+ abspath = sdsnew(cwd);
+ if (sdslen(abspath) && abspath[sdslen(abspath)-1] != '/')
+ abspath = sdscat(abspath,"/");
+
+ /* At this point we have the current path always ending with "/", and
+ * the trimmed relative path. Try to normalize the obvious case of
+ * trailing ../ elements at the start of the path.
+ *
+ * For every "../" we find in the filename, we remove it and also remove
+ * the last element of the cwd, unless the current cwd is "/". */
+ while (sdslen(relpath) >= 3 &&
+ relpath[0] == '.' && relpath[1] == '.' && relpath[2] == '/')
+ {
+ relpath = sdsrange(relpath,3,-1);
+ if (sdslen(abspath) > 1) {
+ char *p = abspath + sdslen(abspath)-2;
+ int trimlen = 1;
+
+ while(*p != '/') {
+ p--;
+ trimlen++;
+ }
+ abspath = sdsrange(abspath,0,-(trimlen+1));
+ }
+ }
+
+ /* Finally glue the two parts together. */
+ abspath = sdscatsds(abspath,relpath);
+ sdsfree(relpath);
+ return abspath;
+}
+
#ifdef UTIL_TEST_MAIN
#include <assert.h>