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 /* 225902Smarks * 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 **); 46*6082Smarks static int (*nvfree)(nvlist_t *); 47*6082Smarks static int (*nvlookupint64)(nvlist_t *, const char *, uint64_t *); 48*6082Smarks 495331Samw static mutex_t attrlock = DEFAULTMUTEX; 505331Samw static int initialized; 515331Samw extern int __openattrdirat(int basefd, const char *name); 525331Samw 535331Samw static char *xattr_view_name[XATTR_VIEW_LAST] = { 545331Samw VIEW_READONLY, 555331Samw VIEW_READWRITE 565331Samw }; 575331Samw 585331Samw static int 595331Samw attrat_init() 605331Samw { 615331Samw if (initialized == 0) { 625914Sraf void *libnvhandle = dlopen("libnvpair.so.1", RTLD_LAZY); 635914Sraf 645331Samw lmutex_lock(&attrlock); 655331Samw if (initialized == 1) { 665331Samw lmutex_unlock(&attrlock); 675914Sraf if (libnvhandle) 685914Sraf dlclose(libnvhandle); 695331Samw return (0); 705331Samw } 715331Samw 725331Samw if (libnvhandle == NULL || (nvpacker = (int (*)(nvlist_t *, 735331Samw char **, size_t *, int, int)) dlsym(libnvhandle, 745331Samw "nvlist_pack")) == NULL || 755331Samw (nvsize = (int (*)(nvlist_t *, 765331Samw size_t *, int)) dlsym(libnvhandle, 775331Samw "nvlist_size")) == NULL || 78*6082Smarks (nvfree = (int (*)(nvlist_t *)) dlsym(libnvhandle, 79*6082Smarks "nvlist_free")) == NULL || 80*6082Smarks (nvlookupint64 = (int (*)(nvlist_t *, const char *, 81*6082Smarks uint64_t *)) dlsym(libnvhandle, 82*6082Smarks "nvlist_lookup_uint64")) == NULL || 835331Samw (nvunpacker = (int (*)(char *, size_t, 845331Samw nvlist_t **)) dlsym(libnvhandle, 855331Samw "nvlist_unpack")) == NULL) { 865331Samw if (libnvhandle) 875331Samw dlclose(libnvhandle); 885331Samw lmutex_unlock(&attrlock); 895902Smarks return (-1); 905331Samw } 915331Samw 925331Samw initialized = 1; 935331Samw lmutex_unlock(&attrlock); 945331Samw } 955331Samw return (0); 965331Samw } 975331Samw 985331Samw static int 995331Samw attr_nv_pack(nvlist_t *request, void **nv_request, size_t *nv_requestlen) 1005331Samw { 1015331Samw size_t bufsize; 1025331Samw char *packbuf = NULL; 1035331Samw 1045331Samw if (nvsize(request, &bufsize, NV_ENCODE_XDR) != 0) { 1055902Smarks errno = EINVAL; 1065902Smarks return (-1); 1075331Samw } 1085331Samw 1095331Samw packbuf = malloc(bufsize); 1105331Samw if (packbuf == NULL) 1115902Smarks return (-1); 1125331Samw if (nvpacker(request, &packbuf, &bufsize, NV_ENCODE_XDR, 0) != 0) { 1135331Samw free(packbuf); 1145902Smarks errno = EINVAL; 1155902Smarks return (-1); 1165331Samw } else { 1175331Samw *nv_request = (void *)packbuf; 1185331Samw *nv_requestlen = bufsize; 1195331Samw } 1205331Samw return (0); 1215331Samw } 1225331Samw 1235331Samw static const char * 1245331Samw view_to_name(xattr_view_t view) 1255331Samw { 1265331Samw if (view >= XATTR_VIEW_LAST || view < 0) 1275331Samw return (NULL); 1285331Samw return (xattr_view_name[view]); 1295331Samw } 1305331Samw 1315331Samw static int 1325331Samw xattr_openat(int basefd, xattr_view_t view, int mode) 1335331Samw { 1345331Samw const char *xattrname; 1355331Samw int xattrfd; 1365331Samw int oflag; 1375331Samw 1385331Samw switch (view) { 1395331Samw case XATTR_VIEW_READONLY: 1405331Samw oflag = O_RDONLY; 1415331Samw break; 1425331Samw case XATTR_VIEW_READWRITE: 1435331Samw oflag = mode & O_RDWR; 1445331Samw break; 1455331Samw default: 1465902Smarks errno = EINVAL; 1475331Samw return (-1); 1485331Samw } 1495331Samw if (mode & O_XATTR) 1505331Samw oflag |= O_XATTR; 1515331Samw 1525331Samw xattrname = view_to_name(view); 1535331Samw xattrfd = openat(basefd, xattrname, oflag); 1545331Samw if (xattrfd < 0) 1555331Samw return (xattrfd); 1565331Samw /* Don't cache sysattr info (advisory) */ 1575331Samw (void) directio(xattrfd, DIRECTIO_ON); 1585331Samw return (xattrfd); 1595331Samw } 1605331Samw 1615331Samw static int 1625331Samw cgetattr(int fd, nvlist_t **response) 1635331Samw { 1645331Samw int error; 1655331Samw int bytesread; 1665331Samw void *nv_response; 1675331Samw size_t nv_responselen; 1685331Samw struct stat buf; 1695331Samw 1705331Samw if (error = attrat_init()) 1715902Smarks return (error); 1725331Samw if ((error = fstat(fd, &buf)) != 0) 1735902Smarks return (error); 1745331Samw nv_responselen = buf.st_size; 1755331Samw 1765331Samw if ((nv_response = malloc(nv_responselen)) == NULL) 1775902Smarks return (-1); 1785331Samw bytesread = read(fd, nv_response, nv_responselen); 1795902Smarks if (bytesread != nv_responselen) { 1805902Smarks free(nv_response); 1815902Smarks errno = EFAULT; 1825902Smarks return (-1); 1835902Smarks } 1845331Samw 1855902Smarks if (nvunpacker(nv_response, nv_responselen, response)) { 1865902Smarks free(nv_response); 1875902Smarks errno = ENOMEM; 1885902Smarks return (-1); 1895902Smarks } 1905902Smarks 1915331Samw free(nv_response); 1925902Smarks return (0); 1935331Samw } 1945331Samw 1955331Samw static int 1965331Samw csetattr(int fd, nvlist_t *request) 1975331Samw { 1985331Samw int error, saveerrno; 1995331Samw int byteswritten; 2005331Samw void *nv_request; 2015331Samw size_t nv_requestlen; 2025331Samw 2035331Samw if (error = attrat_init()) 2045902Smarks return (error); 2055331Samw 2065331Samw if ((error = attr_nv_pack(request, &nv_request, &nv_requestlen)) != 0) 2075902Smarks return (error); 2085331Samw 2095331Samw byteswritten = write(fd, nv_request, nv_requestlen); 2105331Samw if (byteswritten != nv_requestlen) { 2115331Samw saveerrno = errno; 2125331Samw free(nv_request); 2135331Samw errno = saveerrno; 2145902Smarks return (-1); 2155331Samw } 2165331Samw 2175331Samw free(nv_request); 2185331Samw return (0); 2195331Samw } 2205331Samw 2215331Samw int 2225331Samw fgetattr(int basefd, xattr_view_t view, nvlist_t **response) 2235331Samw { 2245331Samw int error, saveerrno, xattrfd; 2255331Samw 2265331Samw if ((xattrfd = xattr_openat(basefd, view, O_XATTR)) < 0) 2275331Samw return (xattrfd); 2285331Samw 2295331Samw error = cgetattr(xattrfd, response); 2305331Samw saveerrno = errno; 2315331Samw (void) close(xattrfd); 2325331Samw errno = saveerrno; 2335331Samw return (error); 2345331Samw } 2355331Samw 2365331Samw int 2375331Samw fsetattr(int basefd, xattr_view_t view, nvlist_t *request) 2385331Samw { 2395331Samw int error, saveerrno, xattrfd; 2405331Samw 2415331Samw if ((xattrfd = xattr_openat(basefd, view, O_RDWR | O_XATTR)) < 0) 2425331Samw return (xattrfd); 2435331Samw error = csetattr(xattrfd, request); 2445331Samw saveerrno = errno; 2455331Samw (void) close(xattrfd); 2465331Samw errno = saveerrno; 2475331Samw return (error); 2485331Samw } 2495331Samw 2505331Samw int 2515331Samw getattrat(int basefd, xattr_view_t view, const char *name, nvlist_t **response) 2525331Samw { 2535331Samw int error, saveerrno, namefd, xattrfd; 2545331Samw 2555331Samw if ((namefd = __openattrdirat(basefd, name)) < 0) 2565331Samw return (namefd); 2575331Samw 2585331Samw if ((xattrfd = xattr_openat(namefd, view, 0)) < 0) { 2595331Samw saveerrno = errno; 2605331Samw (void) close(namefd); 2615331Samw errno = saveerrno; 2625331Samw return (xattrfd); 2635331Samw } 2645331Samw 2655331Samw error = cgetattr(xattrfd, response); 2665331Samw saveerrno = errno; 2675331Samw (void) close(namefd); 2685331Samw (void) close(xattrfd); 2695331Samw errno = saveerrno; 2705331Samw return (error); 2715331Samw } 2725331Samw 2735331Samw int 2745331Samw setattrat(int basefd, xattr_view_t view, const char *name, nvlist_t *request) 2755331Samw { 2765331Samw int error, saveerrno, namefd, xattrfd; 2775331Samw 2785331Samw if ((namefd = __openattrdirat(basefd, name)) < 0) 2795331Samw return (namefd); 2805331Samw 2815331Samw if ((xattrfd = xattr_openat(namefd, view, O_RDWR)) < 0) { 2825331Samw saveerrno = errno; 2835331Samw (void) close(namefd); 2845331Samw errno = saveerrno; 2855331Samw return (xattrfd); 2865331Samw } 2875331Samw 2885331Samw error = csetattr(xattrfd, request); 2895331Samw saveerrno = errno; 2905331Samw (void) close(namefd); 2915331Samw (void) close(xattrfd); 2925331Samw errno = saveerrno; 2935331Samw return (error); 2945331Samw } 295*6082Smarks 296*6082Smarks void 297*6082Smarks libc_nvlist_free(nvlist_t *nvp) 298*6082Smarks { 299*6082Smarks nvfree(nvp); 300*6082Smarks } 301*6082Smarks 302*6082Smarks int 303*6082Smarks libc_nvlist_lookup_uint64(nvlist_t *nvp, const char *name, uint64_t *value) 304*6082Smarks { 305*6082Smarks return (nvlookupint64(nvp, name, value)); 306*6082Smarks } 307