xref: /onnv-gate/usr/src/lib/libc/port/gen/attrat.c (revision 5902:0a35a89d8450)
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  */
215331Samw /*
22*5902Smarks  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
235331Samw  * Use is subject to license terms.
245331Samw  */
255331Samw 
265331Samw #pragma ident	"%Z%%M%	%I%	%E% SMI"
275331Samw 
285331Samw #include "synonyms.h"
295331Samw #include <string.h>
305331Samw #include <stdlib.h>
315331Samw #include <errno.h>
325331Samw #include <fcntl.h>
335331Samw #include <mtlib.h>
345331Samw #include <attr.h>
355331Samw #include <sys/types.h>
365331Samw #include <sys/syscall.h>
375331Samw #include <sys/stat.h>
385331Samw #include <sys/filio.h>
395331Samw #include <unistd.h>
405331Samw #include <dlfcn.h>
415331Samw #include <stdio.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 **);
465331Samw static mutex_t attrlock = DEFAULTMUTEX;
475331Samw static int initialized;
485331Samw extern int __openattrdirat(int basefd, const char *name);
495331Samw 
505331Samw static char *xattr_view_name[XATTR_VIEW_LAST] = {
515331Samw 	VIEW_READONLY,
525331Samw 	VIEW_READWRITE
535331Samw };
545331Samw 
555331Samw static int
565331Samw attrat_init()
575331Samw {
585331Samw 	if (initialized == 0) {
595331Samw 		lmutex_lock(&attrlock);
605331Samw 		if (initialized == 1) {
615331Samw 			lmutex_unlock(&attrlock);
625331Samw 			return (0);
635331Samw 		}
645331Samw 
655331Samw 		void *libnvhandle = dlopen("libnvpair.so.1", RTLD_LAZY);
665331Samw 		if (libnvhandle == NULL || (nvpacker = (int (*)(nvlist_t *,
675331Samw 		    char **, size_t *, int, int)) dlsym(libnvhandle,
685331Samw 		    "nvlist_pack")) == NULL ||
695331Samw 		    (nvsize = (int (*)(nvlist_t *,
705331Samw 		    size_t *, int)) dlsym(libnvhandle,
715331Samw 		    "nvlist_size")) == NULL ||
725331Samw 		    (nvunpacker = (int (*)(char *, size_t,
735331Samw 		    nvlist_t **)) dlsym(libnvhandle,
745331Samw 		    "nvlist_unpack")) == NULL) {
755331Samw 			if (libnvhandle)
765331Samw 				dlclose(libnvhandle);
775331Samw 			lmutex_unlock(&attrlock);
78*5902Smarks 			return (-1);
795331Samw 		}
805331Samw 
815331Samw 		initialized = 1;
825331Samw 		lmutex_unlock(&attrlock);
835331Samw 	}
845331Samw 	return (0);
855331Samw }
865331Samw 
875331Samw static int
885331Samw attr_nv_pack(nvlist_t *request, void **nv_request, size_t *nv_requestlen)
895331Samw {
905331Samw 	size_t bufsize;
915331Samw 	char *packbuf = NULL;
925331Samw 
935331Samw 	if (nvsize(request, &bufsize, NV_ENCODE_XDR) != 0) {
94*5902Smarks 		errno = EINVAL;
95*5902Smarks 		return (-1);
965331Samw 	}
975331Samw 
985331Samw 	packbuf = malloc(bufsize);
995331Samw 	if (packbuf == NULL)
100*5902Smarks 		return (-1);
1015331Samw 	if (nvpacker(request, &packbuf, &bufsize, NV_ENCODE_XDR, 0) != 0) {
1025331Samw 		free(packbuf);
103*5902Smarks 		errno = EINVAL;
104*5902Smarks 		return (-1);
1055331Samw 	} else {
1065331Samw 		*nv_request = (void *)packbuf;
1075331Samw 		*nv_requestlen = bufsize;
1085331Samw 	}
1095331Samw 	return (0);
1105331Samw }
1115331Samw 
1125331Samw static const char *
1135331Samw view_to_name(xattr_view_t view)
1145331Samw {
1155331Samw 	if (view >= XATTR_VIEW_LAST || view < 0)
1165331Samw 		return (NULL);
1175331Samw 	return (xattr_view_name[view]);
1185331Samw }
1195331Samw 
1205331Samw static int
1215331Samw xattr_openat(int basefd, xattr_view_t view, int mode)
1225331Samw {
1235331Samw 	const char *xattrname;
1245331Samw 	int xattrfd;
1255331Samw 	int oflag;
1265331Samw 
1275331Samw 	switch (view) {
1285331Samw 	case XATTR_VIEW_READONLY:
1295331Samw 		oflag = O_RDONLY;
1305331Samw 		break;
1315331Samw 	case XATTR_VIEW_READWRITE:
1325331Samw 		oflag = mode & O_RDWR;
1335331Samw 		break;
1345331Samw 	default:
135*5902Smarks 		errno = EINVAL;
1365331Samw 		return (-1);
1375331Samw 	}
1385331Samw 	if (mode & O_XATTR)
1395331Samw 		oflag |= O_XATTR;
1405331Samw 
1415331Samw 	xattrname = view_to_name(view);
1425331Samw 	xattrfd = openat(basefd, xattrname, oflag);
1435331Samw 	if (xattrfd < 0)
1445331Samw 		return (xattrfd);
1455331Samw 	/* Don't cache sysattr info (advisory) */
1465331Samw 	(void) directio(xattrfd, DIRECTIO_ON);
1475331Samw 	return (xattrfd);
1485331Samw }
1495331Samw 
1505331Samw static int
1515331Samw cgetattr(int fd, nvlist_t **response)
1525331Samw {
1535331Samw 	int error;
1545331Samw 	int bytesread;
1555331Samw 	void *nv_response;
1565331Samw 	size_t nv_responselen;
1575331Samw 	struct stat buf;
1585331Samw 
1595331Samw 	if (error = attrat_init())
160*5902Smarks 		return (error);
1615331Samw 	if ((error = fstat(fd, &buf)) != 0)
162*5902Smarks 		return (error);
1635331Samw 	nv_responselen = buf.st_size;
1645331Samw 
1655331Samw 	if ((nv_response = malloc(nv_responselen)) == NULL)
166*5902Smarks 		return (-1);
1675331Samw 	bytesread = read(fd, nv_response, nv_responselen);
168*5902Smarks 	if (bytesread != nv_responselen) {
169*5902Smarks 		free(nv_response);
170*5902Smarks 		errno = EFAULT;
171*5902Smarks 		return (-1);
172*5902Smarks 	}
1735331Samw 
174*5902Smarks 	if (nvunpacker(nv_response, nv_responselen, response)) {
175*5902Smarks 		free(nv_response);
176*5902Smarks 		errno = ENOMEM;
177*5902Smarks 		return (-1);
178*5902Smarks 	}
179*5902Smarks 
1805331Samw 	free(nv_response);
181*5902Smarks 	return (0);
1825331Samw }
1835331Samw 
1845331Samw static int
1855331Samw csetattr(int fd, nvlist_t *request)
1865331Samw {
1875331Samw 	int error, saveerrno;
1885331Samw 	int byteswritten;
1895331Samw 	void *nv_request;
1905331Samw 	size_t nv_requestlen;
1915331Samw 
1925331Samw 	if (error = attrat_init())
193*5902Smarks 		return (error);
1945331Samw 
1955331Samw 	if ((error = attr_nv_pack(request, &nv_request, &nv_requestlen)) != 0)
196*5902Smarks 		return (error);
1975331Samw 
1985331Samw 	byteswritten = write(fd, nv_request, nv_requestlen);
1995331Samw 	if (byteswritten != nv_requestlen) {
2005331Samw 		saveerrno = errno;
2015331Samw 		free(nv_request);
2025331Samw 		errno = saveerrno;
203*5902Smarks 		return (-1);
2045331Samw 	}
2055331Samw 
2065331Samw 	free(nv_request);
2075331Samw 	return (0);
2085331Samw }
2095331Samw 
2105331Samw int
2115331Samw fgetattr(int basefd, xattr_view_t view, nvlist_t **response)
2125331Samw {
2135331Samw 	int error, saveerrno, xattrfd;
2145331Samw 
2155331Samw 	if ((xattrfd = xattr_openat(basefd, view, O_XATTR)) < 0)
2165331Samw 		return (xattrfd);
2175331Samw 
2185331Samw 	error = cgetattr(xattrfd, response);
2195331Samw 	saveerrno = errno;
2205331Samw 	(void) close(xattrfd);
2215331Samw 	errno = saveerrno;
2225331Samw 	return (error);
2235331Samw }
2245331Samw 
2255331Samw int
2265331Samw fsetattr(int basefd, xattr_view_t view, nvlist_t *request)
2275331Samw {
2285331Samw 	int error, saveerrno, xattrfd;
2295331Samw 
2305331Samw 	if ((xattrfd = xattr_openat(basefd, view, O_RDWR | O_XATTR)) < 0)
2315331Samw 		return (xattrfd);
2325331Samw 	error = csetattr(xattrfd, request);
2335331Samw 	saveerrno = errno;
2345331Samw 	(void) close(xattrfd);
2355331Samw 	errno = saveerrno;
2365331Samw 	return (error);
2375331Samw }
2385331Samw 
2395331Samw int
2405331Samw getattrat(int basefd, xattr_view_t view, const char *name, nvlist_t **response)
2415331Samw {
2425331Samw 	int error, saveerrno, namefd, xattrfd;
2435331Samw 
2445331Samw 	if ((namefd = __openattrdirat(basefd, name)) < 0)
2455331Samw 		return (namefd);
2465331Samw 
2475331Samw 	if ((xattrfd = xattr_openat(namefd, view, 0)) < 0) {
2485331Samw 		saveerrno = errno;
2495331Samw 		(void) close(namefd);
2505331Samw 		errno = saveerrno;
2515331Samw 		return (xattrfd);
2525331Samw 	}
2535331Samw 
2545331Samw 	error = cgetattr(xattrfd, response);
2555331Samw 	saveerrno = errno;
2565331Samw 	(void) close(namefd);
2575331Samw 	(void) close(xattrfd);
2585331Samw 	errno = saveerrno;
2595331Samw 	return (error);
2605331Samw }
2615331Samw 
2625331Samw int
2635331Samw setattrat(int basefd, xattr_view_t view, const char *name, nvlist_t *request)
2645331Samw {
2655331Samw 	int error, saveerrno, namefd, xattrfd;
2665331Samw 
2675331Samw 	if ((namefd = __openattrdirat(basefd, name)) < 0)
2685331Samw 		return (namefd);
2695331Samw 
2705331Samw 	if ((xattrfd = xattr_openat(namefd, view, O_RDWR)) < 0) {
2715331Samw 		saveerrno = errno;
2725331Samw 		(void) close(namefd);
2735331Samw 		errno = saveerrno;
2745331Samw 		return (xattrfd);
2755331Samw 	}
2765331Samw 
2775331Samw 	error = csetattr(xattrfd, request);
2785331Samw 	saveerrno = errno;
2795331Samw 	(void) close(namefd);
2805331Samw 	(void) close(xattrfd);
2815331Samw 	errno = saveerrno;
2825331Samw 	return (error);
2835331Samw }
284