]> arthur.barton.de Git - netatalk.git/commitdiff
copy native EA in afp_copyfile, doesn't work if copy between two volumes with differe...
authordidg <didg>
Wed, 18 Nov 2009 11:14:59 +0000 (11:14 +0000)
committerdidg <didg>
Wed, 18 Nov 2009 11:14:59 +0000 (11:14 +0000)
include/atalk/adouble.h
include/atalk/ea.h
libatalk/vfs/ea_sys.c
libatalk/vfs/sys_ea.c
libatalk/vfs/vfs.c

index 11c7ef3d8e0b8af6f70b1398ec1e4832343e4fc9..0ac822a49d67e9935a5532cf9c7af74fd8b6916b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: adouble.h,v 1.49 2009-11-13 02:52:07 didg Exp $
+ * $Id: adouble.h,v 1.50 2009-11-18 11:14:59 didg Exp $
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
  *
@@ -514,6 +514,7 @@ int sys_fremovexattr (int filedes, const char *name);
 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags);
 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags);
 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags);
+int sys_copyxattr (const char *src, const char *dst);
 
 /* ad_read.c/ad_write.c */
 extern int     sys_ftruncate(int fd, off_t length);
index b990bd732699f1ef43f2243abdbb797960a38097..4d47a0d3f69d07d4987e5990f5793cc1caa78c65 100644 (file)
@@ -1,5 +1,5 @@
 /*
-   $Id: ea.h,v 1.8 2009-11-17 12:33:30 franklahm Exp $
+   $Id: ea.h,v 1.9 2009-11-18 11:14:59 didg Exp $
    Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
 
    This program is free software; you can redistribute it and/or modify
@@ -146,5 +146,7 @@ extern int sys_get_eacontent(VFS_FUNC_ARGS_EA_GETCONTENT);
 extern int sys_list_eas(VFS_FUNC_ARGS_EA_LIST);
 extern int sys_set_ea(VFS_FUNC_ARGS_EA_SET);
 extern int sys_remove_ea(VFS_FUNC_ARGS_EA_REMOVE);
+/* native EA VFSfile/dir cp/mv/rm */
+extern int sys_ea_copyfile(VFS_FUNC_ARGS_COPYFILE);
 
 #endif /* ATALK_EA_H */
index 4e7b8788108e76a289dd821b35659e986b3b1950..aba68a3026c917e22b8013f82efb74388f87827a 100644 (file)
@@ -1,5 +1,5 @@
 /*
-  $Id: ea_sys.c,v 1.1 2009-11-17 12:33:30 franklahm Exp $
+  $Id: ea_sys.c,v 1.2 2009-11-18 11:14:59 didg Exp $
   Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
 
   This program is free software; you can redistribute it and/or modify
@@ -365,3 +365,27 @@ int sys_remove_ea(VFS_FUNC_ARGS_EA_REMOVE)
 
     return AFP_OK;
 }
+
+/* --------------------- 
+   copy EA 
+*/
+int sys_ea_copyfile(VFS_FUNC_ARGS_COPYFILE)
+{
+    int ret;
+    ret = sys_copyxattr(src, dst);
+    if (ret == -1) {
+        switch(errno) {
+        case ENOENT:
+            /* no attribute */
+            break;
+        case EACCES:
+            LOG(log_debug, logtype_afpd, "sys_ea_copyfile(%s, %s): error: %s", src, dst, strerror(errno));
+            return AFPERR_ACCESS;
+        default:
+            LOG(log_error, logtype_afpd, "sys_ea_copyfile(%s, %s): error: %s", src, dst, strerror(errno));
+            return AFPERR_MISC;
+        }
+    }
+
+    return AFP_OK;
+}
index ff231ad9b25545837fc539aa0a357d19b058f0d7..1af3d5ea2cbb685006e2b622cbc485395fcfed22 100644 (file)
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    
+   sys_copyxattr modified from LGPL2.1 libattr copyright
+   Copyright (C) 2001-2002 Silicon Graphics, Inc.  All Rights Reserved.
+   Copyright (C) 2001 Andreas Gruenbacher.
+      
    Samba 3.0.28, modified for netatalk.
-   $Id: sys_ea.c,v 1.1 2009-11-17 12:33:30 franklahm Exp $
+   $Id: sys_ea.c,v 1.2 2009-11-18 11:14:59 didg Exp $
    
 */
 
@@ -29,6 +33,7 @@
 #include "config.h"
 #endif
 
+#include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
 #include <errno.h>
@@ -664,6 +669,93 @@ int sys_lsetxattr (const char *path, const char *uname, const void *value, size_
 #endif
 }
 
+/* copy EA, from LGPL2.1 libattr attr_copy_file.c
+   should use fgetxattr? We don't have them but they are in Samba.
+   Or add a sys_copyfxattr? Currently it's only call by afp_copyfile so we can open
+   the both files for reading and get a fd.
+
+   Or don't use sys_xxx and copy all attributes.
+
+*/
+int sys_copyxattr(const char *src_path, const char *dst_path)
+{
+#if defined(HAVE_LISTXATTR) && defined(HAVE_GETXATTR) && defined(HAVE_SETXATTR)
+       int ret = 0;
+       ssize_t size;
+       char *names = NULL, *end_names, *name, *value = NULL;
+       unsigned int setxattr_ENOTSUP = 0;
+
+       size = sys_listxattr(src_path, NULL, 0);
+       if (size < 0) {
+               if (errno != ENOSYS && errno != ENOTSUP) {
+                       ret = -1;
+               }
+               goto getout;
+       }
+       names = malloc(size+1);
+       if (names == NULL) {
+               ret = -1;
+               goto getout;
+       }
+       size = sys_listxattr(src_path, names, size);
+       if (size < 0) {
+               ret = -1;
+               goto getout;
+       } else {
+               names[size] = '\0';
+               end_names = names + size;
+       }
+
+       for (name = names; name != end_names; name = strchr(name, '\0') + 1) {
+               void *old_value;
+
+               /* check if this attribute shall be preserved */
+               if (!*name)
+                       continue;
+
+               size = sys_getxattr (src_path, name, NULL, 0);
+               if (size < 0) {
+                       ret = -1;
+                       continue;
+               }
+               value = realloc(old_value = value, size);
+               if (size != 0 && value == NULL) {
+                       free(old_value);
+                       ret = -1;
+               }
+               size = sys_getxattr(src_path, name, value, size);
+               if (size < 0) {
+                       ret = -1;
+                       continue;
+               }
+               if (sys_setxattr(dst_path, name, value, size, 0) != 0) {
+                       if (errno == ENOTSUP)
+                               setxattr_ENOTSUP++;
+                       else {
+                               if (errno == ENOSYS) {
+                                       ret = -1;
+                                       /* no hope of getting any further */
+                                       break;
+                               } else {
+                                       ret = -1;
+                               }
+                       }
+               }
+       }
+       if (setxattr_ENOTSUP) {
+               errno = ENOTSUP;
+               ret = -1;
+       }
+getout:
+       free(value);
+       free(names);
+       return ret;
+#else
+       /* FIXME same for solaris */
+       return 0;
+#endif
+}
+
 /**************************************************************************
  helper functions for Solaris' EA support
 ****************************************************************************/
index c2647ceca0f674dcd628bfc2329f6c6ca37ae031..481e269eece56b3686c77ef956fa2d4e2d19c50b 100644 (file)
@@ -936,7 +936,7 @@ static struct vfs_ops netatalk_ea_sys = {
     /* rf_setdirowner:    */ NULL,
     /* rf_deletefile:     */ NULL,
     /* rf_renamefile:     */ NULL,
-    /* vfs_copyfile:      */ NULL,
+    /* vfs_copyfile:      */ sys_ea_copyfile,
     /* rf_acl:            */ NULL,
     /* rf_remove_acl      */ NULL,
     /* ea_getsize         */ sys_get_easize,