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 2015 Nexenta Systems, Inc. All rights reserved.
24 */
25
26 /*
27 * General Structures Layout
28 * -------------------------
29 *
30 * This is a simplified diagram showing the relationship between most of the
31 * main structures.
32 *
33 * +-------------------+
34 * | SMB_INFO |
35 * +-------------------+
36 * |
37 * |
38 * v
39 * +-------------------+ +-------------------+ +-------------------+
40 * | SESSION |<----->| SESSION |......| SESSION |
41 * +-------------------+ +-------------------+ +-------------------+
42 * | |
43 * | |
247 *
248 * See smb_search, smb_find, smb_find_unique, and smb_trans2_find for details
249 */
250
251 #include <smbsrv/smb_kproto.h>
252 #include <smbsrv/smb_fsops.h>
253 #include <smbsrv/smb_share.h>
254 #include <sys/extdirent.h>
255
256 /* static functions */
257 static smb_odir_t *smb_odir_create(smb_request_t *, smb_node_t *,
258 const char *, uint16_t, uint16_t, cred_t *);
259 static int smb_odir_single_fileinfo(smb_request_t *, smb_odir_t *,
260 smb_fileinfo_t *);
261 static int smb_odir_wildcard_fileinfo(smb_request_t *, smb_odir_t *,
262 smb_odirent_t *, smb_fileinfo_t *);
263 static int smb_odir_next_odirent(smb_odir_t *, smb_odirent_t *);
264 static boolean_t smb_odir_lookup_link(smb_request_t *, smb_odir_t *,
265 char *, smb_node_t **);
266 static boolean_t smb_odir_match_name(smb_odir_t *, smb_odirent_t *);
267
268
269 /*
270 * smb_odir_openpath
271 *
272 * Create an odir representing the directory specified in pathname.
273 *
274 * Returns:
275 * NT Status
276 */
277 uint32_t
278 smb_odir_openpath(smb_request_t *sr, char *path, uint16_t sattr,
279 uint32_t flags, smb_odir_t **odp)
280 {
281 int rc;
282 smb_tree_t *tree;
283 smb_node_t *dnode;
284 char pattern[MAXNAMELEN];
285 uint16_t odid;
286 cred_t *cr;
428 case SMB_ODIR_STATE_CLOSING:
429 case SMB_ODIR_STATE_CLOSED:
430 default:
431 mutex_exit(&od->d_mutex);
432 return (B_FALSE);
433 }
434
435 mutex_exit(&od->d_mutex);
436 return (B_TRUE);
437 }
438
439 /*
440 * If the odir is in SMB_ODIR_STATE_CLOSING and this release results in
441 * a refcnt of 0, change the state to SMB_ODIR_STATE_CLOSED and post the
442 * object for deletion. Object deletion is deferred to avoid modifying
443 * a list while an iteration may be in progress.
444 */
445 void
446 smb_odir_release(smb_odir_t *od)
447 {
448 SMB_ODIR_VALID(od);
449
450 mutex_enter(&od->d_mutex);
451 ASSERT(od->d_refcnt > 0);
452
453 switch (od->d_state) {
454 case SMB_ODIR_STATE_OPEN:
455 break;
456 case SMB_ODIR_STATE_IN_USE:
457 od->d_refcnt--;
458 if (od->d_refcnt == 0)
459 od->d_state = SMB_ODIR_STATE_OPEN;
460 break;
461 case SMB_ODIR_STATE_CLOSING:
462 od->d_refcnt--;
463 if (od->d_refcnt == 0) {
464 od->d_state = SMB_ODIR_STATE_CLOSED;
465 smb_tree_post_odir(od->d_tree, od);
466 }
467 break;
468 case SMB_ODIR_STATE_CLOSED:
469 default:
470 break;
471 }
472
473 mutex_exit(&od->d_mutex);
474 }
475
476 /*
477 * smb_odir_close
478 */
479 void
480 smb_odir_close(smb_odir_t *od)
481 {
482 ASSERT(od);
483 ASSERT(od->d_magic == SMB_ODIR_MAGIC);
484
485 mutex_enter(&od->d_mutex);
972 (void) strlcpy(od->d_pattern, pattern, sizeof (od->d_pattern));
973 if (smb_contains_wildcards(od->d_pattern))
974 od->d_flags |= SMB_ODIR_FLAG_WILDCARDS;
975 else
976 od->d_flags &= ~SMB_ODIR_FLAG_WILDCARDS;
977
978 /* Internal smb_odir_resume_at */
979 od->d_offset = 0;
980 od->d_bufptr = NULL;
981 od->d_eof = B_FALSE;
982
983 mutex_exit(&od->d_mutex);
984 }
985
986 /*
987 * Delete an odir.
988 *
989 * Remove the odir from the tree list before freeing resources
990 * associated with the odir.
991 */
992 void
993 smb_odir_delete(void *arg)
994 {
995 smb_tree_t *tree;
996 smb_odir_t *od = (smb_odir_t *)arg;
997
998 SMB_ODIR_VALID(od);
999 ASSERT(od->d_refcnt == 0);
1000 ASSERT(od->d_state == SMB_ODIR_STATE_CLOSED);
1001
1002 tree = od->d_tree;
1003 smb_llist_enter(&tree->t_odir_list, RW_WRITER);
1004 smb_llist_remove(&tree->t_odir_list, od);
1005 if (od->d_odid != 0)
1006 smb_idpool_free(&tree->t_odid_pool, od->d_odid);
1007 atomic_dec_32(&tree->t_session->s_dir_cnt);
1008 smb_llist_exit(&tree->t_odir_list);
1009
1010 mutex_enter(&od->d_mutex);
1011 mutex_exit(&od->d_mutex);
1012
1013 od->d_magic = 0;
1014 smb_node_release(od->d_dnode);
1015 smb_user_release(od->d_user);
1016 mutex_destroy(&od->d_mutex);
1017 kmem_cache_free(smb_cache_odir, od);
1018 }
1019
1020 /*
1021 * smb_odir_next_odirent
1022 *
1023 * Find the next directory entry in d_buf. If d_bufptr is NULL (buffer
1024 * is empty or we've reached the end of it), read the next set of
1025 * entries from the file system (vop_readdir).
1026 *
1027 * File systems which support VFSFT_EDIRENT_FLAGS will return the
1028 * directory entries as a buffer of edirent_t structure. Others will
1029 * return a buffer of dirent64_t structures. For simplicity translate
1031 * The ed_name/d_name in d_buf is NULL terminated by the file system.
1032 *
1033 * Some file systems can have directories larger than SMB_MAXDIRSIZE.
1034 * If the odirent offset >= SMB_MAXDIRSIZE return ENOENT and set d_eof
1035 * to true to stop subsequent calls to smb_vop_readdir.
1036 *
1037 * Returns:
1038 * 0 - success. odirent is populated with the next directory entry
1039 * ENOENT - no more directory entries
1040 * errno - error
1041 */
1042 static int
1043 smb_odir_next_odirent(smb_odir_t *od, smb_odirent_t *odirent)
1044 {
1045 int rc;
1046 int reclen;
1047 int eof;
1048 dirent64_t *dp;
1049 edirent_t *edp;
1050 char *np;
1051 uint32_t abe_flag = 0;
1052
1053 ASSERT(MUTEX_HELD(&od->d_mutex));
1054
1055 bzero(odirent, sizeof (smb_odirent_t));
1056
1057 if (od->d_bufptr != NULL) {
1058 if (od->d_flags & SMB_ODIR_FLAG_EDIRENT)
1059 reclen = od->d_edp->ed_reclen;
1060 else
1061 reclen = od->d_dp->d_reclen;
1062
1063 if (reclen == 0) {
1064 od->d_bufptr = NULL;
1065 } else {
1066 od->d_bufptr += reclen;
1067 if (od->d_bufptr >= od->d_buf + od->d_bufsize)
1068 od->d_bufptr = NULL;
1069 }
1070 }
1071
1072 if (od->d_bufptr == NULL) {
1073 if (od->d_eof)
1074 return (ENOENT);
1075
1076 od->d_bufsize = sizeof (od->d_buf);
1077
1078 if (od->d_flags & SMB_ODIR_FLAG_ABE)
1079 abe_flag = SMB_ABE;
1080
1081 rc = smb_vop_readdir(od->d_dnode->vp, od->d_offset,
1082 od->d_buf, &od->d_bufsize, &eof, abe_flag, od->d_cred);
1083
1084 if ((rc == 0) && (od->d_bufsize == 0))
1085 rc = ENOENT;
1086
1087 if (rc != 0) {
1088 od->d_bufptr = NULL;
1089 od->d_bufsize = 0;
1090 return (rc);
1091 }
1092
1093 od->d_eof = (eof != 0);
1094 od->d_bufptr = od->d_buf;
1095 }
1096
1097 if (od->d_flags & SMB_ODIR_FLAG_EDIRENT)
1098 od->d_offset = od->d_edp->ed_off;
1099 else
1100 od->d_offset = od->d_dp->d_off;
1101
1102 if (od->d_offset >= SMB_MAXDIRSIZE) {
|
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 2018 Nexenta Systems, Inc. All rights reserved.
24 */
25
26 /*
27 * General Structures Layout
28 * -------------------------
29 *
30 * This is a simplified diagram showing the relationship between most of the
31 * main structures.
32 *
33 * +-------------------+
34 * | SMB_INFO |
35 * +-------------------+
36 * |
37 * |
38 * v
39 * +-------------------+ +-------------------+ +-------------------+
40 * | SESSION |<----->| SESSION |......| SESSION |
41 * +-------------------+ +-------------------+ +-------------------+
42 * | |
43 * | |
247 *
248 * See smb_search, smb_find, smb_find_unique, and smb_trans2_find for details
249 */
250
251 #include <smbsrv/smb_kproto.h>
252 #include <smbsrv/smb_fsops.h>
253 #include <smbsrv/smb_share.h>
254 #include <sys/extdirent.h>
255
256 /* static functions */
257 static smb_odir_t *smb_odir_create(smb_request_t *, smb_node_t *,
258 const char *, uint16_t, uint16_t, cred_t *);
259 static int smb_odir_single_fileinfo(smb_request_t *, smb_odir_t *,
260 smb_fileinfo_t *);
261 static int smb_odir_wildcard_fileinfo(smb_request_t *, smb_odir_t *,
262 smb_odirent_t *, smb_fileinfo_t *);
263 static int smb_odir_next_odirent(smb_odir_t *, smb_odirent_t *);
264 static boolean_t smb_odir_lookup_link(smb_request_t *, smb_odir_t *,
265 char *, smb_node_t **);
266 static boolean_t smb_odir_match_name(smb_odir_t *, smb_odirent_t *);
267 static void smb_odir_delete(void *);
268
269
270 /*
271 * smb_odir_openpath
272 *
273 * Create an odir representing the directory specified in pathname.
274 *
275 * Returns:
276 * NT Status
277 */
278 uint32_t
279 smb_odir_openpath(smb_request_t *sr, char *path, uint16_t sattr,
280 uint32_t flags, smb_odir_t **odp)
281 {
282 int rc;
283 smb_tree_t *tree;
284 smb_node_t *dnode;
285 char pattern[MAXNAMELEN];
286 uint16_t odid;
287 cred_t *cr;
429 case SMB_ODIR_STATE_CLOSING:
430 case SMB_ODIR_STATE_CLOSED:
431 default:
432 mutex_exit(&od->d_mutex);
433 return (B_FALSE);
434 }
435
436 mutex_exit(&od->d_mutex);
437 return (B_TRUE);
438 }
439
440 /*
441 * If the odir is in SMB_ODIR_STATE_CLOSING and this release results in
442 * a refcnt of 0, change the state to SMB_ODIR_STATE_CLOSED and post the
443 * object for deletion. Object deletion is deferred to avoid modifying
444 * a list while an iteration may be in progress.
445 */
446 void
447 smb_odir_release(smb_odir_t *od)
448 {
449 smb_tree_t *tree = od->d_tree;
450
451 SMB_ODIR_VALID(od);
452
453 mutex_enter(&od->d_mutex);
454 ASSERT(od->d_refcnt > 0);
455
456 switch (od->d_state) {
457 case SMB_ODIR_STATE_OPEN:
458 break;
459 case SMB_ODIR_STATE_IN_USE:
460 od->d_refcnt--;
461 if (od->d_refcnt == 0)
462 od->d_state = SMB_ODIR_STATE_OPEN;
463 break;
464 case SMB_ODIR_STATE_CLOSING:
465 od->d_refcnt--;
466 if (od->d_refcnt == 0) {
467 od->d_state = SMB_ODIR_STATE_CLOSED;
468 smb_llist_post(&tree->t_odir_list, od,
469 smb_odir_delete);
470 }
471 break;
472 case SMB_ODIR_STATE_CLOSED:
473 default:
474 break;
475 }
476
477 mutex_exit(&od->d_mutex);
478 }
479
480 /*
481 * smb_odir_close
482 */
483 void
484 smb_odir_close(smb_odir_t *od)
485 {
486 ASSERT(od);
487 ASSERT(od->d_magic == SMB_ODIR_MAGIC);
488
489 mutex_enter(&od->d_mutex);
976 (void) strlcpy(od->d_pattern, pattern, sizeof (od->d_pattern));
977 if (smb_contains_wildcards(od->d_pattern))
978 od->d_flags |= SMB_ODIR_FLAG_WILDCARDS;
979 else
980 od->d_flags &= ~SMB_ODIR_FLAG_WILDCARDS;
981
982 /* Internal smb_odir_resume_at */
983 od->d_offset = 0;
984 od->d_bufptr = NULL;
985 od->d_eof = B_FALSE;
986
987 mutex_exit(&od->d_mutex);
988 }
989
990 /*
991 * Delete an odir.
992 *
993 * Remove the odir from the tree list before freeing resources
994 * associated with the odir.
995 */
996 static void
997 smb_odir_delete(void *arg)
998 {
999 smb_tree_t *tree;
1000 smb_odir_t *od = (smb_odir_t *)arg;
1001
1002 SMB_ODIR_VALID(od);
1003 ASSERT(od->d_refcnt == 0);
1004 ASSERT(od->d_state == SMB_ODIR_STATE_CLOSED);
1005
1006 tree = od->d_tree;
1007 smb_llist_enter(&tree->t_odir_list, RW_WRITER);
1008 smb_llist_remove(&tree->t_odir_list, od);
1009 if (od->d_odid != 0)
1010 smb_idpool_free(&tree->t_odid_pool, od->d_odid);
1011 atomic_dec_32(&tree->t_session->s_dir_cnt);
1012 smb_llist_exit(&tree->t_odir_list);
1013
1014 /*
1015 * This ofile is no longer on t_odir_list, however...
1016 *
1017 * This is called via smb_llist_post, which means it may run
1018 * BEFORE smb_odir_release drops d_mutex (if another thread
1019 * flushes the delete queue before we do). Synchronize.
1020 */
1021 mutex_enter(&od->d_mutex);
1022 mutex_exit(&od->d_mutex);
1023
1024 od->d_magic = 0;
1025 smb_node_release(od->d_dnode);
1026 smb_user_release(od->d_user);
1027 mutex_destroy(&od->d_mutex);
1028 kmem_cache_free(smb_cache_odir, od);
1029 }
1030
1031 /*
1032 * smb_odir_next_odirent
1033 *
1034 * Find the next directory entry in d_buf. If d_bufptr is NULL (buffer
1035 * is empty or we've reached the end of it), read the next set of
1036 * entries from the file system (vop_readdir).
1037 *
1038 * File systems which support VFSFT_EDIRENT_FLAGS will return the
1039 * directory entries as a buffer of edirent_t structure. Others will
1040 * return a buffer of dirent64_t structures. For simplicity translate
1042 * The ed_name/d_name in d_buf is NULL terminated by the file system.
1043 *
1044 * Some file systems can have directories larger than SMB_MAXDIRSIZE.
1045 * If the odirent offset >= SMB_MAXDIRSIZE return ENOENT and set d_eof
1046 * to true to stop subsequent calls to smb_vop_readdir.
1047 *
1048 * Returns:
1049 * 0 - success. odirent is populated with the next directory entry
1050 * ENOENT - no more directory entries
1051 * errno - error
1052 */
1053 static int
1054 smb_odir_next_odirent(smb_odir_t *od, smb_odirent_t *odirent)
1055 {
1056 int rc;
1057 int reclen;
1058 int eof;
1059 dirent64_t *dp;
1060 edirent_t *edp;
1061 char *np;
1062 uint32_t rddir_flags = 0;
1063
1064 ASSERT(MUTEX_HELD(&od->d_mutex));
1065
1066 bzero(odirent, sizeof (smb_odirent_t));
1067
1068 if (od->d_flags & SMB_ODIR_FLAG_ABE)
1069 rddir_flags |= SMB_ABE;
1070 if (od->d_flags & SMB_ODIR_FLAG_EDIRENT)
1071 rddir_flags |= SMB_EDIRENT;
1072
1073 if (od->d_bufptr != NULL) {
1074 if (od->d_flags & SMB_ODIR_FLAG_EDIRENT)
1075 reclen = od->d_edp->ed_reclen;
1076 else
1077 reclen = od->d_dp->d_reclen;
1078
1079 if (reclen == 0) {
1080 od->d_bufptr = NULL;
1081 } else {
1082 od->d_bufptr += reclen;
1083 if (od->d_bufptr >= od->d_buf + od->d_bufsize)
1084 od->d_bufptr = NULL;
1085 }
1086 }
1087
1088 if (od->d_bufptr == NULL) {
1089 if (od->d_eof)
1090 return (ENOENT);
1091
1092 od->d_bufsize = sizeof (od->d_buf);
1093
1094 rc = smb_vop_readdir(od->d_dnode->vp, od->d_offset,
1095 od->d_buf, &od->d_bufsize, &eof, rddir_flags, od->d_cred);
1096
1097 if ((rc == 0) && (od->d_bufsize == 0))
1098 rc = ENOENT;
1099
1100 if (rc != 0) {
1101 od->d_bufptr = NULL;
1102 od->d_bufsize = 0;
1103 return (rc);
1104 }
1105
1106 od->d_eof = (eof != 0);
1107 od->d_bufptr = od->d_buf;
1108 }
1109
1110 if (od->d_flags & SMB_ODIR_FLAG_EDIRENT)
1111 od->d_offset = od->d_edp->ed_off;
1112 else
1113 od->d_offset = od->d_dp->d_off;
1114
1115 if (od->d_offset >= SMB_MAXDIRSIZE) {
|