]> arthur.barton.de Git - netatalk.git/blobdiff - libatalk/util/volinfo.c
Merge master
[netatalk.git] / libatalk / util / volinfo.c
index 3e639f09ff28837bfcdc37d2d931315b27094658..6dec61a0ccf4f817d91d9128be7629ea2469a6bf 100644 (file)
@@ -294,10 +294,9 @@ static int parseline ( char *buf, struct volinfo *vol)
         }
         break;
       case CNID_DBPATH:
-        if ((vol->v_dbpath = strdup(value)) == NULL) {
-           fprintf (stderr, "strdup: %s", strerror(errno));
-            return -1;
-        }
+          if ((vol->v_dbpath = malloc(MAXPATHLEN+1)) == NULL)
+              return -1;
+          strcpy(vol->v_dbpath, value);
         break;
       case ADOUBLE_VER:
         if (strcasecmp(value, "v2") == 0) {
@@ -340,7 +339,7 @@ int loadvolinfo (char *path, struct volinfo *vol)
     char   volinfofile[MAXPATHLEN];
     char   buf[MAXPATHLEN];
     struct flock lock;
-    int    fd;
+    int    fd, len;
     FILE   *fp;
 
     if ( !path || !vol)
@@ -354,9 +353,16 @@ int loadvolinfo (char *path, struct volinfo *vol)
         return -1;
 
     if ((vol->v_path = strdup(volinfofile)) == NULL ) {
-       fprintf (stderr, "strdup: %s", strerror(errno));
+        fprintf (stderr, "strdup: %s", strerror(errno));
         return (-1);
     }
+    /* Remove trailing slashes */
+    len = strlen(vol->v_path);
+    while (len && (vol->v_path[len-1] == '/')) {
+        vol->v_path[len-1] = 0;
+        len--;
+    }
+
     strlcat(volinfofile, ".AppleDesktop/", sizeof(volinfofile));
     strlcat(volinfofile, VOLINFOFILE, sizeof(volinfofile));
 
@@ -399,10 +405,63 @@ int loadvolinfo (char *path, struct volinfo *vol)
     if ((vol->v_flags & AFPVOL_INV_DOTS))
         vol->v_ad_options |= ADVOL_INVDOTS;
 
+    vol->retaincount = 1;
+
     fclose(fp);
     return 0;
 }
 
+/*!
+ * Allocate a struct volinfo object for refcounting usage with retain and close, and
+ * call loadvolinfo with it
+ */
+struct volinfo *allocvolinfo(char *path)
+{
+    struct volinfo *p = malloc(sizeof(struct volinfo));
+    if (p == NULL)
+        return NULL;
+
+    if (loadvolinfo(path, p) == -1)
+        return NULL;
+
+    p->malloced = 1;
+
+    return p;
+}
+
+void retainvolinfo(struct volinfo *vol)
+{
+    vol->retaincount++;
+}
+
+/*!
+ * Decrement retain count, free resources when retaincount reaches 0
+ */
+int closevolinfo(struct volinfo *volinfo)
+{
+    if (volinfo->retaincount <= 0)
+        abort();
+
+    volinfo->retaincount--;
+
+    if (volinfo->retaincount == 0) {
+        free(volinfo->v_name); volinfo->v_name = NULL;
+        free(volinfo->v_path); volinfo->v_path = NULL;
+        free(volinfo->v_cnidscheme); volinfo->v_cnidscheme = NULL;
+        free(volinfo->v_dbpath); volinfo->v_dbpath = NULL;
+        free(volinfo->v_volcodepage); volinfo->v_volcodepage = NULL;
+        free(volinfo->v_maccodepage); volinfo->v_maccodepage = NULL;
+        free(volinfo->v_dbd_host); volinfo->v_dbd_host = NULL;
+        free(volinfo->v_dbd_port); volinfo->v_dbd_port = NULL;
+        if (volinfo->malloced) {
+            volinfo->malloced = 0;
+            free(volinfo);
+        }
+    }
+
+    return 0;
+}
+
 /*
  * Save the volume options to a file, used by shell utilities. Writing the file
  * everytime a volume is opened is unnecessary, but it shouldn't hurt much.