]> arthur.barton.de Git - netatalk.git/blobdiff - libatalk/util/unix.c
Merge from branch-2-1
[netatalk.git] / libatalk / util / unix.c
index a8a1e1a5f3e59ee2c86133f46ec4732fdc10f41a..1c131ad507c9712a4de3a18f8648795b89c950ef 100644 (file)
@@ -1,5 +1,4 @@
 /*
-  $Id: unix.c,v 1.4 2010-02-19 11:29:52 franklahm Exp $
   Copyright (c) 2010 Frank Lahm <franklahm@gmail.com>
 
   This program is free software; you can redistribute it and/or modify
@@ -36,7 +35,6 @@
 #include <atalk/ea.h>
 #include <atalk/afp.h>
 #include <atalk/logger.h>
-#include <atalk/volume.h>
 #include <atalk/vfs.h>
 #include <atalk/util.h>
 #include <atalk/unix.h>
@@ -57,6 +55,26 @@ const char *getcwdpath(void)
         return strerror(errno);
 }
 
+/*!
+ * Takes a buffer with a path, strips slashs, returns basename
+ *
+ * @param p (rw) path
+ *        path may be
+ *          "[/][dir/[...]]file"
+ *        or
+ *          "[/][dir/[...]]dir/[/]"
+ *        Result is "file" or "dir" 
+ *
+ * @returns pointer to basename in path buffer, buffer is possibly modified
+ */
+char *stripped_slashes_basename(char *p)
+{
+    int i = strlen(p) - 1;
+    while (i > 0 && p[i] == '/')
+        p[i--] = 0;
+    return (strrchr(p, '/') ? strrchr(p, '/') + 1 : p);
+}
+
 /*!
  * @brief symlink safe chdir replacement
  *
@@ -66,38 +84,23 @@ const char *getcwdpath(void)
  */
 int lchdir(const char *dir)
 {
-    int ret = 0;
     char buf[MAXPATHLEN+1];
-#ifdef REALPATH_TAKES_NULL
-    char *rpath = NULL;
-#else
-    char rpath[MAXPATHLEN+1];
-#endif
-
-    /* dir might be an relative or an absolute path */
-    if (dir[0] == '/') {
-        /* absolute path, just make sure buf is prepared for strlcat */
-        buf[0] = 0;
-    } else {
-        /* relative path, push cwd int buf */
-        if (getcwd(buf, MAXPATHLEN) == NULL)
-            return -1;
-        if (strlcat(buf, "/", MAXPATHLEN) >= MAXPATHLEN)
+    char cwd[MAXPATHLEN+1];
+    char *test;
+    int  i;
+
+    /*
+     dir is a canonical path (without "../" "./" "//" )
+     but may end with a / 
+    */
+    *cwd = 0;
+    if (*dir != '/') {
+        if (getcwd(cwd, MAXPATHLEN) == NULL)
             return -1;
     }
-
-    if (strlcat(buf, dir, MAXPATHLEN) >= MAXPATHLEN)
+    if (chdir(dir) != 0)
         return -1;
 
-#ifdef REALPATH_TAKES_NULL
-    if ((rpath = realpath(dir, NULL)) == NULL) {
-#else
-    if (realpath(dir, rpath) == NULL) {
-#endif
-        ret = -1;
-        goto exit;
-    }
-
     /* 
      * Cases:
      * chdir request   | realpath result | ret
@@ -107,22 +110,41 @@ int lchdir(const char *dir)
      * /a/b/.          | /c              | 1
      * /a/b/.          | /c/d/e/f        | 1
      */
-    ret = 0;
-    for (int i = 0; rpath[i]; i++) {
-        if (buf[i] != rpath[i]) {
-            ret = 1;
-            goto exit;
+    if (getcwd(buf, MAXPATHLEN) == NULL)
+        return 1;
+
+    i = 0;
+    if (*cwd) {
+        /* relative path requested, 
+         * Same directory?
+        */
+        for (; cwd[i]; i++) {
+            if (buf[i] != cwd[i])
+                return 1;
         }
+        if (buf[i]) {
+            if (buf[i] != '/')
+                return 1;
+            i++;
+        }                    
     }
 
-    if (chdir(dir) != 0) {
-        ret = -1;
-        goto exit;
+    test = &buf[i];    
+    for (i = 0; test[i]; i++) {
+        if (test[i] != dir[i]) {
+            return 1;
+        }
     }
+    /* trailing '/' ? */
+    if (!dir[i])
+        return 0;
+
+    if (dir[i] != '/')
+        return 1;
+
+    i++;
+    if (dir[i])
+        return 1;
 
-exit:
-#ifdef REALPATH_TAKES_NULL
-    free(rpath);
-#endif
-    return ret;
+    return 0;
 }