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.
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.
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]
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
34 #include <sys/types.h>
35 #include <sys/syscall.h>
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 int (*nvfree
)(nvlist_t
*);
47 static int (*nvlookupint64
)(nvlist_t
*, const char *, uint64_t *);
49 static mutex_t attrlock
= DEFAULTMUTEX
;
50 static int initialized
;
52 static char *xattr_view_name
[XATTR_VIEW_LAST
] = {
58 __openattrdirat(int fd
, const char *name
)
60 return (syscall(SYS_openat
, fd
, name
, FXATTRDIROPEN
, 0));
72 if (initialized
== 0) {
73 void *handle
= dlopen("libnvpair.so.1", RTLD_LAZY
);
76 (packer
= dlsym(handle
, "nvlist_pack")) == NULL
||
77 (sizer
= dlsym(handle
, "nvlist_size")) == NULL
||
78 (unpacker
= dlsym(handle
, "nvlist_unpack")) == NULL
||
79 (freer
= dlsym(handle
, "nvlist_free")) == NULL
||
80 (looker
= dlsym(handle
, "nvlist_lookup_uint64")) == NULL
) {
82 (void) dlclose(handle
);
86 lmutex_lock(&attrlock
);
88 if (initialized
!= 0) {
89 lmutex_unlock(&attrlock
);
90 (void) dlclose(handle
);
94 nvpacker
= (int (*)(nvlist_t
*, char **, size_t *, int, int))
96 nvsize
= (int (*)(nvlist_t
*, size_t *, int))
98 nvunpacker
= (int (*)(char *, size_t, nvlist_t
**))
100 nvfree
= (int (*)(nvlist_t
*))
102 nvlookupint64
= (int (*)(nvlist_t
*, const char *, uint64_t *))
107 lmutex_unlock(&attrlock
);
113 attr_nv_pack(nvlist_t
*request
, void **nv_request
, size_t *nv_requestlen
)
116 char *packbuf
= NULL
;
118 if (nvsize(request
, &bufsize
, NV_ENCODE_XDR
) != 0) {
123 packbuf
= malloc(bufsize
);
126 if (nvpacker(request
, &packbuf
, &bufsize
, NV_ENCODE_XDR
, 0) != 0) {
131 *nv_request
= (void *)packbuf
;
132 *nv_requestlen
= bufsize
;
138 view_to_name(xattr_view_t view
)
140 if (view
>= XATTR_VIEW_LAST
|| view
< 0)
142 return (xattr_view_name
[view
]);
146 xattr_openat(int basefd
, xattr_view_t view
, int mode
)
148 const char *xattrname
;
153 case XATTR_VIEW_READONLY
:
156 case XATTR_VIEW_READWRITE
:
157 oflag
= mode
& O_RDWR
;
166 xattrname
= view_to_name(view
);
167 xattrfd
= openat(basefd
, xattrname
, oflag
);
170 /* Don't cache sysattr info (advisory) */
171 (void) directio(xattrfd
, DIRECTIO_ON
);
176 cgetattr(int fd
, nvlist_t
**response
)
181 size_t nv_responselen
;
184 if (error
= attrat_init())
186 if ((error
= fstat(fd
, &buf
)) != 0)
188 nv_responselen
= buf
.st_size
;
190 if ((nv_response
= malloc(nv_responselen
)) == NULL
)
192 bytesread
= read(fd
, nv_response
, nv_responselen
);
193 if (bytesread
!= nv_responselen
) {
199 if (nvunpacker(nv_response
, nv_responselen
, response
)) {
210 csetattr(int fd
, nvlist_t
*request
)
212 int error
, saveerrno
;
215 size_t nv_requestlen
;
217 if (error
= attrat_init())
220 if ((error
= attr_nv_pack(request
, &nv_request
, &nv_requestlen
)) != 0)
223 byteswritten
= write(fd
, nv_request
, nv_requestlen
);
224 if (byteswritten
!= nv_requestlen
) {
236 fgetattr(int basefd
, xattr_view_t view
, nvlist_t
**response
)
238 int error
, saveerrno
, xattrfd
;
240 if ((xattrfd
= xattr_openat(basefd
, view
, O_XATTR
)) < 0)
243 error
= cgetattr(xattrfd
, response
);
245 (void) close(xattrfd
);
251 fsetattr(int basefd
, xattr_view_t view
, nvlist_t
*request
)
253 int error
, saveerrno
, xattrfd
;
255 if ((xattrfd
= xattr_openat(basefd
, view
, O_RDWR
| O_XATTR
)) < 0)
257 error
= csetattr(xattrfd
, request
);
259 (void) close(xattrfd
);
265 getattrat(int basefd
, xattr_view_t view
, const char *name
, nvlist_t
**response
)
267 int error
, saveerrno
, namefd
, xattrfd
;
269 if ((namefd
= __openattrdirat(basefd
, name
)) < 0)
272 if ((xattrfd
= xattr_openat(namefd
, view
, 0)) < 0) {
274 (void) close(namefd
);
279 error
= cgetattr(xattrfd
, response
);
281 (void) close(namefd
);
282 (void) close(xattrfd
);
288 setattrat(int basefd
, xattr_view_t view
, const char *name
, nvlist_t
*request
)
290 int error
, saveerrno
, namefd
, xattrfd
;
292 if ((namefd
= __openattrdirat(basefd
, name
)) < 0)
295 if ((xattrfd
= xattr_openat(namefd
, view
, O_RDWR
)) < 0) {
297 (void) close(namefd
);
302 error
= csetattr(xattrfd
, request
);
304 (void) close(namefd
);
305 (void) close(xattrfd
);
311 libc_nvlist_free(nvlist_t
*nvp
)
317 libc_nvlist_lookup_uint64(nvlist_t
*nvp
, const char *name
, uint64_t *value
)
319 return (nvlookupint64(nvp
, name
, value
));