Exemplo n.º 1
0
ssize_t
ceph_os_getxattr(const char *path, const char *name,
void *value, size_t size)
{
	ssize_t error = -1;

#if defined(__FreeBSD__)
	if (value == NULL || size == 0) {
		error = extattr_get_file(path, EXTATTR_NAMESPACE_USER, name, value,
		    size);
	} else {
		error = extattr_get_file(path, EXTATTR_NAMESPACE_USER, name, NULL,
		    0);
		if (error > 0) {
			if (error > size) {
				errno = ERANGE;
				error = -1;
			} else  {
				error = extattr_get_file(path, EXTATTR_NAMESPACE_USER,
				    name, value, size);
			}
		}
	}
#elif defined(__linux__)
	error = getxattr(path, name, value, size);
#elif defined(DARWIN)
	error = getxattr(path, name, value, size, 0);
#endif

	return (error);
}
Exemplo n.º 2
0
Arquivo: xattr.c Projeto: 0day-ci/ceph
ssize_t
ceph_os_getxattr(const char *path, const char *name,
void *value, size_t size)
{
	ssize_t error = -1;

#if defined(__FreeBSD__)
	if (value == NULL || size == 0) {
		error = extattr_get_file(path, EXTATTR_NAMESPACE_USER, name, value,
		    size);
	} else {
		error = extattr_get_file(path, EXTATTR_NAMESPACE_USER, name, NULL,
		    0);
		if (error > 0) {
			if (error > size) {
				errno = ERANGE;
				error = -1;
			} else  {
				error = extattr_get_file(path, EXTATTR_NAMESPACE_USER,
				    name, value, size);
			}
		}
	}
#elif defined(__linux__)
	error = getxattr(path, name, value, size);
#elif defined(DARWIN)
	error = getxattr(path, name, value, size, 0 /* position  */, 0);
	/* ENOATTR and ENODATA have different values */
	if (error < 0 && errno == ENOATTR)
		errno = ENODATA;
#endif

	return (error);
}
Exemplo n.º 3
0
ssize_t sys_getxattr (const char *path, const char *uname, void *value, size_t size)
{
	const char *name = prefix(uname);

#if defined(HAVE_GETXATTR)
#ifndef XATTR_ADD_OPT
	return getxattr(path, name, value, size);
#else
	int options = 0;
	return getxattr(path, name, value, size, 0, options);
#endif
#elif defined(HAVE_GETEA)
	return getea(path, name, value, size);
#elif defined(HAVE_EXTATTR_GET_FILE)
	ssize_t retval;
	/*
	 * The BSD implementation has a nasty habit of silently truncating
	 * the returned value to the size of the buffer, so we have to check
	 * that the buffer is large enough to fit the returned value.
	 */
	if((retval = extattr_get_file(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0)) >= 0) {
        if (size == 0)
            /* size == 0 means only return size */
            return retval;
		if (retval > size) {
			errno = ERANGE;
			return -1;
		}
		if ((retval = extattr_get_file(path, EXTATTR_NAMESPACE_USER, uname, value, size)) >= 0)
			return retval;
	}

	LOG(log_maxdebug, logtype_default, "sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno));
	return -1;
#elif defined(HAVE_ATTR_GET)
	int retval, flags = 0;
	int valuelength = (int)size;
	char *attrname = strchr(name,'.') + 1;
	
	if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;

	retval = attr_get(path, attrname, (char *)value, &valuelength, flags);

	return retval ? retval : valuelength;
#elif defined(HAVE_ATTROPEN)
	ssize_t ret = -1;
	int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
	if (attrfd >= 0) {
		ret = solaris_read_xattr(attrfd, value, size);
		close(attrfd);
	}
	return ret;
#else
	errno = ENOSYS;
	return -1;
#endif
}
Exemplo n.º 4
0
ssize_t getAttr( const char* path, const char* attrname, void* data, size_t nbytes ) {
    ssize_t ret = extattr_get_file( path, EXTATTR_NAMESPACE_USER, attrname, data, nbytes );

    checkReturnValue( "getAttr", ret );

    return ret;
}
Exemplo n.º 5
0
static void
clear_dosattrib(struct windows_acl_info *w, const char *path)
{
	if (extattr_get_file(path, EXTATTR_NAMESPACE_USER,
		"DOSATTRIB", NULL, 0) > 0) {
		if (extattr_delete_file(path,
			EXTATTR_NAMESPACE_USER, "DOSATTRIB") < 0) 
			warn("%s: extattr_delete_file() failed", path);
	}
}
Exemplo n.º 6
0
static int stat_cache_attr_get(buffer *buf, char *name) {
	ssize_t attrlen;

	buffer_prepare_copy(buf, 1023);

	if (-1 != (attrlen = extattr_get_file(name, EXTATTR_NAMESPACE_USER, "Content-Type", buf->ptr, buf->size - 1))) {
		buf->used = attrlen + 1;
		buf->ptr[attrlen] = '\0';
		return 0;
	}
	return -1;
}
Exemplo n.º 7
0
static ssize_t xattr_getxattr(const char *path, const char *name,
                              void *value, ssize_t size, u_int32_t position,
                              int options)
{
    if (position != 0 ||
        !(options == 0 || options == XATTR_XATTR_NOFOLLOW)) {
        return -1;
    }

    if (options & XATTR_XATTR_NOFOLLOW) {
        return extattr_get_link(path, EXTATTR_NAMESPACE_USER,
                                name, value, size);
    }
    else {
        return extattr_get_file(path, EXTATTR_NAMESPACE_USER,
                                name, value, size);
    }
}
Exemplo n.º 8
0
int sys_setxattr (const char *path, const char *uname, const void *value, size_t size, int flags)
{
	const char *name = prefix(uname);
#if defined(HAVE_SETXATTR)
#ifndef XATTR_ADD_OPT
	return setxattr(path, name, value, size, flags);
#else
	int options = 0;
	return setxattr(path, name, value, size, 0, options);
#endif
#elif defined(HAVE_SETEA)
	return setea(path, name, value, size, flags);
#elif defined(HAVE_EXTATTR_SET_FILE)
	int retval = 0;
	if (flags) {
		/* Check attribute existence */
		retval = extattr_get_file(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0);
		if (retval < 0) {
			/* REPLACE attribute, that doesn't exist */
			if (flags & XATTR_REPLACE && errno == ENOATTR) {
				errno = ENOATTR;
				return -1;
			}
			/* Ignore other errors */
		}
		else {
			/* CREATE attribute, that already exists */
			if (flags & XATTR_CREATE) {
				errno = EEXIST;
				return -1;
			}
		}
	}
	retval = extattr_set_file(path, EXTATTR_NAMESPACE_USER, uname, value, size);
	return (retval < 0) ? -1 : 0;
#elif defined(HAVE_ATTR_SET)
	int myflags = 0;
	char *attrname = strchr(name,'.') + 1;
	
	if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
	if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
	if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;

	return attr_set(path, attrname, (const char *)value, size, myflags);
#elif defined(HAVE_ATTROPEN)
	int ret = -1;
	int myflags = O_RDWR;
	int attrfd;
	if (flags & XATTR_CREATE) myflags |= O_EXCL;
	if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
	attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
	if (attrfd >= 0) {
		ret = solaris_write_xattr(attrfd, value, size);
		close(attrfd);
	}
	return ret;
#else
	errno = ENOSYS;
	return -1;
#endif
}
Exemplo n.º 9
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);
}
Exemplo n.º 10
0
static int http_list_directory(server *srv, connection *con, plugin_data *p, buffer *dir) {
	DIR *dp;
	buffer *out;
	struct dirent *dent;
	struct stat st;
	char *path, *path_file;
	size_t i;
	int hide_dotfiles = p->conf.hide_dot_files;
	dirls_list_t dirs, files, *list;
	dirls_entry_t *tmp;
	char sizebuf[sizeof("999.9K")];
	char datebuf[sizeof("2005-Jan-01 22:23:24")];
	size_t k;
	const char *content_type;
	long name_max;
#if defined(HAVE_XATTR) || defined(HAVE_EXTATTR)
	char attrval[128];
	int attrlen;
#endif
#ifdef HAVE_LOCALTIME_R
	struct tm tm;
#endif

	if (buffer_string_is_empty(dir)) return -1;

	i = buffer_string_length(dir);

#ifdef HAVE_PATHCONF
	if (0 >= (name_max = pathconf(dir->ptr, _PC_NAME_MAX))) {
		/* some broken fs (fuse) return 0 instead of -1 */
#ifdef NAME_MAX
		name_max = NAME_MAX;
#else
		name_max = 255; /* stupid default */
#endif
	}
#elif defined __WIN32
	name_max = FILENAME_MAX;
#else
	name_max = NAME_MAX;
#endif

	path = malloc(i + name_max + 1);
	force_assert(NULL != path);
	memcpy(path, dir->ptr, i+1);
	path_file = path + i;

	if (NULL == (dp = opendir(path))) {
		log_error_write(srv, __FILE__, __LINE__, "sbs",
			"opendir failed:", dir, strerror(errno));

		free(path);
		return -1;
	}

	dirs.ent   = (dirls_entry_t**) malloc(sizeof(dirls_entry_t*) * DIRLIST_BLOB_SIZE);
	force_assert(dirs.ent);
	dirs.size  = DIRLIST_BLOB_SIZE;
	dirs.used  = 0;
	files.ent  = (dirls_entry_t**) malloc(sizeof(dirls_entry_t*) * DIRLIST_BLOB_SIZE);
	force_assert(files.ent);
	files.size = DIRLIST_BLOB_SIZE;
	files.used = 0;

	while ((dent = readdir(dp)) != NULL) {
		unsigned short exclude_match = 0;

		if (dent->d_name[0] == '.') {
			if (hide_dotfiles)
				continue;
			if (dent->d_name[1] == '\0')
				continue;
			if (dent->d_name[1] == '.' && dent->d_name[2] == '\0')
				continue;
		}

		if (p->conf.hide_readme_file && !buffer_string_is_empty(p->conf.show_readme)) {
			if (strcmp(dent->d_name, p->conf.show_readme->ptr) == 0)
				continue;
		}
		if (p->conf.hide_header_file && !buffer_string_is_empty(p->conf.show_header)) {
			if (strcmp(dent->d_name, p->conf.show_header->ptr) == 0)
				continue;
		}

		/* compare d_name against excludes array
		 * elements, skipping any that match.
		 */
#ifdef HAVE_PCRE_H
		for(i = 0; i < p->conf.excludes->used; i++) {
			int n;
#define N 10
			int ovec[N * 3];
			pcre *regex = p->conf.excludes->ptr[i]->regex;

			if ((n = pcre_exec(regex, NULL, dent->d_name,
				    strlen(dent->d_name), 0, 0, ovec, 3 * N)) < 0) {
				if (n != PCRE_ERROR_NOMATCH) {
					log_error_write(srv, __FILE__, __LINE__, "sd",
						"execution error while matching:", n);

					/* aborting would require a lot of manual cleanup here.
					 * skip instead (to not leak names that break pcre matching)
					 */
					exclude_match = 1;
					break;
				}
			}
			else {
				exclude_match = 1;
				break;
			}
		}

		if (exclude_match) {
			continue;
		}
#endif

		i = strlen(dent->d_name);

		/* NOTE: the manual says, d_name is never more than NAME_MAX
		 *       so this should actually not be a buffer-overflow-risk
		 */
		if (i > (size_t)name_max) continue;

		memcpy(path_file, dent->d_name, i + 1);
		if (stat(path, &st) != 0)
			continue;

		list = &files;
		if (S_ISDIR(st.st_mode))
			list = &dirs;

		if (list->used == list->size) {
			list->size += DIRLIST_BLOB_SIZE;
			list->ent   = (dirls_entry_t**) realloc(list->ent, sizeof(dirls_entry_t*) * list->size);
			force_assert(list->ent);
		}

		tmp = (dirls_entry_t*) malloc(sizeof(dirls_entry_t) + 1 + i);
		tmp->mtime = st.st_mtime;
		tmp->size  = st.st_size;
		tmp->namelen = i;
		memcpy(DIRLIST_ENT_NAME(tmp), dent->d_name, i + 1);

		list->ent[list->used++] = tmp;
	}
	closedir(dp);

	if (dirs.used) http_dirls_sort(dirs.ent, dirs.used);

	if (files.used) http_dirls_sort(files.ent, files.used);

	out = buffer_init();
	http_list_directory_header(srv, con, p, out);

	/* directories */
	for (i = 0; i < dirs.used; i++) {
		tmp = dirs.ent[i];

#ifdef HAVE_LOCALTIME_R
		localtime_r(&(tmp->mtime), &tm);
		strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", &tm);
#else
		strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", localtime(&(tmp->mtime)));
#endif

		buffer_append_string_len(out, CONST_STR_LEN("<tr class=\"d\"><td class=\"n\"><a href=\""));
		buffer_append_string_encoded(out, DIRLIST_ENT_NAME(tmp), tmp->namelen, ENCODING_REL_URI_PART);
		buffer_append_string_len(out, CONST_STR_LEN("/\">"));
		buffer_append_string_encoded(out, DIRLIST_ENT_NAME(tmp), tmp->namelen, ENCODING_MINIMAL_XML);
		buffer_append_string_len(out, CONST_STR_LEN("</a>/</td><td class=\"m\">"));
		buffer_append_string_len(out, datebuf, sizeof(datebuf) - 1);
		buffer_append_string_len(out, CONST_STR_LEN("</td><td class=\"s\">- &nbsp;</td><td class=\"t\">Directory</td></tr>\n"));

		free(tmp);
	}

	/* files */
	for (i = 0; i < files.used; i++) {
		tmp = files.ent[i];

		content_type = NULL;
#if defined(HAVE_XATTR)
		if (con->conf.use_xattr) {
			memcpy(path_file, DIRLIST_ENT_NAME(tmp), tmp->namelen + 1);
			attrlen = sizeof(attrval) - 1;
			if (attr_get(path, srv->srvconf.xattr_name->ptr, attrval, &attrlen, 0) == 0) {
				attrval[attrlen] = '\0';
				content_type = attrval;
			}
		}
#elif defined(HAVE_EXTATTR)
		if (con->conf.use_xattr) {
			memcpy(path_file, DIRLIST_ENT_NAME(tmp), tmp->namelen + 1);
			if(-1 != (attrlen = extattr_get_file(path, EXTATTR_NAMESPACE_USER, srv->srvconf.xattr_name->ptr, attrval, sizeof(attrval)-1))) {
				attrval[attrlen] = '\0';
				content_type = attrval;
			}
		}
#endif

		if (content_type == NULL) {
			content_type = "application/octet-stream";
			for (k = 0; k < con->conf.mimetypes->used; k++) {
				data_string *ds = (data_string *)con->conf.mimetypes->data[k];
				size_t ct_len;

				if (buffer_is_empty(ds->key))
					continue;

				ct_len = buffer_string_length(ds->key);
				if (tmp->namelen < ct_len)
					continue;

				if (0 == strncasecmp(DIRLIST_ENT_NAME(tmp) + tmp->namelen - ct_len, ds->key->ptr, ct_len)) {
					content_type = ds->value->ptr;
					break;
				}
			}
		}

#ifdef HAVE_LOCALTIME_R
		localtime_r(&(tmp->mtime), &tm);
		strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", &tm);
#else
		strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", localtime(&(tmp->mtime)));
#endif
		http_list_directory_sizefmt(sizebuf, sizeof(sizebuf), tmp->size);

		buffer_append_string_len(out, CONST_STR_LEN("<tr><td class=\"n\"><a href=\""));
		buffer_append_string_encoded(out, DIRLIST_ENT_NAME(tmp), tmp->namelen, ENCODING_REL_URI_PART);
		buffer_append_string_len(out, CONST_STR_LEN("\">"));
		buffer_append_string_encoded(out, DIRLIST_ENT_NAME(tmp), tmp->namelen, ENCODING_MINIMAL_XML);
		buffer_append_string_len(out, CONST_STR_LEN("</a></td><td class=\"m\">"));
		buffer_append_string_len(out, datebuf, sizeof(datebuf) - 1);
		buffer_append_string_len(out, CONST_STR_LEN("</td><td class=\"s\">"));
		buffer_append_string(out, sizebuf);
		buffer_append_string_len(out, CONST_STR_LEN("</td><td class=\"t\">"));
		buffer_append_string(out, content_type);
		buffer_append_string_len(out, CONST_STR_LEN("</td></tr>\n"));

		free(tmp);
	}

	free(files.ent);
	free(dirs.ent);
	free(path);

	http_list_directory_footer(srv, con, p, out);

	/* Insert possible charset to Content-Type */
	if (buffer_string_is_empty(p->conf.encoding)) {
		response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
	} else {
		buffer_copy_string_len(p->content_charset, CONST_STR_LEN("text/html; charset="));
		buffer_append_string_buffer(p->content_charset, p->conf.encoding);
		response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(p->content_charset));
	}

	con->file_finished = 1;
	chunkqueue_append_buffer(con->write_queue, out);
	buffer_free(out);

	return 0;
}
Exemplo n.º 11
0
/* Obtain the Extended Attributes and/or the ACLs of the given file in a form
   that is ready for aaip_encode().
   @param path          Path to the file
   @param num_attrs     Will return the number of name-value pairs
   @param names         Will return an array of pointers to 0-terminated names
   @param value_lengths Will return an arry with the lenghts of values
   @param values        Will return an array of pointers to 8-bit values
   @param flag          Bitfield for control purposes
                        bit0=  obtain ACL (access and eventually default)
                        bit1=  use numeric ACL qualifiers rather than names
                        bit2=  do not obtain attributes other than ACL
                        bit3=  do not ignore eventual non-user attributes
                               I.e. those with a name which does not begin
                               by "user."
                        bit4=  do not return trivial ACL that matches st_mode
                        bit5=  in case of symbolic link: inquire link target
                        bit15= free memory of names, value_lengths, values
   @return              >0  ok
                        <=0 error
                        -1= out of memory
                        -2= program error with prediction of result size
                        -3= error with conversion of name to uid or gid
*/
int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
                       size_t **value_lengths, char ***values, int flag)
{
 int ret;
 ssize_t i, num_names= 0, acl_names= 0;

#ifdef Libisofs_with_aaip_acL
 unsigned char *a_acl= NULL;
 char *a_acl_text= NULL;
 size_t a_acl_len= 0;
#endif
#ifdef Libisofs_with_freebsd_extattR
 char *list= NULL, *user_list= NULL, *sys_list= NULL, *namept;
 ssize_t value_ret, retry= 0, list_size= 0, user_list_size= 0;
 ssize_t sys_list_size= 0;
 int attrnamespace;
#endif

 if(flag & (1 << 15)) { /* Free memory */
   {ret= 1; goto ex;}
 }

 *num_attrs= 0;
 *names= NULL;
 *value_lengths= NULL;
 *values= NULL;

 /* Set up arrays */

#ifdef Libisofs_with_freebsd_extattR

 if(!(flag & 4)) { /* Get extattr names */

   /* Linux  : Names are encoded as name NUL
      FreeBSD: Names are encoded as length_byte:chars (no NUL)
      AAIP demands names not to contain NUL bytes. 
   */

   /* Obtain lists of names
      Must be done separately for namespaces. See man 9 extattr :
      EXTATTR_NAMESPACE_USER , EXTATTR_NAMESPACE_SYSTEM
      Must then be marked by "user." and "system." for libisofs use.
   */
   ret= aaip_extattr_make_list(path, EXTATTR_NAMESPACE_USER,
                               &user_list, &user_list_size, flag & 32);
   if(ret <= 0)
     {ret= -1; goto ex;}
   if(flag & 8) {
     ret= aaip_extattr_make_list(path, EXTATTR_NAMESPACE_SYSTEM,
                                 &sys_list, &sys_list_size, flag & 32);
     if(ret <= 0)
       {ret= -1; goto ex;}
   }

   /* Check for NUL in names, convert into a linuxish list of namespace.name */
   ret= aaip_extattr_make_namelist(path, "user", user_list, user_list_size,
                                   &list, &list_size, &num_names, 0);
   if(ret <= 0)
     goto ex;
   ret= aaip_extattr_make_namelist(path, "system", sys_list, sys_list_size,
                                   &list, &list_size, &num_names, 1);
   if(ret <= 0)
     goto ex;
 }

#endif /* Libisofs_with_freebsd_extattR */

#ifdef Libisofs_with_aaip_acL
 if(flag & 1) {
   num_names++;
   acl_names= 1;
 }
#endif
 
 if(num_names == 0)
   {ret= 1; goto ex;}
 (*names)= calloc(num_names, sizeof(char *));
 (*value_lengths)= calloc(num_names, sizeof(size_t));
 (*values)= calloc(num_names, sizeof(char *));
 if(*names == NULL || *value_lengths == NULL || *values == NULL)
   {ret= -1; goto ex;}

 for(i= 0; i < num_names; i++) {
   (*names)[i]= NULL;
   (*values)[i]= NULL;
   (*value_lengths)[i]= 0;
 }

#ifdef Libisofs_with_freebsd_extattR

 if(!(flag & 4)) { /* Get xattr values */
   for(i= 0; i < list_size && (size_t) num_names - acl_names > *num_attrs;
       i+= strlen(list + i) + 1) {
     if(!(flag & 8))
       if(strncmp(list + i, "user.", 5))
   continue;
     (*names)[(*num_attrs)++]= strdup(list + i);
     if((*names)[(*num_attrs) - 1] == NULL)
       {ret= -1; goto ex;}
   }
 
   for(i= 0; (size_t) i < *num_attrs; i++) {
     if(strncmp((*names)[i], "user.", 5) == 0) {
       attrnamespace= EXTATTR_NAMESPACE_USER;
       namept= (*names)[i] + 5;
     } else {
       if(!(flag & 8))
   continue;
       attrnamespace= EXTATTR_NAMESPACE_SYSTEM;
       namept= (*names)[i] + 7;
     }
     /* Predict length of value */
     if(flag & 32) /* follow link */
       value_ret= extattr_get_file(path, attrnamespace, namept,
                                   NULL, (size_t) 0);
     else
       value_ret= extattr_get_link(path, attrnamespace, namept,
                                   NULL, (size_t) 0);
     if(value_ret == -1)
 continue;

     (*values)[i]= calloc(value_ret + 1, 1);
     if((*values)[i] == NULL)
       {ret= -1; goto ex;}

     /* Obtain value */
     if(flag & 32) /* follow link */
       value_ret= extattr_get_file(path, attrnamespace, namept,
                                   (*values)[i], (size_t) value_ret);
     else
       value_ret= extattr_get_link(path, attrnamespace, namept,
                                   (*values)[i], (size_t) value_ret);
     if(value_ret == -1) { /* there could be a race condition */

       if(retry++ > 5)
         {ret= -1; goto ex;}
       i--;
 continue;
     }
     (*value_lengths)[i]= value_ret;
     retry= 0;
   }
 }

#endif /* Libisofs_with_freebsd_extattR */

#ifdef Libisofs_with_aaip_acL

 if(flag & 1) { /* Obtain ACL */
  /* access-ACL */
   aaip_get_acl_text(path, &a_acl_text, flag & (16 | 32));
   if(a_acl_text == NULL)
     {ret= 1; goto ex;} /* empty ACL / only st_mode info was found in ACL */
   ret= aaip_encode_acl(a_acl_text, (mode_t) 0, &a_acl_len, &a_acl, flag & 2);
   if(ret <= 0)
     goto ex;

   /* Note: There are no default-ACL in FreeBSD */

   /* Set as attribute with empty name */;
   (*names)[*num_attrs]= strdup("");
   if((*names)[*num_attrs] == NULL)
     {ret= -1; goto ex;}
   (*values)[*num_attrs]= (char *) a_acl;
   a_acl= NULL;
   (*value_lengths)[*num_attrs]= a_acl_len;
   (*num_attrs)++;
 }

#endif /* Libisofs_with_aaip_acL */

 ret= 1;
ex:;
#ifdef Libisofs_with_aaip_acL
 if(a_acl != NULL)
   free(a_acl);
 if(a_acl_text != NULL)
   aaip_get_acl_text("", &a_acl_text, 1 << 15); /* free */
#endif
#ifdef Libisofs_with_freebsd_extattR
 if(list != NULL)
   free(list);
 if(user_list != NULL)
   free(user_list);
 if(sys_list != NULL)
   free(sys_list);
#endif

 if(ret <= 0 || (flag & (1 << 15))) {
   if(*names != NULL) {
     for(i= 0; (size_t) i < *num_attrs; i++)
       free((*names)[i]);
     free(*names);
   }
   *names= NULL;
   if(*value_lengths != NULL)
     free(*value_lengths);
   *value_lengths= NULL;
   if(*values != NULL) {
     for(i= 0; (size_t) i < *num_attrs; i++)
       free((*values)[i]);
     free(*values);
   }
   *values= NULL;
   *num_attrs= 0;
 }
 return(ret);
}
Exemplo n.º 12
0
/*
 * This program displays the location information of a data storage file
 * for a given file on a MetaData Server (MDS) in a pNFS service.  This program
 * must be run on the MDS and the file argument must be a file in a local
 * file system that has been exported for the pNFS service.
 */
int
main(int argc, char *argv[])
{
	struct addrinfo *res, *ad, *newres;
	struct sockaddr_in *sin, adsin;
	struct sockaddr_in6 *sin6, adsin6;
	char hostn[2 * NI_MAXHOST + 2], *cp;
	struct pnfsdsfile dsfile[NFSDEV_MAXMIRRORS];
	int ch, dosetxattr, i, mirrorcnt, mirrorit, quiet, zerods, zerofh;
	in_port_t tport;
	ssize_t xattrsize, xattrsize2;

	zerods = 0;
	zerofh = 0;
	mirrorit = 0;
	quiet = 0;
	dosetxattr = 0;
	res = NULL;
	newres = NULL;
	cp = NULL;
	while ((ch = getopt_long(argc, argv, "c:m:qr:s:z", longopts, NULL)) !=
	    -1) {
		switch (ch) {
		case 'c':
			/* Replace the first DS server with the second one. */
			if (zerofh != 0 || zerods != 0 || mirrorit != 0 ||
			    newres != NULL || res != NULL)
				errx(1, "-c, -m, -r, -s and -z are mutually "
				    "exclusive and only can be used once");
			strlcpy(hostn, optarg, 2 * NI_MAXHOST + 2);
			cp = strchr(hostn, ',');
			if (cp == NULL)
				errx(1, "Bad -c argument %s", hostn);
			*cp = '\0';
			if (getaddrinfo(hostn, NULL, NULL, &res) != 0)
				errx(1, "Can't get IP# for %s", hostn);
			*cp++ = ',';
			if (getaddrinfo(cp, NULL, NULL, &newres) != 0)
				errx(1, "Can't get IP# for %s", cp);
			break;
		case 'm':
			/* Add 0.0.0.0 entries up to mirror level. */
			if (zerofh != 0 || zerods != 0 || mirrorit != 0 ||
			    newres != NULL || res != NULL)
				errx(1, "-c, -m, -r, -s and -z are mutually "
				    "exclusive and only can be used once");
			mirrorit = atoi(optarg);
			if (mirrorit < 2 || mirrorit > NFSDEV_MAXMIRRORS)
				errx(1, "-m %d out of range", mirrorit);
			break;
		case 'q':
			quiet = 1;
			break;
		case 'r':
			/* Reset the DS server in a mirror with 0.0.0.0. */
			if (zerofh != 0 || zerods != 0 || mirrorit != 0 ||
			    newres != NULL || res != NULL)
				errx(1, "-c, -m, -r, -s and -z are mutually "
				    "exclusive and only can be used once");
			zerods = 1;
			/* Translate the server name to an IP address. */
			if (getaddrinfo(optarg, NULL, NULL, &res) != 0)
				errx(1, "Can't get IP# for %s", optarg);
			break;
		case 's':
			/* Translate the server name to an IP address. */
			if (zerods != 0 || mirrorit != 0 || newres != NULL ||
			    res != NULL)
				errx(1, "-c, -m and -r are mutually exclusive "
				    "from use with -s and -z");
			if (getaddrinfo(optarg, NULL, NULL, &res) != 0)
				errx(1, "Can't get IP# for %s", optarg);
			break;
		case 'z':
			if (zerofh != 0 || zerods != 0 || mirrorit != 0 ||
			    newres != NULL)
				errx(1, "-c, -m and -r are mutually exclusive "
				    "from use with -s and -z");
			zerofh = 1;
			break;
		default:
			usage();
		}
	}
	argc -= optind;
	if (argc != 1)
		usage();
	argv += optind;

	/*
	 * The host address and directory where the data storage file is
	 * located is in the extended attribute "pnfsd.dsfile".
	 */
	xattrsize = extattr_get_file(*argv, EXTATTR_NAMESPACE_SYSTEM,
	    "pnfsd.dsfile", dsfile, sizeof(dsfile));
	mirrorcnt = xattrsize / sizeof(struct pnfsdsfile);
	xattrsize2 = mirrorcnt * sizeof(struct pnfsdsfile);
	if (mirrorcnt < 1 || xattrsize != xattrsize2)
		err(1, "Can't get extattr pnfsd.dsfile for %s", *argv);

	if (quiet == 0)
		printf("%s:\t", *argv);
	for (i = 0; i < mirrorcnt; i++) {
		if (i > 0 && quiet == 0)
			printf("\t");
		/* Do the zerofh option. You must be root. */
		if (zerofh != 0) {
			if (geteuid() != 0)
				errx(1, "Must be root/su to zerofh");
	
			/*
			 * Do it for the server specified by -s/--ds or all
			 * servers, if -s/--ds was not specified.
			 */
			sin = &dsfile[i].dsf_sin;
			sin6 = &dsfile[i].dsf_sin6;
			ad = res;
			while (ad != NULL) {
				if (ad->ai_addr->sa_family == AF_INET &&
				    sin->sin_family == AF_INET &&
				    ad->ai_addrlen >= sizeof(adsin)) {
					memcpy(&adsin, ad->ai_addr,
					    sizeof(adsin));
					if (sin->sin_addr.s_addr ==
					    adsin.sin_addr.s_addr)
						break;
				}
				if (ad->ai_addr->sa_family == AF_INET6 &&
				    sin6->sin6_family == AF_INET6 &&
				    ad->ai_addrlen >= sizeof(adsin6)) {
					memcpy(&adsin6, ad->ai_addr,
					    sizeof(adsin6));
					if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
					    &adsin6.sin6_addr))
						break;
				}
				ad = ad->ai_next;
			}
			if (res == NULL || ad != NULL) {
				memset(&dsfile[i].dsf_fh, 0, sizeof(fhandle_t));
				dosetxattr = 1;
			}
		}
	
		/* Do the zerods option. You must be root. */
		if (zerods != 0 && mirrorcnt > 1) {
			if (geteuid() != 0)
				errx(1, "Must be root/su to zerods");
	
			/*
			 * Do it for the server specified.
			 */
			sin = &dsfile[i].dsf_sin;
			sin6 = &dsfile[i].dsf_sin6;
			ad = res;
			while (ad != NULL) {
				if (ad->ai_addr->sa_family == AF_INET &&
				    sin->sin_family == AF_INET &&
				    ad->ai_addrlen >= sizeof(adsin)) {
					memcpy(&adsin, ad->ai_addr,
					    sizeof(adsin));
					if (sin->sin_addr.s_addr ==
					    adsin.sin_addr.s_addr)
						break;
				}
				if (ad->ai_addr->sa_family == AF_INET6 &&
				    sin6->sin6_family == AF_INET6 &&
				    ad->ai_addrlen >= sizeof(adsin6)) {
					memcpy(&adsin6, ad->ai_addr,
					    sizeof(adsin6));
					if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
					    &adsin6.sin6_addr))
						break;
				}
				ad = ad->ai_next;
			}
			if (ad != NULL) {
				sin->sin_family = AF_INET;
				sin->sin_len = sizeof(*sin);
				sin->sin_port = 0;
				sin->sin_addr.s_addr = 0;
				dosetxattr = 1;
			}
		}
	
		/* Do the -c option to replace the DS host address. */
		if (newres != NULL) {
			if (geteuid() != 0)
				errx(1, "Must be root/su to replace the host"
				    " addr");
	
			/*
			 * Check that the old host address matches.
			 */
			sin = &dsfile[i].dsf_sin;
			sin6 = &dsfile[i].dsf_sin6;
			ad = res;
			while (ad != NULL) {
				if (ad->ai_addr->sa_family == AF_INET &&
				    sin->sin_family == AF_INET &&
				    ad->ai_addrlen >= sizeof(adsin)) {
					memcpy(&adsin, ad->ai_addr,
					    sizeof(adsin));
					if (sin->sin_addr.s_addr ==
					    adsin.sin_addr.s_addr)
						break;
				}
				if (ad->ai_addr->sa_family == AF_INET6 &&
				    sin6->sin6_family == AF_INET6 &&
				    ad->ai_addrlen >= sizeof(adsin6)) {
					memcpy(&adsin6, ad->ai_addr,
					    sizeof(adsin6));
					if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
					    &adsin6.sin6_addr))
						break;
				}
				ad = ad->ai_next;
			}
			if (ad != NULL) {
				if (sin->sin_family == AF_INET)
					tport = sin->sin_port;
				else
					tport = sin6->sin6_port;
				/*
				 * We have a match, so replace it with the first
				 * AF_INET or AF_INET6 address in the newres
				 * list.
				 */
				while (newres->ai_addr->sa_family != AF_INET &&
				    newres->ai_addr->sa_family != AF_INET6) {
					newres = newres->ai_next;
					if (newres == NULL)
						errx(1, "Hostname %s has no"
						    " IP#", cp);
				}
				if (newres->ai_addr->sa_family == AF_INET) {
					memcpy(sin, newres->ai_addr,
					    sizeof(*sin));
					sin->sin_port = tport;
				} else if (newres->ai_addr->sa_family ==
				    AF_INET6) {
					memcpy(sin6, newres->ai_addr,
					    sizeof(*sin6));
					sin6->sin6_port = tport;
				}
				dosetxattr = 1;
			}
		}
	
		if (quiet == 0) {
			/* Translate the IP address to a hostname. */
			if (getnameinfo((struct sockaddr *)&dsfile[i].dsf_sin,
			    dsfile[i].dsf_sin.sin_len, hostn, sizeof(hostn),
			    NULL, 0, 0) < 0)
				err(1, "Can't get hostname");
			printf("%s\tds%d/%s", hostn, dsfile[i].dsf_dir,
			    dsfile[i].dsf_filename);
		}
	}
	/* Add entrie(s) with IP address set to 0.0.0.0, as required. */
	for (i = mirrorcnt; i < mirrorit; i++) {
		dsfile[i] = dsfile[0];
		dsfile[i].dsf_sin.sin_family = AF_INET;
		dsfile[i].dsf_sin.sin_len = sizeof(struct sockaddr_in);
		dsfile[i].dsf_sin.sin_addr.s_addr = 0;
		dsfile[i].dsf_sin.sin_port = 0;
		if (quiet == 0) {
			/* Print out the 0.0.0.0 entry. */
			printf("\t0.0.0.0\tds%d/%s", dsfile[i].dsf_dir,
			    dsfile[i].dsf_filename);
		}
	}
	if (mirrorit > mirrorcnt) {
		xattrsize = mirrorit * sizeof(struct pnfsdsfile);
		dosetxattr = 1;
	}
	if (quiet == 0)
		printf("\n");

	if (dosetxattr != 0 && extattr_set_file(*argv, EXTATTR_NAMESPACE_SYSTEM,
	    "pnfsd.dsfile", dsfile, xattrsize) != xattrsize)
		err(1, "Can't set pnfsd.dsfile");
}
Exemplo n.º 13
0
ssize_t rep_getxattr (const char *path, const char *name, void *value, size_t size)
{
#if defined(HAVE_GETXATTR)
#ifndef XATTR_ADDITIONAL_OPTIONS
	return getxattr(path, name, value, size);
#else

/* So that we do not recursivly call this function */
#undef getxattr
	int options = 0;
	return getxattr(path, name, value, size, 0, options);
#endif
#elif defined(HAVE_GETEA)
	return getea(path, name, value, size);
#elif defined(HAVE_EXTATTR_GET_FILE)
	char *s;
	ssize_t retval;
	int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
		EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
	const char *attrname = ((s=strchr(name, '.')) == NULL) ? name : s + 1;
	/*
	 * The BSD implementation has a nasty habit of silently truncating
	 * the returned value to the size of the buffer, so we have to check
	 * that the buffer is large enough to fit the returned value.
	 */
	if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
		if (size == 0) {
			return retval;
		} else if (retval > size) {
			errno = ERANGE;
			return -1;
		}
		if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
			return retval;
	}

	return -1;
#elif defined(HAVE_ATTR_GET)
	int retval, flags = 0;
	int valuelength = (int)size;
	char *attrname = strchr(name,'.') + 1;

	if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;

	retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
	if (size == 0 && retval == -1 && errno == E2BIG) {
		return valuelength;
	}

	return retval ? retval : valuelength;
#elif defined(HAVE_ATTROPEN)
	ssize_t ret = -1;
	int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
	if (attrfd >= 0) {
		ret = solaris_read_xattr(attrfd, value, size);
		close(attrfd);
	}
	return ret;
#else
	errno = ENOSYS;
	return -1;
#endif
}