Home | History | Annotate | Download | only in gen
      1 /*
      2  * CDDL HEADER START
      3  *
      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.
      7  *
      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.
     12  *
     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]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     27 
     28 #include "lint.h"
     29 #include <string.h>
     30 #include <stdlib.h>
     31 #include <errno.h>
     32 #include <fcntl.h>
     33 #include <mtlib.h>
     34 #include <attr.h>
     35 #include <sys/types.h>
     36 #include <sys/syscall.h>
     37 #include <sys/stat.h>
     38 #include <sys/filio.h>
     39 #include <unistd.h>
     40 #include <dlfcn.h>
     41 #include <stdio.h>
     42 #include <atomic.h>
     43 
     44 static int (*nvpacker)(nvlist_t *, char **, size_t *, int, int);
     45 static int (*nvsize)(nvlist_t *, size_t *, int);
     46 static int (*nvunpacker)(char *, size_t, nvlist_t **);
     47 static int (*nvfree)(nvlist_t *);
     48 static int (*nvlookupint64)(nvlist_t *, const char *, uint64_t *);
     49 
     50 static mutex_t attrlock = DEFAULTMUTEX;
     51 static int initialized;
     52 extern int __openattrdirat(int basefd, const char *name);
     53 
     54 static char *xattr_view_name[XATTR_VIEW_LAST] = {
     55 	VIEW_READONLY,
     56 	VIEW_READWRITE
     57 };
     58 
     59 static int
     60 attrat_init()
     61 {
     62 	void *packer;
     63 	void *sizer;
     64 	void *unpacker;
     65 	void *freer;
     66 	void *looker;
     67 
     68 	if (initialized == 0) {
     69 		void *handle = dlopen("libnvpair.so.1", RTLD_LAZY);
     70 
     71 		if (handle == NULL ||
     72 		    (packer = dlsym(handle, "nvlist_pack")) == NULL ||
     73 		    (sizer = dlsym(handle, "nvlist_size")) == NULL ||
     74 		    (unpacker = dlsym(handle, "nvlist_unpack")) == NULL ||
     75 		    (freer = dlsym(handle, "nvlist_free")) == NULL ||
     76 		    (looker = dlsym(handle, "nvlist_lookup_uint64")) == NULL) {
     77 			if (handle)
     78 				dlclose(handle);
     79 			return (-1);
     80 		}
     81 
     82 		lmutex_lock(&attrlock);
     83 
     84 		if (initialized != 0) {
     85 			lmutex_unlock(&attrlock);
     86 			dlclose(handle);
     87 			return (0);
     88 		}
     89 
     90 		nvpacker = (int (*)(nvlist_t *, char **, size_t *, int, int))
     91 		    packer;
     92 		nvsize = (int (*)(nvlist_t *, size_t *, int))
     93 		    sizer;
     94 		nvunpacker = (int (*)(char *, size_t, nvlist_t **))
     95 		    unpacker;
     96 		nvfree = (int (*)(nvlist_t *))
     97 		    freer;
     98 		nvlookupint64 = (int (*)(nvlist_t *, const char *, uint64_t *))
     99 		    looker;
    100 
    101 		membar_producer();
    102 		initialized = 1;
    103 		lmutex_unlock(&attrlock);
    104 	}
    105 	return (0);
    106 }
    107 
    108 static int
    109 attr_nv_pack(nvlist_t *request, void **nv_request, size_t *nv_requestlen)
    110 {
    111 	size_t bufsize;
    112 	char *packbuf = NULL;
    113 
    114 	if (nvsize(request, &bufsize, NV_ENCODE_XDR) != 0) {
    115 		errno = EINVAL;
    116 		return (-1);
    117 	}
    118 
    119 	packbuf = malloc(bufsize);
    120 	if (packbuf == NULL)
    121 		return (-1);
    122 	if (nvpacker(request, &packbuf, &bufsize, NV_ENCODE_XDR, 0) != 0) {
    123 		free(packbuf);
    124 		errno = EINVAL;
    125 		return (-1);
    126 	} else {
    127 		*nv_request = (void *)packbuf;
    128 		*nv_requestlen = bufsize;
    129 	}
    130 	return (0);
    131 }
    132 
    133 static const char *
    134 view_to_name(xattr_view_t view)
    135 {
    136 	if (view >= XATTR_VIEW_LAST || view < 0)
    137 		return (NULL);
    138 	return (xattr_view_name[view]);
    139 }
    140 
    141 static int
    142 xattr_openat(int basefd, xattr_view_t view, int mode)
    143 {
    144 	const char *xattrname;
    145 	int xattrfd;
    146 	int oflag;
    147 
    148 	switch (view) {
    149 	case XATTR_VIEW_READONLY:
    150 		oflag = O_RDONLY;
    151 		break;
    152 	case XATTR_VIEW_READWRITE:
    153 		oflag = mode & O_RDWR;
    154 		break;
    155 	default:
    156 		errno = EINVAL;
    157 		return (-1);
    158 	}
    159 	if (mode & O_XATTR)
    160 		oflag |= O_XATTR;
    161 
    162 	xattrname = view_to_name(view);
    163 	xattrfd = openat(basefd, xattrname, oflag);
    164 	if (xattrfd < 0)
    165 		return (xattrfd);
    166 	/* Don't cache sysattr info (advisory) */
    167 	(void) directio(xattrfd, DIRECTIO_ON);
    168 	return (xattrfd);
    169 }
    170 
    171 static int
    172 cgetattr(int fd, nvlist_t **response)
    173 {
    174 	int error;
    175 	int bytesread;
    176 	void *nv_response;
    177 	size_t nv_responselen;
    178 	struct stat buf;
    179 
    180 	if (error = attrat_init())
    181 		return (error);
    182 	if ((error = fstat(fd, &buf)) != 0)
    183 		return (error);
    184 	nv_responselen = buf.st_size;
    185 
    186 	if ((nv_response = malloc(nv_responselen)) == NULL)
    187 		return (-1);
    188 	bytesread = read(fd, nv_response, nv_responselen);
    189 	if (bytesread != nv_responselen) {
    190 		free(nv_response);
    191 		errno = EFAULT;
    192 		return (-1);
    193 	}
    194 
    195 	if (nvunpacker(nv_response, nv_responselen, response)) {
    196 		free(nv_response);
    197 		errno = ENOMEM;
    198 		return (-1);
    199 	}
    200 
    201 	free(nv_response);
    202 	return (0);
    203 }
    204 
    205 static int
    206 csetattr(int fd, nvlist_t *request)
    207 {
    208 	int error, saveerrno;
    209 	int byteswritten;
    210 	void *nv_request;
    211 	size_t nv_requestlen;
    212 
    213 	if (error = attrat_init())
    214 		return (error);
    215 
    216 	if ((error = attr_nv_pack(request, &nv_request, &nv_requestlen)) != 0)
    217 		return (error);
    218 
    219 	byteswritten = write(fd, nv_request, nv_requestlen);
    220 	if (byteswritten != nv_requestlen) {
    221 		saveerrno = errno;
    222 		free(nv_request);
    223 		errno = saveerrno;
    224 		return (-1);
    225 	}
    226 
    227 	free(nv_request);
    228 	return (0);
    229 }
    230 
    231 int
    232 fgetattr(int basefd, xattr_view_t view, nvlist_t **response)
    233 {
    234 	int error, saveerrno, xattrfd;
    235 
    236 	if ((xattrfd = xattr_openat(basefd, view, O_XATTR)) < 0)
    237 		return (xattrfd);
    238 
    239 	error = cgetattr(xattrfd, response);
    240 	saveerrno = errno;
    241 	(void) close(xattrfd);
    242 	errno = saveerrno;
    243 	return (error);
    244 }
    245 
    246 int
    247 fsetattr(int basefd, xattr_view_t view, nvlist_t *request)
    248 {
    249 	int error, saveerrno, xattrfd;
    250 
    251 	if ((xattrfd = xattr_openat(basefd, view, O_RDWR | O_XATTR)) < 0)
    252 		return (xattrfd);
    253 	error = csetattr(xattrfd, request);
    254 	saveerrno = errno;
    255 	(void) close(xattrfd);
    256 	errno = saveerrno;
    257 	return (error);
    258 }
    259 
    260 int
    261 getattrat(int basefd, xattr_view_t view, const char *name, nvlist_t **response)
    262 {
    263 	int error, saveerrno, namefd, xattrfd;
    264 
    265 	if ((namefd = __openattrdirat(basefd, name)) < 0)
    266 		return (namefd);
    267 
    268 	if ((xattrfd = xattr_openat(namefd, view, 0)) < 0) {
    269 		saveerrno = errno;
    270 		(void) close(namefd);
    271 		errno = saveerrno;
    272 		return (xattrfd);
    273 	}
    274 
    275 	error = cgetattr(xattrfd, response);
    276 	saveerrno = errno;
    277 	(void) close(namefd);
    278 	(void) close(xattrfd);
    279 	errno = saveerrno;
    280 	return (error);
    281 }
    282 
    283 int
    284 setattrat(int basefd, xattr_view_t view, const char *name, nvlist_t *request)
    285 {
    286 	int error, saveerrno, namefd, xattrfd;
    287 
    288 	if ((namefd = __openattrdirat(basefd, name)) < 0)
    289 		return (namefd);
    290 
    291 	if ((xattrfd = xattr_openat(namefd, view, O_RDWR)) < 0) {
    292 		saveerrno = errno;
    293 		(void) close(namefd);
    294 		errno = saveerrno;
    295 		return (xattrfd);
    296 	}
    297 
    298 	error = csetattr(xattrfd, request);
    299 	saveerrno = errno;
    300 	(void) close(namefd);
    301 	(void) close(xattrfd);
    302 	errno = saveerrno;
    303 	return (error);
    304 }
    305 
    306 void
    307 libc_nvlist_free(nvlist_t *nvp)
    308 {
    309 	nvfree(nvp);
    310 }
    311 
    312 int
    313 libc_nvlist_lookup_uint64(nvlist_t *nvp, const char *name, uint64_t *value)
    314 {
    315 	return (nvlookupint64(nvp, name, value));
    316 }
    317