libaacs | branch: master | npzacs <npz...@gmail.com> | Thu Oct 24 13:51:18 2013 
+0300| [d0a4d77889e9f7891e20306830fa2a7e3f706137] | committer: npzacs

Avoid using realpath

> http://git.videolan.org/gitweb.cgi/libaacs.git/?a=commit;h=d0a4d77889e9f7891e20306830fa2a7e3f706137
---

 configure.ac      |    2 -
 src/Makefile.am   |    4 +-
 src/file/path.c   |  142 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/file/path.h   |   31 ++++++++++++
 src/libaacs/mmc.c |   13 ++---
 5 files changed, 179 insertions(+), 13 deletions(-)

diff --git a/configure.ac b/configure.ac
index 2c3db97..db0454a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -104,8 +104,6 @@ AC_SYS_LARGEFILE
 dnl required functions
 AC_CHECK_FUNC([snprintf],, [AC_MSG_ERROR($function_not_found)])
 
-AC_CHECK_FUNC([realpath],[AC_DEFINE([HAVE_REALPATH],[1],[realpath])])
-
 dnl required libraries
 
 dnl pthread check (not on win32)
diff --git a/src/Makefile.am b/src/Makefile.am
index 83ce5af..f3078cc 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -23,6 +23,7 @@ libaacs_la_SOURCES=\
        file/keydb.h \
        file/keydbcfg-parser.y \
        file/keydbcfg-lexer.l \
+       file/path.h \
        util/attributes.h \
        util/macro.h \
        util/logging.c \
@@ -42,7 +43,8 @@ libaacs_la_SOURCES+= \
        file/dirs_win32.c
 else
 libaacs_la_SOURCES+= \
-       file/dirs_xdg.c
+       file/dirs_xdg.c \
+       file/path.c
 endif
 endif
 
diff --git a/src/file/path.c b/src/file/path.c
new file mode 100644
index 0000000..8a53a09
--- /dev/null
+++ b/src/file/path.c
@@ -0,0 +1,142 @@
+/*
+ * This file is part of libaacs
+ * Copyright (C) 2013  VideoLAN
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include "file.h"
+
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#define MAX_LINKS 32
+
+char *aacs_resolve_path(const char *path, char *resolved_path)
+{
+    char tmp_path[AACS_PATH_MAX];
+    char link[AACS_PATH_MAX];
+    char *new_path = resolved_path;
+    char *path_end = tmp_path + AACS_PATH_MAX - 1;
+    int readlinks = 0;
+    int n;
+
+    if (!path || !*path || strlen(path) >= AACS_PATH_MAX - 2) {
+        return NULL;
+    }
+
+    /* shadow original path with a copy */
+    strcpy(tmp_path, path);
+    path = tmp_path;
+
+    /* handle relative path */
+    if (*path != '/') {
+        if (!getcwd(new_path, AACS_PATH_MAX - 1)) {
+            return NULL;
+        }
+        new_path += strlen(new_path);
+        if (new_path[-1] != '/') {
+            *new_path++ = '/';
+        }
+    } else {
+        *new_path++ = '/';
+        path++;
+    }
+
+
+    while (*path) {
+        /* "/" */
+        if (*path == '/') {
+            path++;
+            continue;
+        }
+        /* "." */
+        if (path[0] == '.' && (!path[1] || path[1] == '/')) {
+            path++;
+            continue;
+        }
+        /* ".." */
+        if (path[0] == '.' && path[1] == '.' && (!path[2] || path[2] == '/')) {
+            path += 2;
+            /* not at root ? -> back up one level */
+            if (new_path != resolved_path + 1) {
+                while ((--new_path)[-1] != '/');
+            }
+            continue;
+        }
+
+        /* copy next component */
+        while (*path && *path != '/') {
+            if (path >= path_end) {
+                return NULL;
+            }
+            *new_path++ = *path++;
+        }
+
+        /* avoid symlink loops */
+        if (readlinks++ > MAX_LINKS) {
+            return NULL;
+        }
+
+        /* resolve symlink */
+
+        *new_path = 0;
+        n = readlink(resolved_path, link, AACS_PATH_MAX - 1);
+
+        if (n < 0) {
+            if (errno != EINVAL) {
+              return NULL;
+            }
+            /* file exists but isn't a symlink. */
+
+        } else if (n >= AACS_PATH_MAX - 1) {
+            return NULL;
+
+        } else {
+            link[n] = 0;
+            if (*link == '/') {
+                new_path = resolved_path;
+            } else {
+                while (*(--new_path) != '/');
+            }
+
+            if (path + n >= path_end) {
+                return NULL;
+            }
+
+            /* update what's left */
+            strcat(link, path);
+            strcpy(tmp_path, link);
+            path = tmp_path;
+        }
+
+        if (*path) {
+            *new_path++ = '/';
+        }
+    }
+
+    *new_path = 0;
+    return resolved_path;
+}
+
+#ifdef TEST_AACS_RESOLVE_PATH
+#include <stdio.h>
+void main(int argc, char *argv[]) {
+    char path[AACS_PATH_MAX];
+    printf("%s -> %s\n", argv[0], aacs_resolve_path(argv[0], path));
+    printf("%s -> %s\n", argv[1], aacs_resolve_path(argv[1], path));
+}
+#endif
diff --git a/src/file/path.h b/src/file/path.h
new file mode 100644
index 0000000..8d6f0c2
--- /dev/null
+++ b/src/file/path.h
@@ -0,0 +1,31 @@
+/*
+ * This file is part of libaacs
+ * Copyright (C) 2013  VideoLAN
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef AACS_PATH_H
+#define AACS_PATH_H
+
+#include <util/attributes.h>
+
+#ifndef AACS_PATH_MAX
+#define AACS_PATH_MAX 1024
+#endif
+
+AACS_PRIVATE char *aacs_resolve_path(const char *path, char *resolved_path);
+
+#endif /* AACS_PATH_H */
diff --git a/src/libaacs/mmc.c b/src/libaacs/mmc.c
index 2cdfae5..969f543 100644
--- a/src/libaacs/mmc.c
+++ b/src/libaacs/mmc.c
@@ -25,6 +25,7 @@
 
 #include "mmc.h"
 #include "crypto.h"
+#include "file/path.h"
 #include "util/macro.h"
 #include "util/logging.h"
 
@@ -872,18 +873,12 @@ MMC *mmc_open(const char *path)
 
 #elif defined(HAVE_MNTENT_H)
 
-#ifdef HAVE_REALPATH
-    char *file_path = malloc(PATH_MAX);
-    if (!file_path || !realpath(path, file_path)) {
+    char file_path [AACS_PATH_MAX];
+    if (!aacs_resolve_path(path, file_path)) {
         DEBUG(DBG_MMC | DBG_CRIT, "Failed resolving path %s\n", path);
         X_FREE(mmc);
-        X_FREE(file_path);
         return NULL;
     }
-#else
-    char *file_path = (char*)malloc(strlen(path) + 1);
-    strcpy(file_path, path);
-#endif
 
     int   path_len  = strlen(file_path);
     FILE *proc_mounts;
@@ -924,8 +919,6 @@ MMC *mmc_open(const char *path)
         X_FREE(mmc);
     }
 
-    X_FREE(file_path);
-
 #elif defined(_WIN32)
     char drive[] = { path[0], ':', '\\', 0 };
     char volume[] = {'\\', '\\', '.', '\\', path[0], ':', 0};

_______________________________________________
libaacs-devel mailing list
libaacs-devel@videolan.org
https://mailman.videolan.org/listinfo/libaacs-devel

Reply via email to