libsmb/clilist.c

ソースコードを見る。

関数

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]

clilist.c32 行で定義されています。

参照先 clicli_make_unix_date2()clistr_align_in()convert_time_t_to_timespec()data_blob_::datadef_finfoflagsinterpret_long_date()lendata_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 
)

clilist.c156 行で定義されています。

参照先 cli_state::capabilitiesclicli_cm_get_mntpoint()cli_dos_error()cli_is_dos_error()cli_is_error()cli_receive_trans()cli_reset_error()cli_send_trans()data_blob_::datadata_blob()data_blob_free()endiffninterpret_long_filename()cli_state::max_xmitfile_info::namesmb_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, &param_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]

clilist.c384 行で定義されています。

参照先 file_info::atime_tsclifile_info::clicli_make_unix_date()file_info::ctime_tsdef_finfofile_info::modefile_info::mtime_tsfile_info::namefile_info::short_namefile_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 
)

clilist.c414 行で定義されています。

参照先 clicli_errstr()cli_is_error()cli_receive_smb()cli_send_smb()cli_setup_bcc()cli_setup_packet()cli_state::cnumfncli_state::inbufinterpret_short_filename()cli_state::max_xmitcli_state::outbufset_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 
)

clilist.c532 行で定義されています。

参照先 clicli_list_new()cli_list_old()cli_state::protocolPROTOCOL_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 }


変数

file_info def_finfo

util.c64 行で定義されています。


Sambaに対してSat Aug 29 21:23:47 2009に生成されました。  doxygen 1.4.7