xref: /titanic_50/usr/src/lib/smbsrv/libfksmbsrv/common/fake_xattr.c (revision b819cea2f73f98c5662230cc9affc8cc84f77fcf)
1*b819cea2SGordon Ross /*
2*b819cea2SGordon Ross  * CDDL HEADER START
3*b819cea2SGordon Ross  *
4*b819cea2SGordon Ross  * The contents of this file are subject to the terms of the
5*b819cea2SGordon Ross  * Common Development and Distribution License (the "License").
6*b819cea2SGordon Ross  * You may not use this file except in compliance with the License.
7*b819cea2SGordon Ross  *
8*b819cea2SGordon Ross  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*b819cea2SGordon Ross  * or http://www.opensolaris.org/os/licensing.
10*b819cea2SGordon Ross  * See the License for the specific language governing permissions
11*b819cea2SGordon Ross  * and limitations under the License.
12*b819cea2SGordon Ross  *
13*b819cea2SGordon Ross  * When distributing Covered Code, include this CDDL HEADER in each
14*b819cea2SGordon Ross  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*b819cea2SGordon Ross  * If applicable, add the following below this CDDL HEADER, with the
16*b819cea2SGordon Ross  * fields enclosed by brackets "[]" replaced with your own identifying
17*b819cea2SGordon Ross  * information: Portions Copyright [yyyy] [name of copyright owner]
18*b819cea2SGordon Ross  *
19*b819cea2SGordon Ross  * CDDL HEADER END
20*b819cea2SGordon Ross  */
21*b819cea2SGordon Ross /*
22*b819cea2SGordon Ross  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23*b819cea2SGordon Ross  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
24*b819cea2SGordon Ross  */
25*b819cea2SGordon Ross 
26*b819cea2SGordon Ross #include <sys/types.h>
27*b819cea2SGordon Ross #include <sys/vnode.h>
28*b819cea2SGordon Ross #include <sys/debug.h>
29*b819cea2SGordon Ross 
30*b819cea2SGordon Ross #include <attr.h>
31*b819cea2SGordon Ross #include <libnvpair.h>
32*b819cea2SGordon Ross 
33*b819cea2SGordon Ross static uint64_t zero_times[2];
34*b819cea2SGordon Ross 
35*b819cea2SGordon Ross static int
36*b819cea2SGordon Ross getxva_parse_nvl(xvattr_t *xvap,
37*b819cea2SGordon Ross     xoptattr_t *xoap, nvlist_t *nvl);
38*b819cea2SGordon Ross 
39*b819cea2SGordon Ross /*
40*b819cea2SGordon Ross  * See similar code to parse the nvlist in:
41*b819cea2SGordon Ross  * uts/common/fs/xattr.c : xattr_file_write()
42*b819cea2SGordon Ross  */
43*b819cea2SGordon Ross int
fop__getxvattr(vnode_t * vp,xvattr_t * xvap)44*b819cea2SGordon Ross fop__getxvattr(vnode_t *vp, xvattr_t *xvap)
45*b819cea2SGordon Ross {
46*b819cea2SGordon Ross 	nvlist_t *nvl = NULL;
47*b819cea2SGordon Ross 	xoptattr_t *xoap = NULL;
48*b819cea2SGordon Ross 	int error;
49*b819cea2SGordon Ross 
50*b819cea2SGordon Ross 	if ((xoap = xva_getxoptattr(xvap)) == NULL) {
51*b819cea2SGordon Ross 		return (EINVAL);
52*b819cea2SGordon Ross 	}
53*b819cea2SGordon Ross 
54*b819cea2SGordon Ross 	error = fgetattr(vp->v_fd, XATTR_VIEW_READWRITE, &nvl);
55*b819cea2SGordon Ross 	if (error == 0) {
56*b819cea2SGordon Ross 		error = getxva_parse_nvl(xvap, xoap, nvl);
57*b819cea2SGordon Ross 		nvlist_free(nvl);
58*b819cea2SGordon Ross 		nvl = NULL;
59*b819cea2SGordon Ross 	}
60*b819cea2SGordon Ross 
61*b819cea2SGordon Ross 	/*
62*b819cea2SGordon Ross 	 * Also get the readonly attrs, but don't fail.
63*b819cea2SGordon Ross 	 */
64*b819cea2SGordon Ross 	if (fgetattr(vp->v_fd, XATTR_VIEW_READONLY, &nvl) == 0) {
65*b819cea2SGordon Ross 		(void) getxva_parse_nvl(xvap, xoap, nvl);
66*b819cea2SGordon Ross 		nvlist_free(nvl);
67*b819cea2SGordon Ross 	}
68*b819cea2SGordon Ross 
69*b819cea2SGordon Ross 	return (error);
70*b819cea2SGordon Ross }
71*b819cea2SGordon Ross 
72*b819cea2SGordon Ross static int
getxva_parse_nvl(xvattr_t * xvap,xoptattr_t * xoap,nvlist_t * nvl)73*b819cea2SGordon Ross getxva_parse_nvl(xvattr_t *xvap,
74*b819cea2SGordon Ross     xoptattr_t *xoap, nvlist_t *nvl)
75*b819cea2SGordon Ross {
76*b819cea2SGordon Ross 	nvpair_t *pair = NULL;
77*b819cea2SGordon Ross 	int error;
78*b819cea2SGordon Ross 
79*b819cea2SGordon Ross 	while (pair = nvlist_next_nvpair(nvl, pair)) {
80*b819cea2SGordon Ross 		data_type_t type;
81*b819cea2SGordon Ross 		f_attr_t attr;
82*b819cea2SGordon Ross 		boolean_t value = B_FALSE;
83*b819cea2SGordon Ross 		uint64_t *times = zero_times;
84*b819cea2SGordon Ross 		uint_t nelems = 2;
85*b819cea2SGordon Ross 
86*b819cea2SGordon Ross 		/*
87*b819cea2SGordon Ross 		 * Validate the name and type of each attribute.
88*b819cea2SGordon Ross 		 * Log any unknown names and continue.  This will
89*b819cea2SGordon Ross 		 * help if additional attributes are added later.
90*b819cea2SGordon Ross 		 */
91*b819cea2SGordon Ross 		type = nvpair_type(pair);
92*b819cea2SGordon Ross 		attr = name_to_attr(nvpair_name(pair));
93*b819cea2SGordon Ross 		if (attr == F_ATTR_INVAL)
94*b819cea2SGordon Ross 			continue;
95*b819cea2SGordon Ross 
96*b819cea2SGordon Ross 		/*
97*b819cea2SGordon Ross 		 * Verify nvlist type matches required type and view is OK
98*b819cea2SGordon Ross 		 */
99*b819cea2SGordon Ross 
100*b819cea2SGordon Ross 		if (type != attr_to_data_type(attr) ||
101*b819cea2SGordon Ross 		    (attr_to_xattr_view(attr) == XATTR_VIEW_READONLY))
102*b819cea2SGordon Ross 			continue;
103*b819cea2SGordon Ross 
104*b819cea2SGordon Ross 		/*
105*b819cea2SGordon Ross 		 * For OWNERSID/GROUPSID, just skip.
106*b819cea2SGordon Ross 		 */
107*b819cea2SGordon Ross 		if ((attr == F_OWNERSID || attr == F_GROUPSID))
108*b819cea2SGordon Ross 			continue;
109*b819cea2SGordon Ross 
110*b819cea2SGordon Ross 		/*
111*b819cea2SGordon Ross 		 * Retrieve data from nvpair
112*b819cea2SGordon Ross 		 */
113*b819cea2SGordon Ross 		switch (type) {
114*b819cea2SGordon Ross 		case DATA_TYPE_BOOLEAN_VALUE:
115*b819cea2SGordon Ross 			if (nvpair_value_boolean_value(pair, &value)) {
116*b819cea2SGordon Ross 				error = EINVAL;
117*b819cea2SGordon Ross 				goto out;
118*b819cea2SGordon Ross 			}
119*b819cea2SGordon Ross 			break;
120*b819cea2SGordon Ross 
121*b819cea2SGordon Ross 		case DATA_TYPE_UINT64_ARRAY:
122*b819cea2SGordon Ross 			if (nvpair_value_uint64_array(pair, &times, &nelems)) {
123*b819cea2SGordon Ross 				error = EINVAL;
124*b819cea2SGordon Ross 				goto out;
125*b819cea2SGordon Ross 			}
126*b819cea2SGordon Ross 			if (nelems < 2)
127*b819cea2SGordon Ross 				continue;
128*b819cea2SGordon Ross 			break;
129*b819cea2SGordon Ross 
130*b819cea2SGordon Ross 		case DATA_TYPE_NVLIST:
131*b819cea2SGordon Ross 			continue;
132*b819cea2SGordon Ross 
133*b819cea2SGordon Ross 		case DATA_TYPE_UINT8_ARRAY:
134*b819cea2SGordon Ross 			continue;
135*b819cea2SGordon Ross 
136*b819cea2SGordon Ross 		default:
137*b819cea2SGordon Ross 			error = EINVAL;
138*b819cea2SGordon Ross 			goto out;
139*b819cea2SGordon Ross 		}
140*b819cea2SGordon Ross 
141*b819cea2SGordon Ross 		switch (attr) {
142*b819cea2SGordon Ross 		/*
143*b819cea2SGordon Ross 		 * If we have several similar optional attributes to
144*b819cea2SGordon Ross 		 * process then we should do it all together here so that
145*b819cea2SGordon Ross 		 * xoap and the requested bitmap can be set in one place.
146*b819cea2SGordon Ross 		 */
147*b819cea2SGordon Ross 		case F_READONLY:
148*b819cea2SGordon Ross 			XVA_SET_RTN(xvap, XAT_READONLY);
149*b819cea2SGordon Ross 			xoap->xoa_readonly = value;
150*b819cea2SGordon Ross 			break;
151*b819cea2SGordon Ross 
152*b819cea2SGordon Ross 		case F_HIDDEN:
153*b819cea2SGordon Ross 			XVA_SET_RTN(xvap, XAT_HIDDEN);
154*b819cea2SGordon Ross 			xoap->xoa_hidden = value;
155*b819cea2SGordon Ross 			break;
156*b819cea2SGordon Ross 
157*b819cea2SGordon Ross 		case F_SYSTEM:
158*b819cea2SGordon Ross 			XVA_SET_RTN(xvap, XAT_SYSTEM);
159*b819cea2SGordon Ross 			xoap->xoa_system = value;
160*b819cea2SGordon Ross 			break;
161*b819cea2SGordon Ross 
162*b819cea2SGordon Ross 		case F_ARCHIVE:
163*b819cea2SGordon Ross 			XVA_SET_RTN(xvap, XAT_ARCHIVE);
164*b819cea2SGordon Ross 			xoap->xoa_archive = value;
165*b819cea2SGordon Ross 			break;
166*b819cea2SGordon Ross 
167*b819cea2SGordon Ross 		case F_CRTIME:
168*b819cea2SGordon Ross 			XVA_SET_RTN(xvap, XAT_CREATETIME);
169*b819cea2SGordon Ross 			xoap->xoa_createtime.tv_sec = times[0];
170*b819cea2SGordon Ross 			xoap->xoa_createtime.tv_nsec = times[1];
171*b819cea2SGordon Ross 			break;
172*b819cea2SGordon Ross 
173*b819cea2SGordon Ross 		case F_REPARSE:
174*b819cea2SGordon Ross 			XVA_SET_RTN(xvap, XAT_REPARSE);
175*b819cea2SGordon Ross 			xoap->xoa_reparse = value;
176*b819cea2SGordon Ross 			break;
177*b819cea2SGordon Ross 
178*b819cea2SGordon Ross 		case F_OFFLINE:
179*b819cea2SGordon Ross 			XVA_SET_RTN(xvap, XAT_OFFLINE);
180*b819cea2SGordon Ross 			xoap->xoa_offline = value;
181*b819cea2SGordon Ross 			break;
182*b819cea2SGordon Ross 
183*b819cea2SGordon Ross 		case F_SPARSE:
184*b819cea2SGordon Ross 			XVA_SET_RTN(xvap, XAT_SPARSE);
185*b819cea2SGordon Ross 			xoap->xoa_sparse = value;
186*b819cea2SGordon Ross 			break;
187*b819cea2SGordon Ross 
188*b819cea2SGordon Ross 		default:
189*b819cea2SGordon Ross 			break;
190*b819cea2SGordon Ross 		}
191*b819cea2SGordon Ross 	}
192*b819cea2SGordon Ross 	error = 0;
193*b819cea2SGordon Ross 
194*b819cea2SGordon Ross out:
195*b819cea2SGordon Ross 	return (error);
196*b819cea2SGordon Ross }
197*b819cea2SGordon Ross 
198*b819cea2SGordon Ross /*
199*b819cea2SGordon Ross  * See similar code to build the nvlist in:
200*b819cea2SGordon Ross  * uts/common/fs/xattr.c : xattr_fill_nvlist()
201*b819cea2SGordon Ross  */
202*b819cea2SGordon Ross int
fop__setxvattr(vnode_t * vp,xvattr_t * xvap)203*b819cea2SGordon Ross fop__setxvattr(vnode_t *vp, xvattr_t *xvap)
204*b819cea2SGordon Ross {
205*b819cea2SGordon Ross 	uint64_t times[2];
206*b819cea2SGordon Ross 	nvlist_t *nvl;
207*b819cea2SGordon Ross 	int error;
208*b819cea2SGordon Ross 	xoptattr_t *xoap;	/* Pointer to optional attributes */
209*b819cea2SGordon Ross 
210*b819cea2SGordon Ross 	if ((xoap = xva_getxoptattr(xvap)) == NULL)
211*b819cea2SGordon Ross 		return (EINVAL);
212*b819cea2SGordon Ross 
213*b819cea2SGordon Ross 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP))
214*b819cea2SGordon Ross 		return (ENOMEM);
215*b819cea2SGordon Ross 
216*b819cea2SGordon Ross 	if (XVA_ISSET_REQ(xvap, XAT_READONLY)) {
217*b819cea2SGordon Ross 		VERIFY(nvlist_add_boolean_value(nvl,
218*b819cea2SGordon Ross 		    attr_to_name(F_READONLY),
219*b819cea2SGordon Ross 		    xoap->xoa_readonly) == 0);
220*b819cea2SGordon Ross 	}
221*b819cea2SGordon Ross 
222*b819cea2SGordon Ross 	if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) {
223*b819cea2SGordon Ross 		VERIFY(nvlist_add_boolean_value(nvl,
224*b819cea2SGordon Ross 		    attr_to_name(F_HIDDEN),
225*b819cea2SGordon Ross 		    xoap->xoa_hidden) == 0);
226*b819cea2SGordon Ross 	}
227*b819cea2SGordon Ross 
228*b819cea2SGordon Ross 	if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) {
229*b819cea2SGordon Ross 		VERIFY(nvlist_add_boolean_value(nvl,
230*b819cea2SGordon Ross 		    attr_to_name(F_SYSTEM),
231*b819cea2SGordon Ross 		    xoap->xoa_system) == 0);
232*b819cea2SGordon Ross 	}
233*b819cea2SGordon Ross 
234*b819cea2SGordon Ross 	if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) {
235*b819cea2SGordon Ross 		VERIFY(nvlist_add_boolean_value(nvl,
236*b819cea2SGordon Ross 		    attr_to_name(F_ARCHIVE),
237*b819cea2SGordon Ross 		    xoap->xoa_archive) == 0);
238*b819cea2SGordon Ross 	}
239*b819cea2SGordon Ross 
240*b819cea2SGordon Ross 	if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) {
241*b819cea2SGordon Ross 		times[0] = xoap->xoa_createtime.tv_sec;
242*b819cea2SGordon Ross 		times[1] = xoap->xoa_createtime.tv_nsec;
243*b819cea2SGordon Ross 		VERIFY(nvlist_add_uint64_array(nvl,
244*b819cea2SGordon Ross 		    attr_to_name(F_CRTIME),
245*b819cea2SGordon Ross 		    times, 2) == 0);
246*b819cea2SGordon Ross 	}
247*b819cea2SGordon Ross 
248*b819cea2SGordon Ross 	if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) {
249*b819cea2SGordon Ross 		VERIFY(nvlist_add_boolean_value(nvl,
250*b819cea2SGordon Ross 		    attr_to_name(F_REPARSE),
251*b819cea2SGordon Ross 		    xoap->xoa_reparse) == 0);
252*b819cea2SGordon Ross 	}
253*b819cea2SGordon Ross 
254*b819cea2SGordon Ross 	if (XVA_ISSET_REQ(xvap, XAT_OFFLINE)) {
255*b819cea2SGordon Ross 		VERIFY(nvlist_add_boolean_value(nvl,
256*b819cea2SGordon Ross 		    attr_to_name(F_OFFLINE),
257*b819cea2SGordon Ross 		    xoap->xoa_offline) == 0);
258*b819cea2SGordon Ross 	}
259*b819cea2SGordon Ross 
260*b819cea2SGordon Ross 	if (XVA_ISSET_REQ(xvap, XAT_SPARSE)) {
261*b819cea2SGordon Ross 		VERIFY(nvlist_add_boolean_value(nvl,
262*b819cea2SGordon Ross 		    attr_to_name(F_SPARSE),
263*b819cea2SGordon Ross 		    xoap->xoa_sparse) == 0);
264*b819cea2SGordon Ross 	}
265*b819cea2SGordon Ross 
266*b819cea2SGordon Ross 	error = fsetattr(vp->v_fd, XATTR_VIEW_READWRITE, nvl);
267*b819cea2SGordon Ross 
268*b819cea2SGordon Ross 	nvlist_free(nvl);
269*b819cea2SGordon Ross 
270*b819cea2SGordon Ross 	return (error);
271*b819cea2SGordon Ross }
272