]> arthur.barton.de Git - netatalk.git/blobdiff - bin/ad/ad_util.c
Support for using $u username variable in AFP volume definitions
[netatalk.git] / bin / ad / ad_util.c
index 3032b93b13d2c04259bfdc3346d7a50563461de4..27f42b052cec9faff446681358ede8d251d8c557 100644 (file)
@@ -51,6 +51,9 @@
 #ifdef HAVE_SOLARIS_ACLS
 #include <sys/acl.h>
 #endif  /* HAVE_SOLARIS_ACLS */
+#ifdef HAVE_FREEBSD_SUNACL
+#include <sunacl.h>
+#endif
 
 #ifdef HAVE_POSIX_ACLS
 #include <sys/types.h>
 
 #include <atalk/util.h>
 #include <atalk/cnid.h>
-#include <atalk/volinfo.h>
 #include <atalk/bstrlib.h>
 #include <atalk/bstradd.h>
 #include <atalk/logger.h>
 #include <atalk/errchk.h>
 #include <atalk/unicode.h>
+#include <atalk/globals.h>
+#include <atalk/netatalk_conf.h>
+
 
 #include "ad.h"
 
@@ -96,46 +101,35 @@ void _log(enum logtype lt, char *fmt, ...)
  *
  * @returns 0 on success, exits on error
  */
-int openvol(const char *path, afpvol_t *vol)
+int openvol(AFPObj *obj, const char *path, afpvol_t *vol)
 {
     int flags = 0;
 
     memset(vol, 0, sizeof(afpvol_t));
 
-    /* try to find a .AppleDesktop/.volinfo */
-    if (loadvolinfo((char *)path, &vol->volinfo) != 0)
+    if ((vol->vol = getvolbypath(obj, path)) == NULL)
         return -1;
 
-    if (STRCMP(vol->volinfo.v_cnidscheme, != , "dbd"))
-        ERROR("\"%s\" isn't a \"dbd\" CNID volume!", vol->volinfo.v_path);
-
-    if (vol_load_charsets(&vol->volinfo) == -1)
-        ERROR("Error loading charsets!");
+    if (STRCMP(vol->vol->v_cnidscheme, != , "dbd"))
+        ERROR("\"%s\" isn't a \"dbd\" CNID volume!", vol->vol->v_path);
 
     /* Sanity checks to ensure we can touch this volume */
-    if (vol->volinfo.v_adouble != AD_VERSION2)
-        ERROR("Unsupported adouble versions: %u", vol->volinfo.v_adouble);
-
-    if (vol->volinfo.v_vfs_ea != AFPVOL_EA_SYS)
-        ERROR("Unsupported Extended Attributes option: %u", vol->volinfo.v_vfs_ea);
+    if (vol->vol->v_adouble != AD_VERSION2
+        && vol->vol->v_adouble != AD_VERSION_EA)
+        ERROR("Unsupported adouble versions: %u", vol->vol->v_adouble);
 
-    /* initialize sufficient struct vol for VFS initialisation */
-    vol->volume.v_adouble = AD_VERSION2;
-    vol->volume.v_vfs_ea = AFPVOL_EA_SYS;
-    initvol_vfs(&vol->volume);
+    if (vol->vol->v_vfs_ea != AFPVOL_EA_SYS)
+        ERROR("Unsupported Extended Attributes option: %u", vol->vol->v_vfs_ea);
 
-    if ((vol->volinfo.v_flags & AFPVOL_NODEV))
+    if ((vol->vol->v_flags & AFPVOL_NODEV))
         flags |= CNID_FLAG_NODEV;
 
-    if ((vol->volume.v_cdb = cnid_open(vol->volinfo.v_dbpath,
-                                       0000,
-                                       "dbd",
-                                       flags,
-                                       vol->volinfo.v_dbd_host,
-                                       vol->volinfo.v_dbd_port)) == NULL)
-        ERROR("Cant initialize CNID database connection for %s", vol->volinfo.v_path);
+    if ((vol->vol->v_cdb = cnid_open(vol->vol,
+                                     "dbd",
+                                     flags)) == NULL)
+        ERROR("Cant initialize CNID database connection for %s", vol->vol->v_path);
 
-    cnid_getstamp(vol->volume.v_cdb,
+    cnid_getstamp(vol->vol->v_cdb,
                   vol->db_stamp,
                   sizeof(vol->db_stamp));
     
@@ -144,16 +138,19 @@ int openvol(const char *path, afpvol_t *vol)
 
 void closevol(afpvol_t *vol)
 {
-    if (vol->volume.v_cdb)
-        cnid_close(vol->volume.v_cdb);
-
+    if (vol->vol) {
+        if (vol->vol->v_cdb) {
+            cnid_close(vol->vol->v_cdb);
+            vol->vol->v_cdb = NULL;
+        }
+    }
     memset(vol, 0, sizeof(afpvol_t));
 }
 
 /*
   Taken form afpd/desktop.c
 */
-char *utompath(const struct volinfo *volinfo, const char *upath)
+char *utompath(const struct vol *vol, const char *upath)
 {
     static char  mpath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
     char         *m;
@@ -168,101 +165,28 @@ char *utompath(const struct volinfo *volinfo, const char *upath)
     u = upath;
     outlen = strlen(upath);
 
-    if ((volinfo->v_casefold & AFPVOL_UTOMUPPER))
+    if ((vol->v_casefold & AFPVOL_UTOMUPPER))
         flags |= CONV_TOUPPER;
-    else if ((volinfo->v_casefold & AFPVOL_UTOMLOWER))
+    else if ((vol->v_casefold & AFPVOL_UTOMLOWER))
         flags |= CONV_TOLOWER;
 
-    if ((volinfo->v_flags & AFPVOL_EILSEQ)) {
+    if ((vol->v_flags & AFPVOL_EILSEQ)) {
         flags |= CONV__EILSEQ;
     }
 
     /* convert charsets */
-    if ((size_t)-1 == ( outlen = convert_charset(volinfo->v_volcharset,
+    if ((size_t)-1 == ( outlen = convert_charset(vol->v_volcharset,
                                                  CH_UTF8_MAC,
-                                                 volinfo->v_maccharset,
+                                                 vol->v_maccharset,
                                                  u, outlen, mpath, MAXPATHLEN, &flags)) ) {
         SLOG("Conversion from %s to %s for %s failed.",
-             volinfo->v_volcodepage, volinfo->v_maccodepage, u);
+             vol->v_volcodepage, vol->v_maccodepage, u);
         return NULL;
     }
 
     return(m);
 }
 
-/*!
- * Build path relativ to volume root
- *
- * path might be:
- * (a) relative:
- *     "dir/subdir" with cwd: "/afp_volume/topdir"
- * (b) absolute:
- *     "/afp_volume/dir/subdir"
- *
- * @param path     (r) path relative to cwd() or absolute
- * @param volpath  (r) volume path that path is a subdir of (has been computed in volinfo funcs)
- *
- * @returns relative path in new bstring, caller must bdestroy it
- */
-static bstring rel_path_in_vol(const char *path, const char *volpath)
-{
-    EC_INIT;
-    int cwd = -1;
-    bstring fpath = NULL;
-    char *dname = NULL;
-    struct stat st;
-
-    if (path == NULL || volpath == NULL)
-        return NULL;
-
-    EC_NEG1_LOG(cwd = open(".", O_RDONLY));
-
-    EC_ZERO_LOGSTR(lstat(path, &st), "lstat(%s): %s", path, strerror(errno));
-    switch (S_IFMT & st.st_mode) {
-
-    case S_IFREG:
-    case S_IFLNK:
-        EC_NULL_LOG(dname = strdup(path));
-        EC_ZERO_LOGSTR(chdir(dirname(dname)), "chdir(%s): %s", dirname, strerror(errno));
-        free(dname);
-        dname = NULL;
-        EC_NULL(fpath = bfromcstr(getcwdpath()));
-        BSTRING_STRIP_SLASH(fpath);
-        EC_ZERO(bcatcstr(fpath, "/"));
-        EC_NULL_LOG(dname = strdup(path));
-        EC_ZERO(bcatcstr(fpath, basename(dname)));
-        break;
-
-    case S_IFDIR:
-        EC_ZERO_LOGSTR(chdir(path), "chdir(%s): %s", path, strerror(errno));
-        EC_NULL(fpath = bfromcstr(getcwdpath()));
-        break;
-
-    default:
-        SLOG("special: %s", path);
-        EC_FAIL;
-    }
-
-    BSTRING_STRIP_SLASH(fpath);
-
-    /*
-     * Now we have eg:
-     *   fpath:   /Volume/netatalk/dir/bla
-     *   volpath: /Volume/netatalk/
-     * we want: "dir/bla"
-     */
-    EC_ZERO(bdelete(fpath, 0, strlen(volpath)));
-
-EC_CLEANUP:
-    if (dname) free(dname);
-    if (cwd != -1) {
-        fchdir(cwd);
-        close(cwd);
-    }
-    if (ret != 0)
-        return NULL;
-    return fpath;
-}
 
 /*!
  * Convert dot encoding of basename _in place_
@@ -286,26 +210,18 @@ int convert_dots_encoding(const afpvol_t *svol, const afpvol_t *dvol, char *path
     int pos = bname - path;
     uint16_t flags = 0;
 
-    if ( ! svol->volinfo.v_path) {
+    if ( ! svol->vol->v_path) {
         /* no source volume: escape special chars (eg ':') */
-        from = dvol->volinfo.v_volcharset; /* src = dst charset */
-        flags |= CONV_ESCAPEHEX;
+        from = dvol->vol->v_volcharset; /* src = dst charset */
+        if (dvol->vol->v_adouble == AD_VERSION2)
+            flags |= CONV_ESCAPEHEX;
     } else {
-        from = svol->volinfo.v_volcharset;
-    }
-
-    if ( (svol->volinfo.v_path)
-         && ! (svol->volinfo.v_flags & AFPVOL_USEDOTS)
-         && (dvol->volinfo.v_flags & AFPVOL_USEDOTS)) {
-        /* source is without dots, destination is with */
-        flags |= CONV_UNESCAPEHEX;
-    } else if (! (dvol->volinfo.v_flags & AFPVOL_USEDOTS)) {
-        flags |= CONV_ESCAPEDOTS;
+        from = svol->vol->v_volcharset;
     }
 
     int len = convert_charset(from,
-                              dvol->volinfo.v_volcharset,
-                              dvol->volinfo.v_maccharset,
+                              dvol->vol->v_volcharset,
+                              dvol->vol->v_maccharset,
                               bname, strlen(bname),
                               buf, MAXPATHLEN,
                               &flags);
@@ -317,72 +233,6 @@ int convert_dots_encoding(const afpvol_t *svol, const afpvol_t *dvol, char *path
     return 0;
 }
 
-/*!
- * ResolvesCNID of a given paths
- *
- * path might be:
- * (a) relative:
- *     "dir/subdir" with cwd: "/afp_volume/topdir"
- * (b) absolute:
- *     "/afp_volume/dir/subdir"
- *
- * path MUST be pointing inside vol, this is usually the case as vol has been build from
- * path using loadvolinfo and friends.
- *
- * @param vol  (r) pointer to afpvol_t
- * @param path (r) path, see above
- * @param did  (rw) parent CNID of returned CNID
- *
- * @returns CNID of path
- */
-cnid_t cnid_for_path(const afpvol_t *vol,
-                     const char *path,
-                     cnid_t *did)
-{
-    EC_INIT;
-
-    cnid_t cnid;
-    bstring rpath = NULL;
-    bstring statpath = NULL;
-    struct bstrList *l = NULL;
-    struct stat st;
-
-    *did = htonl(1);
-    cnid = htonl(2);
-
-    EC_NULL(rpath = rel_path_in_vol(path, vol->volinfo.v_path));
-    EC_NULL(statpath = bfromcstr(vol->volinfo.v_path));
-
-    l = bsplit(rpath, '/');
-    for (int i = 0; i < l->qty ; i++) {
-        *did = cnid;
-        EC_ZERO(bconcat(statpath, l->entry[i]));
-        EC_ZERO_LOGSTR(lstat(cfrombstr(statpath), &st),
-                       "lstat(rpath: %s, elem: %s): %s: %s",
-                       cfrombstr(rpath), cfrombstr(l->entry[i]),
-                       cfrombstr(statpath), strerror(errno));
-
-        if ((cnid = cnid_add(vol->volume.v_cdb,
-                             &st,
-                             *did,
-                             cfrombstr(l->entry[i]),
-                             blength(l->entry[i]),
-                             0)) == CNID_INVALID) {
-            EC_FAIL;
-        }
-        EC_ZERO(bcatcstr(statpath, "/"));
-    }
-
-EC_CLEANUP:
-    bdestroy(rpath);
-    bstrListDestroy(l);
-    bdestroy(statpath);
-    if (ret != 0)
-        return CNID_INVALID;
-
-    return cnid;
-}
-
 /*!
  * Resolves CNID of a given paths parent directory
  *
@@ -416,8 +266,8 @@ cnid_t cnid_for_paths_parent(const afpvol_t *vol,
     *did = htonl(1);
     cnid = htonl(2);
 
-    EC_NULL(rpath = rel_path_in_vol(path, vol->volinfo.v_path));
-    EC_NULL(statpath = bfromcstr(vol->volinfo.v_path));
+    EC_NULL(rpath = rel_path_in_vol(path, vol->vol->v_path));
+    EC_NULL(statpath = bfromcstr(vol->vol->v_path));
 
     l = bsplit(rpath, '/');
     if (l->qty == 1)
@@ -431,7 +281,7 @@ cnid_t cnid_for_paths_parent(const afpvol_t *vol,
                        cfrombstr(rpath), cfrombstr(l->entry[i]),
                        cfrombstr(statpath), strerror(errno));
 
-        if ((cnid = cnid_add(vol->volume.v_cdb,
+        if ((cnid = cnid_add(vol->vol->v_cdb,
                              &st,
                              *did,
                              cfrombstr(l->entry[i]),