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*5902Smarks * 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 **); 465331Samw static mutex_t attrlock = DEFAULTMUTEX; 475331Samw static int initialized; 485331Samw extern int __openattrdirat(int basefd, const char *name); 495331Samw 505331Samw static char *xattr_view_name[XATTR_VIEW_LAST] = { 515331Samw VIEW_READONLY, 525331Samw VIEW_READWRITE 535331Samw }; 545331Samw 555331Samw static int 565331Samw attrat_init() 575331Samw { 585331Samw if (initialized == 0) { 595331Samw lmutex_lock(&attrlock); 605331Samw if (initialized == 1) { 615331Samw lmutex_unlock(&attrlock); 625331Samw return (0); 635331Samw } 645331Samw 655331Samw void *libnvhandle = dlopen("libnvpair.so.1", RTLD_LAZY); 665331Samw if (libnvhandle == NULL || (nvpacker = (int (*)(nvlist_t *, 675331Samw char **, size_t *, int, int)) dlsym(libnvhandle, 685331Samw "nvlist_pack")) == NULL || 695331Samw (nvsize = (int (*)(nvlist_t *, 705331Samw size_t *, int)) dlsym(libnvhandle, 715331Samw "nvlist_size")) == NULL || 725331Samw (nvunpacker = (int (*)(char *, size_t, 735331Samw nvlist_t **)) dlsym(libnvhandle, 745331Samw "nvlist_unpack")) == NULL) { 755331Samw if (libnvhandle) 765331Samw dlclose(libnvhandle); 775331Samw lmutex_unlock(&attrlock); 78*5902Smarks return (-1); 795331Samw } 805331Samw 815331Samw initialized = 1; 825331Samw lmutex_unlock(&attrlock); 835331Samw } 845331Samw return (0); 855331Samw } 865331Samw 875331Samw static int 885331Samw attr_nv_pack(nvlist_t *request, void **nv_request, size_t *nv_requestlen) 895331Samw { 905331Samw size_t bufsize; 915331Samw char *packbuf = NULL; 925331Samw 935331Samw if (nvsize(request, &bufsize, NV_ENCODE_XDR) != 0) { 94*5902Smarks errno = EINVAL; 95*5902Smarks return (-1); 965331Samw } 975331Samw 985331Samw packbuf = malloc(bufsize); 995331Samw if (packbuf == NULL) 100*5902Smarks return (-1); 1015331Samw if (nvpacker(request, &packbuf, &bufsize, NV_ENCODE_XDR, 0) != 0) { 1025331Samw free(packbuf); 103*5902Smarks errno = EINVAL; 104*5902Smarks return (-1); 1055331Samw } else { 1065331Samw *nv_request = (void *)packbuf; 1075331Samw *nv_requestlen = bufsize; 1085331Samw } 1095331Samw return (0); 1105331Samw } 1115331Samw 1125331Samw static const char * 1135331Samw view_to_name(xattr_view_t view) 1145331Samw { 1155331Samw if (view >= XATTR_VIEW_LAST || view < 0) 1165331Samw return (NULL); 1175331Samw return (xattr_view_name[view]); 1185331Samw } 1195331Samw 1205331Samw static int 1215331Samw xattr_openat(int basefd, xattr_view_t view, int mode) 1225331Samw { 1235331Samw const char *xattrname; 1245331Samw int xattrfd; 1255331Samw int oflag; 1265331Samw 1275331Samw switch (view) { 1285331Samw case XATTR_VIEW_READONLY: 1295331Samw oflag = O_RDONLY; 1305331Samw break; 1315331Samw case XATTR_VIEW_READWRITE: 1325331Samw oflag = mode & O_RDWR; 1335331Samw break; 1345331Samw default: 135*5902Smarks errno = EINVAL; 1365331Samw return (-1); 1375331Samw } 1385331Samw if (mode & O_XATTR) 1395331Samw oflag |= O_XATTR; 1405331Samw 1415331Samw xattrname = view_to_name(view); 1425331Samw xattrfd = openat(basefd, xattrname, oflag); 1435331Samw if (xattrfd < 0) 1445331Samw return (xattrfd); 1455331Samw /* Don't cache sysattr info (advisory) */ 1465331Samw (void) directio(xattrfd, DIRECTIO_ON); 1475331Samw return (xattrfd); 1485331Samw } 1495331Samw 1505331Samw static int 1515331Samw cgetattr(int fd, nvlist_t **response) 1525331Samw { 1535331Samw int error; 1545331Samw int bytesread; 1555331Samw void *nv_response; 1565331Samw size_t nv_responselen; 1575331Samw struct stat buf; 1585331Samw 1595331Samw if (error = attrat_init()) 160*5902Smarks return (error); 1615331Samw if ((error = fstat(fd, &buf)) != 0) 162*5902Smarks return (error); 1635331Samw nv_responselen = buf.st_size; 1645331Samw 1655331Samw if ((nv_response = malloc(nv_responselen)) == NULL) 166*5902Smarks return (-1); 1675331Samw bytesread = read(fd, nv_response, nv_responselen); 168*5902Smarks if (bytesread != nv_responselen) { 169*5902Smarks free(nv_response); 170*5902Smarks errno = EFAULT; 171*5902Smarks return (-1); 172*5902Smarks } 1735331Samw 174*5902Smarks if (nvunpacker(nv_response, nv_responselen, response)) { 175*5902Smarks free(nv_response); 176*5902Smarks errno = ENOMEM; 177*5902Smarks return (-1); 178*5902Smarks } 179*5902Smarks 1805331Samw free(nv_response); 181*5902Smarks return (0); 1825331Samw } 1835331Samw 1845331Samw static int 1855331Samw csetattr(int fd, nvlist_t *request) 1865331Samw { 1875331Samw int error, saveerrno; 1885331Samw int byteswritten; 1895331Samw void *nv_request; 1905331Samw size_t nv_requestlen; 1915331Samw 1925331Samw if (error = attrat_init()) 193*5902Smarks return (error); 1945331Samw 1955331Samw if ((error = attr_nv_pack(request, &nv_request, &nv_requestlen)) != 0) 196*5902Smarks return (error); 1975331Samw 1985331Samw byteswritten = write(fd, nv_request, nv_requestlen); 1995331Samw if (byteswritten != nv_requestlen) { 2005331Samw saveerrno = errno; 2015331Samw free(nv_request); 2025331Samw errno = saveerrno; 203*5902Smarks return (-1); 2045331Samw } 2055331Samw 2065331Samw free(nv_request); 2075331Samw return (0); 2085331Samw } 2095331Samw 2105331Samw int 2115331Samw fgetattr(int basefd, xattr_view_t view, nvlist_t **response) 2125331Samw { 2135331Samw int error, saveerrno, xattrfd; 2145331Samw 2155331Samw if ((xattrfd = xattr_openat(basefd, view, O_XATTR)) < 0) 2165331Samw return (xattrfd); 2175331Samw 2185331Samw error = cgetattr(xattrfd, response); 2195331Samw saveerrno = errno; 2205331Samw (void) close(xattrfd); 2215331Samw errno = saveerrno; 2225331Samw return (error); 2235331Samw } 2245331Samw 2255331Samw int 2265331Samw fsetattr(int basefd, xattr_view_t view, nvlist_t *request) 2275331Samw { 2285331Samw int error, saveerrno, xattrfd; 2295331Samw 2305331Samw if ((xattrfd = xattr_openat(basefd, view, O_RDWR | O_XATTR)) < 0) 2315331Samw return (xattrfd); 2325331Samw error = csetattr(xattrfd, request); 2335331Samw saveerrno = errno; 2345331Samw (void) close(xattrfd); 2355331Samw errno = saveerrno; 2365331Samw return (error); 2375331Samw } 2385331Samw 2395331Samw int 2405331Samw getattrat(int basefd, xattr_view_t view, const char *name, nvlist_t **response) 2415331Samw { 2425331Samw int error, saveerrno, namefd, xattrfd; 2435331Samw 2445331Samw if ((namefd = __openattrdirat(basefd, name)) < 0) 2455331Samw return (namefd); 2465331Samw 2475331Samw if ((xattrfd = xattr_openat(namefd, view, 0)) < 0) { 2485331Samw saveerrno = errno; 2495331Samw (void) close(namefd); 2505331Samw errno = saveerrno; 2515331Samw return (xattrfd); 2525331Samw } 2535331Samw 2545331Samw error = cgetattr(xattrfd, response); 2555331Samw saveerrno = errno; 2565331Samw (void) close(namefd); 2575331Samw (void) close(xattrfd); 2585331Samw errno = saveerrno; 2595331Samw return (error); 2605331Samw } 2615331Samw 2625331Samw int 2635331Samw setattrat(int basefd, xattr_view_t view, const char *name, nvlist_t *request) 2645331Samw { 2655331Samw int error, saveerrno, namefd, xattrfd; 2665331Samw 2675331Samw if ((namefd = __openattrdirat(basefd, name)) < 0) 2685331Samw return (namefd); 2695331Samw 2705331Samw if ((xattrfd = xattr_openat(namefd, view, O_RDWR)) < 0) { 2715331Samw saveerrno = errno; 2725331Samw (void) close(namefd); 2735331Samw errno = saveerrno; 2745331Samw return (xattrfd); 2755331Samw } 2765331Samw 2775331Samw error = csetattr(xattrfd, request); 2785331Samw saveerrno = errno; 2795331Samw (void) close(namefd); 2805331Samw (void) close(xattrfd); 2815331Samw errno = saveerrno; 2825331Samw return (error); 2835331Samw } 284