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