xref: /illumos-gate/usr/src/lib/libc/port/gen/attrat.c (revision 1c2187e7a735b31a46941879f0bd124e0aa325a3)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include "synonyms.h"
29 #include <string.h>
30 #include <stdlib.h>
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <mtlib.h>
34 #include <attr.h>
35 #include <sys/types.h>
36 #include <sys/syscall.h>
37 #include <sys/stat.h>
38 #include <sys/filio.h>
39 #include <unistd.h>
40 #include <dlfcn.h>
41 #include <stdio.h>
42 
43 static int (*nvpacker)(nvlist_t *, char **, size_t *, int, int);
44 static int (*nvsize)(nvlist_t *, size_t *, int);
45 static int (*nvunpacker)(char *, size_t, nvlist_t **);
46 static mutex_t attrlock = DEFAULTMUTEX;
47 static int initialized;
48 extern int __openattrdirat(int basefd, const char *name);
49 
50 static char *xattr_view_name[XATTR_VIEW_LAST] = {
51 	VIEW_READONLY,
52 	VIEW_READWRITE
53 };
54 
55 static int
56 attrat_init()
57 {
58 	if (initialized == 0) {
59 		lmutex_lock(&attrlock);
60 		if (initialized == 1) {
61 			lmutex_unlock(&attrlock);
62 			return (0);
63 		}
64 
65 		void *libnvhandle = dlopen("libnvpair.so.1", RTLD_LAZY);
66 		if (libnvhandle == NULL || (nvpacker = (int (*)(nvlist_t *,
67 		    char **, size_t *, int, int)) dlsym(libnvhandle,
68 		    "nvlist_pack")) == NULL ||
69 		    (nvsize = (int (*)(nvlist_t *,
70 		    size_t *, int)) dlsym(libnvhandle,
71 		    "nvlist_size")) == NULL ||
72 		    (nvunpacker = (int (*)(char *, size_t,
73 		    nvlist_t **)) dlsym(libnvhandle,
74 		    "nvlist_unpack")) == NULL) {
75 			if (libnvhandle)
76 				dlclose(libnvhandle);
77 			lmutex_unlock(&attrlock);
78 			return (EINVAL);
79 		}
80 
81 		initialized = 1;
82 		lmutex_unlock(&attrlock);
83 	}
84 	return (0);
85 }
86 
87 static int
88 attr_nv_pack(nvlist_t *request, void **nv_request, size_t *nv_requestlen)
89 {
90 	size_t bufsize;
91 	char *packbuf = NULL;
92 
93 	if (nvsize(request, &bufsize, NV_ENCODE_XDR) != 0) {
94 		return (EINVAL);
95 	}
96 
97 	packbuf = malloc(bufsize);
98 	if (packbuf == NULL)
99 		return (EINVAL);
100 	if (nvpacker(request, &packbuf, &bufsize, NV_ENCODE_XDR, 0) != 0) {
101 		free(packbuf);
102 	} else {
103 		*nv_request = (void *)packbuf;
104 		*nv_requestlen = bufsize;
105 	}
106 	return (0);
107 }
108 
109 static const char *
110 view_to_name(xattr_view_t view)
111 {
112 	if (view >= XATTR_VIEW_LAST || view < 0)
113 		return (NULL);
114 	return (xattr_view_name[view]);
115 }
116 
117 static int
118 xattr_openat(int basefd, xattr_view_t view, int mode)
119 {
120 	const char *xattrname;
121 	int xattrfd;
122 	int oflag;
123 
124 	switch (view) {
125 	case XATTR_VIEW_READONLY:
126 		oflag = O_RDONLY;
127 		break;
128 	case XATTR_VIEW_READWRITE:
129 		oflag = mode & O_RDWR;
130 		break;
131 	default:
132 		(void) __set_errno(EINVAL);
133 		return (-1);
134 	}
135 	if (mode & O_XATTR)
136 		oflag |= O_XATTR;
137 
138 	xattrname = view_to_name(view);
139 	xattrfd = openat(basefd, xattrname, oflag);
140 	if (xattrfd < 0)
141 		return (xattrfd);
142 	/* Don't cache sysattr info (advisory) */
143 	(void) directio(xattrfd, DIRECTIO_ON);
144 	return (xattrfd);
145 }
146 
147 static int
148 cgetattr(int fd, nvlist_t **response)
149 {
150 	int error;
151 	int bytesread;
152 	void *nv_response;
153 	size_t nv_responselen;
154 	struct stat buf;
155 
156 	if (error = attrat_init())
157 		return (__set_errno(error));
158 	if ((error = fstat(fd, &buf)) != 0)
159 		return (__set_errno(error));
160 	nv_responselen = buf.st_size;
161 
162 	if ((nv_response = malloc(nv_responselen)) == NULL)
163 		return (__set_errno(ENOMEM));
164 	bytesread = read(fd, nv_response, nv_responselen);
165 	if (bytesread != nv_responselen)
166 		return (__set_errno(EFAULT));
167 
168 	error = nvunpacker(nv_response, nv_responselen, response);
169 	free(nv_response);
170 	return (error);
171 }
172 
173 static int
174 csetattr(int fd, nvlist_t *request)
175 {
176 	int error, saveerrno;
177 	int byteswritten;
178 	void *nv_request;
179 	size_t nv_requestlen;
180 
181 	if (error = attrat_init())
182 		return (__set_errno(error));
183 
184 	if ((error = attr_nv_pack(request, &nv_request, &nv_requestlen)) != 0)
185 		return (__set_errno(error));
186 
187 	(void) __set_errno(0);
188 	byteswritten = write(fd, nv_request, nv_requestlen);
189 	if (byteswritten != nv_requestlen) {
190 		saveerrno = errno;
191 		free(nv_request);
192 		errno = saveerrno;
193 		return (__set_errno(errno));
194 	}
195 
196 	free(nv_request);
197 	return (0);
198 }
199 
200 int
201 fgetattr(int basefd, xattr_view_t view, nvlist_t **response)
202 {
203 	int error, saveerrno, xattrfd;
204 
205 	if ((xattrfd = xattr_openat(basefd, view, O_XATTR)) < 0)
206 		return (xattrfd);
207 
208 	error = cgetattr(xattrfd, response);
209 	saveerrno = errno;
210 	(void) close(xattrfd);
211 	errno = saveerrno;
212 	return (error);
213 }
214 
215 int
216 fsetattr(int basefd, xattr_view_t view, nvlist_t *request)
217 {
218 	int error, saveerrno, xattrfd;
219 
220 	if ((xattrfd = xattr_openat(basefd, view, O_RDWR | O_XATTR)) < 0)
221 		return (xattrfd);
222 	error = csetattr(xattrfd, request);
223 	saveerrno = errno;
224 	(void) close(xattrfd);
225 	errno = saveerrno;
226 	return (error);
227 }
228 
229 int
230 getattrat(int basefd, xattr_view_t view, const char *name, nvlist_t **response)
231 {
232 	int error, saveerrno, namefd, xattrfd;
233 
234 	if ((namefd = __openattrdirat(basefd, name)) < 0)
235 		return (namefd);
236 
237 	if ((xattrfd = xattr_openat(namefd, view, 0)) < 0) {
238 		saveerrno = errno;
239 		(void) close(namefd);
240 		errno = saveerrno;
241 		return (xattrfd);
242 	}
243 
244 	error = cgetattr(xattrfd, response);
245 	saveerrno = errno;
246 	(void) close(namefd);
247 	(void) close(xattrfd);
248 	errno = saveerrno;
249 	return (error);
250 }
251 
252 int
253 setattrat(int basefd, xattr_view_t view, const char *name, nvlist_t *request)
254 {
255 	int error, saveerrno, namefd, xattrfd;
256 
257 	if ((namefd = __openattrdirat(basefd, name)) < 0)
258 		return (namefd);
259 
260 	if ((xattrfd = xattr_openat(namefd, view, O_RDWR)) < 0) {
261 		saveerrno = errno;
262 		(void) close(namefd);
263 		errno = saveerrno;
264 		return (xattrfd);
265 	}
266 
267 	error = csetattr(xattrfd, request);
268 	saveerrno = errno;
269 	(void) close(namefd);
270 	(void) close(xattrfd);
271 	errno = saveerrno;
272 	return (error);
273 }
274