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 /*
23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
25 */
26
27 #include <smbsrv/smb_kproto.h>
28 #include <smbsrv/smb_vops.h>
29 #include <smbsrv/smb_fsops.h>
30
31 /*
32 * Trans2 Query File/Path Information Levels:
33 *
34 * SMB_INFO_STANDARD
35 * SMB_INFO_QUERY_EA_SIZE
36 * SMB_INFO_QUERY_EAS_FROM_LIST
37 * SMB_INFO_QUERY_ALL_EAS - not valid for pipes
38 * SMB_INFO_IS_NAME_VALID - only valid when query is by path
39 *
40 * SMB_QUERY_FILE_BASIC_INFO
41 * SMB_QUERY_FILE_STANDARD_INFO
42 * SMB_QUERY_FILE_EA_INFO
43 * SMB_QUERY_FILE_NAME_INFO
44 * SMB_QUERY_FILE_ALL_INFO
132 sr, &infolev, &fqi->fq_path.pn_path) != 0)
133 return (SDRC_ERROR);
134
135 if (smb_query_by_path(sr, xa, infolev) != 0)
136 return (SDRC_ERROR);
137
138 return (SDRC_SUCCESS);
139 }
140
141 /*
142 * smb_com_query_information (aka getattr)
143 */
144 smb_sdrc_t
145 smb_pre_query_information(smb_request_t *sr)
146 {
147 int rc;
148 smb_fqi_t *fqi = &sr->arg.dirop.fqi;
149
150 rc = smbsr_decode_data(sr, "%S", sr, &fqi->fq_path.pn_path);
151
152 DTRACE_SMB_2(op__QueryInformation__start, smb_request_t *, sr,
153 smb_fqi_t *, fqi);
154
155 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
156 }
157
158 void
159 smb_post_query_information(smb_request_t *sr)
160 {
161 DTRACE_SMB_1(op__QueryInformation__done, smb_request_t *, sr);
162 }
163
164 smb_sdrc_t
165 smb_com_query_information(smb_request_t *sr)
166 {
167 uint16_t infolev = SMB_QUERY_INFORMATION;
168
169 if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
170 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
171 ERRDOS, ERROR_ACCESS_DENIED);
172 return (SDRC_ERROR);
173 }
174
175 if (smb_query_by_path(sr, NULL, infolev) != 0)
176 return (SDRC_ERROR);
177
178 return (SDRC_SUCCESS);
179 }
180
181 /*
182 * smb_com_query_information2 (aka getattre)
183 */
184 smb_sdrc_t
185 smb_pre_query_information2(smb_request_t *sr)
186 {
187 int rc;
188 rc = smbsr_decode_vwv(sr, "w", &sr->smb_fid);
189
190 DTRACE_SMB_1(op__QueryInformation2__start, smb_request_t *, sr);
191
192 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
193 }
194
195 void
196 smb_post_query_information2(smb_request_t *sr)
197 {
198 DTRACE_SMB_1(op__QueryInformation2__done, smb_request_t *, sr);
199 }
200
201 smb_sdrc_t
202 smb_com_query_information2(smb_request_t *sr)
203 {
204 uint16_t infolev = SMB_QUERY_INFORMATION2;
205
206 if (smb_query_by_fid(sr, NULL, infolev) != 0)
207 return (SDRC_ERROR);
208
209 return (SDRC_SUCCESS);
210 }
211
212 /*
213 * smb_query_by_fid
214 *
215 * Common code for querying file information by open file (or pipe) id.
216 * Use the id to identify the node / pipe object and request the
217 * smb_queryinfo_t data for that object.
218 */
313 }
314
315 pn = &sr->arg.dirop.fqi.fq_path;
316 smb_pathname_init(sr, pn, pn->pn_path);
317 if (!smb_pathname_validate(sr, pn))
318 return (-1);
319
320 qinfo = kmem_alloc(sizeof (smb_queryinfo_t), KM_SLEEP);
321
322 rc = smb_pathname_reduce(sr, sr->user_cr, pn->pn_path,
323 sr->tid_tree->t_snode, sr->tid_tree->t_snode, &dnode,
324 qinfo->qi_name);
325
326 if (rc == 0) {
327 rc = smb_fsop_lookup_name(sr, sr->user_cr, SMB_FOLLOW_LINKS,
328 sr->tid_tree->t_snode, dnode, qinfo->qi_name, &node);
329 smb_node_release(dnode);
330 }
331
332 if (rc != 0) {
333 if (rc == ENOENT)
334 smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
335 ERRDOS, ERROR_FILE_NOT_FOUND);
336 else
337 smbsr_errno(sr, rc);
338
339 kmem_free(qinfo, sizeof (smb_queryinfo_t));
340 return (-1);
341 }
342
343 if ((sr->smb_flg2 & SMB_FLAGS2_DFS) && smb_node_is_dfslink(node)) {
344 smbsr_error(sr, NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
345 kmem_free(qinfo, sizeof (smb_queryinfo_t));
346 smb_node_release(node);
347 return (-1);
348 }
349
350 rc = smb_query_fileinfo(sr, node, infolev, qinfo);
351 if (rc != 0) {
352 kmem_free(qinfo, sizeof (smb_queryinfo_t));
353 smb_node_release(node);
354 return (rc);
355 }
356
638 smb_node_t *fnode = qinfo->qi_node;
639 smb_attr_t *attr = &qinfo->qi_attr;
640
641 ASSERT(fnode);
642 if (SMB_IS_STREAM(fnode)) {
643 fnode = fnode->n_unode;
644 ASSERT(fnode);
645 }
646 ASSERT(fnode->n_magic == SMB_NODE_MAGIC);
647 ASSERT(fnode->n_state != SMB_NODE_STATE_DESTROYING);
648
649 sinfo = kmem_alloc(sizeof (smb_streaminfo_t), KM_SLEEP);
650 sinfo_next = kmem_alloc(sizeof (smb_streaminfo_t), KM_SLEEP);
651 datasz = attr->sa_vattr.va_size;
652 allocsz = attr->sa_allocsz;
653
654 status = smb_odir_openat(sr, fnode, &od);
655 switch (status) {
656 case 0:
657 break;
658 case NT_STATUS_NO_SUCH_FILE:
659 case NT_STATUS_NOT_SUPPORTED:
660 /* No streams. */
661 done = B_TRUE;
662 break;
663 default:
664 return (status);
665 }
666
667 if (!done) {
668 rc = smb_odir_read_streaminfo(sr, od, sinfo, &eos);
669 if ((rc != 0) || (eos))
670 done = B_TRUE;
671 }
672
673 /* If not a directory, encode an entry for the unnamed stream. */
674 if (qinfo->qi_isdir == 0) {
675 stream_name = "::$DATA";
676 stream_nlen = smb_ascii_or_unicode_strlen(sr, stream_name);
677 next_offset = SMB_STREAM_ENCODE_FIXED_SZ + stream_nlen +
678 smb_ascii_or_unicode_null_len(sr);
679
680 /* Can unnamed stream fit in response buffer? */
|
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 /*
23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
25 */
26
27 #include <smbsrv/smb_kproto.h>
28 #include <smbsrv/smb_vops.h>
29 #include <smbsrv/smb_fsops.h>
30
31 /*
32 * Trans2 Query File/Path Information Levels:
33 *
34 * SMB_INFO_STANDARD
35 * SMB_INFO_QUERY_EA_SIZE
36 * SMB_INFO_QUERY_EAS_FROM_LIST
37 * SMB_INFO_QUERY_ALL_EAS - not valid for pipes
38 * SMB_INFO_IS_NAME_VALID - only valid when query is by path
39 *
40 * SMB_QUERY_FILE_BASIC_INFO
41 * SMB_QUERY_FILE_STANDARD_INFO
42 * SMB_QUERY_FILE_EA_INFO
43 * SMB_QUERY_FILE_NAME_INFO
44 * SMB_QUERY_FILE_ALL_INFO
132 sr, &infolev, &fqi->fq_path.pn_path) != 0)
133 return (SDRC_ERROR);
134
135 if (smb_query_by_path(sr, xa, infolev) != 0)
136 return (SDRC_ERROR);
137
138 return (SDRC_SUCCESS);
139 }
140
141 /*
142 * smb_com_query_information (aka getattr)
143 */
144 smb_sdrc_t
145 smb_pre_query_information(smb_request_t *sr)
146 {
147 int rc;
148 smb_fqi_t *fqi = &sr->arg.dirop.fqi;
149
150 rc = smbsr_decode_data(sr, "%S", sr, &fqi->fq_path.pn_path);
151
152 DTRACE_SMB_START(op__QueryInformation, smb_request_t *, sr);
153
154 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
155 }
156
157 void
158 smb_post_query_information(smb_request_t *sr)
159 {
160 DTRACE_SMB_DONE(op__QueryInformation, smb_request_t *, sr);
161 }
162
163 smb_sdrc_t
164 smb_com_query_information(smb_request_t *sr)
165 {
166 uint16_t infolev = SMB_QUERY_INFORMATION;
167
168 if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
169 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
170 ERRDOS, ERROR_ACCESS_DENIED);
171 return (SDRC_ERROR);
172 }
173
174 if (smb_query_by_path(sr, NULL, infolev) != 0)
175 return (SDRC_ERROR);
176
177 return (SDRC_SUCCESS);
178 }
179
180 /*
181 * smb_com_query_information2 (aka getattre)
182 */
183 smb_sdrc_t
184 smb_pre_query_information2(smb_request_t *sr)
185 {
186 int rc;
187 rc = smbsr_decode_vwv(sr, "w", &sr->smb_fid);
188
189 DTRACE_SMB_START(op__QueryInformation2, smb_request_t *, sr);
190
191 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
192 }
193
194 void
195 smb_post_query_information2(smb_request_t *sr)
196 {
197 DTRACE_SMB_DONE(op__QueryInformation2, smb_request_t *, sr);
198 }
199
200 smb_sdrc_t
201 smb_com_query_information2(smb_request_t *sr)
202 {
203 uint16_t infolev = SMB_QUERY_INFORMATION2;
204
205 if (smb_query_by_fid(sr, NULL, infolev) != 0)
206 return (SDRC_ERROR);
207
208 return (SDRC_SUCCESS);
209 }
210
211 /*
212 * smb_query_by_fid
213 *
214 * Common code for querying file information by open file (or pipe) id.
215 * Use the id to identify the node / pipe object and request the
216 * smb_queryinfo_t data for that object.
217 */
312 }
313
314 pn = &sr->arg.dirop.fqi.fq_path;
315 smb_pathname_init(sr, pn, pn->pn_path);
316 if (!smb_pathname_validate(sr, pn))
317 return (-1);
318
319 qinfo = kmem_alloc(sizeof (smb_queryinfo_t), KM_SLEEP);
320
321 rc = smb_pathname_reduce(sr, sr->user_cr, pn->pn_path,
322 sr->tid_tree->t_snode, sr->tid_tree->t_snode, &dnode,
323 qinfo->qi_name);
324
325 if (rc == 0) {
326 rc = smb_fsop_lookup_name(sr, sr->user_cr, SMB_FOLLOW_LINKS,
327 sr->tid_tree->t_snode, dnode, qinfo->qi_name, &node);
328 smb_node_release(dnode);
329 }
330
331 if (rc != 0) {
332 smbsr_errno(sr, rc);
333
334 kmem_free(qinfo, sizeof (smb_queryinfo_t));
335 return (-1);
336 }
337
338 if ((sr->smb_flg2 & SMB_FLAGS2_DFS) && smb_node_is_dfslink(node)) {
339 smbsr_error(sr, NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
340 kmem_free(qinfo, sizeof (smb_queryinfo_t));
341 smb_node_release(node);
342 return (-1);
343 }
344
345 rc = smb_query_fileinfo(sr, node, infolev, qinfo);
346 if (rc != 0) {
347 kmem_free(qinfo, sizeof (smb_queryinfo_t));
348 smb_node_release(node);
349 return (rc);
350 }
351
633 smb_node_t *fnode = qinfo->qi_node;
634 smb_attr_t *attr = &qinfo->qi_attr;
635
636 ASSERT(fnode);
637 if (SMB_IS_STREAM(fnode)) {
638 fnode = fnode->n_unode;
639 ASSERT(fnode);
640 }
641 ASSERT(fnode->n_magic == SMB_NODE_MAGIC);
642 ASSERT(fnode->n_state != SMB_NODE_STATE_DESTROYING);
643
644 sinfo = kmem_alloc(sizeof (smb_streaminfo_t), KM_SLEEP);
645 sinfo_next = kmem_alloc(sizeof (smb_streaminfo_t), KM_SLEEP);
646 datasz = attr->sa_vattr.va_size;
647 allocsz = attr->sa_allocsz;
648
649 status = smb_odir_openat(sr, fnode, &od);
650 switch (status) {
651 case 0:
652 break;
653 case NT_STATUS_OBJECT_NAME_NOT_FOUND:
654 case NT_STATUS_NO_SUCH_FILE:
655 case NT_STATUS_NOT_SUPPORTED:
656 /* No streams. */
657 status = 0;
658 done = B_TRUE;
659 break;
660 default:
661 return (status);
662 }
663
664 if (!done) {
665 rc = smb_odir_read_streaminfo(sr, od, sinfo, &eos);
666 if ((rc != 0) || (eos))
667 done = B_TRUE;
668 }
669
670 /* If not a directory, encode an entry for the unnamed stream. */
671 if (qinfo->qi_isdir == 0) {
672 stream_name = "::$DATA";
673 stream_nlen = smb_ascii_or_unicode_strlen(sr, stream_name);
674 next_offset = SMB_STREAM_ENCODE_FIXED_SZ + stream_nlen +
675 smb_ascii_or_unicode_null_len(sr);
676
677 /* Can unnamed stream fit in response buffer? */
|