xref: /onnv-gate/usr/src/lib/libc/port/gen/attrat.c (revision 11798:1e7f1f154004)
15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
21*11798SRoger.Faulkner@Sun.COM 
225331Samw /*
23*11798SRoger.Faulkner@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
245331Samw  * Use is subject to license terms.
255331Samw  */
265331Samw 
276812Sraf #include "lint.h"
285331Samw #include <string.h>
295331Samw #include <stdlib.h>
305331Samw #include <errno.h>
315331Samw #include <fcntl.h>
325331Samw #include <mtlib.h>
335331Samw #include <attr.h>
345331Samw #include <sys/types.h>
355331Samw #include <sys/syscall.h>
365331Samw #include <sys/stat.h>
37*11798SRoger.Faulkner@Sun.COM #include <sys/file.h>
385331Samw #include <unistd.h>
395331Samw #include <dlfcn.h>
405331Samw #include <stdio.h>
416515Sraf #include <atomic.h>
425331Samw 
435331Samw static int (*nvpacker)(nvlist_t *, char **, size_t *, int, int);
445331Samw static int (*nvsize)(nvlist_t *, size_t *, int);
455331Samw static int (*nvunpacker)(char *, size_t, nvlist_t **);
466082Smarks static int (*nvfree)(nvlist_t *);
476082Smarks static int (*nvlookupint64)(nvlist_t *, const char *, uint64_t *);
486082Smarks 
495331Samw static mutex_t attrlock = DEFAULTMUTEX;
505331Samw static int initialized;
515331Samw 
525331Samw static char *xattr_view_name[XATTR_VIEW_LAST] = {
535331Samw 	VIEW_READONLY,
545331Samw 	VIEW_READWRITE
555331Samw };
565331Samw 
57*11798SRoger.Faulkner@Sun.COM int
__openattrdirat(int fd,const char * name)58*11798SRoger.Faulkner@Sun.COM __openattrdirat(int fd, const char *name)
59*11798SRoger.Faulkner@Sun.COM {
60*11798SRoger.Faulkner@Sun.COM 	return (syscall(SYS_openat, fd, name, FXATTRDIROPEN, 0));
61*11798SRoger.Faulkner@Sun.COM }
62*11798SRoger.Faulkner@Sun.COM 
635331Samw static int
attrat_init()645331Samw attrat_init()
655331Samw {
666515Sraf 	void *packer;
676515Sraf 	void *sizer;
686515Sraf 	void *unpacker;
696515Sraf 	void *freer;
706515Sraf 	void *looker;
716515Sraf 
725331Samw 	if (initialized == 0) {
736515Sraf 		void *handle = dlopen("libnvpair.so.1", RTLD_LAZY);
746515Sraf 
756515Sraf 		if (handle == NULL ||
766515Sraf 		    (packer = dlsym(handle, "nvlist_pack")) == NULL ||
776515Sraf 		    (sizer = dlsym(handle, "nvlist_size")) == NULL ||
786515Sraf 		    (unpacker = dlsym(handle, "nvlist_unpack")) == NULL ||
796515Sraf 		    (freer = dlsym(handle, "nvlist_free")) == NULL ||
806515Sraf 		    (looker = dlsym(handle, "nvlist_lookup_uint64")) == NULL) {
816515Sraf 			if (handle)
8211411SSurya.Prakki@Sun.COM 				(void) dlclose(handle);
836515Sraf 			return (-1);
846515Sraf 		}
855914Sraf 
865331Samw 		lmutex_lock(&attrlock);
876515Sraf 
886515Sraf 		if (initialized != 0) {
895331Samw 			lmutex_unlock(&attrlock);
9011411SSurya.Prakki@Sun.COM 			(void) dlclose(handle);
915331Samw 			return (0);
925331Samw 		}
935331Samw 
946515Sraf 		nvpacker = (int (*)(nvlist_t *, char **, size_t *, int, int))
956515Sraf 		    packer;
966515Sraf 		nvsize = (int (*)(nvlist_t *, size_t *, int))
976515Sraf 		    sizer;
986515Sraf 		nvunpacker = (int (*)(char *, size_t, nvlist_t **))
996515Sraf 		    unpacker;
1006515Sraf 		nvfree = (int (*)(nvlist_t *))
1016515Sraf 		    freer;
1026515Sraf 		nvlookupint64 = (int (*)(nvlist_t *, const char *, uint64_t *))
1036515Sraf 		    looker;
1045331Samw 
1056515Sraf 		membar_producer();
1065331Samw 		initialized = 1;
1075331Samw 		lmutex_unlock(&attrlock);
1085331Samw 	}
1095331Samw 	return (0);
1105331Samw }
1115331Samw 
1125331Samw static int
attr_nv_pack(nvlist_t * request,void ** nv_request,size_t * nv_requestlen)1135331Samw attr_nv_pack(nvlist_t *request, void **nv_request, size_t *nv_requestlen)
1145331Samw {
1155331Samw 	size_t bufsize;
1165331Samw 	char *packbuf = NULL;
1175331Samw 
1185331Samw 	if (nvsize(request, &bufsize, NV_ENCODE_XDR) != 0) {
1195902Smarks 		errno = EINVAL;
1205902Smarks 		return (-1);
1215331Samw 	}
1225331Samw 
1235331Samw 	packbuf = malloc(bufsize);
1245331Samw 	if (packbuf == NULL)
1255902Smarks 		return (-1);
1265331Samw 	if (nvpacker(request, &packbuf, &bufsize, NV_ENCODE_XDR, 0) != 0) {
1275331Samw 		free(packbuf);
1285902Smarks 		errno = EINVAL;
1295902Smarks 		return (-1);
1305331Samw 	} else {
1315331Samw 		*nv_request = (void *)packbuf;
1325331Samw 		*nv_requestlen = bufsize;
1335331Samw 	}
1345331Samw 	return (0);
1355331Samw }
1365331Samw 
1375331Samw static const char *
view_to_name(xattr_view_t view)1385331Samw view_to_name(xattr_view_t view)
1395331Samw {
1405331Samw 	if (view >= XATTR_VIEW_LAST || view < 0)
1415331Samw 		return (NULL);
1425331Samw 	return (xattr_view_name[view]);
1435331Samw }
1445331Samw 
1455331Samw static int
xattr_openat(int basefd,xattr_view_t view,int mode)1465331Samw xattr_openat(int basefd, xattr_view_t view, int mode)
1475331Samw {
1485331Samw 	const char *xattrname;
1495331Samw 	int xattrfd;
1505331Samw 	int oflag;
1515331Samw 
1525331Samw 	switch (view) {
1535331Samw 	case XATTR_VIEW_READONLY:
1545331Samw 		oflag = O_RDONLY;
1555331Samw 		break;
1565331Samw 	case XATTR_VIEW_READWRITE:
1575331Samw 		oflag = mode & O_RDWR;
1585331Samw 		break;
1595331Samw 	default:
1605902Smarks 		errno = EINVAL;
1615331Samw 		return (-1);
1625331Samw 	}
1635331Samw 	if (mode & O_XATTR)
1645331Samw 		oflag |= O_XATTR;
1655331Samw 
1665331Samw 	xattrname = view_to_name(view);
1675331Samw 	xattrfd = openat(basefd, xattrname, oflag);
1685331Samw 	if (xattrfd < 0)
1695331Samw 		return (xattrfd);
1705331Samw 	/* Don't cache sysattr info (advisory) */
1715331Samw 	(void) directio(xattrfd, DIRECTIO_ON);
1725331Samw 	return (xattrfd);
1735331Samw }
1745331Samw 
1755331Samw static int
cgetattr(int fd,nvlist_t ** response)1765331Samw cgetattr(int fd, nvlist_t **response)
1775331Samw {
1785331Samw 	int error;
1795331Samw 	int bytesread;
1805331Samw 	void *nv_response;
1815331Samw 	size_t nv_responselen;
1825331Samw 	struct stat buf;
1835331Samw 
1845331Samw 	if (error = attrat_init())
1855902Smarks 		return (error);
1865331Samw 	if ((error = fstat(fd, &buf)) != 0)
1875902Smarks 		return (error);
1885331Samw 	nv_responselen = buf.st_size;
1895331Samw 
1905331Samw 	if ((nv_response = malloc(nv_responselen)) == NULL)
1915902Smarks 		return (-1);
1925331Samw 	bytesread = read(fd, nv_response, nv_responselen);
1935902Smarks 	if (bytesread != nv_responselen) {
1945902Smarks 		free(nv_response);
1955902Smarks 		errno = EFAULT;
1965902Smarks 		return (-1);
1975902Smarks 	}
1985331Samw 
1995902Smarks 	if (nvunpacker(nv_response, nv_responselen, response)) {
2005902Smarks 		free(nv_response);
2015902Smarks 		errno = ENOMEM;
2025902Smarks 		return (-1);
2035902Smarks 	}
2045902Smarks 
2055331Samw 	free(nv_response);
2065902Smarks 	return (0);
2075331Samw }
2085331Samw 
2095331Samw static int
csetattr(int fd,nvlist_t * request)2105331Samw csetattr(int fd, nvlist_t *request)
2115331Samw {
2125331Samw 	int error, saveerrno;
2135331Samw 	int byteswritten;
2145331Samw 	void *nv_request;
2155331Samw 	size_t nv_requestlen;
2165331Samw 
2175331Samw 	if (error = attrat_init())
2185902Smarks 		return (error);
2195331Samw 
2205331Samw 	if ((error = attr_nv_pack(request, &nv_request, &nv_requestlen)) != 0)
2215902Smarks 		return (error);
2225331Samw 
2235331Samw 	byteswritten = write(fd, nv_request, nv_requestlen);
2245331Samw 	if (byteswritten != nv_requestlen) {
2255331Samw 		saveerrno = errno;
2265331Samw 		free(nv_request);
2275331Samw 		errno = saveerrno;
2285902Smarks 		return (-1);
2295331Samw 	}
2305331Samw 
2315331Samw 	free(nv_request);
2325331Samw 	return (0);
2335331Samw }
2345331Samw 
2355331Samw int
fgetattr(int basefd,xattr_view_t view,nvlist_t ** response)2365331Samw fgetattr(int basefd, xattr_view_t view, nvlist_t **response)
2375331Samw {
2385331Samw 	int error, saveerrno, xattrfd;
2395331Samw 
2405331Samw 	if ((xattrfd = xattr_openat(basefd, view, O_XATTR)) < 0)
2415331Samw 		return (xattrfd);
2425331Samw 
2435331Samw 	error = cgetattr(xattrfd, response);
2445331Samw 	saveerrno = errno;
2455331Samw 	(void) close(xattrfd);
2465331Samw 	errno = saveerrno;
2475331Samw 	return (error);
2485331Samw }
2495331Samw 
2505331Samw int
fsetattr(int basefd,xattr_view_t view,nvlist_t * request)2515331Samw fsetattr(int basefd, xattr_view_t view, nvlist_t *request)
2525331Samw {
2535331Samw 	int error, saveerrno, xattrfd;
2545331Samw 
2555331Samw 	if ((xattrfd = xattr_openat(basefd, view, O_RDWR | O_XATTR)) < 0)
2565331Samw 		return (xattrfd);
2575331Samw 	error = csetattr(xattrfd, request);
2585331Samw 	saveerrno = errno;
2595331Samw 	(void) close(xattrfd);
2605331Samw 	errno = saveerrno;
2615331Samw 	return (error);
2625331Samw }
2635331Samw 
2645331Samw int
getattrat(int basefd,xattr_view_t view,const char * name,nvlist_t ** response)2655331Samw getattrat(int basefd, xattr_view_t view, const char *name, nvlist_t **response)
2665331Samw {
2675331Samw 	int error, saveerrno, namefd, xattrfd;
2685331Samw 
2695331Samw 	if ((namefd = __openattrdirat(basefd, name)) < 0)
2705331Samw 		return (namefd);
2715331Samw 
2725331Samw 	if ((xattrfd = xattr_openat(namefd, view, 0)) < 0) {
2735331Samw 		saveerrno = errno;
2745331Samw 		(void) close(namefd);
2755331Samw 		errno = saveerrno;
2765331Samw 		return (xattrfd);
2775331Samw 	}
2785331Samw 
2795331Samw 	error = cgetattr(xattrfd, response);
2805331Samw 	saveerrno = errno;
2815331Samw 	(void) close(namefd);
2825331Samw 	(void) close(xattrfd);
2835331Samw 	errno = saveerrno;
2845331Samw 	return (error);
2855331Samw }
2865331Samw 
2875331Samw int
setattrat(int basefd,xattr_view_t view,const char * name,nvlist_t * request)2885331Samw setattrat(int basefd, xattr_view_t view, const char *name, nvlist_t *request)
2895331Samw {
2905331Samw 	int error, saveerrno, namefd, xattrfd;
2915331Samw 
2925331Samw 	if ((namefd = __openattrdirat(basefd, name)) < 0)
2935331Samw 		return (namefd);
2945331Samw 
2955331Samw 	if ((xattrfd = xattr_openat(namefd, view, O_RDWR)) < 0) {
2965331Samw 		saveerrno = errno;
2975331Samw 		(void) close(namefd);
2985331Samw 		errno = saveerrno;
2995331Samw 		return (xattrfd);
3005331Samw 	}
3015331Samw 
3025331Samw 	error = csetattr(xattrfd, request);
3035331Samw 	saveerrno = errno;
3045331Samw 	(void) close(namefd);
3055331Samw 	(void) close(xattrfd);
3065331Samw 	errno = saveerrno;
3075331Samw 	return (error);
3085331Samw }
3096082Smarks 
3106082Smarks void
libc_nvlist_free(nvlist_t * nvp)3116082Smarks libc_nvlist_free(nvlist_t *nvp)
3126082Smarks {
3136082Smarks 	nvfree(nvp);
3146082Smarks }
3156082Smarks 
3166082Smarks int
libc_nvlist_lookup_uint64(nvlist_t * nvp,const char * name,uint64_t * value)3176082Smarks libc_nvlist_lookup_uint64(nvlist_t *nvp, const char *name, uint64_t *value)
3186082Smarks {
3196082Smarks 	return (nvlookupint64(nvp, name, value));
3206082Smarks }
321