]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/desktop.c
Warning fixes.
[netatalk.git] / etc / afpd / desktop.c
index 43672599126386072a4d87f7e9e2320585e02451..2cd1ae896d8934bbafc9dee44721393e907b9af6 100644 (file)
@@ -1,7 +1,12 @@
 /*
- * $Id: desktop.c,v 1.15 2002-09-05 14:52:05 didg Exp $
+ * $Id: desktop.c,v 1.30 2003-06-09 14:42:38 srittau Exp $
  *
  * See COPYRIGHT.
+ *
+ * bug:
+ * afp_XXXcomment are (the only) functions able to open
+ * a ressource fork when there's no data fork, eg after
+ * it was removed with samba.
  */
 
 #ifdef HAVE_CONFIG_H
 #include "fork.h"
 #include "globals.h"
 #include "desktop.h"
+
 #ifdef FILE_MANGLING
 #include "mangle.h"
 #endif /* CNID_DB */
 
+#ifdef AFP3x
+#include <iconv.h>
+#endif
+
 int afp_opendt(obj, ibuf, ibuflen, rbuf, rbuflen )
 AFPObj      *obj;
 char   *ibuf, *rbuf;
@@ -55,7 +65,7 @@ int           ibuflen, *rbuflen;
     ibuf += 2;
 
     memcpy( &vid, ibuf, sizeof(vid));
-    if (( vol = getvolbyvid( vid )) == NULL ) {
+    if (NULL == ( vol = getvolbyvid( vid )) ) {
         *rbuflen = 0;
         return( AFPERR_PARAM );
     }
@@ -141,7 +151,7 @@ int         ibuflen, *rbuflen;
 
     memcpy( &vid, ibuf, sizeof( vid ));
     ibuf += sizeof( vid );
-    if (( vol = getvolbyvid( vid )) == NULL ) {
+    if (NULL == ( vol = getvolbyvid( vid )) ) {
         cc = AFPERR_PARAM;
         goto addicon_err;
     }
@@ -358,7 +368,7 @@ int         ibuflen, *rbuflen;
 
     memcpy( &vid, ibuf, sizeof( vid ));
     ibuf += sizeof( vid );
-    if (( vol = getvolbyvid( vid )) == NULL ) {
+    if (NULL == ( vol = getvolbyvid( vid )) ) {
         return( AFPERR_PARAM );
     }
 
@@ -435,7 +445,7 @@ int         ibuflen, *rbuflen;
 
     memcpy( &vid, ibuf, sizeof( vid ));
     ibuf += sizeof( vid );
-    if (( vol = getvolbyvid( vid )) == NULL ) {
+    if (NULL == ( vol = getvolbyvid( vid )) ) {
         return( AFPERR_PARAM );
     }
 
@@ -574,7 +584,7 @@ char *dtfile(const struct vol *vol, u_char creator[], char *ext )
 {
     static char        path[ MAXPATHLEN + 1];
     char       *p;
-    int                i;
+    unsigned int i;
 
     strcpy( path, vol->v_path );
     strcat( path, "/.AppleDesktop/" );
@@ -604,22 +614,26 @@ char *dtfile(const struct vol *vol, u_char creator[], char *ext )
     return( path );
 }
 
-char *mtoupath(const struct vol *vol, char *mpath)
+/* ---------------------------
+ * mpath is only a filename 
+*/
+static char  upath[ MAXPATHLEN + 1];
+static char  mpath[ MAXPATHLEN + 1];
+#ifdef AFP3x
+static char  ucs2[ MAXPATHLEN + 1];
+#endif
+
+static char *old_mtoupath(const struct vol *vol, char *mpath)
 {
-    static char  upath[ MAXPATHLEN + 1];
     char       *m, *u;
     int                 i = 0;
-
-    if ( *mpath == '\0' ) {
-        return( "." );
-    }
-
-#ifdef FILE_MANGLING
-    mpath = demangle(vol, mpath);
-#endif /* FILE_MANGLING */
-
+    int          changed = 0;
+        
     m = mpath;
     u = upath;
+    if ((vol->v_casefold & (AFPVOL_MTOUUPPER| AFPVOL_MTOULOWER))) {
+        changed = 1;
+    }
     while ( *m != '\0' ) {
         /* handle case conversion first */
         if (vol->v_casefold & AFPVOL_MTOUUPPER)
@@ -629,62 +643,77 @@ char *mtoupath(const struct vol *vol, char *mpath)
 
         /* we have a code page. we only use the ascii range
          * if we have map ascii specified. */
-#if 1
         if (vol->v_mtoupage && ((*m & 0x80) ||
                                 vol->v_flags & AFPVOL_MAPASCII)) {
             *u = vol->v_mtoupage->map[(unsigned char) *m].value;
-        } else
-#endif /* 1 */
+            changed = 1;
+            if (!*u && *m) {
+                /* if conversion failed, encode in hex
+                 * to prevent silly truncation
+                 * H.P. Jansen <hpj@urpla.net> */
+#ifdef DEBUG
+                LOG(log_debug, logtype_afpd, "mtoupath: hex encode: 0x%x", (unsigned char) *m);
+#endif
+                *u++ = ':';
+                *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
+                *u = hexdig[ *m & 0x0f ];
+            }
+        } else {
 #if AD_VERSION == AD_VERSION1
             if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
                     (!isascii(*m) || *m == '/')) ||
                     (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
                      ( i == 0 && (*m == '.' )))) {
-#else /* AD_VERSION == AD_VERSION1 */
+#else 
             if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
                     (!isprint(*m) || *m == '/')) ||
                     (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
                      ( i == 0 && (*m == '.' )))) {
-#endif /* AD_VERSION == AD_VERSION1 */
+#endif
                 /* do hex conversion. */
                 *u++ = ':';
                 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
                 *u = hexdig[ *m & 0x0f ];
+                changed = 1;
             } else
                 *u = *m;
+        }
         u++;
         i++;
         m++;
     }
     *u = '\0';
 
-    return( upath );
+#ifdef DEBUG
+    LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
+#endif /* DEBUG */
+
+    return( (changed)?upath:mpath );
 }
 
+/* ---------------------------- */
 #define hextoint( c )  ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
 #define islxdigit(x)   (!isupper(x)&&isxdigit(x))
 
-char *utompath(const struct vol *vol, char *upath)
+static char *old_utompath(const struct vol *vol, char *upath)
 {
-    static char  mpath[ MAXPATHLEN + 1];
     char        *m, *u;
     int          h;
-
-#ifdef FILE_MANGLING
-    upath = mangle(vol, upath);
-#endif /* FILE_MANGLING */
+    int          changed = 0;
 
     /* do the hex conversion */
     u = upath;
     m = mpath;
+    if ((vol->v_casefold & (AFPVOL_MTOUUPPER| AFPVOL_MTOULOWER))) {
+        changed = 1;
+    }
     while ( *u != '\0' ) {
         /* we have a code page */
-#if 1
         if (vol->v_utompage && ((*u & 0x80) ||
                                 (vol->v_flags & AFPVOL_MAPASCII))) {
             *m = vol->v_utompage->map[(unsigned char) *u].value;
+            changed = 1;
         } else
-#endif /* 1 */
             if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
                     *(u+2) != '\0' && islxdigit( *(u+2))) {
                 ++u;
@@ -692,6 +721,7 @@ char *utompath(const struct vol *vol, char *upath)
                 ++u;
                 h |= hextoint( *u );
                 *m = h;
+                changed = 1;
             } else
                 *m = *u;
 
@@ -705,9 +735,280 @@ char *utompath(const struct vol *vol, char *upath)
         m++;
     }
     *m = '\0';
-    return( mpath );
+    m = mpath;
+
+#ifdef FILE_MANGLING
+    m = mangle(vol, mpath, upath, 0);
+    if (m != mpath) {
+        changed = 1;
+    }
+#endif /* FILE_MANGLING */
+
+#ifdef DEBUG
+    LOG(log_debug, logtype_afpd, "utompath: '%s':'%s'", upath, mpath);
+#endif /* DEBUG */
+
+    return((changed)? m:upath );
+}
+
+/* --------------- */
+#ifdef AFP3x
+extern unsigned int do_precomposition(unsigned int base, unsigned int comb);
+
+static char comp[MAXPATHLEN +1];
+
+static char *precompose(u_int16_t  *name, size_t inplen, size_t *outlen)
+{
+size_t i;
+u_int16_t base, comb;
+u_int16_t *in, *out;
+u_int16_t result;
+
+    if (!inplen || (inplen & 1) || inplen > sizeof(comp)/sizeof(u_int16_t))
+        return NULL;
+    i = 0;
+    in  = name;
+    out = (u_int16_t *)comp;
+    *outlen = 0;
+    
+    base = *in;
+    while (1) {
+        i += 2;
+        in++;
+        if (i == inplen) {
+           *out = base;
+           *outlen += 2;
+           return comp;
+        }
+        comb = *in;
+        if (comb >= 0x300 && (result = do_precomposition(base, comb))) {
+           *out = result;
+           out++;
+           *outlen += 2;
+           i += 2;
+           in++;
+           if (i == inplen) 
+              return comp;
+           base = *in;
+        }
+        else {
+           *out = base;
+           out++;
+           *outlen += 2;
+           base = comb;
+        }
+    }
+}
+
+/* --------------- */
+extern unsigned int do_decomposition(unsigned int base);
+
+static char *decompose(u_int16_t  *name, size_t inplen, size_t *outlen)
+{
+size_t i;
+u_int16_t base;
+u_int16_t *in, *out;
+unsigned int result;
+
+    if (!inplen || (inplen & 1))
+        return NULL;
+    i = 0;
+    in  = name;
+    out = (u_int16_t *)comp;
+    *outlen = 0;
+    
+    while (i < inplen) {
+        if (*outlen >= sizeof(comp)/sizeof(u_int16_t) +2) {
+            return NULL;
+        }
+        base = *in;
+        if ((result = do_decomposition(base))) {
+           *out = result  >> 16;
+           out++;
+           *outlen += 2;
+           *out = result & 0xffff;
+           out++;
+           *outlen += 2;
+        }
+        else {
+           *out = base;
+           out++;
+           *outlen += 2;
+        }
+        i += 2;
+        in++;
+     }
+     return comp;
+}
+#endif
+
+/* --------------------------- */
+char *mtoupath(const struct vol *vol, char *mpath, int utf8)
+{
+    int                i = 0;
+    char       *m, *u;
+#ifdef AFP3x
+    char       *r;
+    size_t       inplen;
+    size_t       outlen;
+#endif
+        
+    if ( *mpath == '\0' ) {
+        return( "." );
+    }
+
+#ifdef FILE_MANGLING
+    m = demangle(vol, mpath);
+    if (m != mpath) {
+        return m;
+    }
+#endif /* FILE_MANGLING */
+
+    if (!vol_utf8(vol))
+       return old_mtoupath(vol, mpath);
+
+    m = mpath;
+    u = upath;
+    while ( *m != '\0' ) {
+        if ( (!(vol->v_flags & AFPVOL_NOHEX) && *m == '/') ||
+             (!(vol->v_flags & AFPVOL_USEDOTS) && i == 0 && *m == '.') ||
+             (!utf8 && (unsigned char)*m == 0xf0) /* Apple logo */
+        ) {
+          /* do hex conversion. */
+          *u++ = ':';
+          *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
+          *u = hexdig[ *m & 0x0f ];
+        } else
+           *u = *m;
+        u++;
+        i++;
+        m++;
+    }
+    *u = '\0';
+    u = upath;
+#ifdef AFP3x
+    inplen = strlen(u);
+    outlen = MAXPATHLEN;
+    r = ucs2;
+    if (!utf8) {
+        if ((size_t)(-1) == iconv(vol->v_mactoutf8, 0,0,0,0) )
+            return NULL;
+        /* assume precompose */
+        if ((size_t)(-1) == iconv(vol->v_mactoutf8, &u, &inplen, &r, &outlen))
+            return NULL;
+        u = ucs2;
+    }
+    else { 
+        if ((size_t)(-1) == iconv(vol->v_utf8toucs2, 0,0,0,0) )
+            return NULL;
+
+        if ((size_t)(-1) == iconv(vol->v_utf8toucs2, &u, &inplen, &r, &outlen))
+            return NULL;
+
+        u = precompose((u_int16_t *)ucs2, MAXPATHLEN -outlen, &inplen);
+
+        if ((size_t)(-1) == iconv(vol->v_ucs2toutf8, 0,0,0,0))
+            return NULL;
+            
+        outlen = MAXPATHLEN;
+        r = upath;
+        if ((size_t)(-1) == iconv(vol->v_ucs2toutf8, &u, &inplen, &r, &outlen))
+            return NULL;
+        u = upath;
+    }
+    u[MAXPATHLEN -outlen] = 0;
+#endif
+#ifdef DEBUG
+    LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
+#endif /* DEBUG */
+    return( u );
+}
+
+/* --------------- */
+char *utompath(const struct vol *vol, char *upath, int utf8)
+{
+    int          h;
+    int          mangleflag = 0;
+    char       *m, *u;
+#ifdef AFP3x
+    char       *r;
+    size_t       inplen;
+    size_t       outlen;
+#endif
+
+    if (!vol_utf8(vol))
+       return old_utompath(vol, upath);
+    /* do the hex conversion */
+    u = upath;
+    m = mpath;
+    while ( *u != '\0' ) {
+        if ( *u == ':' && islxdigit( *(u+1)) && islxdigit( *(u+2))) {
+            ++u;
+            h = hextoint( *u ) << 4;
+            ++u;
+            h |= hextoint( *u );
+            *m = h;
+        } else
+            *m = *u;
+        u++;
+        m++;
+    }
+    *m = '\0';
+    m = mpath;
+#ifdef AFP3x    
+    if ((size_t)(-1) == iconv(vol->v_utf8toucs2, 0,0,0,0) )
+        return NULL;
+    inplen = strlen(mpath);
+    outlen = MAXPATHLEN;
+    r = ucs2;
+    if ((size_t)(-1) == iconv(vol->v_utf8toucs2, &m, &inplen, &r, &outlen))
+        return NULL;
+
+    if (utf8) {
+        if ( NULL == (m = decompose((u_int16_t *)ucs2, MAXPATHLEN -outlen, &inplen)))
+            return NULL;
+
+        if ((size_t)(-1) == iconv(vol->v_ucs2toutf8, 0,0,0,0))
+            return NULL;
+            
+        outlen = MAXPATHLEN;
+        r = mpath;
+        if ((size_t)(-1) == iconv(vol->v_ucs2toutf8, &m, &inplen, &r, &outlen))
+            return NULL;
+    }
+    else {
+        m = precompose((u_int16_t *)ucs2, MAXPATHLEN -outlen, &inplen);
+
+        if ((size_t)(-1) == iconv(vol->v_ucs2tomac, 0,0,0,0))
+            return NULL;
+            
+        outlen = MAXPATHLEN;
+        r = mpath;
+        if ((size_t)(-1) == iconv(vol->v_ucs2tomac, &m, &inplen, &r, &outlen)) {
+            switch (errno) {
+            case EILSEQ:
+                if (outlen != MAXPATHLEN) {
+                    mangleflag = 1;
+                }
+            default:
+                return NULL;
+            }
+        }
+    }
+    mpath[MAXPATHLEN -outlen] = 0;
+#endif
+#ifdef FILE_MANGLING
+    m = mangle(vol, mpath, upath, mangleflag);
+#else
+    if (mangleflag)
+        return NULL;
+    m = mpath;
+#endif /* FILE_MANGLING */
+
+    return(m);
 }
 
+/* ----------------------------- */
 int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
 AFPObj      *obj;
 char   *ibuf, *rbuf;
@@ -717,28 +1018,30 @@ int              ibuflen, *rbuflen;
     struct vol         *vol;
     struct dir         *dir;
     struct ofork        *of;
-    char               *path, *name, *upath;
+    struct path         *path;
+    char                *name, *upath;
     int                        clen;
     u_int32_t           did;
     u_int16_t          vid;
+    int                 isadir;
 
     *rbuflen = 0;
     ibuf += 2;
 
     memcpy( &vid, ibuf, sizeof( vid ));
     ibuf += sizeof( vid );
-    if (( vol = getvolbyvid( vid )) == NULL ) {
+    if (NULL == ( vol = getvolbyvid( vid )) ) {
         return( AFPERR_PARAM );
     }
 
     memcpy( &did, ibuf, sizeof( did ));
     ibuf += sizeof( did );
-    if (( dir = dirsearch( vol, did )) == NULL ) {
-        return( AFPERR_NOOBJ );
+    if (NULL == ( dir = dirlookup( vol, did )) ) {
+       return afp_errno;
     }
 
-    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
-        return( AFPERR_NOOBJ );
+    if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
+       return get_afp_errno(AFPERR_NOOBJ);
     }
 
     if ((u_long)ibuf & 1 ) {
@@ -747,23 +1050,30 @@ int              ibuflen, *rbuflen;
 
     clen = (u_char)*ibuf++;
     clen = min( clen, 199 );
-    upath = mtoupath( vol, path );
-    if ((*path == '\0') || !(of = of_findname(upath, NULL))) {
+
+    upath = path->u_name;
+    if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
+        return AFPERR_ACCESS;
+    }
+
+    isadir = path_isadir(path);
+    if (isadir || !(of = of_findname(path))) {
         memset(&ad, 0, sizeof(ad));
         adp = &ad;
     } else
         adp = of->of_ad;
+
     if (ad_open( upath , vol_noadouble(vol) |
-                 (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
+                 (( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
                  O_RDWR|O_CREAT, 0666, adp) < 0 ) {
         return( AFPERR_ACCESS );
     }
 
-    if ( ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT ) {
-        if ( *path == '\0' ) {
-            name = curdir->d_name;
+    if ( (ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT) ) {
+        if ( *path->m_name == '\0' ) {
+            name = curdir->d_m_name;
         } else {
-            name = path;
+            name = path->m_name;
         }
         ad_setentrylen( adp, ADEID_NAME, strlen( name ));
         memcpy( ad_entry( adp, ADEID_NAME ), name,
@@ -786,38 +1096,40 @@ int              ibuflen, *rbuflen;
     struct vol         *vol;
     struct dir         *dir;
     struct ofork        *of;
-    char               *path, *upath;
+    struct path         *s_path;
+    char               *upath;
     u_int32_t          did;
     u_int16_t          vid;
-
+    int                 isadir;
+    
     *rbuflen = 0;
     ibuf += 2;
 
     memcpy( &vid, ibuf, sizeof( vid ));
     ibuf += sizeof( vid );
-    if (( vol = getvolbyvid( vid )) == NULL ) {
+    if (NULL == ( vol = getvolbyvid( vid )) ) {
         return( AFPERR_PARAM );
     }
 
     memcpy( &did, ibuf, sizeof( did ));
     ibuf += sizeof( did );
-    if (( dir = dirsearch( vol, did )) == NULL ) {
-        return( AFPERR_NOOBJ );
+    if (NULL == ( dir = dirlookup( vol, did )) ) {
+       return afp_errno;
     }
 
-    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
-        return( AFPERR_NOOBJ );
+    if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
+       return get_afp_errno(AFPERR_NOOBJ);
     }
 
-
-    upath = mtoupath( vol, path );
-    if ((*path == '\0') || !(of = of_findname(upath, NULL))) {
+    upath = s_path->u_name;
+    isadir = path_isadir(s_path);
+    if (isadir || !(of = of_findname(s_path))) {
         memset(&ad, 0, sizeof(ad));
         adp = &ad;
     } else
         adp = of->of_ad;
     if ( ad_open( upath,
-                  (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
+                  ( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
                   O_RDONLY, 0666, adp) < 0 ) {
         return( AFPERR_NOITEM );
     }
@@ -836,6 +1148,8 @@ int                ibuflen, *rbuflen;
             ad_getentrylen( adp, ADEID_COMMENT ));
     *rbuflen = ad_getentrylen( adp, ADEID_COMMENT ) + 1;
     ad_close( adp, ADFLAGS_HF );
+
+    /* return AFPERR_NOITEM if len == 0 ? */
     return( AFP_OK );
 }
 
@@ -848,38 +1162,45 @@ int              ibuflen, *rbuflen;
     struct vol         *vol;
     struct dir         *dir;
     struct ofork        *of;
-    char               *path, *upath;
+    struct path         *s_path;
+    char               *upath;
     u_int32_t          did;
     u_int16_t          vid;
+    int                 isadir;
 
     *rbuflen = 0;
     ibuf += 2;
 
     memcpy( &vid, ibuf, sizeof( vid ));
     ibuf += sizeof( vid );
-    if (( vol = getvolbyvid( vid )) == NULL ) {
+    if (NULL == ( vol = getvolbyvid( vid )) ) {
         return( AFPERR_PARAM );
     }
 
     memcpy( &did, ibuf, sizeof( did ));
     ibuf += sizeof( did );
-    if (( dir = dirsearch( vol, did )) == NULL ) {
-        return( AFPERR_NOOBJ );
+    if (NULL == ( dir = dirlookup( vol, did )) ) {
+       return afp_errno;
+    }
+
+    if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
+       return get_afp_errno(AFPERR_NOOBJ);
     }
 
-    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
-        return( AFPERR_NOOBJ );
+    upath = s_path->u_name;
+    if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
+        return AFPERR_ACCESS;
     }
 
-    upath = mtoupath( vol, path );
-    if ((*path == '\0') || !(of = of_findname(upath, NULL))) {
+    isadir = path_isadir(s_path);
+    if (isadir || !(of = of_findname(s_path))) {
         memset(&ad, 0, sizeof(ad));
         adp = &ad;
     } else
         adp = of->of_ad;
 
     if ( ad_open( upath,
-                  (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
+                   (isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
                   O_RDWR, 0, adp) < 0 ) {
         switch ( errno ) {
         case ENOENT :