Changeset 883 for trunk/client/src/smbwrp.c
- Timestamp:
- May 12, 2015, 2:32:32 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/client/src/smbwrp.c
r818 r883 20 20 21 21 #include "includes.h" 22 #include "rpc_client/cli_pipe.h" 23 #include "librpc/gen_ndr/ndr_srvsvc_c.h" 24 #include "libsmb/libsmb.h" 25 #include "libsmb/clirap.h" 26 #include "trans2.h" 22 27 #include "smbwrp.h" 23 /****************************************************************************24 Calculate a safe next_entry_offset.25 ****************************************************************************/26 27 static size_t calc_next_entry_offset(const char *base, const char *pdata_end)28 {29 size_t next_entry_offset = (size_t)IVAL(base,0);30 31 if (next_entry_offset == 0 ||32 base + next_entry_offset < base ||33 base + next_entry_offset > pdata_end) {34 next_entry_offset = pdata_end - base;35 }36 return next_entry_offset;37 }38 39 static int40 net_share_enum_rpc(struct cli_state *cli,41 void (*fn)(const char *name,42 uint32 type,43 const char *comment,44 void *state),45 void *state)46 {47 int i;48 NTSTATUS status;49 WERROR werr;50 uint32_t resume_handle = 0;51 uint32_t total_entries = 0;52 struct srvsvc_NetShareInfoCtr info_ctr;53 struct srvsvc_NetShareCtr1 ctr1;54 fstring name = "";55 fstring comment = "";56 void *mem_ctx;57 struct rpc_pipe_client *pipe_hnd;58 59 /* Open the server service pipe */60 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc.syntax_id, &pipe_hnd);61 if (!NT_STATUS_IS_OK(status)) {62 DEBUG(1, ("net_share_enum_rpc pipe open fail!\n"));63 return -1;64 }65 66 /* Allocate a context for parsing and for the entries in "ctr" */67 mem_ctx = talloc_init("libsmbclient: net_share_enum_rpc");68 if (mem_ctx == NULL) {69 DEBUG(0, ("out of memory for net_share_enum_rpc!\n"));70 TALLOC_FREE(pipe_hnd);71 return -1;72 }73 74 /* Issue the NetShareEnum RPC call and retrieve the response */75 ZERO_STRUCT(info_ctr);76 ZERO_STRUCT(ctr1);77 info_ctr.level = 1;78 info_ctr.ctr.ctr1 = &ctr1;79 status = rpccli_srvsvc_NetShareEnumAll(pipe_hnd, mem_ctx,80 pipe_hnd->desthost,81 &info_ctr,82 0xffffffff,83 &total_entries,84 &resume_handle,85 &werr);86 87 /* Was it successful? */88 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr) || info_ctr.ctr.ctr1->count == 0) {89 /* Nope. Go clean up. */90 goto done;91 }92 93 /* For each returned entry... */94 for (i = 0; i < info_ctr.ctr.ctr1->count; i++) {95 struct srvsvc_NetShareInfo1 info = info_ctr.ctr.ctr1->array[i];96 97 /* Add this share to the list */98 (*fn)(info.name, info.type, info.comment, state);99 }100 101 done:102 /* Close the server service pipe */103 TALLOC_FREE(pipe_hnd);104 105 /* Free all memory which was allocated for this request */106 TALLOC_FREE(mem_ctx);107 108 /* Tell 'em if it worked */109 return W_ERROR_IS_OK(status) ? 0 : -1;110 }111 28 112 29 /* … … 300 217 #endif 301 218 302 303 /****************************************************************************304 send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level305 ****************************************************************************/306 bool cli_qpathinfo3(struct cli_state *cli, const char *fname,307 time_t *c_time, time_t *a_time, time_t *m_time,308 time_t *w_time, off_t *size, uint16 *mode,309 SMB_INO_T *ino)310 {311 unsigned int data_len = 0;312 unsigned int param_len = 0;313 uint16 setup = TRANSACT2_QPATHINFO;314 char *param;315 size_t nlen = 2*(strlen(fname)+1);316 char *rparam=NULL, *rdata=NULL;317 char *p;318 319 param = SMB_MALLOC_ARRAY(char, 6+nlen+2);320 if (!param) {321 return false;322 }323 324 p = param;325 memset(p, '\0', 6);326 SSVAL(p, 0, SMB_QUERY_FILE_ALL_INFO);327 p += 6;328 p += clistr_push(cli, p, fname, nlen, STR_TERMINATE);329 330 param_len = PTR_DIFF(p, param);331 332 if (!cli_send_trans(cli, SMBtrans2,333 NULL, /* name */334 -1, 0, /* fid, flags */335 &setup, 1, 0, /* setup, length, max */336 param, param_len, 10, /* param, length, max */337 NULL, data_len, cli->max_xmit /* data, length, max */338 )) {339 return False;340 }341 342 SAFE_FREE(param);343 if (!cli_receive_trans(cli, SMBtrans2,344 &rparam, ¶m_len,345 &rdata, &data_len)) {346 return False;347 }348 349 if (!rdata || data_len < 22) {350 return False;351 }352 353 if (c_time) {354 *c_time = convert_timespec_to_time_t(interpret_long_date(rdata+0));355 }356 if (a_time) {357 *a_time = convert_timespec_to_time_t(interpret_long_date(rdata+8));358 }359 if (m_time) {360 *m_time = convert_timespec_to_time_t(interpret_long_date(rdata+16));361 }362 if (w_time) {363 *w_time = convert_timespec_to_time_t(interpret_long_date(rdata+24));364 }365 if (mode) {366 *mode = SVAL(rdata, 32);367 }368 if (size) {369 *size = IVAL2_TO_SMB_BIG_UINT(rdata, 48);370 }371 if (ino) {372 *ino = IVAL(rdata, 64);373 }374 375 SAFE_FREE(rdata);376 SAFE_FREE(rparam);377 return True;378 }379 380 /****************************************************************************381 send a qfileinfo call382 ****************************************************************************/383 bool cli_qfileinfo3(struct cli_state *cli, int fnum,384 uint16 *mode, off_t *size,385 time_t *c_time, time_t *a_time, time_t *m_time,386 time_t *w_time, SMB_INO_T *ino)387 {388 unsigned int data_len = 0;389 unsigned int param_len = 0;390 uint16 setup = TRANSACT2_QFILEINFO;391 char param[4];392 char *rparam=NULL, *rdata=NULL;393 394 /* if its a win95 server then fail this - win95 totally screws it395 up */396 if (cli->win95) return False;397 398 param_len = 4;399 400 SSVAL(param, 0, fnum);401 SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);402 403 if (!cli_send_trans(cli, SMBtrans2,404 NULL, /* name */405 -1, 0, /* fid, flags */406 &setup, 1, 0, /* setup, length, max */407 param, param_len, 2, /* param, length, max */408 NULL, data_len, cli->max_xmit /* data, length, max */409 )) {410 return False;411 }412 413 if (!cli_receive_trans(cli, SMBtrans2,414 &rparam, ¶m_len,415 &rdata, &data_len)) {416 return False;417 }418 419 if (!rdata || data_len < 68) {420 return False;421 }422 423 if (c_time) {424 *c_time = convert_timespec_to_time_t(interpret_long_date(rdata+0));425 }426 if (a_time) {427 *a_time = convert_timespec_to_time_t(interpret_long_date(rdata+8));428 }429 if (m_time) {430 *m_time = convert_timespec_to_time_t(interpret_long_date(rdata+16));431 }432 if (w_time) {433 *w_time = convert_timespec_to_time_t(interpret_long_date(rdata+24));434 }435 if (mode) {436 *mode = SVAL(rdata, 32);437 }438 if (size) {439 *size = IVAL2_TO_SMB_BIG_UINT(rdata, 48);440 }441 if (ino) {442 *ino = IVAL(rdata, 64);443 }444 445 SAFE_FREE(rdata);446 SAFE_FREE(rparam);447 return True;448 }449 450 219 /***************************************************** 451 220 return a connection to a server … … 671 440 int _System smbwrp_write(cli_state * cli, smbwrp_file * file, void *buf, unsigned long count, unsigned long * result) 672 441 { 673 int ret; 442 NTSTATUS status; 443 size_t ret; 674 444 675 445 if (!cli || !file || !buf || !result) … … 680 450 *result = 0; 681 451 //debuglocal(1,("Write %x %d %lld %d", cli, file->fd, file->offset, count)); 682 ret = cli_write(cli, file->fd, 0, buf, file->offset, count); 683 if (ret == -1) 684 { 452 status = cli_writeall(cli, file->fd, 0, buf, file->offset, count, &ret); 453 if (!NT_STATUS_IS_OK(status)) { 685 454 return os2cli_errno(cli); 686 455 } … … 719 488 { 720 489 debuglocal(4,"Set pathinfo on close %s %08x %d %d\n", file->fname, file->openattr, file->mtime, file->ctime); 721 if (!NT_STATUS_IS_OK(cli_setpathinfo (cli, file->fname, file->ctime, 0, file->mtime, 0, file->openattr)))490 if (!NT_STATUS_IS_OK(cli_setpathinfo_basic(cli, file->fname, file->ctime, 0, file->mtime, 0, file->openattr))) 722 491 { 723 492 debuglocal(4,"Set pathinfo on close failed %d\n", os2cli_errno(cli)); … … 736 505 } 737 506 738 /*****************************************************739 a wrapper for setfilesize()740 *******************************************************/741 int cli_setfilenewsize(struct cli_state *cli, int fnum, off_t newsize)742 {743 unsigned int data_len = 8;744 unsigned int param_len = 6;745 uint16 setup = TRANSACT2_SETFILEINFO;746 char param[6];747 unsigned char data[8];748 char *rparam=NULL, *rdata=NULL;749 750 SSVAL(param,0,fnum);751 SSVAL(param,2,SMB_SET_FILE_END_OF_FILE_INFO);752 SSVAL(param,4,0);753 754 SBVAL(data, 0, newsize);755 756 if (!cli_send_trans(cli, SMBtrans2,757 NULL, /* name */758 -1, 0, /* fid, flags */759 &setup, 1, 0, /* setup, length, max */760 param, param_len, 2, /* param, length, max */761 (char *)&data, data_len, /* data, length */762 cli->max_xmit /* max */763 )) {764 return False;765 }766 767 if (!cli_receive_trans(cli, SMBtrans2,768 &rparam, ¶m_len,769 &rdata, &data_len)) {770 return False;771 }772 773 SAFE_FREE(rdata);774 SAFE_FREE(rparam);775 776 return True;777 }778 779 507 int _System smbwrp_setfilesize(cli_state * cli, smbwrp_file * file, long long newsize) 780 508 { … … 786 514 787 515 debuglocal(4,"cli_setnewfilesize(%s) %lld\n", file->fname, newsize); 788 if (! cli_setfilenewsize(cli, file->fd, newsize))516 if (!NT_STATUS_IS_OK(cli_ftruncate(cli, file->fd, newsize))) 789 517 { 790 518 if (newsize) … … 823 551 824 552 debuglocal(1,"Rename <%s> -> <%s>\n", oldname, newname); 825 //cli_unlink(cli, newname);826 // if (!cli_rename(cli, oldname, newname) && !cli_ntrename(cli, oldname, newname))827 553 if (!NT_STATUS_IS_OK(cli_rename(cli, oldname, newname))) 828 554 { … … 913 639 return maperror(EINVAL); 914 640 } 915 if (! cli_qfileinfo3(cli, file->fd,641 if (!NT_STATUS_IS_OK(cli_qfileinfo_basic(cli, file->fd, 916 642 NULL, &size, NULL, NULL, NULL, 917 NULL, NULL) &&643 NULL, NULL)) && 918 644 !NT_STATUS_IS_OK(cli_getattrE(cli, file->fd, 919 645 NULL, &size, NULL, NULL, NULL))) … … 936 662 { 937 663 SMB_INO_T ino = 0; 664 struct timespec ctime; 665 struct timespec mtime; 666 struct timespec atime; 667 938 668 if (!cli || !finfo || !*finfo->fname) 939 669 { … … 942 672 debuglocal(4,"getattr %d %d <%s>\n", cli->capabilities & CAP_NOPATHINFO2, cli->capabilities & CAP_NT_SMBS, finfo->fname); 943 673 if (!(cli->capabilities & CAP_NOPATHINFO2) && 944 cli_qpathinfo 3(cli, finfo->fname, (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime, NULL,674 cli_qpathinfo2(cli, finfo->fname, &ctime, &atime, &mtime, NULL, 945 675 (off_t *)&finfo->size, (unsigned short *)&finfo->attr, &ino)) 946 676 { 947 677 finfo->attr &= 0x7F; 948 //debuglocal(2,("gotattr %08x <%s>\n", finfo->attr, finfo->fname)); 949 // finfo->ctime -= get_time_zone(finfo->ctime); 950 // finfo->atime -= get_time_zone(finfo->atime); 951 // finfo->mtime -= get_time_zone(finfo->mtime); 678 finfo->ctime = convert_timespec_to_time_t(ctime); 679 finfo->atime = convert_timespec_to_time_t(atime); 680 finfo->mtime = convert_timespec_to_time_t(mtime); 952 681 return 0; 953 682 } 954 //debuglocal(2,("getattr rc1 %d\n", os2cli_errno(cli)));955 683 956 684 if (cli->fd == -1) … … 961 689 962 690 /* If the path is not on a share (it is a workgroup or a server), 963 * then cli_qpathinfo 3obviously fails. Return some fake information691 * then cli_qpathinfo2 obviously fails. Return some fake information 964 692 * about the directory. 965 693 */ … … 1013 741 int _System smbwrp_fgetattr(cli_state * cli, smbwrp_file *file, smbwrp_fileinfo *finfo) 1014 742 { 743 struct timespec ctime; 744 struct timespec mtime; 745 struct timespec atime; 1015 746 SMB_INO_T ino = 0; 747 1016 748 if (!cli || !file || !finfo) 1017 749 { … … 1020 752 1021 753 strncpy(finfo->fname, file->fname, sizeof(finfo->fname) - 1); 1022 if (! cli_qfileinfo3(cli, file->fd,1023 (unsigned short *)&finfo->attr, (off_t *)&finfo->size, (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime, NULL,1024 &ino)) 754 if (!NT_STATUS_IS_OK(cli_qfileinfo_basic(cli, file->fd, 755 (unsigned short *)&finfo->attr, (off_t *)&finfo->size, &ctime, &atime, &mtime, NULL, 756 &ino))) 1025 757 { 1026 758 if (!NT_STATUS_IS_OK(cli_getattrE(cli, file->fd, … … 1038 770 else 1039 771 { 1040 // finfo->ctime -= get_time_zone(finfo->ctime);1041 // finfo->atime -= get_time_zone(finfo->atime);1042 // finfo->mtime -= get_time_zone(finfo->mtime);772 finfo->ctime = convert_timespec_to_time_t(ctime); 773 finfo->atime = convert_timespec_to_time_t(atime); 774 finfo->mtime = convert_timespec_to_time_t(mtime); 1043 775 } 1044 776 … … 1118 850 1119 851 /**************************************************************************** 1120 Interpret a long filename structure - this is mostly guesses at the moment. 1121 The length of the structure is returned 1122 The structure of a long filename depends on the info level. 260 is used 1123 by NT and 2 is used by OS/2 852 Do a directory listing, calling fn on each file found. 853 Modified from cli_list 1124 854 ****************************************************************************/ 1125 // YD from libsmb\clilist.c 1126 static size_t _os2_interpret_long_filename(TALLOC_CTX *ctx, struct cli_state *cli, 1127 int level,const char *p, const char *pdata_end, smbwrp_fileinfo *finfo, 1128 uint32 *p_resume_key, DATA_BLOB *p_last_name_raw) 1129 { 1130 int len; 1131 const char *base = p; 1132 size_t ret; 1133 char *fname; 1134 1135 data_blob_free(p_last_name_raw); 1136 1137 if (p_resume_key) { 1138 *p_resume_key = 0; 1139 } 1140 1141 /* ZERO_STRUCTP(finfo); */ 1142 finfo->atime = 0; 1143 finfo->ctime = 0; 1144 finfo->mtime = 0; 1145 *finfo->fname = '\0'; 1146 1147 switch (level) { 1148 case SMB_FIND_INFO_STANDARD: /* OS/2 understands this */ 1149 /* these dates are converted to GMT by 1150 make_unix_date */ 1151 if (pdata_end - base < 27) { 1152 return pdata_end - base; 1153 } 1154 finfo->ctime = cli_make_unix_date2(cli, p+4) - cli->serverzone; 1155 finfo->atime = cli_make_unix_date2(cli, p+8) - cli->serverzone; 1156 finfo->mtime = cli_make_unix_date2(cli, p+12) - cli->serverzone; 1157 finfo->size = IVAL(p,16); 1158 finfo->attr = CVAL(p,24); 1159 len = CVAL(p, 26); 1160 p += 27; 1161 p += clistr_align_in(cli, p, 0); 1162 1163 /* We can safely use len here (which is required by OS/2) 1164 * and the NAS-BASIC server instead of +2 or +1 as the 1165 * STR_TERMINATE flag below is 1166 * actually used as the length calculation. 1167 * The len is merely an upper bound. 1168 * Due to the explicit 2 byte null termination 1169 * in cli_receive_trans/cli_receive_nt_trans 1170 * we know this is safe. JRA + kukks 1171 */ 1172 1173 if (p + len > pdata_end) { 1174 return pdata_end - base; 1175 } 1176 1177 /* the len+2 below looks strange but it is 1178 important to cope with the differences 1179 between win2000 and win9x for this call 1180 (tridge) */ 1181 ret = clistr_pull_talloc(ctx, cli->inbuf, &fname, p, 1182 len+2, 1183 STR_TERMINATE); 1184 if (ret == (size_t)-1) { 1185 return pdata_end - base; 1186 } 1187 p += ret; 1188 finfo->easize = -1; 1189 strncat(finfo->fname, fname, sizeof(finfo->fname) -1); 1190 return PTR_DIFF(p, base); 1191 1192 case SMB_FIND_EA_SIZE: /* this is what OS/2 uses mostly */ 1193 /* these dates are converted to GMT by 1194 make_unix_date */ 1195 if (pdata_end - base < 31) { 1196 return pdata_end - base; 1197 } 1198 finfo->ctime = cli_make_unix_date2(cli, p+4) - cli->serverzone; 1199 finfo->atime = cli_make_unix_date2(cli, p+8) - cli->serverzone; 1200 finfo->mtime = cli_make_unix_date2(cli, p+12) - cli->serverzone; 1201 finfo->size = IVAL(p,16); 1202 finfo->attr = CVAL(p,24); 1203 finfo->easize = IVAL(p,26); 1204 len = CVAL(p, 30); 1205 p += 31; 1206 /* check for unisys! */ 1207 if (p + len + 1 > pdata_end) { 1208 return pdata_end - base; 1209 } 1210 ret = clistr_pull_talloc(ctx, cli->inbuf, &fname, p, 1211 len, 1212 STR_NOALIGN); 1213 if (ret == (size_t)-1) { 1214 return pdata_end - base; 1215 } 1216 p += ret; 1217 strncat(finfo->fname, fname, sizeof(finfo->fname) -1); 1218 return PTR_DIFF(p, base) + 1; 1219 1220 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: /* NT uses this, but also accepts 2 */ 1221 { 1222 size_t namelen, slen; 1223 1224 if (pdata_end - base < 94) { 1225 return pdata_end - base; 1226 } 1227 1228 p += 4; /* next entry offset */ 1229 1230 if (p_resume_key) { 1231 *p_resume_key = IVAL(p,0); 1232 } 1233 1234 p += 4; /* fileindex */ 1235 1236 /* Offset zero is "create time", not "change time". */ 1237 p += 8; 1238 finfo->atime = interpret_long_date(p).tv_sec; 1239 p += 8; 1240 finfo->mtime = interpret_long_date(p).tv_sec; 1241 p += 8; 1242 finfo->ctime = interpret_long_date(p).tv_sec; 1243 p += 8; 1244 finfo->size = IVAL2_TO_SMB_BIG_UINT(p,0); 1245 p += 8; 1246 p += 8; /* alloc size */ 1247 finfo->attr = CVAL(p,0); 1248 p += 4; 1249 namelen = IVAL(p,0); 1250 p += 4; 1251 finfo->easize = IVAL(p,0); 1252 p += 4; /* EA size */ 1253 slen = SVAL(p, 0); 1254 if (slen > 24) { 1255 /* Bad short name length. */ 1256 return pdata_end - base; 1257 } 1258 p += 2; 1259 #if 0 1260 { 1261 /* stupid NT bugs. grr */ 1262 int flags = 0; 1263 if (p[1] == 0 && namelen > 1) flags |= STR_UNICODE; 1264 clistr_pull(cli, finfo->short_name, p, 1265 sizeof(finfo->short_name), 1266 slen, flags); 1267 } 1268 #endif 1269 p += 24; /* short name? */ 1270 if (p + namelen < p || p + namelen > pdata_end) { 1271 return pdata_end - base; 1272 } 1273 ret = clistr_pull_talloc(ctx, cli->inbuf, &fname, p, 1274 namelen, 0); 1275 if (ret == (size_t)-1) { 1276 return pdata_end - base; 1277 } 1278 strncat(finfo->fname, fname, sizeof(finfo->fname) -1); 1279 1280 /* To be robust in the face of unicode conversion failures 1281 we need to copy the raw bytes of the last name seen here. 1282 Namelen doesn't include the terminating unicode null, so 1283 copy it here. */ 1284 #if 0 1285 if (p_last_name_raw) { 1286 *p_last_name_raw = data_blob(NULL, namelen+2); 1287 memcpy(p_last_name_raw->data, p, namelen); 1288 SSVAL(p_last_name_raw->data, namelen, 0); 1289 } 1290 #endif 1291 return calc_next_entry_offset(base, pdata_end); 1292 } 1293 } 1294 1295 debuglocal(1,"Unknown long filename format %d\n",level); 1296 return calc_next_entry_offset(base, pdata_end); 1297 } 1298 1299 /**************************************************************************** 1300 Do a directory listing, calling fn on each file found. 1301 Modified from cli_list_new 1302 ****************************************************************************/ 1303 1304 static int list_files(struct cli_state *cli, const char *Mask, uint16 attribute, 1305 void (*fn)(const char*, smbwrp_fileinfo *, const char *, void *), void *state) 1306 { 1307 #if 1 1308 int max_matches = 1366; /* Match W2k - was 512. */ 1309 #else 1310 int max_matches = 512; 1311 #endif 1312 int info_level; 1313 char *p, *p2, *rdata_end; 1314 char *mask=NULL; 1315 smbwrp_fileinfo finfo; 1316 int i; 1317 char *dirlist = NULL; 1318 int dirlist_len = 0; 1319 int total_received = -1; 1320 bool First = True; 1321 int ff_searchcount=0; 1322 int ff_eos=0; 1323 int ff_dir_handle=0; 1324 int loop_count = 0; 1325 char *rparam=NULL, *rdata=NULL; 1326 unsigned int param_len, data_len; 1327 uint16 setup; 1328 char *param; 1329 uint32 resume_key = 0; 855 static int list_files(struct cli_state *cli, const char *mask, uint16 attribute, 856 void (*fn)(const char *, smbwrp_fileinfo *, const char *, 857 void *), void *state) 858 { 1330 859 TALLOC_CTX *frame = talloc_stackframe(); 1331 DATA_BLOB last_name_raw = data_blob(NULL, 0); 1332 1333 /* NT uses SMB_FIND_FILE_BOTH_DIRECTORY_INFO, 1334 OS/2 uses SMB_FIND_EA_SIZE. Both accept SMB_FIND_INFO_STANDARD. */ 1335 info_level = (cli->capabilities&CAP_NT_SMBS)? 1336 SMB_FIND_FILE_BOTH_DIRECTORY_INFO : SMB_FIND_EA_SIZE; 1337 1338 debuglocal(4,"list_files level %d. mask <%s>\n", info_level, Mask); 1339 1340 mask = SMB_STRDUP(Mask); 1341 if (!mask) { 1342 TALLOC_FREE(frame); 1343 return -1; 1344 } 860 struct event_context *ev; 861 struct tevent_req *req; 862 NTSTATUS status = NT_STATUS_NO_MEMORY; 863 struct file_info *finfo; 864 size_t i, num_finfo; 865 uint16_t info_level; 866 void *dircachectx = NULL; 867 smbwrp_fileinfo wrpfinfo; 1345 868 1346 869 /* Try to get the listing from cache. */ 1347 if (dircache_list_files(fn, state, & total_received))870 if (dircache_list_files(fn, state, &num_finfo)) 1348 871 { 1349 872 /* Got from cache. */ 1350 return(total_received); 1351 } 1352 1353 while (ff_eos == 0) { 1354 size_t nlen = 2*(strlen(mask)+1); 1355 1356 loop_count++; 1357 if (loop_count > 200) { 1358 debuglocal(0,"Error: Looping in FIND_NEXT??\n"); 1359 break; 1360 } 1361 1362 param = SMB_MALLOC_ARRAY(char, 12+nlen+last_name_raw.length+2); 1363 if (!param) { 1364 break; 1365 } 1366 1367 if (First) { 1368 setup = TRANSACT2_FINDFIRST; 1369 SSVAL(param,0,attribute); /* attribute */ 1370 SSVAL(param,2,max_matches); /* max count */ 1371 SSVAL(param,4,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */ 1372 SSVAL(param,6,info_level); 1373 SIVAL(param,8,0); 1374 p = param+12; 1375 p += clistr_push(cli, param+12, mask, nlen, 1376 STR_TERMINATE); 1377 } else { 1378 setup = TRANSACT2_FINDNEXT; 1379 SSVAL(param,0,ff_dir_handle); 1380 SSVAL(param,2,max_matches); /* max count */ 1381 SSVAL(param,4,info_level); 1382 /* For W2K servers serving out FAT filesystems we *must* set the 1383 resume key. If it's not FAT then it's returned as zero. */ 1384 SIVAL(param,6,resume_key); /* ff_resume_key */ 1385 /* NB. *DON'T* use continue here. If you do it seems that W2K and bretheren 1386 can miss filenames. Use last filename continue instead. JRA */ 1387 SSVAL(param,10,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */ 1388 p = param+12; 1389 if (last_name_raw.length) { 1390 memcpy(p, last_name_raw.data, last_name_raw.length); 1391 p += last_name_raw.length; 1392 } else { 1393 p += clistr_push(cli, param+12, mask, 1394 nlen, STR_TERMINATE); 1395 } 1396 } 1397 1398 param_len = PTR_DIFF(p, param); 1399 1400 if (!cli_send_trans(cli, SMBtrans2, 1401 NULL, /* Name */ 1402 -1, 0, /* fid, flags */ 1403 &setup, 1, 0, /* setup, length, max */ 1404 param, param_len, 10, /* param, length, max */ 1405 NULL, 0, 1406 #if 0 1407 /* w2k value. */ 1408 MIN(16384,cli->max_xmit) /* data, length, max. */ 1409 #else 1410 cli->max_xmit /* data, length, max. */ 1411 #endif 1412 )) { 1413 SAFE_FREE(param); 1414 TALLOC_FREE(frame); 1415 break; 1416 } 1417 1418 SAFE_FREE(param); 1419 1420 if (!cli_receive_trans(cli, SMBtrans2, 1421 &rparam, ¶m_len, 1422 &rdata, &data_len) && 1423 cli_is_dos_error(cli)) { 1424 /* we need to work around a Win95 bug - sometimes 1425 it gives ERRSRV/ERRerror temprarily */ 1426 uint8 eclass; 1427 uint32 ecode; 1428 1429 SAFE_FREE(rdata); 1430 SAFE_FREE(rparam); 1431 1432 cli_dos_error(cli, &eclass, &ecode); 1433 1434 /* 1435 * OS/2 might return "no more files", 1436 * which just tells us, that searchcount is zero 1437 * in this search. 1438 * Guenter Kukkukk <linux@kukkukk.com> 1439 */ 1440 1441 if (eclass == ERRDOS && ecode == ERRnofiles) { 1442 ff_searchcount = 0; 1443 cli_reset_error(cli); 1444 break; 1445 } 1446 1447 if (eclass != ERRSRV || ecode != ERRerror) 1448 break; 1449 smb_msleep(100); 1450 continue; 1451 } 1452 1453 if (cli_is_error(cli) || !rdata || !rparam) 1454 { 1455 if (First && info_level == SMB_FIND_EA_SIZE) 1456 { 1457 // we have tried query ea size, but now will try without ea size 1458 info_level = SMB_FIND_INFO_STANDARD; 1459 debuglocal(4,"list_files fallback to level %d\n", info_level); 1460 continue; 1461 } 1462 SAFE_FREE(rdata); 1463 SAFE_FREE(rparam); 1464 break; 1465 } 1466 1467 if (total_received == -1) 1468 total_received = 0; 1469 1470 /* parse out some important return info */ 1471 p = rparam; 1472 if (First) { 1473 ff_dir_handle = SVAL(p,0); 1474 ff_searchcount = SVAL(p,2); 1475 ff_eos = SVAL(p,4); 1476 } else { 1477 ff_searchcount = SVAL(p,0); 1478 ff_eos = SVAL(p,2); 1479 } 1480 debuglocal(4,"list_files %d %d %d %d\n", ff_searchcount, ff_eos, "(ff_lastname)", First); 1481 1482 if (ff_searchcount == 0) { 1483 SAFE_FREE(rdata); 1484 SAFE_FREE(rparam); 1485 break; 1486 } 1487 1488 /* point to the data bytes */ 1489 p = rdata; 1490 rdata_end = rdata + data_len; 1491 1492 memset(&finfo, 0, sizeof(finfo)); 1493 finfo.easize = -1; 1494 /* we might need the lastname for continuations */ 1495 for (p2=p,i=0;i<ff_searchcount && p2 < rdata_end;i++) { 1496 if ((info_level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) && 1497 (i == ff_searchcount-1)) { 1498 /* Last entry - fixup the last offset length. */ 1499 SIVAL(p2,0,PTR_DIFF((rdata + data_len),p2)); 1500 } 1501 p2 += _os2_interpret_long_filename(frame, cli, info_level, p2, rdata_end, &finfo, 1502 &resume_key, &last_name_raw); 1503 1504 if (!finfo.fname) { 1505 debuglocal(0,"Error: unable to parse name from info level %d\n", 1506 info_level); 1507 ff_eos = 1; 1508 break; 1509 } 1510 1511 if (!First && *mask && strcsequal(finfo.fname, mask)) { 1512 debuglocal(0,"Error: Looping in FIND_NEXT as name %s has already been seen?\n", 1513 finfo.fname); 1514 ff_eos = 1; 1515 break; 1516 } 1517 } 1518 1519 SAFE_FREE(mask); 1520 if (ff_searchcount > 0 && ff_eos == 0 && finfo.fname) { 1521 mask = SMB_STRDUP(finfo.fname); 1522 } else { 1523 mask = SMB_STRDUP(""); 1524 } 1525 if (!mask) { 1526 SAFE_FREE(rdata); 1527 SAFE_FREE(rparam); 1528 break; 1529 } 1530 1531 /* grab the data for later use */ 1532 /* and add them to the dirlist pool */ 1533 dirlist = (char *)SMB_REALLOC(dirlist,dirlist_len + data_len); 1534 1535 if (!dirlist) { 1536 debuglocal(0,"cli_list_new: Failed to expand dirlist\n"); 1537 SAFE_FREE(rdata); 1538 SAFE_FREE(rparam); 1539 break; 1540 } 1541 1542 memcpy(dirlist+dirlist_len,p,data_len); 1543 dirlist_len += data_len; 1544 1545 total_received += ff_searchcount; 1546 1547 SAFE_FREE(rdata); 1548 SAFE_FREE(rparam); 1549 1550 debuglocal(3,"received %d entries (eos=%d)\n", 1551 ff_searchcount,ff_eos); 1552 1553 if (ff_searchcount > 0) 1554 loop_count = 0; 1555 1556 First = False; 1557 } 1558 1559 /* see if the server disconnected or the connection otherwise failed */ 1560 if (cli_is_error(cli)) { 1561 total_received = -1; 1562 } else { 1563 void *dircachectx = dircache_write_begin(state, total_received); 1564 1565 /* no connection problem. let user function add each entry */ 1566 rdata_end = dirlist + dirlist_len; 1567 for (p=dirlist,i=0;i<total_received;i++) { 1568 p += _os2_interpret_long_filename(frame, cli, info_level, p, rdata_end, 1569 &finfo,NULL,NULL); 1570 1571 if (!finfo.fname) { 1572 debuglocal(0,"list_new: unable to parse name from info level %d\n", 1573 info_level); 1574 break; 1575 } 1576 fn(cli->dfs_mountpoint,&finfo, Mask, state ); 1577 1578 /* Also add the entry to the cache. */ 1579 dircache_write_entry(dircachectx, &finfo); 1580 } 1581 1582 dircache_write_end(dircachectx); 1583 1584 } 1585 1586 /* free up the dirlist buffer and last name raw blob */ 1587 SAFE_FREE(dirlist); 1588 data_blob_free(&last_name_raw); 1589 SAFE_FREE(mask); 873 return(num_finfo); 874 } 875 876 if (cli_has_async_calls(cli)) { 877 /* 878 * Can't use sync call while an async call is in flight 879 */ 880 status = NT_STATUS_INVALID_PARAMETER; 881 goto fail; 882 } 883 ev = event_context_init(frame); 884 if (ev == NULL) { 885 goto fail; 886 } 887 888 info_level = (cli->capabilities & CAP_NT_SMBS) 889 ? SMB_FIND_FILE_BOTH_DIRECTORY_INFO : SMB_FIND_EA_SIZE; 890 891 debuglocal(4,"list_files level %d. mask <%s>\n", info_level, mask); 892 893 req = cli_list_send(frame, ev, cli, mask, attribute, info_level); 894 if (req == NULL) { 895 goto fail; 896 } 897 if (!tevent_req_poll(req, ev)) { 898 status = map_nt_error_from_unix(errno); 899 goto fail; 900 } 901 902 status = cli_list_recv(req, frame, &finfo, &num_finfo); 903 if (!NT_STATUS_IS_OK(status)) { 904 goto fail; 905 } 906 907 dircachectx = dircache_write_begin(state, num_finfo); 908 909 debuglocal(4,"list_files: got %d files\n", num_finfo); 910 911 912 for (i=0; i<num_finfo; i++) { 913 //as samba and this client have different finfo, we need to convert 914 memset(&wrpfinfo, 0, sizeof(wrpfinfo)); 915 wrpfinfo.size = finfo[i].size; 916 wrpfinfo.attr = finfo[i].mode; 917 wrpfinfo.ctime = convert_timespec_to_time_t(finfo[i].ctime_ts); 918 wrpfinfo.mtime = convert_timespec_to_time_t(finfo[i].mtime_ts); 919 wrpfinfo.atime = convert_timespec_to_time_t(finfo[i].atime_ts); 920 wrpfinfo.easize = finfo[i].easize; 921 strncpy(wrpfinfo.fname, finfo[i].name, sizeof(wrpfinfo.fname) -1); 922 923 fn(cli->dfs_mountpoint, &wrpfinfo, mask, state); 924 // Also add the entry to the cache. 925 dircache_write_entry(dircachectx, &wrpfinfo); 926 } 927 928 dircache_write_end(dircachectx); 929 fail: 1590 930 TALLOC_FREE(frame); 1591 return(total_received); 1592 } 1593 931 return num_finfo; 932 } 1594 933 1595 934 /***************************************************** … … 1640 979 else 1641 980 { 1642 #if 01643 if (strcmp(path,"\\") == 0) {1644 smbwrp_special_add(".", state);1645 smbwrp_special_add("..", state);1646 }1647 #endif1648 #if 01649 if (cli_list(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,1650 smbwrp_dir_add_old, state) < 0)1651 #else1652 981 if (list_files(cli, state->mask, aHIDDEN|aSYSTEM|aDIR, 1653 982 smbwrp_dir_add, state) < 0) 1654 #endif1655 983 { 1656 984 return os2cli_errno(cli); … … 1769 1097 #pragma pack() 1770 1098 1771 static int unilistea(cli_state * cli, char *fname, smbwrp_file *file,void * buffer, unsigned long size)1099 static int unilistea(cli_state * cli, char *fname, void * buffer, unsigned long size) 1772 1100 { 1773 1101 int fnum, i; … … 1784 1112 pfealist->cbList = 0; 1785 1113 1786 if (file) 1787 { 1788 if (!cli_get_ea_list_fnum(cli, file->fd, mem_ctx, &num_eas, &ea_list)) 1789 { 1790 debuglocal(4,"ea_get_fnum list failed - %s\n", cli_errstr(cli)); 1791 talloc_destroy(mem_ctx); 1792 return os2cli_errno(cli); 1793 } 1794 } 1795 else 1796 { 1797 if (!cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list)) 1798 { 1799 debuglocal(4,"ea_get_file list failed - %s\n", cli_errstr(cli)); 1800 talloc_destroy(mem_ctx); 1801 return os2cli_errno(cli); 1802 } 1114 if (!cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list)) 1115 { 1116 debuglocal(4,"ea_get_file list failed - %s\n", cli_errstr(cli)); 1117 talloc_destroy(mem_ctx); 1118 return os2cli_errno(cli); 1803 1119 } 1804 1120 … … 1847 1163 1848 1164 debuglocal(4,"EALIst for <%s>\n", fname); 1849 return unilistea(cli, fname, NULL,buffer, size);1165 return unilistea(cli, fname, buffer, size); 1850 1166 } 1851 1167 … … 1860 1176 } 1861 1177 1862 debuglocal(4,"FEALIst for <%s> /%d\n", file->fname, file->fd);1863 return unilistea(cli, NULL, file, buffer, size);1178 debuglocal(4,"FEALIst for <%s>\n", file->fname); 1179 return unilistea(cli, file->fname, buffer, size); 1864 1180 } 1865 1181
Note:
See TracChangeset
for help on using the changeset viewer.