]>
Commit | Line | Data |
---|---|---|
2d21ac55 A |
1 | /* |
2 | * Copyright (c) 2006-2007 Apple Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
14 | * | |
15 | * Please obtain a copy of the License at | |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
18 | * The Original Code and all software distributed under the License are | |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
23 | * Please see the License for the specific language governing rights and | |
24 | * limitations under the License. | |
25 | * | |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ | |
27 | */ | |
28 | ||
29 | /* | |
30 | * miscellaneous support functions for NFSv4 | |
31 | */ | |
32 | #include <sys/param.h> | |
33 | #include <sys/proc.h> | |
34 | #include <sys/kauth.h> | |
35 | #include <sys/systm.h> | |
36 | #include <sys/kernel.h> | |
37 | #include <sys/mount_internal.h> | |
38 | #include <sys/vnode_internal.h> | |
39 | #include <sys/kpi_mbuf.h> | |
40 | #include <sys/socket.h> | |
41 | #include <sys/stat.h> | |
42 | #include <sys/malloc.h> | |
43 | #include <sys/syscall.h> | |
44 | #include <sys/ubc_internal.h> | |
45 | #include <sys/fcntl.h> | |
46 | #include <sys/quota.h> | |
47 | #include <sys/uio_internal.h> | |
48 | #include <sys/domain.h> | |
49 | #include <libkern/OSAtomic.h> | |
50 | #include <kern/thread_call.h> | |
51 | ||
52 | #include <sys/vm.h> | |
53 | #include <sys/vmparam.h> | |
54 | ||
55 | #include <sys/time.h> | |
56 | #include <kern/clock.h> | |
57 | ||
58 | #include <nfs/rpcv2.h> | |
59 | #include <nfs/nfsproto.h> | |
60 | #include <nfs/nfs.h> | |
61 | #include <nfs/nfsnode.h> | |
62 | #include <nfs/xdr_subs.h> | |
63 | #include <nfs/nfsm_subs.h> | |
64 | #include <nfs/nfs_gss.h> | |
65 | #include <nfs/nfsmount.h> | |
66 | #include <nfs/nfs_lock.h> | |
67 | ||
68 | #include <miscfs/specfs/specdev.h> | |
69 | ||
70 | #include <netinet/in.h> | |
71 | #include <net/kpi_interface.h> | |
72 | ||
73 | ||
74 | /* | |
75 | * NFSv4 SETCLIENTID | |
76 | */ | |
77 | int | |
78 | nfs4_setclientid(struct nfsmount *nmp) | |
79 | { | |
80 | struct sockaddr *saddr; | |
81 | uint64_t verifier; | |
82 | char id[128]; | |
83 | int idlen, len, error = 0, status, numops; | |
84 | u_int64_t xid; | |
85 | vfs_context_t ctx; | |
86 | thread_t thd; | |
87 | kauth_cred_t cred; | |
88 | struct nfsm_chain nmreq, nmrep; | |
89 | ||
90 | static uint8_t en0addr[6]; | |
91 | static uint8_t en0addr_set = 0; | |
92 | ||
93 | lck_mtx_lock(nfs_request_mutex); | |
94 | if (!en0addr_set) { | |
95 | ifnet_t interface = NULL; | |
96 | error = ifnet_find_by_name("en0", &interface); | |
97 | if (!error) | |
98 | error = ifnet_lladdr_copy_bytes(interface, en0addr, sizeof(en0addr)); | |
99 | if (error) | |
100 | printf("nfs4_setclientid: error getting en0 address, %d\n", error); | |
101 | if (!error) | |
102 | en0addr_set = 1; | |
103 | error = 0; | |
104 | if (interface) | |
105 | ifnet_release(interface); | |
106 | } | |
107 | lck_mtx_unlock(nfs_request_mutex); | |
108 | ||
109 | ctx = vfs_context_kernel(); /* XXX */ | |
110 | thd = vfs_context_thread(ctx); | |
111 | cred = vfs_context_ucred(ctx); | |
112 | ||
113 | nfsm_chain_null(&nmreq); | |
114 | nfsm_chain_null(&nmrep); | |
115 | ||
116 | /* ID: en0_address + server_address */ | |
117 | idlen = len = sizeof(en0addr); | |
118 | bcopy(en0addr, &id[0], len); | |
119 | saddr = mbuf_data(nmp->nm_nam); | |
120 | len = min(saddr->sa_len, sizeof(id)-idlen); | |
121 | bcopy(saddr, &id[idlen], len); | |
122 | idlen += len; | |
123 | ||
124 | // SETCLIENTID | |
125 | numops = 1; | |
126 | nfsm_chain_build_alloc_init(error, &nmreq, 14 * NFSX_UNSIGNED + idlen); | |
127 | nfsm_chain_add_compound_header(error, &nmreq, "setclientid", numops); | |
128 | numops--; | |
129 | nfsm_chain_add_32(error, &nmreq, NFS_OP_SETCLIENTID); | |
130 | /* nfs_client_id4 client; */ | |
131 | nfsm_chain_add_64(error, &nmreq, nmp->nm_mounttime); | |
132 | nfsm_chain_add_32(error, &nmreq, idlen); | |
133 | nfsm_chain_add_opaque(error, &nmreq, id, idlen); | |
134 | /* cb_client4 callback; */ | |
135 | /* We don't provide callback info yet */ | |
136 | nfsm_chain_add_32(error, &nmreq, 0); /* callback program */ | |
137 | nfsm_chain_add_string(error, &nmreq, "", 0); /* callback r_netid */ | |
138 | nfsm_chain_add_string(error, &nmreq, "", 0); /* callback r_addr */ | |
139 | nfsm_chain_add_32(error, &nmreq, 0); /* callback_ident */ | |
140 | nfsm_chain_build_done(error, &nmreq); | |
141 | nfsm_assert(error, (numops == 0), EPROTO); | |
142 | nfsmout_if(error); | |
143 | error = nfs_request2(NULL, nmp->nm_mountp, &nmreq, NFSPROC4_COMPOUND, thd, cred, R_SETUP, &nmrep, &xid, &status); | |
144 | nfsm_chain_skip_tag(error, &nmrep); | |
145 | nfsm_chain_get_32(error, &nmrep, numops); | |
146 | nfsm_chain_op_check(error, &nmrep, NFS_OP_SETCLIENTID); | |
147 | if (error == NFSERR_CLID_INUSE) | |
148 | printf("nfs4_setclientid: client ID in use?\n"); | |
149 | nfsmout_if(error); | |
150 | nfsm_chain_get_64(error, &nmrep, nmp->nm_clientid); | |
151 | nfsm_chain_get_64(error, &nmrep, verifier); | |
152 | nfsm_chain_cleanup(&nmreq); | |
153 | nfsm_chain_cleanup(&nmrep); | |
154 | ||
155 | // SETCLIENTID_CONFIRM | |
156 | numops = 1; | |
157 | nfsm_chain_build_alloc_init(error, &nmreq, 13 * NFSX_UNSIGNED); | |
158 | nfsm_chain_add_compound_header(error, &nmreq, "setclientid_confirm", numops); | |
159 | numops--; | |
160 | nfsm_chain_add_32(error, &nmreq, NFS_OP_SETCLIENTID_CONFIRM); | |
161 | nfsm_chain_add_64(error, &nmreq, nmp->nm_clientid); | |
162 | nfsm_chain_add_64(error, &nmreq, verifier); | |
163 | nfsm_chain_build_done(error, &nmreq); | |
164 | nfsm_assert(error, (numops == 0), EPROTO); | |
165 | nfsmout_if(error); | |
166 | error = nfs_request2(NULL, nmp->nm_mountp, &nmreq, NFSPROC4_COMPOUND, thd, cred, R_SETUP, &nmrep, &xid, &status); | |
167 | nfsm_chain_skip_tag(error, &nmrep); | |
168 | nfsm_chain_get_32(error, &nmrep, numops); | |
169 | nfsm_chain_op_check(error, &nmrep, NFS_OP_SETCLIENTID_CONFIRM); | |
170 | if (error) | |
171 | printf("nfs4_setclientid: confirm error %d\n", error); | |
172 | nfsmout: | |
173 | nfsm_chain_cleanup(&nmreq); | |
174 | nfsm_chain_cleanup(&nmrep); | |
175 | if (error) | |
176 | printf("nfs4_setclientid failed, %d\n", error); | |
177 | return (error); | |
178 | } | |
179 | ||
180 | /* | |
181 | * periodic timer to renew lease state on server | |
182 | */ | |
183 | void | |
184 | nfs4_renew_timer(void *param0, __unused void *param1) | |
185 | { | |
186 | struct nfsmount *nmp = param0; | |
187 | int error = 0, status, numops, interval; | |
188 | u_int64_t xid; | |
189 | vfs_context_t ctx; | |
190 | struct nfsm_chain nmreq, nmrep; | |
191 | ||
192 | ctx = vfs_context_kernel(); /* XXX */ | |
193 | ||
194 | nfsm_chain_null(&nmreq); | |
195 | nfsm_chain_null(&nmrep); | |
196 | ||
197 | // RENEW | |
198 | numops = 1; | |
199 | nfsm_chain_build_alloc_init(error, &nmreq, 8 * NFSX_UNSIGNED); | |
200 | nfsm_chain_add_compound_header(error, &nmreq, "renew", numops); | |
201 | numops--; | |
202 | nfsm_chain_add_32(error, &nmreq, NFS_OP_RENEW); | |
203 | nfsm_chain_add_64(error, &nmreq, nmp->nm_clientid); | |
204 | nfsm_chain_build_done(error, &nmreq); | |
205 | nfsm_assert(error, (numops == 0), EPROTO); | |
206 | nfsmout_if(error); | |
207 | error = nfs_request(NULL, nmp->nm_mountp, &nmreq, NFSPROC4_COMPOUND, ctx, &nmrep, &xid, &status); | |
208 | nfsm_chain_skip_tag(error, &nmrep); | |
209 | nfsm_chain_get_32(error, &nmrep, numops); | |
210 | nfsm_chain_op_check(error, &nmrep, NFS_OP_RENEW); | |
211 | nfsmout: | |
212 | if (error) | |
213 | printf("nfs4_renew_timer: error %d\n", error); | |
214 | nfsm_chain_cleanup(&nmreq); | |
215 | nfsm_chain_cleanup(&nmrep); | |
216 | ||
217 | interval = nmp->nm_fsattr.nfsa_lease / (error ? 4 : 2); | |
218 | if (interval < 1) | |
219 | interval = 1; | |
220 | nfs_interval_timer_start(nmp->nm_renew_timer, interval * 1000); | |
221 | } | |
222 | ||
223 | /* | |
224 | * Set a vnode attr's supported bits according to the given bitmap | |
225 | */ | |
226 | void | |
227 | nfs_vattr_set_supported(uint32_t *bitmap, struct vnode_attr *vap) | |
228 | { | |
229 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TYPE)) | |
230 | VATTR_SET_SUPPORTED(vap, va_type); | |
231 | // if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_CHANGE)) | |
232 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SIZE)) | |
233 | VATTR_SET_SUPPORTED(vap, va_data_size); | |
234 | // if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_NAMED_ATTR)) | |
235 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_FSID)) | |
236 | VATTR_SET_SUPPORTED(vap, va_fsid); | |
237 | // if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_ACL)) | |
238 | // VATTR_SET_SUPPORTED(vap, va_acl); | |
239 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_ARCHIVE)) | |
240 | VATTR_SET_SUPPORTED(vap, va_flags); | |
241 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_FILEID)) | |
242 | VATTR_SET_SUPPORTED(vap, va_fileid); | |
243 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_HIDDEN)) | |
244 | VATTR_SET_SUPPORTED(vap, va_flags); | |
245 | // if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MIMETYPE)) | |
246 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MODE)) | |
247 | VATTR_SET_SUPPORTED(vap, va_mode); | |
248 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_NUMLINKS)) | |
249 | VATTR_SET_SUPPORTED(vap, va_nlink); | |
250 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_OWNER)) | |
251 | VATTR_SET_SUPPORTED(vap, va_uid); | |
252 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_OWNER_GROUP)) | |
253 | VATTR_SET_SUPPORTED(vap, va_gid); | |
254 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_RAWDEV)) | |
255 | VATTR_SET_SUPPORTED(vap, va_rdev); | |
256 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SPACE_USED)) | |
257 | VATTR_SET_SUPPORTED(vap, va_total_alloc); | |
258 | // if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SYSTEM)) | |
259 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_ACCESS)) | |
260 | VATTR_SET_SUPPORTED(vap, va_access_time); | |
261 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_BACKUP)) | |
262 | VATTR_SET_SUPPORTED(vap, va_backup_time); | |
263 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_CREATE)) | |
264 | VATTR_SET_SUPPORTED(vap, va_create_time); | |
265 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_METADATA)) | |
266 | VATTR_SET_SUPPORTED(vap, va_change_time); | |
267 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_MODIFY)) | |
268 | VATTR_SET_SUPPORTED(vap, va_modify_time); | |
269 | } | |
270 | ||
271 | /* | |
272 | * Parse the attributes that are in the mbuf list and store them in | |
273 | * the given structures. | |
274 | */ | |
275 | int | |
276 | nfs4_parsefattr( | |
277 | struct nfsm_chain *nmc, | |
278 | struct nfs_fsattr *nfsap, | |
279 | struct nfs_vattr *nvap, | |
280 | fhandle_t *fhp, | |
281 | struct dqblk *dqbp) | |
282 | { | |
283 | int error = 0, attrbytes; | |
284 | uint32_t val, val2, val3, i, j; | |
285 | uint32_t bitmap[NFS_ATTR_BITMAP_LEN], len; | |
286 | char *s; | |
287 | struct nfs_fsattr nfsa_dummy; | |
288 | struct nfs_vattr nva_dummy; | |
289 | struct dqblk dqb_dummy; | |
290 | ||
291 | /* if not interested in some values... throw 'em into a local dummy variable */ | |
292 | if (!nfsap) | |
293 | nfsap = &nfsa_dummy; | |
294 | if (!nvap) | |
295 | nvap = &nva_dummy; | |
296 | if (!dqbp) | |
297 | dqbp = &dqb_dummy; | |
298 | ||
299 | attrbytes = val = val2 = val3 = 0; | |
300 | ||
301 | len = NFS_ATTR_BITMAP_LEN; | |
302 | nfsm_chain_get_bitmap(error, nmc, bitmap, len); | |
303 | /* add bits to object/fs attr bitmaps */ | |
304 | for (i=0; i < NFS_ATTR_BITMAP_LEN; i++) { | |
305 | nvap->nva_bitmap[i] |= bitmap[i] & nfs_object_attr_bitmap[i]; | |
306 | nfsap->nfsa_bitmap[i] |= bitmap[i] & nfs_fs_attr_bitmap[i]; | |
307 | } | |
308 | ||
309 | nfsm_chain_get_32(error, nmc, attrbytes); | |
310 | nfsmout_if(error); | |
311 | ||
312 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SUPPORTED_ATTRS)) { | |
313 | len = NFS_ATTR_BITMAP_LEN; | |
314 | nfsm_chain_get_bitmap(error, nmc, nfsap->nfsa_supp_attr, len); | |
315 | attrbytes -= (len + 1) * NFSX_UNSIGNED; | |
316 | } | |
317 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TYPE)) { | |
318 | nfsm_chain_get_32(error, nmc, val); | |
319 | nvap->nva_type = nfstov_type(val, NFS_VER4); | |
320 | attrbytes -= NFSX_UNSIGNED; | |
321 | } | |
322 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_FH_EXPIRE_TYPE)) { | |
323 | nfsm_chain_get_32(error, nmc, val); | |
324 | nfsmout_if(error); | |
325 | if (val != NFS_FH_PERSISTENT) | |
326 | printf("nfs: warning: non-persistent file handles!\n"); | |
327 | if (val & ~0xff) | |
328 | printf("nfs: warning unknown fh type: 0x%x\n", val); | |
329 | nfsap->nfsa_flags &= ~NFS_FSFLAG_FHTYPE_MASK; | |
330 | nfsap->nfsa_flags |= val << 24; | |
331 | attrbytes -= NFSX_UNSIGNED; | |
332 | } | |
333 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_CHANGE)) { | |
334 | nfsm_chain_get_64(error, nmc, nvap->nva_change); | |
335 | attrbytes -= 2 * NFSX_UNSIGNED; | |
336 | } | |
337 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SIZE)) { | |
338 | nfsm_chain_get_64(error, nmc, nvap->nva_size); | |
339 | attrbytes -= 2 * NFSX_UNSIGNED; | |
340 | } | |
341 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_LINK_SUPPORT)) { | |
342 | nfsm_chain_get_32(error, nmc, val); | |
343 | if (val) | |
344 | nfsap->nfsa_flags |= NFS_FSFLAG_LINK; | |
345 | else | |
346 | nfsap->nfsa_flags &= ~NFS_FSFLAG_LINK; | |
347 | attrbytes -= NFSX_UNSIGNED; | |
348 | } | |
349 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SYMLINK_SUPPORT)) { | |
350 | nfsm_chain_get_32(error, nmc, val); | |
351 | if (val) | |
352 | nfsap->nfsa_flags |= NFS_FSFLAG_SYMLINK; | |
353 | else | |
354 | nfsap->nfsa_flags &= ~NFS_FSFLAG_SYMLINK; | |
355 | attrbytes -= NFSX_UNSIGNED; | |
356 | } | |
357 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_NAMED_ATTR)) { | |
358 | nfsm_chain_get_32(error, nmc, val); | |
359 | if (val) | |
360 | nvap->nva_flags |= NFS_FFLAG_NAMED_ATTR; | |
361 | else | |
362 | nvap->nva_flags &= ~NFS_FFLAG_NAMED_ATTR; | |
363 | attrbytes -= NFSX_UNSIGNED; | |
364 | } | |
365 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_FSID)) { | |
366 | nfsm_chain_get_64(error, nmc, nvap->nva_fsid.major); | |
367 | nfsm_chain_get_64(error, nmc, nvap->nva_fsid.minor); | |
368 | attrbytes -= 4 * NFSX_UNSIGNED; | |
369 | } | |
370 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_UNIQUE_HANDLES)) { | |
371 | nfsm_chain_get_32(error, nmc, val); | |
372 | if (val) | |
373 | nfsap->nfsa_flags |= NFS_FSFLAG_UNIQUE_FH; | |
374 | else | |
375 | nfsap->nfsa_flags &= ~NFS_FSFLAG_UNIQUE_FH; | |
376 | attrbytes -= NFSX_UNSIGNED; | |
377 | } | |
378 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_LEASE_TIME)) { | |
379 | nfsm_chain_get_32(error, nmc, nfsap->nfsa_lease); | |
380 | attrbytes -= NFSX_UNSIGNED; | |
381 | } | |
382 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_RDATTR_ERROR)) { | |
383 | nfsm_chain_get_32(error, nmc, error); | |
384 | attrbytes -= NFSX_UNSIGNED; | |
385 | nfsmout_if(error); | |
386 | } | |
387 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_ACL)) { /* skip for now */ | |
388 | nfsm_chain_get_32(error, nmc, val); /* ACE count */ | |
389 | for (i=0; !error && (i < val); i++) { | |
390 | nfsm_chain_adv(error, nmc, 3 * NFSX_UNSIGNED); | |
391 | nfsm_chain_get_32(error, nmc, val2); /* string length */ | |
392 | nfsm_chain_adv(error, nmc, nfsm_rndup(val2)); | |
393 | attrbytes -= 4*NFSX_UNSIGNED + nfsm_rndup(val2); | |
394 | nfsm_assert(error, (attrbytes >= 0), EBADRPC); | |
395 | } | |
396 | } | |
397 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_ACLSUPPORT)) { | |
398 | nfsm_chain_get_32(error, nmc, val); | |
399 | if (val) | |
400 | nfsap->nfsa_flags |= NFS_FSFLAG_ACL; | |
401 | else | |
402 | nfsap->nfsa_flags &= ~NFS_FSFLAG_ACL; | |
403 | attrbytes -= NFSX_UNSIGNED; | |
404 | } | |
405 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_ARCHIVE)) { /* SF_ARCHIVED */ | |
406 | nfsm_chain_get_32(error, nmc, val); | |
407 | if (val) | |
408 | nvap->nva_flags |= NFS_FFLAG_ARCHIVED; | |
409 | else | |
410 | nvap->nva_flags &= ~NFS_FFLAG_ARCHIVED; | |
411 | attrbytes -= NFSX_UNSIGNED; | |
412 | } | |
413 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_CANSETTIME)) { | |
414 | nfsm_chain_get_32(error, nmc, val); | |
415 | if (val) | |
416 | nfsap->nfsa_flags |= NFS_FSFLAG_SET_TIME; | |
417 | else | |
418 | nfsap->nfsa_flags &= ~NFS_FSFLAG_SET_TIME; | |
419 | attrbytes -= NFSX_UNSIGNED; | |
420 | } | |
421 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_CASE_INSENSITIVE)) { | |
422 | nfsm_chain_get_32(error, nmc, val); | |
423 | if (val) | |
424 | nfsap->nfsa_flags |= NFS_FSFLAG_CASE_INSENSITIVE; | |
425 | else | |
426 | nfsap->nfsa_flags &= ~NFS_FSFLAG_CASE_INSENSITIVE; | |
427 | attrbytes -= NFSX_UNSIGNED; | |
428 | } | |
429 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_CASE_PRESERVING)) { | |
430 | nfsm_chain_get_32(error, nmc, val); | |
431 | if (val) | |
432 | nfsap->nfsa_flags |= NFS_FSFLAG_CASE_PRESERVING; | |
433 | else | |
434 | nfsap->nfsa_flags &= ~NFS_FSFLAG_CASE_PRESERVING; | |
435 | attrbytes -= NFSX_UNSIGNED; | |
436 | } | |
437 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_CHOWN_RESTRICTED)) { | |
438 | nfsm_chain_get_32(error, nmc, val); | |
439 | if (val) | |
440 | nfsap->nfsa_flags |= NFS_FSFLAG_CHOWN_RESTRICTED; | |
441 | else | |
442 | nfsap->nfsa_flags &= ~NFS_FSFLAG_CHOWN_RESTRICTED; | |
443 | attrbytes -= NFSX_UNSIGNED; | |
444 | } | |
445 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_FILEHANDLE)) { | |
446 | nfsm_chain_get_32(error, nmc, val); | |
447 | if (fhp) { | |
448 | fhp->fh_len = val; | |
449 | nfsm_chain_get_opaque(error, nmc, nfsm_rndup(val), fhp->fh_data); | |
450 | } else { | |
451 | nfsm_chain_adv(error, nmc, nfsm_rndup(val)); | |
452 | } | |
453 | attrbytes -= NFSX_UNSIGNED + nfsm_rndup(val); | |
454 | } | |
455 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_FILEID)) { | |
456 | nfsm_chain_get_64(error, nmc, nvap->nva_fileid); | |
457 | attrbytes -= 2 * NFSX_UNSIGNED; | |
458 | } | |
459 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_FILES_AVAIL)) { | |
460 | nfsm_chain_get_64(error, nmc, nfsap->nfsa_files_avail); | |
461 | attrbytes -= 2 * NFSX_UNSIGNED; | |
462 | } | |
463 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_FILES_FREE)) { | |
464 | nfsm_chain_get_64(error, nmc, nfsap->nfsa_files_free); | |
465 | attrbytes -= 2 * NFSX_UNSIGNED; | |
466 | } | |
467 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_FILES_TOTAL)) { | |
468 | nfsm_chain_get_64(error, nmc, nfsap->nfsa_files_total); | |
469 | attrbytes -= 2 * NFSX_UNSIGNED; | |
470 | } | |
471 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_FS_LOCATIONS)) { /* skip for now */ | |
472 | nfsm_chain_get_32(error, nmc, val); /* root path length */ | |
473 | nfsm_chain_adv(error, nmc, nfsm_rndup(val)); /* root path */ | |
474 | attrbytes -= (2 * NFSX_UNSIGNED) + nfsm_rndup(val); | |
475 | nfsm_chain_get_32(error, nmc, val); /* location count */ | |
476 | for (i=0; !error && (i < val); i++) { | |
477 | nfsm_chain_get_32(error, nmc, val2); /* server string length */ | |
478 | nfsm_chain_adv(error, nmc, nfsm_rndup(val2)); /* server string */ | |
479 | attrbytes -= (2 * NFSX_UNSIGNED) + nfsm_rndup(val2); | |
480 | nfsm_chain_get_32(error, nmc, val2); /* pathname component count */ | |
481 | for (j=0; !error && (j < val2); j++) { | |
482 | nfsm_chain_get_32(error, nmc, val3); /* component length */ | |
483 | nfsm_chain_adv(error, nmc, nfsm_rndup(val3)); /* component */ | |
484 | attrbytes -= NFSX_UNSIGNED + nfsm_rndup(val3); | |
485 | nfsm_assert(error, (attrbytes >= 0), EBADRPC); | |
486 | } | |
487 | nfsm_assert(error, (attrbytes >= 0), EBADRPC); | |
488 | } | |
489 | nfsm_assert(error, (attrbytes >= 0), EBADRPC); | |
490 | } | |
491 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_HIDDEN)) { /* UF_HIDDEN */ | |
492 | nfsm_chain_get_32(error, nmc, val); | |
493 | if (val) | |
494 | nvap->nva_flags |= NFS_FFLAG_HIDDEN; | |
495 | else | |
496 | nvap->nva_flags &= ~NFS_FFLAG_HIDDEN; | |
497 | attrbytes -= NFSX_UNSIGNED; | |
498 | } | |
499 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_HOMOGENEOUS)) { | |
500 | /* XXX If NOT homogeneous, we may need to clear flags on the mount */ | |
501 | nfsm_chain_get_32(error, nmc, val); | |
502 | if (val) | |
503 | nfsap->nfsa_flags |= NFS_FSFLAG_HOMOGENEOUS; | |
504 | else | |
505 | nfsap->nfsa_flags &= ~NFS_FSFLAG_HOMOGENEOUS; | |
506 | attrbytes -= NFSX_UNSIGNED; | |
507 | } | |
508 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MAXFILESIZE)) { | |
509 | nfsm_chain_get_64(error, nmc, nfsap->nfsa_maxfilesize); | |
510 | attrbytes -= 2 * NFSX_UNSIGNED; | |
511 | } | |
512 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MAXLINK)) { | |
513 | nfsm_chain_get_32(error, nmc, nvap->nva_maxlink); | |
514 | if (!error && (nfsap->nfsa_maxlink > INT32_MAX)) | |
515 | nfsap->nfsa_maxlink = INT32_MAX; | |
516 | attrbytes -= NFSX_UNSIGNED; | |
517 | } | |
518 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MAXNAME)) { | |
519 | nfsm_chain_get_32(error, nmc, nfsap->nfsa_maxname); | |
520 | if (!error && (nfsap->nfsa_maxname > INT32_MAX)) | |
521 | nfsap->nfsa_maxname = INT32_MAX; | |
522 | attrbytes -= NFSX_UNSIGNED; | |
523 | } | |
524 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MAXREAD)) { | |
525 | nfsm_chain_get_64(error, nmc, nfsap->nfsa_maxread); | |
526 | attrbytes -= 2 * NFSX_UNSIGNED; | |
527 | } | |
528 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MAXWRITE)) { | |
529 | nfsm_chain_get_64(error, nmc, nfsap->nfsa_maxwrite); | |
530 | attrbytes -= 2 * NFSX_UNSIGNED; | |
531 | } | |
532 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MIMETYPE)) { | |
533 | nfsm_chain_get_32(error, nmc, val); | |
534 | nfsm_chain_adv(error, nmc, nfsm_rndup(val)); | |
535 | attrbytes -= NFSX_UNSIGNED + nfsm_rndup(val); | |
536 | } | |
537 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MODE)) { | |
538 | nfsm_chain_get_32(error, nmc, nvap->nva_mode); | |
539 | attrbytes -= NFSX_UNSIGNED; | |
540 | } | |
541 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_NO_TRUNC)) { | |
542 | nfsm_chain_get_32(error, nmc, val); | |
543 | if (val) | |
544 | nfsap->nfsa_flags |= NFS_FSFLAG_NO_TRUNC; | |
545 | else | |
546 | nfsap->nfsa_flags &= ~NFS_FSFLAG_NO_TRUNC; | |
547 | attrbytes -= NFSX_UNSIGNED; | |
548 | } | |
549 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_NUMLINKS)) { | |
550 | nfsm_chain_get_32(error, nmc, val); | |
551 | nvap->nva_nlink = val; | |
552 | attrbytes -= NFSX_UNSIGNED; | |
553 | } | |
554 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_OWNER)) { /* XXX ugly hack for now */ | |
555 | nfsm_chain_get_32(error, nmc, len); | |
556 | nfsm_chain_get_opaque_pointer(error, nmc, len, s); | |
557 | attrbytes -= NFSX_UNSIGNED + nfsm_rndup(len); | |
558 | nfsmout_if(error); | |
559 | if ((*s >= '0') && (*s <= '9')) | |
560 | nvap->nva_uid = strtol(s, NULL, 10); | |
561 | else if (!strncmp(s, "nobody@", 7)) | |
562 | nvap->nva_uid = -2; | |
563 | else if (!strncmp(s, "root@", 5)) | |
564 | nvap->nva_uid = 0; | |
565 | else | |
566 | nvap->nva_uid = 99; /* unknown */ | |
567 | } | |
568 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_OWNER_GROUP)) { /* XXX ugly hack for now */ | |
569 | nfsm_chain_get_32(error, nmc, len); | |
570 | nfsm_chain_get_opaque_pointer(error, nmc, len, s); | |
571 | attrbytes -= NFSX_UNSIGNED + nfsm_rndup(len); | |
572 | nfsmout_if(error); | |
573 | if ((*s >= '0') && (*s <= '9')) | |
574 | nvap->nva_gid = strtol(s, NULL, 10); | |
575 | else if (!strncmp(s, "nobody@", 7)) | |
576 | nvap->nva_gid = -2; | |
577 | else if (!strncmp(s, "root@", 5)) | |
578 | nvap->nva_uid = 0; | |
579 | else | |
580 | nvap->nva_gid = 99; /* unknown */ | |
581 | } | |
582 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_QUOTA_AVAIL_HARD)) { | |
583 | nfsm_chain_get_64(error, nmc, dqbp->dqb_bhardlimit); | |
584 | attrbytes -= 2 * NFSX_UNSIGNED; | |
585 | } | |
586 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_QUOTA_AVAIL_SOFT)) { | |
587 | nfsm_chain_get_64(error, nmc, dqbp->dqb_bsoftlimit); | |
588 | attrbytes -= 2 * NFSX_UNSIGNED; | |
589 | } | |
590 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_QUOTA_USED)) { | |
591 | nfsm_chain_get_64(error, nmc, dqbp->dqb_curbytes); | |
592 | attrbytes -= 2 * NFSX_UNSIGNED; | |
593 | } | |
594 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_RAWDEV)) { | |
595 | nfsm_chain_get_32(error, nmc, nvap->nva_rawdev.specdata1); | |
596 | nfsm_chain_get_32(error, nmc, nvap->nva_rawdev.specdata2); | |
597 | attrbytes -= 2 * NFSX_UNSIGNED; | |
598 | } | |
599 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SPACE_AVAIL)) { | |
600 | nfsm_chain_get_64(error, nmc, nfsap->nfsa_space_avail); | |
601 | attrbytes -= 2 * NFSX_UNSIGNED; | |
602 | } | |
603 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SPACE_FREE)) { | |
604 | nfsm_chain_get_64(error, nmc, nfsap->nfsa_space_free); | |
605 | attrbytes -= 2 * NFSX_UNSIGNED; | |
606 | } | |
607 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SPACE_TOTAL)) { | |
608 | nfsm_chain_get_64(error, nmc, nfsap->nfsa_space_total); | |
609 | attrbytes -= 2 * NFSX_UNSIGNED; | |
610 | } | |
611 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SPACE_USED)) { | |
612 | nfsm_chain_get_64(error, nmc, nvap->nva_bytes); | |
613 | attrbytes -= 2 * NFSX_UNSIGNED; | |
614 | } | |
615 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SYSTEM)) { | |
616 | /* we'd support this if we had a flag to map it to... */ | |
617 | nfsm_chain_adv(error, nmc, NFSX_UNSIGNED); | |
618 | attrbytes -= NFSX_UNSIGNED; | |
619 | } | |
620 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_ACCESS)) { | |
621 | nfsm_chain_get_64(error, nmc, nvap->nva_timesec[NFSTIME_ACCESS]); | |
622 | nfsm_chain_get_32(error, nmc, nvap->nva_timensec[NFSTIME_ACCESS]); | |
623 | attrbytes -= 3 * NFSX_UNSIGNED; | |
624 | } | |
625 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_ACCESS_SET)) { | |
626 | nfsm_chain_adv(error, nmc, 4*NFSX_UNSIGNED); /* just skip it */ | |
627 | attrbytes -= 4 * NFSX_UNSIGNED; | |
628 | } | |
629 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_BACKUP)) { | |
630 | nfsm_chain_get_64(error, nmc, nvap->nva_timesec[NFSTIME_BACKUP]); | |
631 | nfsm_chain_get_32(error, nmc, nvap->nva_timensec[NFSTIME_BACKUP]); | |
632 | attrbytes -= 3 * NFSX_UNSIGNED; | |
633 | } | |
634 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_CREATE)) { | |
635 | nfsm_chain_get_64(error, nmc, nvap->nva_timesec[NFSTIME_CREATE]); | |
636 | nfsm_chain_get_32(error, nmc, nvap->nva_timensec[NFSTIME_CREATE]); | |
637 | attrbytes -= 3 * NFSX_UNSIGNED; | |
638 | } | |
639 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_DELTA)) { /* skip for now */ | |
640 | nfsm_chain_adv(error, nmc, 3*NFSX_UNSIGNED); | |
641 | attrbytes -= 3 * NFSX_UNSIGNED; | |
642 | } | |
643 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_METADATA)) { | |
644 | nfsm_chain_get_64(error, nmc, nvap->nva_timesec[NFSTIME_CHANGE]); | |
645 | nfsm_chain_get_32(error, nmc, nvap->nva_timensec[NFSTIME_CHANGE]); | |
646 | attrbytes -= 3 * NFSX_UNSIGNED; | |
647 | } | |
648 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_MODIFY)) { | |
649 | nfsm_chain_get_64(error, nmc, nvap->nva_timesec[NFSTIME_MODIFY]); | |
650 | nfsm_chain_get_32(error, nmc, nvap->nva_timensec[NFSTIME_MODIFY]); | |
651 | attrbytes -= 3 * NFSX_UNSIGNED; | |
652 | } | |
653 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_MODIFY_SET)) { | |
654 | nfsm_chain_adv(error, nmc, 4*NFSX_UNSIGNED); /* just skip it */ | |
655 | attrbytes -= 4 * NFSX_UNSIGNED; | |
656 | } | |
657 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MOUNTED_ON_FILEID)) { /* skip for now */ | |
658 | nfsm_chain_adv(error, nmc, 2*NFSX_UNSIGNED); | |
659 | attrbytes -= 2 * NFSX_UNSIGNED; | |
660 | } | |
661 | /* advance over any leftover attrbytes */ | |
662 | nfsm_assert(error, (attrbytes >= 0), EBADRPC); | |
663 | nfsm_chain_adv(error, nmc, nfsm_rndup(attrbytes)); | |
664 | nfsmout: | |
665 | return (error); | |
666 | } | |
667 | ||
668 | /* | |
669 | * Add an NFSv4 "sattr" structure to an mbuf chain | |
670 | */ | |
671 | int | |
672 | nfsm_chain_add_fattr4_f(struct nfsm_chain *nmc, struct vnode_attr *vap, struct nfsmount *nmp) | |
673 | { | |
674 | int error = 0, attrbytes, slen, i; | |
675 | uint32_t *pattrbytes; | |
676 | uint32_t bitmap[NFS_ATTR_BITMAP_LEN]; | |
677 | char s[32]; | |
678 | ||
679 | /* | |
680 | * Do this in two passes. | |
681 | * First calculate the bitmap, then pack | |
682 | * everything together and set the size. | |
683 | */ | |
684 | ||
685 | NFS_CLEAR_ATTRIBUTES(bitmap); | |
686 | if (VATTR_IS_ACTIVE(vap, va_data_size)) | |
687 | NFS_BITMAP_SET(bitmap, NFS_FATTR_SIZE); | |
688 | if (VATTR_IS_ACTIVE(vap, va_acl)) { | |
689 | // NFS_BITMAP_SET(bitmap, NFS_FATTR_ACL) | |
690 | } | |
691 | if (VATTR_IS_ACTIVE(vap, va_flags)) { | |
692 | NFS_BITMAP_SET(bitmap, NFS_FATTR_ARCHIVE); | |
693 | NFS_BITMAP_SET(bitmap, NFS_FATTR_HIDDEN); | |
694 | } | |
695 | // NFS_BITMAP_SET(bitmap, NFS_FATTR_MIMETYPE) | |
696 | if (VATTR_IS_ACTIVE(vap, va_mode)) | |
697 | NFS_BITMAP_SET(bitmap, NFS_FATTR_MODE); | |
698 | if (VATTR_IS_ACTIVE(vap, va_uid)) | |
699 | NFS_BITMAP_SET(bitmap, NFS_FATTR_OWNER); | |
700 | if (VATTR_IS_ACTIVE(vap, va_gid)) | |
701 | NFS_BITMAP_SET(bitmap, NFS_FATTR_OWNER_GROUP); | |
702 | // NFS_BITMAP_SET(bitmap, NFS_FATTR_SYSTEM) | |
703 | if (vap->va_vaflags & VA_UTIMES_NULL) { | |
704 | NFS_BITMAP_SET(bitmap, NFS_FATTR_TIME_ACCESS_SET); | |
705 | NFS_BITMAP_SET(bitmap, NFS_FATTR_TIME_MODIFY_SET); | |
706 | } else { | |
707 | if (VATTR_IS_ACTIVE(vap, va_access_time)) | |
708 | NFS_BITMAP_SET(bitmap, NFS_FATTR_TIME_ACCESS_SET); | |
709 | if (VATTR_IS_ACTIVE(vap, va_modify_time)) | |
710 | NFS_BITMAP_SET(bitmap, NFS_FATTR_TIME_MODIFY_SET); | |
711 | } | |
712 | if (VATTR_IS_ACTIVE(vap, va_backup_time)) | |
713 | NFS_BITMAP_SET(bitmap, NFS_FATTR_TIME_BACKUP); | |
714 | if (VATTR_IS_ACTIVE(vap, va_create_time)) | |
715 | NFS_BITMAP_SET(bitmap, NFS_FATTR_TIME_CREATE); | |
716 | /* and limit to what is supported by server */ | |
717 | for (i=0; i < NFS_ATTR_BITMAP_LEN; i++) | |
718 | bitmap[i] &= nmp->nm_fsattr.nfsa_supp_attr[i]; | |
719 | ||
720 | /* | |
721 | * Now pack it all together: | |
722 | * BITMAP, #BYTES, ATTRS | |
723 | * Keep a pointer to the length so we can set it later. | |
724 | */ | |
725 | nfsm_chain_add_bitmap(error, nmc, bitmap, NFS_ATTR_BITMAP_LEN); | |
726 | attrbytes = 0; | |
727 | nfsm_chain_add_32(error, nmc, attrbytes); | |
728 | pattrbytes = (uint32_t*)(nmc->nmc_ptr - NFSX_UNSIGNED); | |
729 | ||
730 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SIZE)) { | |
731 | nfsm_chain_add_64(error, nmc, vap->va_data_size); | |
732 | attrbytes += 2*NFSX_UNSIGNED; | |
733 | } | |
734 | // NFS_BITMAP_ISSET(bitmap, NFS_FATTR_ACL) | |
735 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_ARCHIVE)) { | |
736 | nfsm_chain_add_32(error, nmc, (vap->va_flags & SF_ARCHIVED) ? 1 : 0); | |
737 | attrbytes += NFSX_UNSIGNED; | |
738 | } | |
739 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_HIDDEN)) { | |
740 | nfsm_chain_add_32(error, nmc, (vap->va_flags & UF_HIDDEN) ? 1 : 0); | |
741 | attrbytes += NFSX_UNSIGNED; | |
742 | } | |
743 | // NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MIMETYPE) | |
744 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MODE)) { | |
745 | nfsm_chain_add_32(error, nmc, vap->va_mode); | |
746 | attrbytes += NFSX_UNSIGNED; | |
747 | } | |
748 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_OWNER)) { | |
749 | slen = snprintf(s, sizeof(s), "%d", vap->va_uid); | |
750 | nfsm_chain_add_string(error, nmc, s, slen); | |
751 | attrbytes += NFSX_UNSIGNED + nfsm_rndup(slen); | |
752 | } | |
753 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_OWNER_GROUP)) { | |
754 | slen = snprintf(s, sizeof(s), "%d", vap->va_gid); | |
755 | nfsm_chain_add_string(error, nmc, s, slen); | |
756 | attrbytes += NFSX_UNSIGNED + nfsm_rndup(slen); | |
757 | } | |
758 | // NFS_BITMAP_SET(bitmap, NFS_FATTR_SYSTEM) | |
759 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_ACCESS_SET)) { | |
760 | if (vap->va_vaflags & VA_UTIMES_NULL) { | |
761 | nfsm_chain_add_32(error, nmc, NFS_TIME_SET_TO_SERVER); | |
762 | attrbytes += NFSX_UNSIGNED; | |
763 | } else { | |
764 | nfsm_chain_add_32(error, nmc, NFS_TIME_SET_TO_CLIENT); | |
765 | nfsm_chain_add_64(error, nmc, vap->va_access_time.tv_sec); | |
766 | nfsm_chain_add_32(error, nmc, vap->va_access_time.tv_nsec); | |
767 | attrbytes += 4*NFSX_UNSIGNED; | |
768 | } | |
769 | } | |
770 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_BACKUP)) { | |
771 | nfsm_chain_add_64(error, nmc, vap->va_backup_time.tv_sec); | |
772 | nfsm_chain_add_32(error, nmc, vap->va_backup_time.tv_nsec); | |
773 | attrbytes += 3*NFSX_UNSIGNED; | |
774 | } | |
775 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_CREATE)) { | |
776 | nfsm_chain_add_64(error, nmc, vap->va_create_time.tv_sec); | |
777 | nfsm_chain_add_32(error, nmc, vap->va_create_time.tv_nsec); | |
778 | attrbytes += 3*NFSX_UNSIGNED; | |
779 | } | |
780 | if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_MODIFY_SET)) { | |
781 | if (vap->va_vaflags & VA_UTIMES_NULL) { | |
782 | nfsm_chain_add_32(error, nmc, NFS_TIME_SET_TO_SERVER); | |
783 | attrbytes += NFSX_UNSIGNED; | |
784 | } else { | |
785 | nfsm_chain_add_32(error, nmc, NFS_TIME_SET_TO_CLIENT); | |
786 | nfsm_chain_add_64(error, nmc, vap->va_modify_time.tv_sec); | |
787 | nfsm_chain_add_32(error, nmc, vap->va_modify_time.tv_nsec); | |
788 | attrbytes += 4*NFSX_UNSIGNED; | |
789 | } | |
790 | } | |
791 | nfsmout_if(error); | |
792 | /* Now, set the attribute data length */ | |
793 | *pattrbytes = txdr_unsigned(attrbytes); | |
794 | nfsmout: | |
795 | return (error); | |
796 | } | |
797 |