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, ×, &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