Changeset 940 for branches/client-3.0/src
- Timestamp:
- Jul 26, 2016, 12:07:18 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/client-3.0/src/smbwrp.c
r939 r940 916 916 } 917 917 918 /*************************************************************** 919 Wrapper that allows SMB2 to list a directory. 920 Synchronous only. 921 Based on cli_smb2_list 922 ***************************************************************/ 923 924 NTSTATUS list_files_smb2(struct cli_state *cli, 925 const char *pathname, 926 uint16_t attribute, 927 NTSTATUS (*fn)(const char *, 928 struct smbwrp_fileinfo *, 929 const char *, 930 void *), 931 void *state) 932 { 933 NTSTATUS status; 934 uint16_t fnum = 0xffff; 935 char *parent_dir = NULL; 936 const char *mask = NULL; 937 struct smb2_hnd *ph = NULL; 938 bool processed_file = false; 939 TALLOC_CTX *frame = talloc_stackframe(); 940 TALLOC_CTX *subframe = NULL; 941 bool mask_has_wild; 942 void *dircachectx = NULL; 943 smbwrp_fileinfo wrpfinfo; 944 945 if (smbXcli_conn_has_async_calls(cli->conn)) { 946 /* 947 * Can't use sync call while an async call is in flight 948 */ 949 status = NT_STATUS_INVALID_PARAMETER; 950 goto fail; 951 } 952 953 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) { 954 status = NT_STATUS_INVALID_PARAMETER; 955 goto fail; 956 } 957 958 /* Get the directory name. */ 959 if (!windows_parent_dirname(frame, 960 pathname, 961 &parent_dir, 962 &mask)) { 963 status = NT_STATUS_NO_MEMORY; 964 goto fail; 965 } 966 967 mask_has_wild = ms_has_wild(mask); 968 969 status = cli_smb2_create_fnum(cli, 970 parent_dir, 971 0, /* create_flags */ 972 SEC_DIR_LIST|SEC_DIR_READ_ATTRIBUTE,/* desired_access */ 973 FILE_ATTRIBUTE_DIRECTORY, /* file attributes */ 974 FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */ 975 FILE_OPEN, /* create_disposition */ 976 FILE_DIRECTORY_FILE, /* create_options */ 977 &fnum, 978 NULL); 979 980 if (!NT_STATUS_IS_OK(status)) { 981 goto fail; 982 } 983 984 status = map_fnum_to_smb2_handle(cli, 985 fnum, 986 &ph); 987 if (!NT_STATUS_IS_OK(status)) { 988 goto fail; 989 } 990 991 do { 992 uint8_t *dir_data = NULL; 993 uint32_t dir_data_length = 0; 994 uint32_t next_offset = 0; 995 subframe = talloc_stackframe(); 996 997 status = smb2cli_query_directory(cli->conn, 998 cli->timeout, 999 cli->smb2.session, 1000 cli->smb2.tcon, 1001 SMB2_FIND_ID_BOTH_DIRECTORY_INFO, 1002 0, /* flags */ 1003 0, /* file_index */ 1004 ph->fid_persistent, 1005 ph->fid_volatile, 1006 mask, 1007 0xffff, 1008 subframe, 1009 &dir_data, 1010 &dir_data_length); 1011 1012 if (!NT_STATUS_IS_OK(status)) { 1013 if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES)) { 1014 break; 1015 } 1016 goto fail; 1017 } 1018 1019 do { 1020 struct file_info *finfo = talloc_zero(subframe, 1021 struct file_info); 1022 1023 if (finfo == NULL) { 1024 status = NT_STATUS_NO_MEMORY; 1025 goto fail; 1026 } 1027 1028 status = parse_finfo_id_both_directory_info(dir_data, 1029 dir_data_length, 1030 finfo, 1031 &next_offset); 1032 1033 if (!NT_STATUS_IS_OK(status)) { 1034 goto fail; 1035 } 1036 1037 if (dir_check_ftype((uint32_t)finfo->mode, 1038 (uint32_t)attribute)) { 1039 /* 1040 * Only process if attributes match. 1041 * On SMB1 server does this, so on 1042 * SMB2 we need to emulate in the 1043 * client. 1044 * 1045 * https://bugzilla.samba.org/show_bug.cgi?id=10260 1046 */ 1047 processed_file = true; 1048 1049 //as samba and this client have different finfo, we need to convert 1050 memset(&wrpfinfo, 0, sizeof(wrpfinfo)); 1051 wrpfinfo.size = finfo[0].size; 1052 wrpfinfo.attr = finfo[0].mode; 1053 wrpfinfo.ctime = convert_timespec_to_time_t(finfo[0].ctime_ts); 1054 wrpfinfo.mtime = convert_timespec_to_time_t(finfo[0].mtime_ts); 1055 wrpfinfo.atime = convert_timespec_to_time_t(finfo[0].atime_ts); 1056 wrpfinfo.easize = finfo[0].easize; 1057 strncpy(wrpfinfo.fname, finfo[0].name, sizeof(wrpfinfo.fname) -1); 1058 1059 status = fn(cli->dfs_mountpoint, 1060 &wrpfinfo, 1061 pathname, 1062 state); 1063 1064 if (!NT_STATUS_IS_OK(status)) { 1065 /* not sure why this is required on OS/2 */ 1066 if (status != NT_STATUS_WAIT_1) 1067 break; 1068 } 1069 } 1070 1071 TALLOC_FREE(finfo); 1072 1073 /* Move to next entry. */ 1074 if (next_offset) { 1075 dir_data += next_offset; 1076 dir_data_length -= next_offset; 1077 } 1078 } while (next_offset != 0); 1079 1080 TALLOC_FREE(subframe); 1081 1082 if (!mask_has_wild) { 1083 /* 1084 * MacOSX 10 doesn't set STATUS_NO_MORE_FILES 1085 * when handed a non-wildcard path. Do it 1086 * for the server (with a non-wildcard path 1087 * there should only ever be one file returned. 1088 */ 1089 status = STATUS_NO_MORE_FILES; 1090 break; 1091 } 1092 1093 } while (NT_STATUS_IS_OK(status)); 1094 1095 if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES)) { 1096 status = NT_STATUS_OK; 1097 } 1098 1099 if (NT_STATUS_IS_OK(status) && !processed_file) { 1100 /* 1101 * In SMB1 findfirst returns NT_STATUS_NO_SUCH_FILE 1102 * if no files match. Emulate this in the client. 1103 */ 1104 status = NT_STATUS_NO_SUCH_FILE; 1105 } 1106 1107 fail: 1108 1109 if (fnum != 0xffff) { 1110 cli_smb2_close_fnum(cli, fnum); 1111 } 1112 TALLOC_FREE(subframe); 1113 TALLOC_FREE(frame); 1114 return status; 1115 } 1116 1117 918 1118 /**************************************************************************** 919 1119 Do a directory listing, calling fn on each file found. … … 933 1133 void *dircachectx = NULL; 934 1134 smbwrp_fileinfo wrpfinfo; 1135 1136 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { 1137 debuglocal(4,"SMB2 detected, calling list_files_smb2()\n"); 1138 return list_files_smb2(cli, mask, attribute, fn, state); 935 1139 936 1140 /* Try to get the listing from cache. */
Note:
See TracChangeset
for help on using the changeset viewer.