(root)/
attr-2.5.1/
libattr/
attr_copy_fd.c
       1  /*
       2    Copyright (C) 2002 Andreas Gruenbacher <agruen@suse.de>, SuSE Linux AG.
       3  
       4    This program is free software; you can redistribute it and/or
       5    modify it under the terms of the GNU Lesser General Public
       6    License as published by the Free Software Foundation; either
       7    version 2.1 of the License, or (at your option) any later version.
       8  
       9    This program is distributed in the hope that it will be useful,
      10    but WITHOUT ANY WARRANTY; without even the implied warranty of
      11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12    Lesser General Public License for more details.
      13  
      14    You should have received a copy of the GNU Lesser General Public License
      15    along with this manual.  If not, see <http://www.gnu.org/licenses/>.
      16  */
      17  
      18  /* Copy extended attributes between files. */
      19  
      20  #if defined (HAVE_CONFIG_H)
      21  #include "config.h"
      22  #endif
      23  
      24  #include <sys/types.h>
      25  # include <sys/xattr.h>
      26  #include <stdlib.h>
      27  #include <string.h>
      28  #include <errno.h>
      29  
      30  #if defined(HAVE_ALLOCA_H)
      31  # include <alloca.h>
      32  #endif
      33  
      34  #if defined(HAVE_ATTR_LIBATTR_H)
      35  # include "attr/libattr.h"
      36  #endif
      37  
      38  #define ERROR_CONTEXT_MACROS
      39  #include "error_context.h"
      40  #include "nls.h"
      41  
      42  #if !defined(ENOTSUP)
      43  # define ENOTSUP (-1)
      44  #endif
      45  
      46  #if defined(HAVE_ALLOCA)
      47  # define my_alloc(size) alloca (size)
      48  # define my_free(ptr) do { } while(0)
      49  #else
      50  # define my_alloc(size) malloc (size)
      51  # define my_free(ptr) free (ptr)
      52  #endif
      53  
      54  /* Copy extended attributes from src_path to dst_path. If the file
      55     has an extended Access ACL (system.posix_acl_access) and that is
      56     copied successfully, the file mode permission bits are copied as
      57     a side effect. This may not always the case, so the file mode
      58     and/or ownership must be copied separately. */
      59  int
      60  attr_copy_fd(const char *src_path, int src_fd,
      61  	     const char *dst_path, int dst_fd,
      62  	     int (*check) (const char *, struct error_context *),
      63  	     struct error_context *ctx)
      64  {
      65  #if defined(HAVE_FLISTXATTR) && defined(HAVE_FGETXATTR) && \
      66      defined(HAVE_FSETXATTR)
      67  	int ret = 0;
      68  	ssize_t size;
      69  	char *names = NULL, *end_names, *name, *value = NULL;
      70  	unsigned int setxattr_ENOTSUP = 0;
      71  
      72  	/* ignore acls by default */
      73  	if (check == NULL)
      74  		check = attr_copy_check_permissions;
      75  
      76  	size = flistxattr (src_fd, NULL, 0);
      77  	if (size < 0) {
      78  		if (errno != ENOSYS && errno != ENOTSUP) {
      79  			const char *qpath = quote (ctx, src_path);
      80  			error (ctx, _("listing attributes of %s"), qpath);
      81  			quote_free (ctx, qpath);
      82  			ret = -1;
      83  		}
      84  		goto getout;
      85  	}
      86  	names = (char *) my_alloc (size+1);
      87  	if (names == NULL) {
      88  		error (ctx, "");
      89  		ret = -1;
      90  		goto getout;
      91  	}
      92  	size = flistxattr (src_fd, names, size);
      93  	if (size < 0) {
      94  		const char *qpath = quote (ctx, src_path);
      95  		error (ctx, _("listing attributes of %s"), qpath);
      96  		quote_free (ctx, qpath);
      97  		ret = -1;
      98  		goto getout;
      99  	} else {
     100  		names[size] = '\0';
     101  		end_names = names + size;
     102  	}
     103  
     104  	for (name = names; name != end_names; name = strchr(name, '\0') + 1) {
     105  		void *old_value;
     106  
     107  		/* check if this attribute shall be preserved */
     108  		if (!*name || !check(name, ctx))
     109  			continue;
     110  
     111  		size = fgetxattr (src_fd, name, NULL, 0);
     112  		if (size < 0) {
     113  			const char *qpath = quote (ctx, src_path);
     114  			const char *qname = quote (ctx, name);
     115  			error (ctx, _("getting attribute %s of %s"),
     116  			       qname, qpath);
     117  			quote_free (ctx, qname);
     118  			quote_free (ctx, qpath);
     119  			ret = -1;
     120  			continue;
     121  		}
     122  		value = (char *) realloc (old_value = value, size);
     123  		if (size != 0 && value == NULL) {
     124  			free(old_value);
     125  			error (ctx, "");
     126  			ret = -1;
     127  		}
     128  		size = fgetxattr (src_fd, name, value, size);
     129  		if (size < 0) {
     130  			const char *qpath = quote (ctx, src_path);
     131  			const char *qname = quote (ctx, name);
     132  			error (ctx, _("getting attribute %s of %s"),
     133  			       qname, qpath);
     134  			quote_free (ctx, qname);
     135  			quote_free (ctx, qpath);
     136  			ret = -1;
     137  			continue;
     138  		}
     139  		if (fsetxattr (dst_fd, name, value, size, 0) != 0) {
     140  			if (errno == ENOTSUP)
     141  				setxattr_ENOTSUP++;
     142  			else {
     143  				const char *qpath = quote (ctx, dst_path);
     144  				if (errno == ENOSYS) {
     145  					error (ctx, _("setting attributes for "
     146  					       "%s"), qpath);
     147  					ret = -1;
     148  					/* no hope of getting any further */
     149  					break;
     150  				} else {
     151  					const char *qname = quote (ctx, name);
     152  					error (ctx, _("setting attribute %s for "
     153  					       "%s"), qname, qpath);
     154  					quote_free (ctx, qname);
     155  					ret = -1;
     156  				}
     157  				quote_free (ctx, qpath);
     158  			}
     159  		}
     160  	}
     161  	if (setxattr_ENOTSUP) {
     162  		const char *qpath = quote (ctx, dst_path);
     163  		errno = ENOTSUP;
     164  		error (ctx, _("setting attributes for %s"), qpath);
     165  		ret = -1;
     166  		quote_free (ctx, qpath);
     167  	}
     168  getout:
     169  	free (value);
     170  	my_free (names);
     171  	return ret;
     172  #else
     173  	return 0;
     174  #endif
     175  }
     176