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