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*11411SSurya.Prakki@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 235331Samw * Use is subject to license terms. 245331Samw */ 255331Samw 266812Sraf #include "lint.h" 275331Samw #include <string.h> 285331Samw #include <stdlib.h> 295331Samw #include <errno.h> 305331Samw #include <fcntl.h> 315331Samw #include <mtlib.h> 325331Samw #include <attr.h> 335331Samw #include <sys/types.h> 345331Samw #include <sys/syscall.h> 355331Samw #include <sys/stat.h> 365331Samw #include <sys/filio.h> 375331Samw #include <unistd.h> 385331Samw #include <dlfcn.h> 395331Samw #include <stdio.h> 406515Sraf #include <atomic.h> 415331Samw 425331Samw static int (*nvpacker)(nvlist_t *, char **, size_t *, int, int); 435331Samw static int (*nvsize)(nvlist_t *, size_t *, int); 445331Samw static int (*nvunpacker)(char *, size_t, nvlist_t **); 456082Smarks static int (*nvfree)(nvlist_t *); 466082Smarks static int (*nvlookupint64)(nvlist_t *, const char *, uint64_t *); 476082Smarks 485331Samw static mutex_t attrlock = DEFAULTMUTEX; 495331Samw static int initialized; 505331Samw extern int __openattrdirat(int basefd, const char *name); 515331Samw 525331Samw static char *xattr_view_name[XATTR_VIEW_LAST] = { 535331Samw VIEW_READONLY, 545331Samw VIEW_READWRITE 555331Samw }; 565331Samw 575331Samw static int 585331Samw attrat_init() 595331Samw { 606515Sraf void *packer; 616515Sraf void *sizer; 626515Sraf void *unpacker; 636515Sraf void *freer; 646515Sraf void *looker; 656515Sraf 665331Samw if (initialized == 0) { 676515Sraf void *handle = dlopen("libnvpair.so.1", RTLD_LAZY); 686515Sraf 696515Sraf if (handle == NULL || 706515Sraf (packer = dlsym(handle, "nvlist_pack")) == NULL || 716515Sraf (sizer = dlsym(handle, "nvlist_size")) == NULL || 726515Sraf (unpacker = dlsym(handle, "nvlist_unpack")) == NULL || 736515Sraf (freer = dlsym(handle, "nvlist_free")) == NULL || 746515Sraf (looker = dlsym(handle, "nvlist_lookup_uint64")) == NULL) { 756515Sraf if (handle) 76*11411SSurya.Prakki@Sun.COM (void) dlclose(handle); 776515Sraf return (-1); 786515Sraf } 795914Sraf 805331Samw lmutex_lock(&attrlock); 816515Sraf 826515Sraf if (initialized != 0) { 835331Samw lmutex_unlock(&attrlock); 84*11411SSurya.Prakki@Sun.COM (void) dlclose(handle); 855331Samw return (0); 865331Samw } 875331Samw 886515Sraf nvpacker = (int (*)(nvlist_t *, char **, size_t *, int, int)) 896515Sraf packer; 906515Sraf nvsize = (int (*)(nvlist_t *, size_t *, int)) 916515Sraf sizer; 926515Sraf nvunpacker = (int (*)(char *, size_t, nvlist_t **)) 936515Sraf unpacker; 946515Sraf nvfree = (int (*)(nvlist_t *)) 956515Sraf freer; 966515Sraf nvlookupint64 = (int (*)(nvlist_t *, const char *, uint64_t *)) 976515Sraf looker; 985331Samw 996515Sraf membar_producer(); 1005331Samw initialized = 1; 1015331Samw lmutex_unlock(&attrlock); 1025331Samw } 1035331Samw return (0); 1045331Samw } 1055331Samw 1065331Samw static int 1075331Samw attr_nv_pack(nvlist_t *request, void **nv_request, size_t *nv_requestlen) 1085331Samw { 1095331Samw size_t bufsize; 1105331Samw char *packbuf = NULL; 1115331Samw 1125331Samw if (nvsize(request, &bufsize, NV_ENCODE_XDR) != 0) { 1135902Smarks errno = EINVAL; 1145902Smarks return (-1); 1155331Samw } 1165331Samw 1175331Samw packbuf = malloc(bufsize); 1185331Samw if (packbuf == NULL) 1195902Smarks return (-1); 1205331Samw if (nvpacker(request, &packbuf, &bufsize, NV_ENCODE_XDR, 0) != 0) { 1215331Samw free(packbuf); 1225902Smarks errno = EINVAL; 1235902Smarks return (-1); 1245331Samw } else { 1255331Samw *nv_request = (void *)packbuf; 1265331Samw *nv_requestlen = bufsize; 1275331Samw } 1285331Samw return (0); 1295331Samw } 1305331Samw 1315331Samw static const char * 1325331Samw view_to_name(xattr_view_t view) 1335331Samw { 1345331Samw if (view >= XATTR_VIEW_LAST || view < 0) 1355331Samw return (NULL); 1365331Samw return (xattr_view_name[view]); 1375331Samw } 1385331Samw 1395331Samw static int 1405331Samw xattr_openat(int basefd, xattr_view_t view, int mode) 1415331Samw { 1425331Samw const char *xattrname; 1435331Samw int xattrfd; 1445331Samw int oflag; 1455331Samw 1465331Samw switch (view) { 1475331Samw case XATTR_VIEW_READONLY: 1485331Samw oflag = O_RDONLY; 1495331Samw break; 1505331Samw case XATTR_VIEW_READWRITE: 1515331Samw oflag = mode & O_RDWR; 1525331Samw break; 1535331Samw default: 1545902Smarks errno = EINVAL; 1555331Samw return (-1); 1565331Samw } 1575331Samw if (mode & O_XATTR) 1585331Samw oflag |= O_XATTR; 1595331Samw 1605331Samw xattrname = view_to_name(view); 1615331Samw xattrfd = openat(basefd, xattrname, oflag); 1625331Samw if (xattrfd < 0) 1635331Samw return (xattrfd); 1645331Samw /* Don't cache sysattr info (advisory) */ 1655331Samw (void) directio(xattrfd, DIRECTIO_ON); 1665331Samw return (xattrfd); 1675331Samw } 1685331Samw 1695331Samw static int 1705331Samw cgetattr(int fd, nvlist_t **response) 1715331Samw { 1725331Samw int error; 1735331Samw int bytesread; 1745331Samw void *nv_response; 1755331Samw size_t nv_responselen; 1765331Samw struct stat buf; 1775331Samw 1785331Samw if (error = attrat_init()) 1795902Smarks return (error); 1805331Samw if ((error = fstat(fd, &buf)) != 0) 1815902Smarks return (error); 1825331Samw nv_responselen = buf.st_size; 1835331Samw 1845331Samw if ((nv_response = malloc(nv_responselen)) == NULL) 1855902Smarks return (-1); 1865331Samw bytesread = read(fd, nv_response, nv_responselen); 1875902Smarks if (bytesread != nv_responselen) { 1885902Smarks free(nv_response); 1895902Smarks errno = EFAULT; 1905902Smarks return (-1); 1915902Smarks } 1925331Samw 1935902Smarks if (nvunpacker(nv_response, nv_responselen, response)) { 1945902Smarks free(nv_response); 1955902Smarks errno = ENOMEM; 1965902Smarks return (-1); 1975902Smarks } 1985902Smarks 1995331Samw free(nv_response); 2005902Smarks return (0); 2015331Samw } 2025331Samw 2035331Samw static int 2045331Samw csetattr(int fd, nvlist_t *request) 2055331Samw { 2065331Samw int error, saveerrno; 2075331Samw int byteswritten; 2085331Samw void *nv_request; 2095331Samw size_t nv_requestlen; 2105331Samw 2115331Samw if (error = attrat_init()) 2125902Smarks return (error); 2135331Samw 2145331Samw if ((error = attr_nv_pack(request, &nv_request, &nv_requestlen)) != 0) 2155902Smarks return (error); 2165331Samw 2175331Samw byteswritten = write(fd, nv_request, nv_requestlen); 2185331Samw if (byteswritten != nv_requestlen) { 2195331Samw saveerrno = errno; 2205331Samw free(nv_request); 2215331Samw errno = saveerrno; 2225902Smarks return (-1); 2235331Samw } 2245331Samw 2255331Samw free(nv_request); 2265331Samw return (0); 2275331Samw } 2285331Samw 2295331Samw int 2305331Samw fgetattr(int basefd, xattr_view_t view, nvlist_t **response) 2315331Samw { 2325331Samw int error, saveerrno, xattrfd; 2335331Samw 2345331Samw if ((xattrfd = xattr_openat(basefd, view, O_XATTR)) < 0) 2355331Samw return (xattrfd); 2365331Samw 2375331Samw error = cgetattr(xattrfd, response); 2385331Samw saveerrno = errno; 2395331Samw (void) close(xattrfd); 2405331Samw errno = saveerrno; 2415331Samw return (error); 2425331Samw } 2435331Samw 2445331Samw int 2455331Samw fsetattr(int basefd, xattr_view_t view, nvlist_t *request) 2465331Samw { 2475331Samw int error, saveerrno, xattrfd; 2485331Samw 2495331Samw if ((xattrfd = xattr_openat(basefd, view, O_RDWR | O_XATTR)) < 0) 2505331Samw return (xattrfd); 2515331Samw error = csetattr(xattrfd, request); 2525331Samw saveerrno = errno; 2535331Samw (void) close(xattrfd); 2545331Samw errno = saveerrno; 2555331Samw return (error); 2565331Samw } 2575331Samw 2585331Samw int 2595331Samw getattrat(int basefd, xattr_view_t view, const char *name, nvlist_t **response) 2605331Samw { 2615331Samw int error, saveerrno, namefd, xattrfd; 2625331Samw 2635331Samw if ((namefd = __openattrdirat(basefd, name)) < 0) 2645331Samw return (namefd); 2655331Samw 2665331Samw if ((xattrfd = xattr_openat(namefd, view, 0)) < 0) { 2675331Samw saveerrno = errno; 2685331Samw (void) close(namefd); 2695331Samw errno = saveerrno; 2705331Samw return (xattrfd); 2715331Samw } 2725331Samw 2735331Samw error = cgetattr(xattrfd, response); 2745331Samw saveerrno = errno; 2755331Samw (void) close(namefd); 2765331Samw (void) close(xattrfd); 2775331Samw errno = saveerrno; 2785331Samw return (error); 2795331Samw } 2805331Samw 2815331Samw int 2825331Samw setattrat(int basefd, xattr_view_t view, const char *name, nvlist_t *request) 2835331Samw { 2845331Samw int error, saveerrno, namefd, xattrfd; 2855331Samw 2865331Samw if ((namefd = __openattrdirat(basefd, name)) < 0) 2875331Samw return (namefd); 2885331Samw 2895331Samw if ((xattrfd = xattr_openat(namefd, view, O_RDWR)) < 0) { 2905331Samw saveerrno = errno; 2915331Samw (void) close(namefd); 2925331Samw errno = saveerrno; 2935331Samw return (xattrfd); 2945331Samw } 2955331Samw 2965331Samw error = csetattr(xattrfd, request); 2975331Samw saveerrno = errno; 2985331Samw (void) close(namefd); 2995331Samw (void) close(xattrfd); 3005331Samw errno = saveerrno; 3015331Samw return (error); 3025331Samw } 3036082Smarks 3046082Smarks void 3056082Smarks libc_nvlist_free(nvlist_t *nvp) 3066082Smarks { 3076082Smarks nvfree(nvp); 3086082Smarks } 3096082Smarks 3106082Smarks int 3116082Smarks libc_nvlist_lookup_uint64(nvlist_t *nvp, const char *name, uint64_t *value) 3126082Smarks { 3136082Smarks return (nvlookupint64(nvp, name, value)); 3146082Smarks } 315