void
priv_vfs_extattr_system(int asroot, int injail, struct test *test)
{
	ssize_t ret;
	int error;

	ret = extattr_set_file(fpath, EA_NAMESPACE, EA_NAME, EA_DATA,
	    EA_SIZE);
	if (ret < 0)
		error = -1;
	else if (ret == EA_SIZE)
		error = 0;
	else
		err(-1, "priv_vfs_extattr_system: set returned %zd", ret);
	if (asroot && injail)
		expect("priv_vfs_extattr_system(asroot, injail)", error, -1,
		    EPERM);
	if (asroot && !injail)
		expect("priv_vfs_extattr_system(asroot, !injail)", error, 0,
		    0);
	if (!asroot && injail)
		expect("priv_vfs_extattr_system(!asroot, injail)", error, -1,
		    EPERM);
	if (!asroot && !injail)
		expect("priv_vfs_extattr_system(!asroot, !injail)", error,
		    -1, EPERM);
}
Example #2
0
ssize_t setAttr( const char* path, const char *attrname, const void* data, size_t nbytes ) {
    ssize_t ret = extattr_set_file( path, EXTATTR_NAMESPACE_USER, attrname, data, nbytes );

    checkReturnValue( "setAttr", ret );

    return ret;
}
Example #3
0
/*
 * Set attributes for a file.
 */
void
set_extattr_file(char *name, void *buf, int size)
{
	struct extattr *eap, *eaend;

	vprintf(stdout, "Set attributes for %s:", name);
	eaend = buf + size;
	for (eap = buf; eap < eaend; eap = EXTATTR_NEXT(eap)) {
		/*
		 * Make sure this entry is complete.
		 */
		if (EXTATTR_NEXT(eap) > eaend || eap->ea_length <= 0) {
			dprintf(stdout, "\n\t%scorrupted",
				eap == buf ? "" : "remainder ");
			break;
		}
		if (eap->ea_namespace == EXTATTR_NAMESPACE_EMPTY)
			continue;
		vprintf(stdout, "\n\t%s, (%d bytes), %*s",
			namespace_names[eap->ea_namespace], eap->ea_length,
			eap->ea_namelength, eap->ea_name);
		/*
		 * First we try the general attribute setting interface.
		 * However, some attributes can only be set by root or
		 * by using special interfaces (for example, ACLs).
		 */
		if (extattr_set_file(name, eap->ea_namespace, eap->ea_name,
		    EXTATTR_CONTENT(eap), EXTATTR_CONTENT_SIZE(eap)) != -1) {
			dprintf(stdout, " (set using extattr_set_file)");
			continue;
		}
		/*
		 * If the general interface refuses to set the attribute,
		 * then we try all the specialized interfaces that we
		 * know about.
		 */
		if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM &&
		    !strcmp(eap->ea_name, POSIX1E_ACL_ACCESS_EXTATTR_NAME)) {
			if (acl_set_file(name, ACL_TYPE_ACCESS,
			    EXTATTR_CONTENT(eap)) != -1) {
				dprintf(stdout, " (set using acl_set_file)");
				continue;
			}
		}
		if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM &&
		    !strcmp(eap->ea_name, POSIX1E_ACL_DEFAULT_EXTATTR_NAME)) {
			if (acl_set_file(name, ACL_TYPE_DEFAULT,
			    EXTATTR_CONTENT(eap)) != -1) {
				dprintf(stdout, " (set using acl_set_file)");
				continue;
			}
		}
		vprintf(stdout, " (unable to set)");
	}
	vprintf(stdout, "\n");
}
Example #4
0
void
priv_vfs_clearsugid_extattr(int asroot, int injail, struct test *test)
{

	if (extattr_set_file(fpath, EA_NAMESPACE, EA_NAME, EA_DATA, EA_SIZE)
	    < 0)
		err(-1,
		    "priv_vfs_clearsugid_extattr(%s, %s): extattr_set_file",
		    asroot ? "root" : "!root", injail ? "jail" : "!jail");
	confirm_sugid("priv_vfs_clearsugid_extattr", asroot, injail);
}
Example #5
0
/*
 * Sets extended attribute on a file.
 * Returns 0 on success, -1 on failure.
 */
int
ceph_os_setxattr(const char *path, const char *name,
    const void *value, size_t size)
{
	int error = -1;

#if defined(__FreeBSD__)
	error = extattr_set_file(path, EXTATTR_NAMESPACE_USER, name, value,
	    size);
	if (error > 0)
		error = 0;
#elif defined(__linux__) || defined(DARWIN)
	error = setxattr(path, name, value, size, 0);
#endif

	return (error);
}
Example #6
0
static ssize_t xattr_setxattr(const char *path, const char *name,
                              void *value, ssize_t size, u_int32_t position,
                              int options)
{
    int rv = 0;
    int nofollow;

    if (position != 0) {
        return -1;
    }

    nofollow = options & XATTR_XATTR_NOFOLLOW;
    options &= ~XATTR_XATTR_NOFOLLOW;

    if (options == XATTR_XATTR_CREATE ||
        options == XATTR_XATTR_REPLACE) {

        /* meh. FreeBSD doesn't really have this in its
         * API... Oh well.
         */
    }
    else if (options != 0) {
        return -1;
    }

    if (nofollow) {
        rv = extattr_set_link(path, EXTATTR_NAMESPACE_USER,
                                name, value, size);
    }
    else {
        rv = extattr_set_file(path, EXTATTR_NAMESPACE_USER,
                                name, value, size);
    }

    /* freebsd returns the written length on success, not zero. */
    if (rv >= 0) {
        return 0;
    }
    else {
        return rv;
    }
}
Example #7
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
}
Example #8
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);
}
Example #9
0
/* Bring the given attributes and/or ACLs into effect with the given file.
   @param flag          Bitfield for control purposes
                        bit0= decode and set ACLs
                        bit1= first clear all existing attributes of the file
                        bit2= do not set attributes other than ACLs
                        bit3= do not ignore eventual non-user attributes.
                              I.e. those with a name which does not begin
                              by "user."
                        bit5= in case of symbolic link: manipulate link target
                        bit6= tolerate inappropriate presence or absence of
                              directory default ACL
   @return              1 success
                       -1 error memory allocation
                       -2 error with decoding of ACL
                       -3 error with setting ACL
                       -4 error with setting attribute
                       -5 error with deleting attributes
                       -6 support of xattr not enabled at compile time
                       -7 support of ACL not enabled at compile time
                       -8 unsupported xattr namespace
    ISO_AAIP_ACL_MULT_OBJ multiple entries of user::, group::, other::
*/
int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
                       size_t *value_lengths, char **values, int flag)
{
 int ret, has_default_acl= 0;
 size_t i, consumed, acl_text_fill, acl_idx= 0;
 char *acl_text= NULL;
#ifdef Libisofs_with_freebsd_extattR
 char *user_list= NULL, *sys_list= NULL, *namept;
 ssize_t user_list_size= 0, sys_list_size= 0;
 int attrnamespace;
#endif

#ifdef Libisofs_with_freebsd_extattR

 if(flag & 2) { /* Delete all file attributes */
   ret= aaip_extattr_make_list(path, EXTATTR_NAMESPACE_USER,
                               &user_list, &user_list_size, flag & 32);
   if(ret <= 0)
     {ret= -1; goto ex;}
   ret= aaip_extattr_delete_names(path, EXTATTR_NAMESPACE_USER,
                                  user_list, user_list_size, flag & 32);
   if(ret <= 0)
     {ret= -5; 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= -5; goto ex;}
     ret= aaip_extattr_delete_names(path, EXTATTR_NAMESPACE_SYSTEM,
                                  sys_list, sys_list_size, flag & 32);
     if(ret <= 0)
       {ret= -5; goto ex;}
   }
 }

#endif /* Libisofs_with_freebsd_extattR */

 for(i= 0; i < num_attrs; i++) {
   if(names[i] == NULL || values[i] == NULL)
 continue;
   if(names[i][0] == 0) { /* ACLs */
     if(flag & 1)
       acl_idx= i + 1;
 continue;
   }
   /* Extended Attribute */
   if(flag & 4)
 continue;

#ifdef Libisofs_with_freebsd_extattR

   if(strncmp(names[i], "user.", 5) == 0) {
     attrnamespace= EXTATTR_NAMESPACE_USER;
     namept= names[i] + 5;
   } else if(strncmp(names[i], "isofs.", 6) == 0 || !(flag & 8)) {
 continue;
   } else if(strncmp(names[i], "system.", 7) == 0) {
     attrnamespace= EXTATTR_NAMESPACE_SYSTEM;
     namept= names[i] + 7;
   } else {
     {ret= -8; goto ex;}
   }
   if(flag & 32)
     ret= extattr_set_file(path, attrnamespace, namept,
                           values[i], value_lengths[i]);
   else
     ret= extattr_set_link(path, attrnamespace, namept,
                           values[i], value_lengths[i]);
   if(ret == -1)
     {ret= -4; goto ex;}

#else

   if(strncmp(names[i], "user.", 5) == 0)
     ;
   else if(strncmp(names[i], "isofs.", 6) == 0 || !(flag & 8))
 continue;
   {ret= -6; goto ex;}

#endif /* Libisofs_with_freebsd_extattR */

 }

 /* Decode ACLs */
 if(acl_idx == 0)
   {ret= 1; goto ex;}
 i= acl_idx - 1; 

 ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
                      &consumed, NULL, 0, &acl_text_fill, 1);
 if(ret < -3)
   goto ex;
 if(ret <= 0)
   {ret= -2; goto ex;}
 acl_text= calloc(acl_text_fill, 1);
 if(acl_text == NULL) 
   {ret= -1; goto ex;}
 ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
                      &consumed, acl_text, acl_text_fill, &acl_text_fill, 0);
 if(ret < -3)
   goto ex;
 if(ret <= 0)
   {ret= -2; goto ex;} 
 has_default_acl= (ret == 2);

#ifdef Libisofs_with_aaip_acL
 ret= aaip_set_acl_text(path, acl_text, flag & (32 | 64));
 if(ret <= 0)
   {ret= -3; goto ex;}
#else
 {ret= -7; goto ex;}
#endif

 if(has_default_acl && !(flag & 64))
   {ret= -3; goto ex;}

 ret= 1;
ex:;
 if(acl_text != NULL)
   free(acl_text);
#ifdef Libisofs_with_freebsd_extattR
 if(user_list != NULL)
   free(user_list);
 if(sys_list != NULL)
   free(sys_list);
#endif /* Libisofs_with_freebsd_extattR */
 return(ret);
}
Example #10
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");
}