]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/volume.c
allow more values in cnid_open flags parameter
[netatalk.git] / etc / afpd / volume.c
index 2226b7185b65da5bcd7912afa0b73c91874772e9..c802f8173d7083af335fa9e5667149c87bfdb413 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: volume.c,v 1.98 2009-11-05 14:38:07 franklahm Exp $
+ * $Id: volume.c,v 1.105 2009-11-24 11:40:11 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -556,8 +556,8 @@ static void volset(struct vol_option *options, struct vol_option *save,
     } else if (optionok(tmp, "ea:", val)) {
         if (strcasecmp(val + 1, "ad") == 0) /* the default anyway */
             options[VOLOPT_EA_VFS].i_value = AFPVOL_EA_AD;
-        else if (strcasecmp(val + 1, "solaris") == 0)
-            options[VOLOPT_EA_VFS].i_value = AFPVOL_EA_SOLARIS;
+        else if (strcasecmp(val + 1, "sys") == 0)
+            options[VOLOPT_EA_VFS].i_value = AFPVOL_EA_SYS;
 
     } else {
         /* ignore unknown options */
@@ -623,7 +623,7 @@ static int creatvol(AFPObj *obj, struct passwd *pwd,
         if (tmpvlen + suffixlen > obj->options.volnamelen) {
             flags = CONV_FORCE;
             tmpvlen = convert_charset(obj->options.unixcharset, CH_UTF8_MAC, 0, name, vlen, tmpname, obj->options.volnamelen - suffixlen, &flags);
-            tmpname[tmpvlen != (size_t)-1 ? tmpvlen : 0] = 0;
+            tmpname[tmpvlen >= 0 ? tmpvlen : 0] = 0;
         }
         strcat(tmpname, suffix);
         tmpvlen = strlen(tmpname);
@@ -649,7 +649,7 @@ static int creatvol(AFPObj *obj, struct passwd *pwd,
         if (tmpvlen + suffixlen > AFPVOL_MACNAMELEN) {
             flags = CONV_FORCE;
             tmpvlen = convert_charset(obj->options.unixcharset, obj->options.maccharset, 0, name, vlen, tmpname, AFPVOL_MACNAMELEN - suffixlen, &flags);
-            tmpname[tmpvlen != (size_t)-1 ? tmpvlen : 0] = 0;
+            tmpname[tmpvlen >= 0 ? tmpvlen : 0] = 0;
         }
         strcat(tmpname, suffix);
         tmpvlen = strlen(tmpname);
@@ -770,7 +770,32 @@ static int creatvol(AFPObj *obj, struct passwd *pwd,
        else 
            volume->v_adouble = AD_VERSION;
 
+        /* Mac to Unix conversion flags*/
+        volume->v_mtou_flags = 0;
+        if (!(volume->v_flags & AFPVOL_NOHEX))
+            volume->v_mtou_flags |= CONV_ESCAPEHEX;
+        if (!(volume->v_flags & AFPVOL_USEDOTS))
+            volume->v_mtou_flags |= CONV_ESCAPEDOTS;
+        if ((volume->v_flags & AFPVOL_EILSEQ))
+            volume->v_mtou_flags |= CONV__EILSEQ;
+
+        if ((volume->v_casefold & AFPVOL_MTOUUPPER))
+            volume->v_mtou_flags |= CONV_TOUPPER;
+        else if ((volume->v_casefold & AFPVOL_MTOULOWER))
+            volume->v_mtou_flags |= CONV_TOLOWER;
+
+        /* Unix to Mac conversion flags*/
+        volume->v_utom_flags = CONV_IGNORE | CONV_UNESCAPEHEX;
+        if ((volume->v_casefold & AFPVOL_UTOMUPPER))
+            volume->v_utom_flags |= CONV_TOUPPER;
+        else if ((volume->v_casefold & AFPVOL_UTOMLOWER))
+            volume->v_utom_flags |= CONV_TOLOWER;
+
+        if ((volume->v_flags & AFPVOL_EILSEQ)) 
+            volume->v_utom_flags |= CONV__EILSEQ;
+
        initvol_vfs(volume);
+
 #ifdef FORCE_UIDGID
         if (options[VOLOPT_FORCEUID].c_value) {
             volume->v_forceuid = strdup(options[VOLOPT_FORCEUID].c_value);
@@ -1443,7 +1468,7 @@ static int getvolparams( u_int16_t bitmap, struct vol *vol, struct stat *st, cha
                      (1<<VOLPBIT_XBFREE)|(1<<VOLPBIT_XBTOTAL) |
                      (1<<VOLPBIT_BSIZE)) ) != 0 ) {
         if ( getvolspace( vol, &bfree, &btotal, &xbfree, &xbtotal,
-                          &bsize) < 0 ) {
+                          &bsize) != AFP_OK ) {
             if ( isad ) {
                 ad_close( &ad, ADFLAGS_HF );
             }
@@ -1769,6 +1794,60 @@ int afp_getsrvrparms(AFPObj *obj, char *ibuf _U_, size_t ibuflen _U_, char *rbuf
     return( AFP_OK );
 }
 
+/* ------------------------- */
+static int volume_codepage(AFPObj *obj, struct vol *volume)
+{
+    struct charset_functions *charset;
+    /* Codepages */
+
+    if (!volume->v_volcodepage)
+       volume->v_volcodepage = strdup("UTF8");
+
+    if ( (charset_t) -1 == ( volume->v_volcharset = add_charset(volume->v_volcodepage)) ) {
+       LOG (log_error, logtype_afpd, "Setting codepage %s as volume codepage failed", volume->v_volcodepage);
+       return -1;
+    }
+
+    if ( NULL == (charset = find_charset_functions(volume->v_volcodepage)) || charset->flags & CHARSET_ICONV ) {
+       LOG (log_warning, logtype_afpd, "WARNING: volume encoding %s is *not* supported by netatalk, expect problems !!!!", volume->v_volcodepage);
+    }  
+
+    if (!volume->v_maccodepage)
+       volume->v_maccodepage = strdup(obj->options.maccodepage);
+
+    if ( (charset_t) -1 == ( volume->v_maccharset = add_charset(volume->v_maccodepage)) ) {
+       LOG (log_error, logtype_afpd, "Setting codepage %s as mac codepage failed", volume->v_maccodepage);
+       return -1;
+    }
+
+    if ( NULL == ( charset = find_charset_functions(volume->v_maccodepage)) || ! (charset->flags & CHARSET_CLIENT) ) {
+       LOG (log_error, logtype_afpd, "Fatal error: mac charset %s not supported", volume->v_maccodepage);
+       return -1;
+    }
+    volume->v_kTextEncoding = htonl(charset->kTextEncoding);
+    return 0;
+}
+
+/* ------------------------- */
+static int volume_openDB(struct vol *volume)
+{
+    int flags = 0;
+
+    if ((volume->v_flags & AFPVOL_NODEV)) {
+        flags |= CNID_FLAG_NODEV;
+    }
+
+    if (volume->v_cnidscheme == NULL) {
+        volume->v_cnidscheme = strdup(DEFAULT_CNID_SCHEME);
+        LOG(log_info, logtype_afpd, "Volume %s use CNID scheme %s.", volume->v_path, volume->v_cnidscheme);
+    }
+    if (volume->v_dbpath)
+        volume->v_cdb = cnid_open (volume->v_dbpath, volume->v_umask, volume->v_cnidscheme, flags);
+    else
+        volume->v_cdb = cnid_open (volume->v_path, volume->v_umask, volume->v_cnidscheme, flags);
+    return (!volume->v_cdb)?-1:0;
+}
+
 /* ------------------------- 
  * we are the user here
 */
@@ -1777,6 +1856,7 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t
     struct stat        st;
     char       *volname;
     char        *p;
+    
     struct vol *volume;
     struct dir *dir;
     int                len, ret;
@@ -1786,13 +1866,14 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t
     char        *vol_uname;
     char        *vol_mname;
     char        *volname_tmp;
-
+    
     ibuf += 2;
     memcpy(&bitmap, ibuf, sizeof( bitmap ));
     bitmap = ntohs( bitmap );
     ibuf += sizeof( bitmap );
+
+    *rbuflen = 0;
     if (( bitmap & (1<<VOLPBIT_VID)) == 0 ) {
-        *rbuflen = 0;
         return AFPERR_BITMAP;
     }
 
@@ -1808,8 +1889,7 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t
       namelen = convert_string(obj->options.maccharset, CH_UCS2, ibuf, len, volname, sizeof(obj->oldtmp));
     }
 
-    if ( namelen <= 0){
-        *rbuflen = 0;
+    if ( namelen <= 0) {
         return AFPERR_PARAM;
     }
 
@@ -1826,13 +1906,11 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t
     }
 
     if ( volume == NULL ) {
-        *rbuflen = 0;
         return AFPERR_PARAM;
     }
 
     /* check for a volume password */
     if (volume->v_password && strncmp(ibuf, volume->v_password, VOLPASSLEN)) {
-        *rbuflen = 0;
         return AFPERR_ACCESS;
     }
 
@@ -1844,27 +1922,10 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t
         return stat_vol(bitmap, volume, rbuf, rbuflen);
     }
 
-    /* initialize volume variables
-     * FIXME file size
-    */
-    if (utf8_encoding()) {
-        volume->max_filename = 255;
-    }
-    else {
-        volume->max_filename = MACFILELEN;
-    }
-
-    volume->v_dir = volume->v_root = NULL;
-    volume->v_hash = NULL;
-
-    volume->v_flags |= AFPVOL_OPEN;
-    volume->v_cdb = NULL;  
-
     if (volume->v_root_preexec) {
        if ((ret = afprun(1, volume->v_root_preexec, NULL)) && volume->v_root_preexec_close) {
             LOG(log_error, logtype_afpd, "afp_openvol(%s): root preexec : %d", volume->v_path, ret );
-            ret = AFPERR_MISC;
-            goto openvol_err;
+            return AFPERR_MISC;
        }
     }
 
@@ -1875,21 +1936,45 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t
     if (volume->v_preexec) {
        if ((ret = afprun(0, volume->v_preexec, NULL)) && volume->v_preexec_close) {
             LOG(log_error, logtype_afpd, "afp_openvol(%s): preexec : %d", volume->v_path, ret );
-            ret = AFPERR_MISC;
-            goto openvol_err;
+            return AFPERR_MISC;
        }
     }
 
     if ( stat( volume->v_path, &st ) < 0 ) {
-        ret = AFPERR_PARAM;
-        goto openvol_err;
+        return AFPERR_PARAM;
     }
 
     if ( chdir( volume->v_path ) < 0 ) {
-        ret = AFPERR_PARAM;
-        goto openvol_err;
+        return AFPERR_PARAM;
+    }
+
+    if ( NULL == getcwd(path, MAXPATHLEN)) {
+        /* shouldn't be fatal but it will fail later */
+        LOG(log_error, logtype_afpd, "afp_openvol(%s): volume pathlen too long", volume->v_path);
+        return AFPERR_MISC;
+    }
+
+    if (volume_codepage(obj, volume) < 0) {
+       ret = AFPERR_MISC;
+       goto openvol_err;
+    }    
+
+    /* initialize volume variables
+     * FIXME file size
+    */
+    if (utf8_encoding()) {
+        volume->max_filename = 255;
+    }
+    else {
+        volume->max_filename = MACFILELEN;
     }
 
+    volume->v_dir = volume->v_root = NULL;
+    volume->v_hash = NULL;
+
+    volume->v_flags |= AFPVOL_OPEN;
+    volume->v_cdb = NULL;  
+
     if (utf8_encoding()) {
         len = convert_string_allocate(CH_UCS2, CH_UTF8_MAC, volume->v_u8mname, namelen, &vol_mname);
     } else {
@@ -1900,13 +1985,6 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t
         goto openvol_err;
     }
     
-    if ( NULL == getcwd(path, MAXPATHLEN)) {
-        /* shouldn't be fatal but it will fail later */
-        LOG(log_error, logtype_afpd, "afp_openvol(%s): volume pathlen too long", volume->v_path);
-        ret = AFPERR_MISC;
-        goto openvol_err;
-    }        
-    
     if ((vol_uname = strrchr(path, '/')) == NULL)
          vol_uname = path;
     else if (*(vol_uname + 1) != '\0')
@@ -1924,54 +2002,17 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t
     dir->d_color = DIRTREE_COLOR_BLACK; /* root node is black */
     dir->d_m_name_ucs2 = strdup_w(volume->v_name);
     volume->v_dir = volume->v_root = dir;
+    volume->v_curdir = NULL;
     volume->v_hash = dirhash();
 
     curdir = volume->v_dir;
-    if (volume->v_cnidscheme == NULL) {
-        volume->v_cnidscheme = strdup(DEFAULT_CNID_SCHEME);
-        LOG(log_info, logtype_afpd, "Volume %s use CNID scheme %s.", volume->v_path, volume->v_cnidscheme);
-    }
-    if (volume->v_dbpath)
-        volume->v_cdb = cnid_open (volume->v_dbpath, volume->v_umask, volume->v_cnidscheme, (volume->v_flags & AFPVOL_NODEV));
-    else
-        volume->v_cdb = cnid_open (volume->v_path, volume->v_umask, volume->v_cnidscheme, (volume->v_flags & AFPVOL_NODEV));
-    if (volume->v_cdb == NULL) {
+    if (volume_openDB(volume) < 0) {
         LOG(log_error, logtype_afpd, "Fatal error: cannot open CNID or invalid CNID backend for %s: %s", 
            volume->v_path, volume->v_cnidscheme);
         ret = AFPERR_MISC;
         goto openvol_err;
     }
 
-    /* Codepages */
-
-    if (!volume->v_volcodepage)
-       volume->v_volcodepage = strdup("UTF8");
-
-    if ( (charset_t) -1 == ( volume->v_volcharset = add_charset(volume->v_volcodepage)) ) {
-       LOG (log_error, logtype_afpd, "Setting codepage %s as volume codepage failed", volume->v_volcodepage);
-       ret = AFPERR_MISC;
-       goto openvol_err;
-    }
-
-    if ( NULL == ( volume->v_vol = find_charset_functions(volume->v_volcodepage)) || volume->v_vol->flags & CHARSET_ICONV ) {
-       LOG (log_warning, logtype_afpd, "WARNING: volume encoding %s is *not* supported by netatalk, expect problems !!!!", volume->v_volcodepage);
-    }  
-
-    if (!volume->v_maccodepage)
-       volume->v_maccodepage = strdup(obj->options.maccodepage);
-
-    if ( (charset_t) -1 == ( volume->v_maccharset = add_charset(volume->v_maccodepage)) ) {
-       LOG (log_error, logtype_afpd, "Setting codepage %s as mac codepage failed", volume->v_maccodepage);
-       ret = AFPERR_MISC;
-       goto openvol_err;
-    }
-
-    if ( NULL == ( volume->v_mac = find_charset_functions(volume->v_maccodepage)) || ! (volume->v_mac->flags & CHARSET_CLIENT) ) {
-       LOG (log_error, logtype_afpd, "Fatal error: mac charset %s not supported", volume->v_maccodepage);
-       ret = AFPERR_MISC;
-       goto openvol_err;
-    }  
-
     ret  = stat_vol(bitmap, volume, rbuf, rbuflen);
     if (ret == AFP_OK) {
 
@@ -2135,11 +2176,11 @@ struct extmap *getextmap(const char *path)
     char         *p;
     struct extmap *em;
 
-    if (NULL == ( p = strrchr( path, '.' )) ) {
+    if (!Extmap_cnt || NULL == ( p = strrchr( path, '.' )) ) {
         return( Defextmap );
     }
     p++;
-    if (!*p || !Extmap_cnt) {
+    if (!*p) {
         return( Defextmap );
     }
     em = bsearch(p, Extmap, Extmap_cnt, sizeof(struct extmap), ext_cmp_key);