/****************************************************************************
Interpret a long filename structure - this is mostly guesses at the moment.
The length of the structure is returned
- The structure of a long filename depends on the info level. 260 is used
- by NT and 2 is used by OS/2
+ The structure of a long filename depends on the info level.
+ SMB_FIND_FILE_BOTH_DIRECTORY_INFO is used
+ by NT and SMB_FIND_EA_SIZE is used by OS/2
****************************************************************************/
static size_t interpret_long_filename(TALLOC_CTX *ctx,
finfo->cli = cli;
switch (level) {
- case 1: /* OS/2 understands this */
+ case SMB_FIND_INFO_STANDARD: /* OS/2 understands this */
/* these dates are converted to GMT by
make_unix_date */
if (pdata_end - base < 27) {
len = CVAL(p, 26);
p += 27;
p += clistr_align_in(cli, p, 0);
- if (p + len + 2 > pdata_end) {
+
+ /* We can safely use len here (which is required by OS/2)
+ * and the NAS-BASIC server instead of +2 or +1 as the
+ * STR_TERMINATE flag below is
+ * actually used as the length calculation.
+ * The len is merely an upper bound.
+ * Due to the explicit 2 byte null termination
+ * in cli_receive_trans/cli_receive_nt_trans
+ * we know this is safe. JRA + kukks
+ */
+
+ if (p + len > pdata_end) {
return pdata_end - base;
}
+
/* the len+2 below looks strange but it is
important to cope with the differences
between win2000 and win9x for this call
(tridge) */
ret = clistr_pull_talloc(ctx,
- cli,
+ cli->inbuf,
&finfo->name,
p,
len+2,
p += ret;
return PTR_DIFF(p, base);
- case 2: /* this is what OS/2 uses mostly */
+ case SMB_FIND_EA_SIZE: /* this is what OS/2 uses mostly */
/* these dates are converted to GMT by
make_unix_date */
if (pdata_end - base < 31) {
return pdata_end - base;
}
ret = clistr_pull_talloc(ctx,
- cli,
+ cli->inbuf,
&finfo->name,
p,
len,
p += ret;
return PTR_DIFF(p, base) + 1;
- case 260: /* NT uses this, but also accepts 2 */
+ case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: /* NT uses this, but also accepts 2 */
{
size_t namelen, slen;
/* stupid NT bugs. grr */
int flags = 0;
if (p[1] == 0 && namelen > 1) flags |= STR_UNICODE;
- clistr_pull(cli, finfo->short_name, p,
+ clistr_pull(cli->inbuf, finfo->short_name, p,
sizeof(finfo->short_name),
slen, flags);
}
return pdata_end - base;
}
ret = clistr_pull_talloc(ctx,
- cli,
+ cli->inbuf,
&finfo->name,
p,
namelen,
unsigned int param_len, data_len;
uint16 setup;
char *param;
- const char *mnt;
uint32 resume_key = 0;
TALLOC_CTX *frame = talloc_stackframe();
DATA_BLOB last_name_raw = data_blob(NULL, 0);
- /* NT uses 260, OS/2 uses 2. Both accept 1. */
- info_level = (cli->capabilities&CAP_NT_SMBS)?260:1;
+ /* NT uses SMB_FIND_FILE_BOTH_DIRECTORY_INFO,
+ OS/2 uses SMB_FIND_EA_SIZE. Both accept SMB_FIND_INFO_STANDARD. */
+ info_level = (cli->capabilities&CAP_NT_SMBS)?
+ SMB_FIND_FILE_BOTH_DIRECTORY_INFO : SMB_FIND_INFO_STANDARD;
mask = SMB_STRDUP(Mask);
if (!mask) {
&rparam, ¶m_len,
&rdata, &data_len) &&
cli_is_dos_error(cli)) {
- /* we need to work around a Win95 bug - sometimes
+ /* We need to work around a Win95 bug - sometimes
it gives ERRSRV/ERRerror temprarily */
uint8 eclass;
uint32 ecode;
SAFE_FREE(rparam);
cli_dos_error(cli, &eclass, &ecode);
+
+ /*
+ * OS/2 might return "no more files",
+ * which just tells us, that searchcount is zero
+ * in this search.
+ * Guenter Kukkukk <linux@kukkukk.com>
+ */
+
+ if (eclass == ERRDOS && ecode == ERRnofiles) {
+ ff_searchcount = 0;
+ cli_reset_error(cli);
+ break;
+ }
+
if (eclass != ERRSRV || ecode != ERRerror)
break;
smb_msleep(100);
/* we might need the lastname for continuations */
for (p2=p,i=0;i<ff_searchcount && p2 < rdata_end;i++) {
- if ((info_level == 260) && (i == ff_searchcount-1)) {
+ if ((info_level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) &&
+ (i == ff_searchcount-1)) {
/* Last entry - fixup the last offset length. */
SIVAL(p2,0,PTR_DIFF((rdata + data_len),p2));
}
&resume_key,
&last_name_raw);
+ if (!finfo.name) {
+ DEBUG(0,("cli_list_new: Error: unable to parse name from info level %d\n",
+ info_level));
+ ff_eos = 1;
+ break;
+ }
if (!First && *mask && strcsequal(finfo.name, mask)) {
DEBUG(0,("Error: Looping in FIND_NEXT as name %s has already been seen?\n",
finfo.name));
}
SAFE_FREE(mask);
- if (ff_searchcount > 0) {
+ if (ff_searchcount > 0 && ff_eos == 0 && finfo.name) {
mask = SMB_STRDUP(finfo.name);
} else {
mask = SMB_STRDUP("");
First = False;
}
- mnt = cli_cm_get_mntpoint( cli );
-
/* see if the server disconnected or the connection otherwise failed */
if (cli_is_error(cli)) {
total_received = -1;
&finfo,
NULL,
NULL);
- fn(mnt,&finfo, Mask, state);
+ if (!finfo.name) {
+ DEBUG(0,("cli_list_new: unable to parse name from info level %d\n",
+ info_level));
+ break;
+ }
+ fn(cli->dfs_mountpoint, &finfo, Mask, state);
}
}
The length of the structure is returned.
****************************************************************************/
-static int interpret_short_filename(TALLOC_CTX *ctx,
+static bool interpret_short_filename(TALLOC_CTX *ctx,
struct cli_state *cli,
char *p,
file_info *finfo)
{
+ size_t ret;
ZERO_STRUCTP(finfo);
finfo->cli = cli;
finfo->mtime_ts.tv_sec = finfo->atime_ts.tv_sec = finfo->ctime_ts.tv_sec;
finfo->mtime_ts.tv_nsec = finfo->atime_ts.tv_nsec = 0;
finfo->size = IVAL(p,26);
- clistr_pull_talloc(ctx,
- cli,
+ ret = clistr_pull_talloc(ctx,
+ cli->inbuf,
&finfo->name,
p+30,
12,
STR_ASCII);
- if (!finfo->name) {
- finfo->name = talloc_strdup(ctx, finfo->short_name);
- } else if (strcmp(finfo->name, "..") && strcmp(finfo->name, ".")) {
- finfo->name = talloc_strdup(ctx, finfo->short_name);
+ if (ret == (size_t)-1) {
+ return false;
}
+ if (finfo->name) {
+ strlcpy(finfo->short_name,
+ finfo->name,
+ sizeof(finfo->short_name));
+ }
+ return true;
return(DIR_STRUCT_SIZE);
}
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,2,0,True);
+ cli_set_message(cli->outbuf,2,0,True);
SCVAL(cli->outbuf,smb_com,SMBsearch);
received = SVAL(cli->inbuf,smb_vwv0);
if (received <= 0) break;
+ /* Ensure we received enough data. */
+ if ((cli->inbuf+4+smb_len(cli->inbuf) - (smb_buf(cli->inbuf)+3)) <
+ received*DIR_STRUCT_SIZE) {
+ break;
+ }
+
first = False;
dirlist = (char *)SMB_REALLOC(
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,2,0,True);
+ cli_set_message(cli->outbuf,2,0,True);
SCVAL(cli->outbuf,smb_com,SMBfclose);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
frame = talloc_stackframe();
for (p=dirlist,i=0;i<num_received;i++) {
file_info finfo;
- p += interpret_short_filename(frame,cli, p,&finfo);
+ if (!interpret_short_filename(frame, cli, p, &finfo)) {
+ break;
+ }
+ p += DIR_STRUCT_SIZE;
fn("\\", &finfo, Mask, state);
}
TALLOC_FREE(frame);