]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/directory.c
more 'if ((A = B()) == C)' to 'if (C== (A = B())) changes
[netatalk.git] / etc / afpd / directory.c
index 91e9b558cd1a4f3be3e869f124dc1503d4571b9f..44d40daf1143c9cc4c4acb9ff21d53f18ebe4beb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: directory.c,v 1.48 2002-10-14 06:30:49 didg Exp $
+ * $Id: directory.c,v 1.57 2003-01-21 09:58:58 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -60,6 +60,7 @@ char *strchr (), *strrchr ();
 #include "unix.h"
 
 struct dir     *curdir;
+int             afp_errno;
 
 #define SENTINEL (&sentinel)
 static struct dir sentinel = { SENTINEL, SENTINEL, NULL, DIRTREE_COLOR_BLACK,
@@ -99,9 +100,10 @@ u_int32_t   did;
 
 
     /* check for 0 did */
-    if (!did)
+    if (!did) {
+        afp_errno = AFPERR_PARAM;
         return NULL;
-
+    }
     if ( did == DIRDID_ROOT_PARENT ) {
         if (!rootpar.d_did)
             rootpar.d_did = DIRDID_ROOT_PARENT;
@@ -110,6 +112,7 @@ u_int32_t   did;
     }
 
     dir = vol->v_root;
+    afp_errno = AFPERR_NOOBJ;
     while ( dir != SENTINEL ) {
         if (dir->d_did == did)
             return dir->d_m_name ? dir : NULL;
@@ -144,7 +147,8 @@ u_int32_t   did;
         return ret;
 
     id = did;
-    if ((upath = cnid_resolve(vol->v_db, &id, buffer, buflen)) == NULL) {
+    if (NULL == (upath = cnid_resolve(vol->v_db, &id, buffer, buflen)) ) {
+        afp_errno = AFPERR_NOOBJ;
         return NULL;
     }
     ptr = path + MAXPATHLEN;
@@ -159,13 +163,17 @@ u_int32_t did;
         if (ret != NULL) {
             break;
         }
-        if ((upath = cnid_resolve(vol->v_db, &id, buffer, buflen)) == NULL)
+        if ((upath = cnid_resolve(vol->v_db, &id, buffer, buflen)) == NULL) {
+            afp_errno = AFPERR_NOOBJ;
             return NULL;
+        }
         mpath = utompath(vol, upath);
         len = strlen(mpath) + 1;
         pathlen += len;
-        if (pathlen > 255)
+        if (pathlen > 255) {
+            afp_errno = AFPERR_PARAM;
             return NULL;
+        }
         strcpy(ptr - len, mpath);
         ptr -= len;
     }
@@ -436,7 +444,6 @@ struct dir  *dir;
  * process. It's fixable within afpd if fnctl_lock, doable with smb and
  * next to impossible for nfs and local filesystem access.
  */
 static void dir_invalidate( vol, dir )
 const struct vol *vol;
 struct dir *dir;
@@ -811,17 +818,16 @@ char      **cpath;
     static struct path ret;
 
     char               *data, *p;
-    char        *u;
     int                        extend = 0;
     int                        len;
-    int                        olen = 0;
     u_int32_t   hint;
     u_int16_t   len16;
     int         size = 0;
     char        sep;
                
     data = *cpath;
-    switch (*data) { /* path type */
+    afp_errno = AFPERR_NOOBJ;
+    switch (ret.m_type = *data) { /* path type */
     case 2:
        data++;
        len = (unsigned char) *data++;
@@ -839,17 +845,17 @@ char      **cpath;
            len = ntohs(len16);
            data += 2;
            size = 7;
-           sep = '/';
+           sep = 0; /* '/';*/
            break;
         }
         /* else it's an error */
     default:
+        afp_errno = AFPERR_PARAM;
         return( NULL );
     
     }
     *cpath += len + size;
     *path = '\0';
-    u = NULL;
     ret.m_name = path;
     ret.st_errno = 0;
     ret.st_valid = 0;
@@ -857,45 +863,29 @@ char      **cpath;
         if ( len == 0 ) {
             if ( !extend && movecwd( vol, dir ) < 0 ) {
                /* it's tricky:
-                  movecwd failed so dir is not there anymore.
+                  movecwd failed some of dir path are not there anymore.
                   FIXME Is it true with other errors?
-                  if path == '\0' ==> the cpath parameter is that dir,
-                  and maybe we are trying to recreate it! So we can't 
-                  fail here.
-                  
+                  so we remove dir from the cache 
                */
-                   if ( dir->d_did == DIRDID_ROOT_PARENT) 
-                               return NULL;                    
-               cdir = dir->d_parent;
+               if (dir->d_did == DIRDID_ROOT_PARENT) 
+                   return NULL;
+               if (afp_errno == AFPERR_ACCESS)
+                   return NULL;                
+
                dir_invalidate(vol, dir);
-               if (*path != '\0' || u == NULL) {
-                       /* FIXME: if path != '\0' then extend != 0 ?
-                        * u == NUL ==> cpath is something like:
-                        * toto\0\0\0
-                       */
-                       return NULL;
-               }
-               if (movecwd(vol, cdir) < 0) {
-                       printf("can't change to parent\n");
-                       return NULL; /* give up the whole tree is out of synch*/
-               }
-                               /* restore the previous token */
-                       strncpy(path, u, olen);
-                       path[olen] = '\0';
+               return NULL;
             }
-            if (!ret.st_valid || *path == '\0') {
+            if (*path == '\0') {
                ret.u_name = ".";
             }               
             return &ret;
         }
 
-        if (!*data || *data == sep ) {
+        if (*data == sep ) {
             data++;
             len--;
         }
-       u = NULL;
-
-        while ( *data && *data == sep && len > 0 ) {
+        while (*data == sep && len > 0 ) {
             if ( dir->d_parent == NULL ) {
                 return NULL;
             }
@@ -906,11 +896,7 @@ char       **cpath;
 
         /* would this be faster with strlen + strncpy? */
         p = path;
-        if (len > 0) {
-               u = data;
-               olen = len;
-               }        
-        while ( *data && *data != sep && len > 0 ) {
+        while ( *data != sep && len > 0 ) {
             *p++ = *data++;
             len--;
         }
@@ -927,7 +913,7 @@ char        **cpath;
             if ( !extend ) {
                 cdir = dir->d_child;
                 while (cdir) {
-                    if ( strcasecmp( cdir->d_m_name, path ) == 0 ) {
+                    if ( strcmp( cdir->d_m_name, path ) == 0 ) {
                         break;
                     }
                     cdir = (cdir == dir->d_child->d_prev) ? NULL :
@@ -943,8 +929,10 @@ char       **cpath;
                        /* dir is not valid anymore 
                           we delete dir from the cache and abort.
                        */
-                       if ( dir->d_did != DIRDID_ROOT_PARENT) 
+                       if ( dir->d_did != DIRDID_ROOT_PARENT && 
+                             (afp_errno != AFPERR_ACCESS)) {
                            dir_invalidate(vol, dir);
+                       }
                         return NULL;
                     }
                     cdir = extenddir( vol, dir, &ret );
@@ -955,6 +943,7 @@ char        **cpath;
             }
 
             if ( cdir == NULL ) {
+
                 if ( len > 0 ) {
                     return NULL;
                 }
@@ -983,6 +972,7 @@ struct dir  *dir;
         return( 0 );
     }
     if ( dir->d_did == DIRDID_ROOT_PARENT) {
+        afp_errno = AFPERR_PARAM;
         return( -1 );
     }
 
@@ -990,19 +980,36 @@ struct dir        *dir;
     *p-- = '\0';
     *p = '.';
     for ( d = dir; d->d_parent != NULL && d != curdir; d = d->d_parent ) {
-        *--p = '/';
         u = d->d_u_name;
         n = strlen( u );
+        if (p -n -1 < path) {
+            afp_errno = AFPERR_PARAM;
+            return -1;
+        }
+        *--p = '/';
         p -= n;
         strncpy( p, u, n );
     }
     if ( d != curdir ) {
-        *--p = '/';
         n = strlen( vol->v_path );
+        if (p -n -1 < path) {
+            afp_errno = AFPERR_PARAM;
+            return -1;
+        }
+        *--p = '/';
         p -= n;
         strncpy( p, vol->v_path, n );
     }
     if ( chdir( p ) < 0 ) {
+        switch (errno) {
+        case EACCES:
+        case EPERM:
+            afp_errno = AFPERR_ACCESS;
+            break;
+        default:
+            afp_errno = AFPERR_NOOBJ;
+        
+        }
         return( -1 );
     }
     curdir = dir;
@@ -1047,7 +1054,7 @@ int getdirparams(const struct vol *vol,
 {
     struct maccess     ma;
     struct adouble     ad;
-    char               *data, *nameoff = NULL;
+    char               *data, *l_nameoff = NULL, *utf_nameoff = NULL;
     int                        bit = 0, isad = 0;
     u_int32_t           aint;
     u_int16_t          ashort;
@@ -1143,7 +1150,7 @@ int getdirparams(const struct vol *vol,
 
         case DIRPBIT_LNAME :
             if (dir->d_m_name) /* root of parent can have a null name */
-                nameoff = data;
+                l_nameoff = data;
             else
                 memset(data, 0, sizeof(u_int16_t));
             data += sizeof( u_int16_t );
@@ -1203,7 +1210,7 @@ int getdirparams(const struct vol *vol,
             if (afp_version >= 30) { /* UTF8 name */
                 utf8 = kTextEncodingUTF8;
                 if (dir->d_m_name) /* root of parent can have a null name */
-                    nameoff = data;
+                    utf_nameoff = data;
                 else
                     memset(data, 0, sizeof(u_int16_t));
                 data += sizeof( u_int16_t );
@@ -1231,9 +1238,14 @@ int getdirparams(const struct vol *vol,
         bitmap = bitmap>>1;
         bit++;
     }
-    if ( nameoff ) {
+    if ( l_nameoff ) {
         ashort = htons( data - buf );
-        memcpy( nameoff, &ashort, sizeof( ashort ));
+        memcpy( l_nameoff, &ashort, sizeof( ashort ));
+        data = set_name(data, dir->d_m_name, 0);
+    }
+    if ( utf_nameoff ) {
+        ashort = htons( data - buf );
+        memcpy( utf_nameoff, &ashort, sizeof( ashort ));
         data = set_name(data, dir->d_m_name, utf8);
     }
     if ( isad ) {
@@ -1261,7 +1273,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 );
     }
 
@@ -1271,16 +1283,16 @@ int             ibuflen, *rbuflen;
     memcpy( &did, ibuf, sizeof( did ));
     ibuf += sizeof( int );
 
-    if (( dir = dirlookup( vol, did )) == NULL ) {
-        return( AFPERR_NOOBJ );
+    if (NULL == ( dir = dirlookup( vol, did )) ) {
+        return afp_errno;
     }
 
     memcpy( &bitmap, ibuf, sizeof( bitmap ));
     bitmap = ntohs( bitmap );
     ibuf += sizeof( bitmap );
 
-    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
-        return( AFPERR_NOOBJ );
+    if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
+        return afp_errno;
     }
 
     if ( *path->m_name != '\0' ) {
@@ -1294,7 +1306,7 @@ int               ibuflen, *rbuflen;
         ibuf++;
     }
 
-    if (( rc = setdirparams(vol, path, bitmap, ibuf )) == AFP_OK ) {
+    if (AFP_OK == ( rc = setdirparams(vol, path, bitmap, ibuf )) ) {
         setvoltime(obj, vol );
     }
     return( rc );
@@ -1307,6 +1319,7 @@ int               ibuflen, *rbuflen;
 */
 
 struct path Cur_Path = {
+    0,
     "",  /* mac name */
     ".", /* unix name */
     0,  /* stat is not set */
@@ -1632,7 +1645,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 );
     }
 
@@ -1641,19 +1654,12 @@ int             ibuflen, *rbuflen;
 
     memcpy( &did, ibuf, sizeof( did ));
     ibuf += sizeof( did );
-    if (( dir = dirlookup( vol, did )) == NULL ) {
+    if (NULL == ( dir = dirlookup( vol, did )) ) {
         return( AFPERR_NOOBJ );
     }
 
-    if (( s_path = cname( vol, dir, &ibuf )) == NULL ) {
-        switch( errno ) {
-        case EACCES:
-            return( AFPERR_ACCESS );
-        case EEXIST:                           /* FIXME this one is impossible? */
-            return( AFPERR_EXIST );
-        default:
-            return( AFPERR_NOOBJ );
-        }
+    if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
+        return afp_errno;
     }
     /* FIXME check done elswhere? cname was able to move curdir to it! */
     if (*s_path->m_name == '\0')
@@ -1688,6 +1694,7 @@ int               ibuflen, *rbuflen;
     if (of_stat(s_path) < 0) {
         return AFPERR_MISC;
     }
+    curdir->offcnt++;
     if ((dir = adddir( vol, curdir, s_path)) == NULL) {
         return AFPERR_MISC;
     }
@@ -1732,9 +1739,9 @@ const int noadouble;
     struct dir         *parent;
     char                *buf;
     int                        len, err;
-    
+        
     /* existence check moved to afp_moveandrename */
-    if ( rename( src, dst ) < 0 ) {
+    if ( unix_rename( src, dst ) < 0 ) {
         switch ( errno ) {
         case ENOENT :
             return( AFPERR_NOOBJ );
@@ -1761,27 +1768,17 @@ const int noadouble;
     }
 
     memset(&ad, 0, sizeof(ad));
-    if ( ad_open( dst, ADFLAGS_HF|ADFLAGS_DIR, O_RDWR, 0, &ad) < 0 ) {
-        switch ( errno ) {
-        case ENOENT :
-            if (noadouble) {
-                len = strlen(newname);
-                goto renamedir_done;
-            }
-            return( AFPERR_NOOBJ );
-        case EACCES :
-            return( AFPERR_ACCESS );
-        default :
-            return( AFPERR_PARAM );
-        }
-    }
     len = strlen( newname );
-    ad_setentrylen( &ad, ADEID_NAME, len );
-    memcpy( ad_entry( &ad, ADEID_NAME ), newname, len );
-    ad_flush( &ad, ADFLAGS_HF );
-    ad_close( &ad, ADFLAGS_HF );
-
-renamedir_done:
+    /* rename() succeeded so we need to update our tree even if we can't open
+     * .Parent
+    */
+    if ( !ad_open( dst, ADFLAGS_HF|ADFLAGS_DIR, O_RDWR, 0, &ad)) {
+        ad_setentrylen( &ad, ADEID_NAME, len );
+        memcpy( ad_entry( &ad, ADEID_NAME ), newname, len );
+        ad_flush( &ad, ADFLAGS_HF );
+        ad_close( &ad, ADFLAGS_HF );
+    }
+    
     if (dir->d_m_name == dir->d_u_name)
         dir->d_u_name = NULL;
 
@@ -1936,7 +1933,7 @@ int pathlen;
     }
 
     if ( movecwd( vol, curdir->d_parent ) < 0 ) {
-        return( AFPERR_NOOBJ );
+        return afp_errno;
     }
 
     if ( rmdir(fdir->d_u_name) < 0 ) {
@@ -2156,24 +2153,19 @@ int             ibuflen, *rbuflen;
     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 (( parentdir = dirlookup( vol, did )) == NULL ) {
-        return( AFPERR_NOOBJ );
+    if (NULL == ( parentdir = dirlookup( vol, did )) ) {
+        return afp_errno;
     }
 
-    if (( path = cname( vol, parentdir, &ibuf )) == NULL ) {
-        switch( errno ) {
-        case EACCES:
-            return( AFPERR_ACCESS );
-        default:
-            return( AFPERR_NOOBJ );
-        }
+    if (NULL == ( path = cname( vol, parentdir, &ibuf )) ) {
+        return afp_errno;
     }
 
     if ( *path->m_name != '\0' ) {