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