--- a/src/function.c
+++ b/src/function.c
@@ -13,70 +13,135 @@
 #ifdef HAVE_SETXATTR
   #include <sys/xattr.h>
 #endif
-#include <glib.h>
 
 #include "common.h"
 #include "smbitem.h"
 #include "samba.h"
-#include "stat_workaround.h"
 #include "function.h"
 
-static int		function_free_space_size	= 0;
-static int		function_quiet_flag		= 1;
-static int		function_show_dollar_shares	= 0;
-static int		function_show_hidden_hosts	= 0;
-
-
-int function_set_free_space_size(int blocks_count){
-    DPRINTF(7, "blocks_count=%d\n", blocks_count);
-    g_atomic_int_set(&function_free_space_size, blocks_count);
+size_t		function_free_space_size	= 0;
+int		function_quiet_flag		= 1;
+int		function_show_dollar_shares	= 0;
+int		function_show_hidden_hosts	= 0;
+int		function_kde_workaround_depth	= 3;
+
+pthread_mutex_t	m_function		= PTHREAD_MUTEX_INITIALIZER;
+
+int function_set_free_space_size(size_t blocks_count){
+    DPRINTF(7, "blocks_count=%d\n", (int) blocks_count);
+    pthread_mutex_lock(&m_function);
+    function_free_space_size = blocks_count;
+    pthread_mutex_unlock(&m_function);
     return 1;
 }
 
-static int function_get_free_space_size(void){
-    return g_atomic_int_get(&function_free_space_size);
+size_t function_get_free_space_size(void){
+    size_t blocks_count;
+
+    pthread_mutex_lock(&m_function);
+    blocks_count = function_free_space_size;
+    pthread_mutex_unlock(&m_function);
+    DPRINTF(7, "blocks_count=%d\n", (int) blocks_count);
+    return blocks_count;
 }
 
 int function_set_quiet_flag(int flag){
     DPRINTF(7, "flag=%d\n", flag);
-    g_atomic_int_set(&function_quiet_flag, flag);
+    pthread_mutex_lock(&m_function);
+    function_quiet_flag = flag;
+    pthread_mutex_unlock(&m_function);
     return 1;
 }
 
-static inline int function_get_quiet_flag(void){
-    return g_atomic_int_get(&function_quiet_flag);
+int function_get_quiet_flag(void){
+    int flag;
+
+    pthread_mutex_lock(&m_function);
+    flag = function_quiet_flag;
+    pthread_mutex_unlock(&m_function);
+    DPRINTF(7, "flag=%d\n", flag);
+    return flag;
 }
 
 int function_set_dollar_share_visibility(int flag){
     DPRINTF(7, "flag=%d\n", flag);
-    g_atomic_int_set(&function_show_dollar_shares, flag);
+    pthread_mutex_lock(&m_function);
+    function_show_dollar_shares = flag;
+    pthread_mutex_unlock(&m_function);
     return 1;
 }
 
-static inline int function_get_dollar_share_visibility(void){
-    return g_atomic_int_get(&function_show_dollar_shares);
+int function_get_dollar_share_visibility(void){
+    int flag;
+
+    pthread_mutex_lock(&m_function);
+    flag = function_show_dollar_shares;
+    pthread_mutex_unlock(&m_function);
+    DPRINTF(7, "flag=%d\n", flag);
+    return flag;
 }
 
 int function_set_hidden_hosts_visibility(int flag){
     DPRINTF(7, "flag=%d\n", flag);
-    g_atomic_int_set(&function_show_hidden_hosts, flag);
+    pthread_mutex_lock(&m_function);
+    function_show_hidden_hosts = flag;
+    pthread_mutex_unlock(&m_function);
     return 1;
 }
 
-static inline int function_get_hidden_hosts_visibility(void){
-    return g_atomic_int_get(&function_show_hidden_hosts);
-}
-
-static inline int function_check_xattr_name(const char *name){
-    static char	*xattr_name = "system.nt_sec_desc.";
-    return (strncmp(name, xattr_name, strlen(xattr_name)) == 0);
-}
-
-static inline samba_fd function_get_fd(struct fuse_file_info *fi){
+int function_get_hidden_hosts_visibility(void){
+    int flag;
+
+    pthread_mutex_lock(&m_function);
+    flag = function_show_hidden_hosts;
+    pthread_mutex_unlock(&m_function);
+    DPRINTF(7, "flag=%d\n", flag);
+    return flag;
+}
+
+int function_set_kde_workaround_depth(int depth){
+    if (depth < -1) return 0;
+    DPRINTF(7, "depth=%d\n", depth);
+    pthread_mutex_lock(&m_function);
+    function_kde_workaround_depth = depth;
+    pthread_mutex_unlock(&m_function);
+    return 1;
+}
+
+int function_get_kde_workaround_depth(void){
+    int depth;
+
+    pthread_mutex_lock(&m_function);
+    depth = function_kde_workaround_depth;
+    pthread_mutex_unlock(&m_function);
+    DPRINTF(7, "depth=%d\n", depth);
+    return depth;
+}
+
+int function_is_kde_workaround(const char *path){
+    const char		*kde_dir_name = ".directory";
+    const ssize_t	kde_dir_len = strlen(kde_dir_name);
+    int			i, depth = function_get_kde_workaround_depth();
+    const char		*path_end;
+
+    for(i = 0; (i < depth) || (depth == -1); i++){
+	while(*path == '/') path++;
+	if (*path == '\0') break;
+
+	path_end = path;
+	while((*path_end != '/') && (*path_end != '\0')) path_end++;
+	if ((path_end - path == kde_dir_len) &&
+	    (strncmp(path, kde_dir_name, kde_dir_len) == 0)) return 1;
+	path = path_end;
+    }
+    return 0;
+}
+
+inline samba_fd function_get_fd(struct fuse_file_info *fi){
     return (samba_fd) fi->fh;
 }
 
-static inline void function_store_fd(struct fuse_file_info *fi, samba_fd fd){
+inline void function_store_fd(struct fuse_file_info *fi, samba_fd fd){
     fi->fh = (uint64_t) fd;
 }
 
@@ -109,7 +174,7 @@
     int		result;
     samba_fd	fd;
 
-    DPRINTF(5, "(%s, %zd, fh=%llx, offset=%lld, flags=%o)\n", path, size,
+    DPRINTF(5, "(%s, %d, fh=%llx, offset=%lld, flags=%o)\n", path, (int) size,
 	(long long) fi->fh, (long long) offset, fi->flags);
 
     if ((fd = function_get_fd(fi)) == NULL) return -EBADF;
@@ -123,7 +188,7 @@
     int		result;
     samba_fd	fd;
 
-    DPRINTF(5, "(%s, %zd, fh=%llx, offset=%lld, flags=%o)\n", path, size,
+    DPRINTF(5, "(%s, %d, fh=%llx, offset=%lld, flags=%o)\n", path, (int) size,
 	(long long) fi->fh, (long long) offset, fi->flags);
 
     if ((fd = function_get_fd(fi)) == NULL) return -EBADF;
@@ -219,7 +284,7 @@
 		    break;
 		case SMBITEM_HOST:
 		    st.st_mode = S_IFDIR;
-		    if (!show_hidden_hosts && dir->childs[i]->is_hidden) continue;
+		    if (! show_hidden_hosts) continue;
 		    break;
 		case SMBITEM_LINK:
 		    st.st_mode = S_IFLNK;
@@ -348,7 +413,7 @@
     char		buf[2048];
 
     DPRINTF(5, "(%s)\n", path);
-    if (stat_workaround_is_name_ignored(path)) return -ENOENT;
+    if (function_is_kde_workaround(path)) return -ENOENT;
     switch(smbitem_what_is(path)){
 	case SMBITEM_SMBNETFS_DIR:
 	    while(*path == '/') path++;
@@ -487,10 +552,9 @@
 /* libfuse does not support lsetxattr() and fsetxattr(), but samba does */
 static int function_setxattr(const char *path, const char *name,
 			    const char *value, size_t size, int flags){
-    DPRINTF(5, "(%s, name=%s, value=%s, size=%zd, flags=%o)\n", path,
-	name, value, size, flags);
-    if (smbitem_what_is(path) != SMBITEM_SMB_SHARE_ITEM) return -ENOTSUP;
-    if (!function_check_xattr_name(name)) return -ENOTSUP;
+    DPRINTF(5, "(%s, name=%s, value=%s, size=%d, flags=%o)\n", path,
+	name, value, (int) size, flags);
+    if (smbitem_what_is(path) != SMBITEM_SMB_SHARE_ITEM) return -EINVAL;
     if (samba_setxattr(path, name, value, size, flags) != 0) return -errno;
     return 0;
 }
@@ -498,17 +562,16 @@
 /* libfuse does not support lgetxattr() and fgetxattr(), but samba does */
 static int function_getxattr(const char *path, const char *name,
 			    char *value, size_t size){
-    DPRINTF(5, "(%s, name=%s, size=%zd)\n", path, name, size);
-    if (smbitem_what_is(path) != SMBITEM_SMB_SHARE_ITEM) return -ENOTSUP;
-    if (!function_check_xattr_name(name)) return -ENOTSUP;
+    DPRINTF(5, "(%s, name=%s, size=%d)\n", path, name, (int) size);
+    if (smbitem_what_is(path) != SMBITEM_SMB_SHARE_ITEM) return -EINVAL;
     if (samba_getxattr(path, name, value, size) != 0) return -errno;
     return 0;
 }
 
 /* libfuse does not support llistxattr() and flistxattr(), but samba does */
 static int function_listxattr(const char *path, char *list, size_t size){
-    DPRINTF(5, "(%s, size=%zd)\n", path, size);
-    if (smbitem_what_is(path) != SMBITEM_SMB_SHARE_ITEM) return -ENOTSUP;
+    DPRINTF(5, "(%s, size=%d)\n", path, (int) size);
+    if (smbitem_what_is(path) != SMBITEM_SMB_SHARE_ITEM) return -EINVAL;
     if (samba_listxattr(path, list, size) != 0) return -errno;
     return 0;
 }
@@ -516,14 +579,13 @@
 /* libfuse does not support lremovexattr() and fremovexattr(), but samba does */
 static int function_removexattr(const char *path, const char *name){
     DPRINTF(5, "(%s, name=%s)\n", path, name);
-    if (smbitem_what_is(path) != SMBITEM_SMB_SHARE_ITEM) return -ENOTSUP;
-    if (!function_check_xattr_name(name)) return -ENOTSUP;
+    if (smbitem_what_is(path) != SMBITEM_SMB_SHARE_ITEM) return -EINVAL;
     if (samba_removexattr(path, name) != 0) return -errno;
     return 0;
 }
 
 static int function_readlink(const char *path, char *buf, size_t size){
-    DPRINTF(5, "(%s, %zd)\n", path, size);
+    DPRINTF(5, "(%s, %d)\n", path, (int) size);
     if (smbitem_what_is(path) != SMBITEM_SMBNETFS_LINK) return -EINVAL;
     if (smbitem_readlink(path, buf, size) != 0) return -EINVAL;
     return 0;