関数 | |
static size_t | interpret_long_filename (struct cli_state *cli, int level, char *p, file_info *finfo, uint32 *p_resume_key, DATA_BLOB *p_last_name_raw, uint32 *p_last_name_raw_len) |
int | cli_list_new (struct cli_state *cli, const char *Mask, uint16 attribute, void(*fn)(const char *, file_info *, const char *, void *), void *state) |
static int | interpret_short_filename (struct cli_state *cli, char *p, file_info *finfo) |
int | cli_list_old (struct cli_state *cli, const char *Mask, uint16 attribute, void(*fn)(const char *, file_info *, const char *, void *), void *state) |
int | cli_list (struct cli_state *cli, const char *Mask, uint16 attribute, void(*fn)(const char *, file_info *, const char *, void *), void *state) |
変数 | |
file_info | def_finfo |
static size_t interpret_long_filename | ( | struct cli_state * | cli, | |
int | level, | |||
char * | p, | |||
file_info * | finfo, | |||
uint32 * | p_resume_key, | |||
DATA_BLOB * | p_last_name_raw, | |||
uint32 * | p_last_name_raw_len | |||
) | [static] |
参照先 cli・cli_make_unix_date2()・clistr_align_in()・convert_time_t_to_timespec()・data_blob_::data・def_finfo・flags・interpret_long_date()・len・data_blob_::length.
参照元 cli_list_new().
00034 { 00035 file_info finfo2; 00036 int len; 00037 char *base = p; 00038 00039 if (!finfo) { 00040 finfo = &finfo2; 00041 } 00042 00043 if (p_resume_key) { 00044 *p_resume_key = 0; 00045 } 00046 memcpy(finfo,&def_finfo,sizeof(*finfo)); 00047 finfo->cli = cli; 00048 00049 switch (level) { 00050 case 1: /* OS/2 understands this */ 00051 /* these dates are converted to GMT by 00052 make_unix_date */ 00053 finfo->ctime_ts = convert_time_t_to_timespec(cli_make_unix_date2(cli, p+4)); 00054 finfo->atime_ts = convert_time_t_to_timespec(cli_make_unix_date2(cli, p+8)); 00055 finfo->mtime_ts = convert_time_t_to_timespec(cli_make_unix_date2(cli, p+12)); 00056 finfo->size = IVAL(p,16); 00057 finfo->mode = CVAL(p,24); 00058 len = CVAL(p, 26); 00059 p += 27; 00060 p += clistr_align_in(cli, p, 0); 00061 /* the len+2 below looks strange but it is 00062 important to cope with the differences 00063 between win2000 and win9x for this call 00064 (tridge) */ 00065 p += clistr_pull(cli, finfo->name, p, 00066 sizeof(finfo->name), 00067 len+2, 00068 STR_TERMINATE); 00069 return PTR_DIFF(p, base); 00070 00071 case 2: /* this is what OS/2 uses mostly */ 00072 /* these dates are converted to GMT by 00073 make_unix_date */ 00074 finfo->ctime_ts = convert_time_t_to_timespec(cli_make_unix_date2(cli, p+4)); 00075 finfo->atime_ts = convert_time_t_to_timespec(cli_make_unix_date2(cli, p+8)); 00076 finfo->mtime_ts = convert_time_t_to_timespec(cli_make_unix_date2(cli, p+12)); 00077 finfo->size = IVAL(p,16); 00078 finfo->mode = CVAL(p,24); 00079 len = CVAL(p, 30); 00080 p += 31; 00081 /* check for unisys! */ 00082 p += clistr_pull(cli, finfo->name, p, 00083 sizeof(finfo->name), 00084 len, 00085 STR_NOALIGN); 00086 return PTR_DIFF(p, base) + 1; 00087 00088 case 260: /* NT uses this, but also accepts 2 */ 00089 { 00090 size_t namelen, slen; 00091 p += 4; /* next entry offset */ 00092 00093 if (p_resume_key) { 00094 *p_resume_key = IVAL(p,0); 00095 } 00096 p += 4; /* fileindex */ 00097 00098 /* Offset zero is "create time", not "change time". */ 00099 p += 8; 00100 finfo->atime_ts = interpret_long_date(p); 00101 p += 8; 00102 finfo->mtime_ts = interpret_long_date(p); 00103 p += 8; 00104 finfo->ctime_ts = interpret_long_date(p); 00105 p += 8; 00106 finfo->size = IVAL2_TO_SMB_BIG_UINT(p,0); 00107 p += 8; 00108 p += 8; /* alloc size */ 00109 finfo->mode = CVAL(p,0); 00110 p += 4; 00111 namelen = IVAL(p,0); 00112 p += 4; 00113 p += 4; /* EA size */ 00114 slen = SVAL(p, 0); 00115 p += 2; 00116 { 00117 /* stupid NT bugs. grr */ 00118 int flags = 0; 00119 if (p[1] == 0 && namelen > 1) flags |= STR_UNICODE; 00120 clistr_pull(cli, finfo->short_name, p, 00121 sizeof(finfo->short_name), 00122 slen, flags); 00123 } 00124 p += 24; /* short name? */ 00125 clistr_pull(cli, finfo->name, p, 00126 sizeof(finfo->name), 00127 namelen, 0); 00128 00129 /* To be robust in the face of unicode conversion failures 00130 we need to copy the raw bytes of the last name seen here. 00131 Namelen doesn't include the terminating unicode null, so 00132 copy it here. */ 00133 00134 if (p_last_name_raw && p_last_name_raw_len) { 00135 if (namelen + 2 > p_last_name_raw->length) { 00136 memset(p_last_name_raw->data, '\0', sizeof(p_last_name_raw->length)); 00137 *p_last_name_raw_len = 0; 00138 } else { 00139 memcpy(p_last_name_raw->data, p, namelen); 00140 SSVAL(p_last_name_raw->data, namelen, 0); 00141 *p_last_name_raw_len = namelen + 2; 00142 } 00143 } 00144 return (size_t)IVAL(base, 0); 00145 } 00146 } 00147 00148 DEBUG(1,("Unknown long filename format %d\n",level)); 00149 return (size_t)IVAL(base,0); 00150 }
int cli_list_new | ( | struct cli_state * | cli, | |
const char * | Mask, | |||
uint16 | attribute, | |||
void(*)(const char *, file_info *, const char *, void *) | fn, | |||
void * | state | |||
) |
参照先 cli_state::capabilities・cli・cli_cm_get_mntpoint()・cli_dos_error()・cli_is_dos_error()・cli_is_error()・cli_receive_trans()・cli_reset_error()・cli_send_trans()・data_blob_::data・data_blob()・data_blob_free()・endif・fn・interpret_long_filename()・cli_state::max_xmit・file_info::name・smb_msleep()・strcsequal().
参照元 cli_list()・get_real_name().
00158 { 00159 #if 1 00160 int max_matches = 1366; /* Match W2k - was 512. */ 00161 #else 00162 int max_matches = 512; 00163 #endif 00164 int info_level; 00165 char *p, *p2; 00166 pstring mask; 00167 file_info finfo; 00168 int i; 00169 char *dirlist = NULL; 00170 int dirlist_len = 0; 00171 int total_received = -1; 00172 BOOL First = True; 00173 int ff_searchcount=0; 00174 int ff_eos=0; 00175 int ff_dir_handle=0; 00176 int loop_count = 0; 00177 char *rparam=NULL, *rdata=NULL; 00178 unsigned int param_len, data_len; 00179 uint16 setup; 00180 pstring param; 00181 const char *mnt; 00182 uint32 resume_key = 0; 00183 uint32 last_name_raw_len = 0; 00184 DATA_BLOB last_name_raw = data_blob(NULL, 2*sizeof(pstring)); 00185 00186 /* NT uses 260, OS/2 uses 2. Both accept 1. */ 00187 info_level = (cli->capabilities&CAP_NT_SMBS)?260:1; 00188 00189 pstrcpy(mask,Mask); 00190 00191 while (ff_eos == 0) { 00192 loop_count++; 00193 if (loop_count > 200) { 00194 DEBUG(0,("Error: Looping in FIND_NEXT??\n")); 00195 break; 00196 } 00197 00198 if (First) { 00199 setup = TRANSACT2_FINDFIRST; 00200 SSVAL(param,0,attribute); /* attribute */ 00201 SSVAL(param,2,max_matches); /* max count */ 00202 SSVAL(param,4,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */ 00203 SSVAL(param,6,info_level); 00204 SIVAL(param,8,0); 00205 p = param+12; 00206 p += clistr_push(cli, param+12, mask, sizeof(param)-12, 00207 STR_TERMINATE); 00208 } else { 00209 setup = TRANSACT2_FINDNEXT; 00210 SSVAL(param,0,ff_dir_handle); 00211 SSVAL(param,2,max_matches); /* max count */ 00212 SSVAL(param,4,info_level); 00213 /* For W2K servers serving out FAT filesystems we *must* set the 00214 resume key. If it's not FAT then it's returned as zero. */ 00215 SIVAL(param,6,resume_key); /* ff_resume_key */ 00216 /* NB. *DON'T* use continue here. If you do it seems that W2K and bretheren 00217 can miss filenames. Use last filename continue instead. JRA */ 00218 SSVAL(param,10,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */ 00219 p = param+12; 00220 if (last_name_raw_len && (last_name_raw_len < (sizeof(param)-12))) { 00221 memcpy(p, last_name_raw.data, last_name_raw_len); 00222 p += last_name_raw_len; 00223 } else { 00224 p += clistr_push(cli, param+12, mask, sizeof(param)-12, STR_TERMINATE); 00225 } 00226 } 00227 00228 param_len = PTR_DIFF(p, param); 00229 00230 if (!cli_send_trans(cli, SMBtrans2, 00231 NULL, /* Name */ 00232 -1, 0, /* fid, flags */ 00233 &setup, 1, 0, /* setup, length, max */ 00234 param, param_len, 10, /* param, length, max */ 00235 NULL, 0, 00236 #if 0 00237 /* w2k value. */ 00238 MIN(16384,cli->max_xmit) /* data, length, max. */ 00239 #else 00240 cli->max_xmit /* data, length, max. */ 00241 #endif 00242 )) { 00243 break; 00244 } 00245 00246 if (!cli_receive_trans(cli, SMBtrans2, 00247 &rparam, ¶m_len, 00248 &rdata, &data_len) && 00249 cli_is_dos_error(cli)) { 00250 /* We need to work around a Win95 bug - sometimes 00251 it gives ERRSRV/ERRerror temprarily */ 00252 uint8 eclass; 00253 uint32 ecode; 00254 00255 SAFE_FREE(rdata); 00256 SAFE_FREE(rparam); 00257 00258 cli_dos_error(cli, &eclass, &ecode); 00259 00260 /* 00261 * OS/2 might return "no more files", 00262 * which just tells us, that searchcount is zero 00263 * in this search. 00264 * Guenter Kukkukk <linux@kukkukk.com> 00265 */ 00266 00267 if (eclass == ERRDOS && ecode == ERRnofiles) { 00268 ff_searchcount = 0; 00269 cli_reset_error(cli); 00270 break; 00271 } 00272 00273 if (eclass != ERRSRV || ecode != ERRerror) 00274 break; 00275 smb_msleep(100); 00276 continue; 00277 } 00278 00279 if (cli_is_error(cli) || !rdata || !rparam) { 00280 SAFE_FREE(rdata); 00281 SAFE_FREE(rparam); 00282 break; 00283 } 00284 00285 if (total_received == -1) 00286 total_received = 0; 00287 00288 /* parse out some important return info */ 00289 p = rparam; 00290 if (First) { 00291 ff_dir_handle = SVAL(p,0); 00292 ff_searchcount = SVAL(p,2); 00293 ff_eos = SVAL(p,4); 00294 } else { 00295 ff_searchcount = SVAL(p,0); 00296 ff_eos = SVAL(p,2); 00297 } 00298 00299 if (ff_searchcount == 0) { 00300 SAFE_FREE(rdata); 00301 SAFE_FREE(rparam); 00302 break; 00303 } 00304 00305 /* point to the data bytes */ 00306 p = rdata; 00307 00308 /* we might need the lastname for continuations */ 00309 for (p2=p,i=0;i<ff_searchcount;i++) { 00310 if ((info_level == 260) && (i == ff_searchcount-1)) { 00311 /* Last entry - fixup the last offset length. */ 00312 SIVAL(p2,0,PTR_DIFF((rdata + data_len),p2)); 00313 } 00314 p2 += interpret_long_filename(cli,info_level,p2,&finfo, 00315 &resume_key,&last_name_raw,&last_name_raw_len); 00316 00317 if (!First && *mask && strcsequal(finfo.name, mask)) { 00318 DEBUG(0,("Error: Looping in FIND_NEXT as name %s has already been seen?\n", 00319 finfo.name)); 00320 ff_eos = 1; 00321 break; 00322 } 00323 } 00324 00325 if (ff_searchcount > 0) { 00326 pstrcpy(mask, finfo.name); 00327 } else { 00328 pstrcpy(mask,""); 00329 } 00330 00331 /* grab the data for later use */ 00332 /* and add them to the dirlist pool */ 00333 dirlist = (char *)SMB_REALLOC(dirlist,dirlist_len + data_len); 00334 00335 if (!dirlist) { 00336 DEBUG(0,("cli_list_new: Failed to expand dirlist\n")); 00337 SAFE_FREE(rdata); 00338 SAFE_FREE(rparam); 00339 break; 00340 } 00341 00342 memcpy(dirlist+dirlist_len,p,data_len); 00343 dirlist_len += data_len; 00344 00345 total_received += ff_searchcount; 00346 00347 SAFE_FREE(rdata); 00348 SAFE_FREE(rparam); 00349 00350 DEBUG(3,("received %d entries (eos=%d)\n", 00351 ff_searchcount,ff_eos)); 00352 00353 if (ff_searchcount > 0) 00354 loop_count = 0; 00355 00356 First = False; 00357 } 00358 00359 mnt = cli_cm_get_mntpoint( cli ); 00360 00361 /* see if the server disconnected or the connection otherwise failed */ 00362 if (cli_is_error(cli)) { 00363 total_received = -1; 00364 } else { 00365 /* no connection problem. let user function add each entry */ 00366 for (p=dirlist,i=0;i<total_received;i++) { 00367 p += interpret_long_filename(cli, info_level, p, 00368 &finfo,NULL,NULL,NULL); 00369 fn( mnt,&finfo, Mask, state ); 00370 } 00371 } 00372 00373 /* free up the dirlist buffer and last name raw blob */ 00374 SAFE_FREE(dirlist); 00375 data_blob_free(&last_name_raw); 00376 return(total_received); 00377 }
static int interpret_short_filename | ( | struct cli_state * | cli, | |
char * | p, | |||
file_info * | finfo | |||
) | [static] |
参照先 file_info::atime_ts・cli・file_info::cli・cli_make_unix_date()・file_info::ctime_ts・def_finfo・file_info::mode・file_info::mtime_ts・file_info::name・file_info::short_name・file_info::size.
参照元 cli_list_old().
00385 { 00386 00387 *finfo = def_finfo; 00388 00389 finfo->cli = cli; 00390 finfo->mode = CVAL(p,21); 00391 00392 /* this date is converted to GMT by make_unix_date */ 00393 finfo->ctime_ts.tv_sec = cli_make_unix_date(cli, p+22); 00394 finfo->ctime_ts.tv_nsec = 0; 00395 finfo->mtime_ts.tv_sec = finfo->atime_ts.tv_sec = finfo->ctime_ts.tv_sec; 00396 finfo->mtime_ts.tv_nsec = finfo->atime_ts.tv_nsec = 0; 00397 finfo->size = IVAL(p,26); 00398 clistr_pull(cli, finfo->name, p+30, sizeof(finfo->name), 12, STR_ASCII); 00399 if (strcmp(finfo->name, "..") && strcmp(finfo->name, ".")) { 00400 strncpy(finfo->short_name,finfo->name, sizeof(finfo->short_name)-1); 00401 finfo->short_name[sizeof(finfo->short_name)-1] = '\0'; 00402 } 00403 00404 return(DIR_STRUCT_SIZE); 00405 }
int cli_list_old | ( | struct cli_state * | cli, | |
const char * | Mask, | |||
uint16 | attribute, | |||
void(*)(const char *, file_info *, const char *, void *) | fn, | |||
void * | state | |||
) |
参照先 cli・cli_errstr()・cli_is_error()・cli_receive_smb()・cli_send_smb()・cli_setup_bcc()・cli_setup_packet()・cli_state::cnum・fn・cli_state::inbuf・interpret_short_filename()・cli_state::max_xmit・cli_state::outbuf・set_message()・status.
参照元 cli_list()・run_dirtest1().
00416 { 00417 char *p; 00418 int received = 0; 00419 BOOL first = True; 00420 char status[21]; 00421 int num_asked = (cli->max_xmit - 100)/DIR_STRUCT_SIZE; 00422 int num_received = 0; 00423 int i; 00424 char *dirlist = NULL; 00425 pstring mask; 00426 00427 ZERO_ARRAY(status); 00428 00429 pstrcpy(mask,Mask); 00430 00431 while (1) { 00432 memset(cli->outbuf,'\0',smb_size); 00433 memset(cli->inbuf,'\0',smb_size); 00434 00435 set_message(cli->outbuf,2,0,True); 00436 00437 SCVAL(cli->outbuf,smb_com,SMBsearch); 00438 00439 SSVAL(cli->outbuf,smb_tid,cli->cnum); 00440 cli_setup_packet(cli); 00441 00442 SSVAL(cli->outbuf,smb_vwv0,num_asked); 00443 SSVAL(cli->outbuf,smb_vwv1,attribute); 00444 00445 p = smb_buf(cli->outbuf); 00446 *p++ = 4; 00447 00448 p += clistr_push(cli, p, first?mask:"", -1, STR_TERMINATE); 00449 *p++ = 5; 00450 if (first) { 00451 SSVAL(p,0,0); 00452 p += 2; 00453 } else { 00454 SSVAL(p,0,21); 00455 p += 2; 00456 memcpy(p,status,21); 00457 p += 21; 00458 } 00459 00460 cli_setup_bcc(cli, p); 00461 cli_send_smb(cli); 00462 if (!cli_receive_smb(cli)) break; 00463 00464 received = SVAL(cli->inbuf,smb_vwv0); 00465 if (received <= 0) break; 00466 00467 first = False; 00468 00469 dirlist = (char *)SMB_REALLOC( 00470 dirlist,(num_received + received)*DIR_STRUCT_SIZE); 00471 if (!dirlist) { 00472 DEBUG(0,("cli_list_old: failed to expand dirlist")); 00473 return 0; 00474 } 00475 00476 p = smb_buf(cli->inbuf) + 3; 00477 00478 memcpy(dirlist+num_received*DIR_STRUCT_SIZE, 00479 p,received*DIR_STRUCT_SIZE); 00480 00481 memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21); 00482 00483 num_received += received; 00484 00485 if (cli_is_error(cli)) break; 00486 } 00487 00488 if (!first) { 00489 memset(cli->outbuf,'\0',smb_size); 00490 memset(cli->inbuf,'\0',smb_size); 00491 00492 set_message(cli->outbuf,2,0,True); 00493 SCVAL(cli->outbuf,smb_com,SMBfclose); 00494 SSVAL(cli->outbuf,smb_tid,cli->cnum); 00495 cli_setup_packet(cli); 00496 00497 SSVAL(cli->outbuf, smb_vwv0, 0); /* find count? */ 00498 SSVAL(cli->outbuf, smb_vwv1, attribute); 00499 00500 p = smb_buf(cli->outbuf); 00501 *p++ = 4; 00502 fstrcpy(p, ""); 00503 p += strlen(p) + 1; 00504 *p++ = 5; 00505 SSVAL(p, 0, 21); 00506 p += 2; 00507 memcpy(p,status,21); 00508 p += 21; 00509 00510 cli_setup_bcc(cli, p); 00511 cli_send_smb(cli); 00512 if (!cli_receive_smb(cli)) { 00513 DEBUG(0,("Error closing search: %s\n",cli_errstr(cli))); 00514 } 00515 } 00516 00517 for (p=dirlist,i=0;i<num_received;i++) { 00518 file_info finfo; 00519 p += interpret_short_filename(cli, p,&finfo); 00520 fn("\\", &finfo, Mask, state); 00521 } 00522 00523 SAFE_FREE(dirlist); 00524 return(num_received); 00525 }
int cli_list | ( | struct cli_state * | cli, | |
const char * | Mask, | |||
uint16 | attribute, | |||
void(*)(const char *, file_info *, const char *, void *) | fn, | |||
void * | state | |||
) |
参照先 cli・cli_list_new()・cli_list_old()・cli_state::protocol・PROTOCOL_LANMAN1.
参照元 delete_fn()・do_list()・gpo_sync_files()・nb_deltree()・nb_findfirst()・remote_completion()・run_dirtest()・run_dirtest1()・smbc_opendir_ctx()・smbc_rmdir_ctx()・sync_files()・testpair().
00534 { 00535 if (cli->protocol <= PROTOCOL_LANMAN1) 00536 return cli_list_old(cli, Mask, attribute, fn, state); 00537 return cli_list_new(cli, Mask, attribute, fn, state); 00538 }