]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/directory.c
Check for cached files in dirlookup
[netatalk.git] / etc / afpd / directory.c
index 467bc62d89e936c2cf69988db42f66b27ea3fe36..b658ad1d56995528333101dbc032bb41c3f00fe5 100644 (file)
@@ -43,7 +43,7 @@
 #include "mangle.h"
 #include "hash.h"
 
-#ifdef HAVE_NFSv4_ACLS
+#ifdef HAVE_ACLS
 extern void addir_inherit_acl(const struct vol *vol);
 #endif
 
@@ -85,9 +85,24 @@ struct path Cur_Path = {
 /* -------------------------
    appledouble mkdir afp error code.
 */
-static int netatalk_mkdir(const char *name)
+static int netatalk_mkdir(const struct vol *vol, const char *name)
 {
-    if (ad_mkdir(name, DIRBITS | 0777) < 0) {
+    int ret;
+    struct stat st;
+
+    if (vol->v_flags & AFPVOL_UNIX_PRIV) {
+        if (lstat(".", &st) < 0)
+            return AFPERR_MISC;
+        int mode = (DIRBITS & (~S_ISGID & st.st_mode)) | (0777 & ~vol->v_umask);
+        LOG(log_maxdebug, logtype_afpd, "netatalk_mkdir(\"%s\") {parent mode: %04o, vol umask: %04o}",
+            name, st.st_mode, vol->v_umask);
+
+        ret = mkdir(name, mode);
+    } else {
+        ret = ad_mkdir(name, DIRBITS | 0777);
+    }
+
+    if (ret < 0) {
         switch ( errno ) {
         case ENOENT :
             return( AFPERR_NOOBJ );
@@ -178,7 +193,7 @@ static int copydir(const struct vol *vol, int dirfd, char *src, char *dst)
         return AFPERR_PARAM;
 
     /* try to create the destination directory */
-    if (AFP_OK != (err = netatalk_mkdir(dst)) ) {
+    if (AFP_OK != (err = netatalk_mkdir(vol, dst)) ) {
         closedir(dp);
         return err;
     }
@@ -413,7 +428,8 @@ int get_afp_errno(const int param)
  *
  * Resolve a DID, allocate a struct dir for it
  * 1. Check for special CNIDs 0 (invalid), 1 and 2.
- * 2. Check if the DID is in the cache.
+ * 2a. Check if the DID is in the cache.
+ * 2b. Check if it's really a dir (d_fullpath != NULL) because we cache files too.
  * 3. If it's not in the cache resolve it via the database.
  * 4. Build complete server-side path to the dir.
  * 5. Check if it exists and is a directory.
@@ -455,7 +471,11 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did)
     }
 
     /* Search the cache */
-    if ((ret = dircache_search_by_did(vol, did)) != NULL) { /* 2 */
+    if ((ret = dircache_search_by_did(vol, did)) != NULL) { /* 2a */
+        if (ret->d_fullpath == NULL) {                      /* 2b */
+            afp_errno = AFPERR_BADTYPE;
+            return NULL;
+        }
         if (lstat(cfrombstring(ret->d_fullpath), &st) != 0) {
             LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {lstat: %s}", ntohl(did), strerror(errno));
             switch (errno) {
@@ -662,7 +682,7 @@ int caseenumerate(const struct vol *vol, struct path *path, struct dir *dir)
  * @param vol      (r) pointer to struct vol
  * @param pdid     (r) Parent CNID
  * @param did      (r) CNID
- * @param fullpath (r) Full unix path to dir
+ * @param fullpath (r) Full unix path to dir or NULL for files
  *
  * @returns pointer to new struct dir or NULL on error
  *
@@ -2086,7 +2106,7 @@ int afp_createdir(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_
 
     upath = s_path->u_name;
 
-    if (AFP_OK != (err = netatalk_mkdir( upath))) {
+    if (AFP_OK != (err = netatalk_mkdir(vol, upath))) {
         return err;
     }
 
@@ -2117,10 +2137,10 @@ int afp_createdir(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_
     ad_close_metadata( &ad);
 
 createdir_done:
-#ifdef HAVE_NFSv4_ACLS
+#ifdef HAVE_ACLS
     /* FIXME: are we really inside the created dir? */
     addir_inherit_acl(vol);
-#endif
+#endif /* HAVE_ACLS */
 
     memcpy( rbuf, &dir->d_did, sizeof( u_int32_t ));
     *rbuflen = sizeof( u_int32_t );
@@ -2315,7 +2335,7 @@ int afp_mapid(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *r
             name = NULL;
         }
         break;
-#ifdef HAVE_NFSv4_ACLS
+#ifdef HAVE_ACLS
     case 5 : /* UUID -> username */
     case 6 : /* UUID -> groupname */
         if ((afp_version < 32) || !(obj->options.flags & OPTION_UUID ))
@@ -2349,7 +2369,7 @@ int afp_mapid(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *r
             *rbuflen = 2 * sizeof( id );
         }
         break;
-#endif
+#endif /* HAVE_ACLS */
     default :
         return( AFPERR_PARAM );
     }
@@ -2403,7 +2423,7 @@ int afp_mapname(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, siz
     case 4 :
         len = (unsigned char) *ibuf++;
         break;
-#ifdef HAVE_NFSv4_ACLS
+#ifdef HAVE_ACLS
     case 5 : /* username -> UUID  */
     case 6 : /* groupname -> UUID */
         if ((afp_version < 32) || !(obj->options.flags & OPTION_UUID ))
@@ -2412,7 +2432,7 @@ int afp_mapname(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, siz
         len = ntohs(ulen);
         ibuf += 2;
         break;
-#endif
+#endif /* HAVE_ACLS */
     default :
         return( AFPERR_PARAM );
     }
@@ -2446,7 +2466,7 @@ int afp_mapname(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, siz
             memcpy( rbuf, &id, sizeof( id ));
             *rbuflen = sizeof( id );
             break;
-#ifdef HAVE_NFSv4_ACLS
+#ifdef HAVE_ACLS
         case 5 :        /* username -> UUID */
             LOG(log_debug, logtype_afpd, "afp_mapname: name: %s",ibuf);
             if (0 != getuuidfromname(ibuf, UUID_USER, rbuf))
@@ -2459,7 +2479,7 @@ int afp_mapname(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, siz
                 return AFPERR_NOITEM;
             *rbuflen = UUID_BINSIZE;
             break;
-#endif
+#endif /* HAVE_ACLS */
         }
     }
     return( AFP_OK );