Beispiel #1
0
ssize_t
ceph_os_listxattr(const char *path, char *list, size_t size)
{
	ssize_t error = -1;

#if defined(__FreeBSD__)
	/*
	 * XXX. The format of the list FreeBSD returns differs
	 * from the Linux ones.  We have to perform the conversion. :-(
	 */
	char *newlist, *p, *p1;

	if (size != 0) {
		newlist = malloc(size);
		if (newlist != NULL) {
			error = extattr_list_file(path, EXTATTR_NAMESPACE_USER,
			    newlist, size);
			if (error > 0) {
				p = newlist;
				p1 = list;
				while ((p - newlist) < error) {
					uint8_t len = *(uint8_t *)p;
					p++;
					if ((p + len - newlist) > error)
						break;
					if (len > 0) {
						bcopy(p, p1, len);
						p += len;
						p1 += len;
						*p1++ = '\0';
					}
				}
				error = p1 - list;
			}
			free(newlist);
		}
	} else {
		error = extattr_list_file(path, EXTATTR_NAMESPACE_USER,
		    list, size);
	}
#elif defined(__linux__)
	error = listxattr(path, list, size);
#elif defined(DARWIN)
	error = listxattr(path, list, size, 0);
#endif

	return (error);
}
Beispiel #2
0
static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
{
	ssize_t list_size;
	int i, len;

    switch(type) {
#if defined(HAVE_EXTATTR_LIST_FILE)
    case 0:
        list_size = extattr_list_file(arg.path, EXTATTR_NAMESPACE_USER, list, size);
        break;
#endif
#if defined(HAVE_EXTATTR_LIST_LINK)
    case 1:
        list_size = extattr_list_link(arg.path, EXTATTR_NAMESPACE_USER, list, size);
        break;
#endif
#if defined(HAVE_EXTATTR_LIST_FD)
    case 2:
        list_size = extattr_list_fd(arg.filedes, EXTATTR_NAMESPACE_USER, list, size);
        break;
#endif
    default:
        errno = ENOSYS;
        return -1;
    }

    /* Some error happend. Errno should be set by the previous call */
    if(list_size < 0)
        return -1;

    /* No attributes */
    if(list_size == 0)
        return 0;

    /* XXX: Call with an empty buffer may be used to calculate
       necessary buffer size. Unfortunately, we can't say, how
       many attributes were returned, so here is the potential
       problem with the emulation.
    */
    if(list == NULL)
        return list_size;

    /* Buffer is too small to fit the results */
    if(list_size > size) {
        errno = ERANGE;
        return -1;
    }

    /* Convert from pascal strings to C strings */
    len = list[0];
    memmove(list, list + 1, list_size);

    for(i = len; i < list_size; ) {
        len = list[i];
        list[i] = '\0';
        i += len + 1;
    }

	return list_size;
}
/*
   @param flag          Bitfield for control purposes
                        bit5=  in case of symbolic link: inquire link target
*/
static int aaip_extattr_make_list(char *path, int attrnamespace,
                                  char **list, ssize_t *list_size, int flag)
{
 *list= NULL;
 *list_size= 0;

 /* man 2 extattr_list_file:
    If data is NULL in a call to extattr_get_file() and extattr_list_file()
    then the size of defined extended attribute data will be returned,
 */
 if(flag & 32) /* follow link */
   *list_size= extattr_list_file(path, attrnamespace, NULL, (size_t) 0);
 else
   *list_size= extattr_list_link(path, attrnamespace, NULL, (size_t) 0);
 if(*list_size == -1) {
   if(! aaip_extattr_path_supp(path, 0)) {
     *list_size = 0;
     return(2);
   }
   return(0);
 }
 if(*list_size == 0)
   return(2);
 *list= calloc(*list_size, 1);
 if(*list == NULL)
   return(-1);
 if(flag & 32)
   *list_size= extattr_list_file(path, attrnamespace, *list,
                                 (size_t) *list_size);
 else
   *list_size= extattr_list_link(path, attrnamespace, *list,
                                 (size_t) *list_size);
 if(*list_size == -1)
   return(0);
 return(1);
}
Beispiel #4
0
static ssize_t xattr_listxattr(const char *path, char *namebuf,
                               size_t size, int options)
{
    ssize_t rv = 0;
    if (!(options == 0 ||
          options == XATTR_XATTR_NOFOLLOW)) {
        return -1;
    }

    if (options & XATTR_XATTR_NOFOLLOW) {
        rv = extattr_list_link(path, EXTATTR_NAMESPACE_USER, namebuf, size);
    }
    else {
        rv = extattr_list_file(path, EXTATTR_NAMESPACE_USER, namebuf, size);
    }

    if (rv > 0 && namebuf) {
        convert_bsd_list(namebuf, rv);
    }

    return rv;
}
Beispiel #5
0
ssize_t listAttrs( const char* path, void* data, size_t nbytes ) {
    /* 
	 extattr_list_file() returns a list of attributes present in the requested namespace.
	 Each list entry consists of a single byte containing the length of the attribute name.
	 The attribute name is not terminated by ASCII 0 (nul).
	*/
    ssize_t ret = extattr_list_file( path, EXTATTR_NAMESPACE_USER, data, nbytes );

    checkReturnValue( "listAttrs", ret );

	// Do the string manipulation
	char* bitstring = data;// Cast the void pointer to a string
	int len = (int) bitstring[0];// Bootstrap the first pointer
	for ( int i = 1; i < nbytes; i++ ) {
		if ( i == len ) {
			// Set the position of the next pointer
			len = (int) bitstring[i];
			bitstring[i] = '\0';
		}
		bitstring[i-1] = bitstring[i];
	}
    return ret;
}
Beispiel #6
0
int
main(int argc, char *argv[])
{
	char	*buf, *visbuf, *p;

	const char *options, *attrname;
	size_t	len;
	ssize_t	ret;
	int	 buflen, visbuflen, ch, error, i, arg_counter, attrnamespace,
		 minargc;

	int	flag_force = 0;
	int	flag_nofollow = 0;
	int	flag_null = 0;
	int	flag_quiet = 0;
	int	flag_string = 0;
	int	flag_hex = 0;

	visbuflen = buflen = 0;
	visbuf = buf = NULL;

	p = basename(argv[0]);
	if (p == NULL)
		p = argv[0];
	if (!strcmp(p, "getextattr")) {
		what = EAGET;
		options = "fhqsx";
		minargc = 3;
	} else if (!strcmp(p, "setextattr")) {
		what = EASET;
		options = "fhnq";
		minargc = 4;
	} else if (!strcmp(p, "rmextattr")) {
		what = EARM;
		options = "fhq";
		minargc = 3;
	} else if (!strcmp(p, "lsextattr")) {
		what = EALS;
		options = "fhq";
		minargc = 2;
	} else {
		usage();
	}

	while ((ch = getopt(argc, argv, options)) != -1) {
		switch (ch) {
		case 'f':
			flag_force = 1;
			break;
		case 'h':
			flag_nofollow = 1;
			break;
		case 'n':
			flag_null = 1;
			break;
		case 'q':
			flag_quiet = 1;
			break;
		case 's':
			flag_string = 1;
			break;
		case 'x':
			flag_hex = 1;
			break;
		case '?':
		default:
			usage();
		}
	}

	argc -= optind;
	argv += optind;

	if (argc < minargc)
		usage();

	error = extattr_string_to_namespace(argv[0], &attrnamespace);
	if (error)
		err(-1, "%s", argv[0]);
	argc--; argv++;

	if (what != EALS) {
		attrname = argv[0];
		argc--; argv++;
	} else
		attrname = NULL;

	if (what == EASET) {
		mkbuf(&buf, &buflen, strlen(argv[0]) + 1);
		strcpy(buf, argv[0]);
		argc--; argv++;
	}

	for (arg_counter = 0; arg_counter < argc; arg_counter++) {
		switch (what) {
		case EARM:
			if (flag_nofollow)
				error = extattr_delete_link(argv[arg_counter],
				    attrnamespace, attrname);
			else
				error = extattr_delete_file(argv[arg_counter],
				    attrnamespace, attrname);
			if (error >= 0)
				continue;
			break;
		case EASET:
			len = strlen(buf) + flag_null;
			if (flag_nofollow)
				ret = extattr_set_link(argv[arg_counter],
				    attrnamespace, attrname, buf, len);
			else
				ret = extattr_set_file(argv[arg_counter],
				    attrnamespace, attrname, buf, len);
			if (ret >= 0) {
				if ((size_t)ret != len && !flag_quiet) {
					warnx("Set %zd bytes of %zu for %s",
					    ret, len, attrname);
				}
				continue;
			}
			break;
		case EALS:
			if (flag_nofollow)
				ret = extattr_list_link(argv[arg_counter],
				    attrnamespace, NULL, 0);
			else
				ret = extattr_list_file(argv[arg_counter],
				    attrnamespace, NULL, 0);
			if (ret < 0)
				break;
			mkbuf(&buf, &buflen, ret);
			if (flag_nofollow)
				ret = extattr_list_link(argv[arg_counter],
				    attrnamespace, buf, buflen);
			else
				ret = extattr_list_file(argv[arg_counter],
				    attrnamespace, buf, buflen);
			if (ret < 0)
				break;
			if (!flag_quiet)
				printf("%s\t", argv[arg_counter]);
			for (i = 0; i < ret; i += ch + 1) {
			    /* The attribute name length is unsigned. */
			    ch = (unsigned char)buf[i];
			    printf("%s%*.*s", i ? "\t" : "",
				ch, ch, buf + i + 1);
			}
			if (!flag_quiet || ret > 0)
				printf("\n");
			continue;
		case EAGET:
			if (flag_nofollow)
				ret = extattr_get_link(argv[arg_counter],
				    attrnamespace, attrname, NULL, 0);
			else
				ret = extattr_get_file(argv[arg_counter],
				    attrnamespace, attrname, NULL, 0);
			if (ret < 0)
				break;
			mkbuf(&buf, &buflen, ret);
			if (flag_nofollow)
				ret = extattr_get_link(argv[arg_counter],
				    attrnamespace, attrname, buf, buflen);
			else
				ret = extattr_get_file(argv[arg_counter],
				    attrnamespace, attrname, buf, buflen);
			if (ret < 0)
				break;
			if (!flag_quiet)
				printf("%s\t", argv[arg_counter]);
			if (flag_string) {
				mkbuf(&visbuf, &visbuflen, ret * 4 + 1);
				strvisx(visbuf, buf, ret,
				    VIS_SAFE | VIS_WHITE);
				printf("\"%s\"\n", visbuf);
				continue;
			} else if (flag_hex) {
				for (i = 0; i < ret; i++)
					printf("%s%02x", i ? " " : "",
					    buf[i]);
				printf("\n");
				continue;
			} else {
				fwrite(buf, ret, 1, stdout);
				printf("\n");
				continue;
			}
		default:
			break;
		}
		if (!flag_quiet) 
			warn("%s: failed", argv[arg_counter]);
		if (flag_force)
			continue;
		return(1);
	}
	return (0);
}
Beispiel #7
0
static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
{
	ssize_t list_size, total_size = 0;
	int i, t, len;
	char *buf;
	/* Iterate through extattr(2) namespaces */
	for(t = 0; t < ARRAY_SIZE(extattr); t++) {
		if (t != EXTATTR_NAMESPACE_USER && geteuid() != 0) {
			/* ignore all but user namespace when we are not root, see bug 10247 */
			continue;
		}
		switch(type) {
#if defined(HAVE_EXTATTR_LIST_FILE)
			case 0:
				list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
				break;
#endif
#if defined(HAVE_EXTATTR_LIST_LINK)
			case 1:
				list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
				break;
#endif
#if defined(HAVE_EXTATTR_LIST_FD)
			case 2:
				list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
				break;
#endif
			default:
				errno = ENOSYS;
				return -1;
		}
		/* Some error happend. Errno should be set by the previous call */
		if(list_size < 0)
			return -1;
		/* No attributes */
		if(list_size == 0)
			continue;
		/* XXX: Call with an empty buffer may be used to calculate
		   necessary buffer size. Unfortunately, we can't say, how
		   many attributes were returned, so here is the potential
		   problem with the emulation.
		*/
		if(list == NULL) {
			/* Take the worse case of one char attribute names - 
			   two bytes per name plus one more for sanity.
			*/
			total_size += list_size + (list_size/2 + 1)*extattr[t].len;
			continue;
		}
		/* Count necessary offset to fit namespace prefixes */
		len = 0;
		for(i = 0; i < list_size; i += list[i] + 1)
			len += extattr[t].len;

		total_size += list_size + len;
		/* Buffer is too small to fit the results */
		if(total_size > size) {
			errno = ERANGE;
			return -1;
		}
		/* Shift results back, so we can prepend prefixes */
		buf = (char *)memmove(list + len, list, list_size);

		for(i = 0; i < list_size; i += len + 1) {
			len = buf[i];
			strncpy(list, extattr[t].name, extattr[t].len + 1);
			list += extattr[t].len;
			strncpy(list, buf + i + 1, len);
			list[len] = '\0';
			list += len + 1;
		}
		size -= total_size;
	}
	return total_size;
}