File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / rsync / lib / sysxattrs.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Oct 14 07:51:14 2013 UTC (10 years, 9 months ago) by misho
Branches: rsync, MAIN
CVS tags: RSYNC3_1_0, HEAD
v 3.1.0

    1: /*
    2:  * Extended attribute support for rsync.
    3:  *
    4:  * Copyright (C) 2004 Red Hat, Inc.
    5:  * Copyright (C) 2003-2008 Wayne Davison
    6:  * Written by Jay Fenlason.
    7:  *
    8:  * This program is free software; you can redistribute it and/or modify
    9:  * it under the terms of the GNU General Public License as published by
   10:  * the Free Software Foundation; either version 3 of the License, or
   11:  * (at your option) any later version.
   12:  *
   13:  * This program is distributed in the hope that it will be useful,
   14:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   15:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16:  * GNU General Public License for more details.
   17:  *
   18:  * You should have received a copy of the GNU General Public License along
   19:  * with this program; if not, visit the http://fsf.org website.
   20:  */
   21: 
   22: #include "rsync.h"
   23: #include "sysxattrs.h"
   24: 
   25: #ifdef SUPPORT_XATTRS
   26: 
   27: #if defined HAVE_LINUX_XATTRS
   28: 
   29: ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
   30: {
   31: 	return lgetxattr(path, name, value, size);
   32: }
   33: 
   34: ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
   35: {
   36: 	return fgetxattr(filedes, name, value, size);
   37: }
   38: 
   39: int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
   40: {
   41: 	return lsetxattr(path, name, value, size, 0);
   42: }
   43: 
   44: int sys_lremovexattr(const char *path, const char *name)
   45: {
   46: 	return lremovexattr(path, name);
   47: }
   48: 
   49: ssize_t sys_llistxattr(const char *path, char *list, size_t size)
   50: {
   51: 	return llistxattr(path, list, size);
   52: }
   53: 
   54: #elif HAVE_OSX_XATTRS
   55: 
   56: ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
   57: {
   58: 	return getxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
   59: }
   60: 
   61: ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
   62: {
   63: 	return fgetxattr(filedes, name, value, size, 0, 0);
   64: }
   65: 
   66: int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
   67: {
   68: 	return setxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
   69: }
   70: 
   71: int sys_lremovexattr(const char *path, const char *name)
   72: {
   73: 	return removexattr(path, name, XATTR_NOFOLLOW);
   74: }
   75: 
   76: ssize_t sys_llistxattr(const char *path, char *list, size_t size)
   77: {
   78: 	return listxattr(path, list, size, XATTR_NOFOLLOW);
   79: }
   80: 
   81: #elif HAVE_FREEBSD_XATTRS
   82: 
   83: ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
   84: {
   85: 	return extattr_get_link(path, EXTATTR_NAMESPACE_USER, name, value, size);
   86: }
   87: 
   88: ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
   89: {
   90: 	return extattr_get_fd(filedes, EXTATTR_NAMESPACE_USER, name, value, size);
   91: }
   92: 
   93: int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
   94: {
   95: 	return extattr_set_link(path, EXTATTR_NAMESPACE_USER, name, value, size);
   96: }
   97: 
   98: int sys_lremovexattr(const char *path, const char *name)
   99: {
  100: 	return extattr_delete_link(path, EXTATTR_NAMESPACE_USER, name);
  101: }
  102: 
  103: ssize_t sys_llistxattr(const char *path, char *list, size_t size)
  104: {
  105: 	unsigned char keylen;
  106: 	ssize_t off, len = extattr_list_link(path, EXTATTR_NAMESPACE_USER, list, size);
  107: 
  108: 	if (len <= 0 || (size_t)len > size)
  109: 		return len;
  110: 
  111: 	/* FreeBSD puts a single-byte length before each string, with no '\0'
  112: 	 * terminator.  We need to change this into a series of null-terminted
  113: 	 * strings.  Since the size is the same, we can simply transform the
  114: 	 * output in place. */
  115: 	for (off = 0; off < len; off += keylen + 1) {
  116: 		keylen = ((unsigned char*)list)[off];
  117: 		if (off + keylen >= len) {
  118: 			/* Should be impossible, but kernel bugs happen! */
  119: 			errno = EINVAL;
  120: 			return -1;
  121: 		}
  122: 		memmove(list+off, list+off+1, keylen);
  123: 		list[off+keylen] = '\0';
  124: 	}
  125: 
  126: 	return len;
  127: }
  128: 
  129: #elif HAVE_SOLARIS_XATTRS
  130: 
  131: static ssize_t read_xattr(int attrfd, void *buf, size_t buflen)
  132: {
  133: 	STRUCT_STAT sb;
  134: 	ssize_t ret;
  135: 
  136: 	if (fstat(attrfd, &sb) < 0)
  137: 		ret = -1;
  138: 	else if (sb.st_size > SSIZE_MAX) {
  139: 		errno = ERANGE;
  140: 		ret = -1;
  141: 	} else if (buflen == 0)
  142: 		ret = sb.st_size;
  143: 	else if (sb.st_size > buflen) {
  144: 		errno = ERANGE;
  145: 		ret = -1;
  146: 	} else {
  147: 		size_t bufpos;
  148: 		for (bufpos = 0; bufpos < sb.st_size; ) {
  149: 			ssize_t cnt = read(attrfd, buf + bufpos, sb.st_size - bufpos);
  150: 			if (cnt <= 0) {
  151: 				if (cnt < 0 && errno == EINTR)
  152: 					continue;
  153: 				bufpos = -1;
  154: 				break;
  155: 			}
  156: 			bufpos += cnt;
  157: 		}
  158: 		ret = bufpos;
  159: 	}
  160: 
  161: 	close(attrfd);
  162: 
  163: 	return ret;
  164: }
  165: 
  166: ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
  167: {
  168: 	int attrfd;
  169: 
  170: 	if ((attrfd = attropen(path, name, O_RDONLY)) < 0) {
  171: 		errno = ENOATTR;
  172: 		return -1;
  173: 	}
  174: 
  175: 	return read_xattr(attrfd, value, size);
  176: }
  177: 
  178: ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
  179: {
  180: 	int attrfd;
  181: 
  182: 	if ((attrfd = openat(filedes, name, O_RDONLY|O_XATTR, 0)) < 0) {
  183: 		errno = ENOATTR;
  184: 		return -1;
  185: 	}
  186: 
  187: 	return read_xattr(attrfd, value, size);
  188: }
  189: 
  190: int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
  191: {
  192: 	int attrfd;
  193: 	size_t bufpos;
  194: 	mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
  195: 
  196: 	if ((attrfd = attropen(path, name, O_CREAT|O_TRUNC|O_WRONLY, mode)) < 0)
  197: 		return -1;
  198: 
  199: 	for (bufpos = 0; bufpos < size; ) {
  200: 		ssize_t cnt = write(attrfd, value+bufpos, size);
  201: 		if (cnt <= 0) {
  202: 			if (cnt < 0 && errno == EINTR)
  203: 				continue;
  204: 			bufpos = -1;
  205: 			break;
  206: 		}
  207: 		bufpos += cnt;
  208: 	}
  209: 
  210: 	close(attrfd);
  211: 
  212: 	return bufpos > 0 ? 0 : -1;
  213: }
  214: 
  215: int sys_lremovexattr(const char *path, const char *name)
  216: {
  217: 	int attrdirfd;
  218: 	int ret;
  219: 
  220: 	if ((attrdirfd = attropen(path, ".", O_RDONLY)) < 0)
  221: 		return -1;
  222: 
  223: 	ret = unlinkat(attrdirfd, name, 0);
  224: 
  225: 	close(attrdirfd);
  226: 
  227: 	return ret;
  228: }
  229: 
  230: ssize_t sys_llistxattr(const char *path, char *list, size_t size)
  231: {
  232: 	int attrdirfd;
  233: 	DIR *dirp;
  234: 	struct dirent *dp;
  235: 	ssize_t ret = 0;
  236: 
  237: 	if ((attrdirfd = attropen(path, ".", O_RDONLY)) < 0) {
  238: 		errno = ENOTSUP;
  239: 		return -1;
  240: 	}
  241: 
  242: 	if ((dirp = fdopendir(attrdirfd)) == NULL) {
  243: 		close(attrdirfd);
  244: 		return -1;
  245: 	}
  246: 
  247: 	while ((dp = readdir(dirp))) {
  248: 		int len = strlen(dp->d_name);
  249: 
  250: 		if (dp->d_name[0] == '.' && (len == 1 || (len == 2 && dp->d_name[1] == '.')))
  251: 			continue;
  252: 		if (len == 11 && dp->d_name[0] == 'S' && strncmp(dp->d_name, "SUNWattr_r", 10) == 0
  253: 		 && (dp->d_name[10] == 'o' || dp->d_name[10] == 'w'))
  254: 			continue;
  255: 
  256: 		if ((ret += len+1) > size) {
  257: 			if (size == 0)
  258: 				continue;
  259: 			ret = -1;
  260: 			errno = ERANGE;
  261: 			break;
  262: 		}
  263: 		memcpy(list, dp->d_name, len+1);
  264: 		list += len+1;
  265: 	}
  266: 
  267: 	closedir(dirp);
  268: 	close(attrdirfd);
  269: 
  270: 	return ret;
  271: }
  272: 
  273: #else
  274: 
  275: #error You need to create xattr compatibility functions.
  276: 
  277: #endif
  278: 
  279: #endif /* SUPPORT_XATTRS */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>