*/
#include "includes.h"
-#include "trans2.h"
extern int DEBUGLEVEL;
extern int Protocol;
extern BOOL case_sensitive;
-extern int Client;
extern int smb_read_error;
extern fstring local_machine;
extern int global_oplock_break;
+extern uint32 global_client_caps;
/****************************************************************************
Send the required number of replies back.
the empty packet */
if(params_to_send == 0 && data_to_send == 0)
{
- send_smb(Client,outbuf);
+ send_smb(smbd_server_fd(),outbuf);
return 0;
}
total_sent_thistime = params_to_send + data_to_send +
alignment_offset + data_alignment_offset;
/* We can never send more than useable_space */
- total_sent_thistime = MIN(total_sent_thistime, useable_space);
+ /*
+ * Note that 'useable_space' does not include the alignment offsets,
+ * but we must include the alignment offsets in the calculation of
+ * the length of the data we send over the wire, as the alignment offsets
+ * are sent here. Fix from Marc_Jacobsen@hp.com.
+ */
+ total_sent_thistime = MIN(total_sent_thistime, useable_space+
+ alignment_offset + data_alignment_offset);
set_message(outbuf, 10, total_sent_thistime, True);
data_sent_thistime = MIN(data_sent_thistime,data_to_send);
SSVAL(outbuf,smb_prcnt, params_sent_thistime);
+
+ /* smb_proff is the offset from the start of the SMB header to the
+ parameter bytes, however the first 4 bytes of outbuf are
+ the Netbios over TCP header. Thus use smb_base() to subtract
+ them from the calculation */
+
+ SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
+
if(params_sent_thistime == 0)
- {
- SSVAL(outbuf,smb_proff,0);
SSVAL(outbuf,smb_prdisp,0);
- }
else
- {
- /* smb_proff is the offset from the start of the SMB header to the
- parameter bytes, however the first 4 bytes of outbuf are
- the Netbios over TCP header. Thus use smb_base() to subtract
- them from the calculation */
- SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
/* Absolute displacement of param bytes sent in this packet */
SSVAL(outbuf,smb_prdisp,pp - params);
- }
SSVAL(outbuf,smb_drcnt, data_sent_thistime);
if(data_sent_thistime == 0)
params_to_send, data_to_send, paramsize, datasize));
/* Send the packet */
- send_smb(Client,outbuf);
+ send_smb(smbd_server_fd(),outbuf);
pp += params_sent_thistime;
pd += data_sent_thistime;
unix_convert(fname,conn,0,&bad_path,NULL);
- fsp = file_new();
- if (!fsp)
- return(ERROR(ERRSRV,ERRnofids));
-
if (!check_name(fname,conn))
{
if((errno == ENOENT) && bad_path)
unix_ERR_class = ERRDOS;
unix_ERR_code = ERRbadpath;
}
- file_free(fsp);
return(UNIXERROR(ERRDOS,ERRnoaccess));
}
- unixmode = unix_mode(conn,open_attr | aARCH);
+ unixmode = unix_mode(conn,open_attr | aARCH, fname);
- open_file_shared(fsp,conn,fname,open_mode,open_ofun,unixmode,
+ fsp = open_file_shared(conn,fname,open_mode,open_ofun,unixmode,
oplock_request, &rmode,&smb_action);
- if (!fsp->open)
+ if (!fsp)
{
if((errno == ENOENT) && bad_path)
{
unix_ERR_class = ERRDOS;
unix_ERR_code = ERRbadpath;
}
- file_free(fsp);
return(UNIXERROR(ERRDOS,ERRnoaccess));
}
- if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
+ if (fsp->conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) {
close_file(fsp,False);
- return(ERROR(ERRDOS,ERRnoaccess));
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
}
size = sbuf.st_size;
if(params == NULL)
return(ERROR(ERRDOS,ERRnomem));
- bzero(params,28);
+ memset((char *)params,'\0',28);
SSVAL(params,0,fsp->fnum);
SSVAL(params,2,fmode);
put_dos_date2(params,4, mtime);
/****************************************************************************
get a level dependent lanman2 dir entry.
****************************************************************************/
-static int get_lanman2_dir_entry(connection_struct *conn,
+static BOOL get_lanman2_dir_entry(connection_struct *conn,
char *path_mask,int dirtype,int info_level,
int requires_resume_key,
BOOL dont_descend,char **ppdata,
char *base_data, int space_remaining,
- BOOL *out_of_space,
+ BOOL *out_of_space, BOOL *got_exact_match,
int *last_name_off)
{
char *dname;
uint32 len;
time_t mdate=0, adate=0, cdate=0;
char *nameptr;
- BOOL isrootdir = (strequal(conn->dirpath,"./") ||
- strequal(conn->dirpath,".") ||
- strequal(conn->dirpath,"/"));
BOOL was_8_3;
int nt_extmode; /* Used for NT connections instead of mode */
BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
*fname = 0;
*out_of_space = False;
+ *got_exact_match = False;
if (!conn->dirptr)
return(False);
while (!found)
{
+ BOOL got_match;
+
/* Needed if we run out of space */
prev_dirpos = TellDir(conn->dirptr);
dname = ReadDirName(conn->dirptr);
reskey = 0;
- DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
- (unsigned)conn->dirptr,TellDir(conn->dirptr)));
+ DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
+ (long)conn->dirptr,TellDir(conn->dirptr)));
if (!dname)
return(False);
pstrcpy(fname,dname);
- if(mask_match(fname, mask, case_sensitive, True))
+ if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive)))
+ got_match = mask_match(fname, mask, case_sensitive, True);
+
+ if(!got_match && !is_8_3(fname, False)) {
+
+ /*
+ * It turns out that NT matches wildcards against
+ * both long *and* short names. This may explain some
+ * of the wildcard wierdness from old DOS clients
+ * that some people have been seeing.... JRA.
+ */
+
+ pstring newname;
+ pstrcpy( newname, fname);
+ name_map_mangle( newname, True, False, SNUM(conn));
+ if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive)))
+ got_match = mask_match(newname, mask, case_sensitive, True);
+ }
+
+ if(got_match)
{
BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
if (dont_descend && !isdots)
continue;
- if (isrootdir && isdots)
- continue;
-
pstrcpy(pathreal,conn->dirpath);
if(needslash)
pstrcat(pathreal,"/");
pstrcat(pathreal,dname);
- if (dos_stat(pathreal,&sbuf) != 0)
+ if (conn->vfs_ops.stat(dos_to_unix(pathreal,False),&sbuf) != 0)
{
DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
continue;
}
}
- name_map_mangle(fname,False,SNUM(conn));
+ name_map_mangle(fname,False,True,SNUM(conn));
p = pdata;
nameptr = p;
put_dos_date2(p,l1_fdateLastAccess,adate);
put_dos_date2(p,l1_fdateLastWrite,mdate);
SIVAL(p,l1_cbFile,(uint32)size);
- SIVAL(p,l1_cbFileAlloc,ROUNDUP(size,1024));
+ SIVAL(p,l1_cbFileAlloc,SMB_ROUNDUP(size,1024));
SSVAL(p,l1_attrFile,mode);
SCVAL(p,l1_cchName,strlen(fname));
pstrcpy(p + l1_achName, fname);
put_dos_date2(p,l2_fdateLastAccess,adate);
put_dos_date2(p,l2_fdateLastWrite,mdate);
SIVAL(p,l2_cbFile,(uint32)size);
- SIVAL(p,l2_cbFileAlloc,ROUNDUP(size,1024));
+ SIVAL(p,l2_cbFileAlloc,SMB_ROUNDUP(size,1024));
SSVAL(p,l2_attrFile,mode);
SIVAL(p,l2_cbList,0); /* No extended attributes */
SCVAL(p,l2_cchName,strlen(fname));
put_dos_date2(p,8,adate);
put_dos_date2(p,12,mdate);
SIVAL(p,16,(uint32)size);
- SIVAL(p,20,ROUNDUP(size,1024));
+ SIVAL(p,20,SMB_ROUNDUP(size,1024));
SSVAL(p,24,mode);
SIVAL(p,26,4);
CVAL(p,30) = strlen(fname);
put_dos_date2(p,8,adate);
put_dos_date2(p,12,mdate);
SIVAL(p,16,(uint32)size);
- SIVAL(p,20,ROUNDUP(size,1024));
+ SIVAL(p,20,SMB_ROUNDUP(size,1024));
SSVAL(p,24,mode);
CVAL(p,32) = strlen(fname);
pstrcpy(p + 33, fname);
SIVAL(p,0,0); p += 4;
if (!was_8_3) {
pstrcpy(p+2,fname);
- if (!name_map_mangle(p+2,True,SNUM(conn)))
+ if (!name_map_mangle(p+2,True,True,SNUM(conn)))
(p+2)[12] = 0;
} else
*(p+2) = 0;
*last_name_off = PTR_DIFF(nameptr,base_data);
/* Advance the data pointer to the next slot */
*ppdata = p;
+
return(found);
}
}
/****************************************************************************
- reply to a TRANS2_FINDFIRST
+ Reply to a TRANS2_FINDFIRST.
****************************************************************************/
+
static int call_trans2findfirst(connection_struct *conn,
char *inbuf, char *outbuf, int bufsize,
char **pparams, char **ppdata)
pstrcpy(directory, params + 12); /* Complete directory path with
wildcard mask appended */
+ RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
+
DEBUG(5,("path=%s\n",directory));
unix_convert(directory,conn,0,&bad_path,NULL);
}
#endif
- return(ERROR(ERRDOS,ERRbadpath));
+ return(UNIXERROR(ERRDOS,ERRbadpath));
}
p = strrchr(directory,'/');
pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
if(!*ppdata)
return(ERROR(ERRDOS,ERRnomem));
- bzero(pdata,max_data_bytes);
+ memset((char *)pdata,'\0',max_data_bytes + 1024);
/* Realloc the params space */
params = *pparams = Realloc(*pparams, 10);
if(params == NULL)
return(ERROR(ERRDOS,ERRnomem));
- dptr_num = dptr_create(conn,directory, True ,SVAL(inbuf,smb_pid));
+ dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
if (dptr_num < 0)
- return(ERROR(ERRDOS,ERRbadfile));
+ return(UNIXERROR(ERRDOS,ERRbadfile));
/* Convert the formatted mask. */
mask_convert(mask);
-#if 0 /* JRA */
- /*
- * Now we have a working mask_match in util.c, I believe
- * we no longer need these hacks (in fact they break
- * things). JRA.
- */
-
- /* a special case for 16 bit apps */
- if (strequal(mask,"????????.???")) pstrcpy(mask,"*");
-
- /* handle broken clients that send us old 8.3 format */
- string_sub(mask,"????????","*");
- string_sub(mask,".???",".*");
-#endif /* JRA */
-
/* Save the wildcard match and attribs we are using on this directory -
needed as lanman2 assumes these are being saved between calls */
if(!(wcard = strdup(mask))) {
- dptr_close(dptr_num);
+ dptr_close(&dptr_num);
return(ERROR(ERRDOS,ERRnomem));
}
out_of_space = False;
for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
+ {
+ BOOL got_exact_match = False;
+
+ /* this is a heuristic to avoid seeking the dirptr except when
+ absolutely necessary. It allows for a filename of about 40 chars */
+ if (space_remaining < DIRLEN_GUESS && numentries > 0)
+ {
+ out_of_space = True;
+ finished = False;
+ }
+ else
{
+ finished = !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
+ requires_resume_key,dont_descend,
+ &p,pdata,space_remaining, &out_of_space, &got_exact_match,
+ &last_name_off);
+ }
- /* this is a heuristic to avoid seeking the dirptr except when
- absolutely necessary. It allows for a filename of about 40 chars */
- if (space_remaining < DIRLEN_GUESS && numentries > 0)
- {
- out_of_space = True;
- finished = False;
- }
- else
- {
- finished =
- !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
- requires_resume_key,dont_descend,
- &p,pdata,space_remaining, &out_of_space,
- &last_name_off);
- }
+ if (finished && out_of_space)
+ finished = False;
- if (finished && out_of_space)
- finished = False;
+ if (!finished && !out_of_space)
+ numentries++;
- if (!finished && !out_of_space)
- numentries++;
- space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
- }
+ /*
+ * As an optimisation if we know we aren't looking
+ * for a wildcard name (ie. the name matches the wildcard exactly)
+ * then we can finish on any (first) match.
+ * This speeds up large directory searches. JRA.
+ */
+
+ if(got_exact_match)
+ finished = True;
+
+ space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
+ }
/* Check if we can close the dirptr */
if(close_after_first || (finished && close_if_end))
- {
- dptr_close(dptr_num);
- DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
- dptr_num = -1;
- }
+ {
+ DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
+ dptr_close(&dptr_num);
+ }
/*
* If there are no matching entries we must return ERRDOS/ERRbadfile -
*/
if(numentries == 0)
+ {
+ dptr_close(&dptr_num);
return(ERROR(ERRDOS,ERRbadfile));
+ }
/* At this point pdata points to numentries directory entries. */
smb_fn_name(CVAL(inbuf,smb_com)),
mask, directory, dirtype, numentries ) );
+ /*
+ * Force a name mangle here to ensure that the
+ * mask as an 8.3 name is top of the mangled cache.
+ * The reasons for this are subtle. Don't remove
+ * this code unless you know what you are doing
+ * (see PR#13758). JRA.
+ */
+
+ if(!is_8_3( mask, False))
+ name_map_mangle(mask, True, True, SNUM(conn));
+
return(-1);
}
int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
char *params = *pparams;
char *pdata = *ppdata;
- int16 dptr_num = SVAL(params,0);
+ int dptr_num = SVAL(params,0);
int maxentries = SVAL(params,2);
uint16 info_level = SVAL(params,4);
uint32 resume_key = IVAL(params,6);
pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
if(!*ppdata)
return(ERROR(ERRDOS,ERRnomem));
- bzero(pdata,max_data_bytes);
+ memset((char *)pdata,'\0',max_data_bytes + 1024);
/* Realloc the params space */
params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
/* Get the attr mask from the dptr */
dirtype = dptr_attr(dptr_num);
- DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n",
+ DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
dptr_num, mask, dirtype,
- (unsigned)conn->dirptr,
+ (long)conn->dirptr,
TellDir(conn->dirptr)));
/* We don't need to check for VOL here as this is returned by
*/
if(dname != NULL)
- name_map_mangle( dname, False, SNUM(conn));
+ name_map_mangle( dname, False, True, SNUM(conn));
if(dname && strcsequal( resume_name, dname))
{
*/
if(dname != NULL)
- name_map_mangle( dname, False, SNUM(conn));
+ name_map_mangle( dname, False, True, SNUM(conn));
if(dname && strcsequal( resume_name, dname))
{
} /* end if requires_resume_key && !continue_bit */
for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
+ {
+ BOOL got_exact_match = False;
+
+ /* this is a heuristic to avoid seeking the dirptr except when
+ absolutely necessary. It allows for a filename of about 40 chars */
+ if (space_remaining < DIRLEN_GUESS && numentries > 0)
{
- /* this is a heuristic to avoid seeking the dirptr except when
- absolutely necessary. It allows for a filename of about 40 chars */
- if (space_remaining < DIRLEN_GUESS && numentries > 0)
- {
- out_of_space = True;
- finished = False;
- }
- else
- {
- finished =
- !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
- requires_resume_key,dont_descend,
- &p,pdata,space_remaining, &out_of_space,
- &last_name_off);
- }
+ out_of_space = True;
+ finished = False;
+ }
+ else
+ {
+ finished = !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
+ requires_resume_key,dont_descend,
+ &p,pdata,space_remaining, &out_of_space, &got_exact_match,
+ &last_name_off);
+ }
- if (finished && out_of_space)
- finished = False;
+ if (finished && out_of_space)
+ finished = False;
- if (!finished && !out_of_space)
- numentries++;
- space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
- }
+ if (!finished && !out_of_space)
+ numentries++;
+
+ /*
+ * As an optimisation if we know we aren't looking
+ * for a wildcard name (ie. the name matches the wildcard exactly)
+ * then we can finish on any (first) match.
+ * This speeds up large directory searches. JRA.
+ */
+
+ if(got_exact_match)
+ finished = True;
+
+ space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
+ }
/* Check if we can close the dirptr */
if(close_after_request || (finished && close_if_end))
- {
- dptr_close(dptr_num); /* This frees up the saved mask */
- DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
- dptr_num = -1;
- }
+ {
+ DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
+ dptr_close(&dptr_num); /* This frees up the saved mask */
+ }
/* Set up the return parameter block */
int length, int bufsize,
char **pparams, char **ppdata)
{
+ int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
char *pdata = *ppdata;
char *params = *pparams;
uint16 info_level = SVAL(params,0);
char *vname = volume_label(SNUM(conn));
int snum = SNUM(conn);
char *fstype = lp_fstype(SNUM(conn));
- extern uint32 global_client_caps;
DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
- if(dos_stat(".",&st)!=0) {
+ if(conn->vfs_ops.stat(".",&st)!=0) {
DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
return (ERROR(ERRSRV,ERRinvdevice));
}
- pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
+ pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
+ memset((char *)pdata,'\0',max_data_bytes + 1024);
switch (info_level)
{
{
SMB_BIG_UINT dfree,dsize,bsize;
data_len = 18;
- sys_disk_free(".",&bsize,&dfree,&dsize);
+ conn->vfs_ops.disk_free(".",False,&bsize,&dfree,&dsize);
SIVAL(pdata,l1_idFileSystem,st.st_dev);
SIVAL(pdata,l1_cSectorUnit,bsize/512);
SIVAL(pdata,l1_cUnit,dsize);
break;
}
case SMB_QUERY_FS_ATTRIBUTE_INFO:
- data_len = 12 + 2*strlen(fstype);
- SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES); /* FS ATTRIBUTES */
+ {
+ int fstype_len;
+ SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
+ FILE_DEVICE_IS_MOUNTED|
+ (lp_nt_acl_support() ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */
#if 0 /* Old code. JRA. */
SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
#endif /* Old code. */
+
SIVAL(pdata,4,128); /* Max filename component length */
- SIVAL(pdata,8,2*strlen(fstype));
- PutUniCode(pdata+12,fstype);
+ fstype_len = dos_PutUniCode(pdata+12,unix_to_dos(fstype,False),sizeof(pstring), False);
+ SIVAL(pdata,8,fstype_len);
+ data_len = 12 + fstype_len;
SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
break;
+ }
case SMB_QUERY_FS_LABEL_INFO:
data_len = 4 + strlen(vname);
SIVAL(pdata,0,strlen(vname));
/* NT4 always serves this up as unicode but expects it to be
* delivered as ascii! (tridge && JRA)
*/
- if (global_client_caps & CAP_NT_SMBS) {
+ if ((get_remote_arch() != RA_WIN2K) && (global_client_caps & CAP_NT_SMBS)) {
data_len = 18 + strlen(vname);
SIVAL(pdata,12,strlen(vname));
pstrcpy(pdata+18,vname);
} else {
data_len = 18 + 2*strlen(vname);
SIVAL(pdata,12,strlen(vname)*2);
- PutUniCode(pdata+18,vname);
+ dos_PutUniCode(pdata+18,unix_to_dos(vname,False),sizeof(pstring), False);
+ SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
}
DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n",
- strlen(vname),vname));
+ (int)strlen(vname),vname));
break;
case SMB_QUERY_FS_SIZE_INFO:
{
SMB_BIG_UINT dfree,dsize,bsize;
data_len = 24;
- sys_disk_free(".",&bsize,&dfree,&dsize);
- SIVAL(pdata,0,dsize);
- SIVAL(pdata,8,dfree);
+ conn->vfs_ops.disk_free(".",False,&bsize,&dfree,&dsize);
+ SBIG_UINT(pdata,0,dsize);
+ SBIG_UINT(pdata,8,dfree);
SIVAL(pdata,16,bsize/512);
SIVAL(pdata,20,512);
break;
SIVAL(pdata,0,0); /* dev type */
SIVAL(pdata,4,0); /* characteristics */
break;
+ case SMB_MAC_QUERY_FS_INFO:
+ /*
+ * Thursby MAC extension... ONLY on NTFS filesystems
+ * once we do streams then we don't need this
+ */
+ if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
+ data_len = 88;
+ SIVAL(pdata,84,0x100); /* Don't support mac... */
+ break;
+ }
+ /* drop through */
default:
return(ERROR(ERRDOS,ERRunknownlevel));
}
char **pparams,char **ppdata,
int total_data)
{
+ int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
char *params = *pparams;
char *pdata = *ppdata;
uint16 tran_call = SVAL(inbuf, smb_setup0);
char *fname;
char *p;
int l;
- SMB_OFF_T pos;
+ SMB_OFF_T pos = 0;
BOOL bad_path = False;
+ BOOL delete_pending = False;
if (tran_call == TRANSACT2_QFILEINFO) {
files_struct *fsp = file_fsp(params,0);
info_level = SVAL(params,2);
- CHECK_FSP(fsp,conn);
- CHECK_ERROR(fsp);
+ DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
- fname = fsp->fsp_name;
- if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
- DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
- return(UNIXERROR(ERRDOS,ERRbadfid));
+ if(fsp && (fsp->is_directory || fsp->stat_open)) {
+ /*
+ * This is actually a QFILEINFO on a directory
+ * handle (returned from an NT SMB). NT5.0 seems
+ * to do this call. JRA.
+ */
+ fname = fsp->fsp_name;
+ unix_convert(fname,conn,0,&bad_path,&sbuf);
+ if (!check_name(fname,conn) ||
+ (!VALID_STAT(sbuf) && conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf))) {
+ DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
+ return(UNIXERROR(ERRDOS,ERRbadpath));
+ }
+
+ delete_pending = fsp->directory_delete_on_close;
+
+ } else {
+ /*
+ * Original code - this is an open file.
+ */
+ CHECK_FSP(fsp,conn);
+ CHECK_ERROR(fsp);
+
+ fname = fsp->fsp_name;
+ if (fsp->conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) {
+ DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
+ return(UNIXERROR(ERRDOS,ERRbadfid));
+ }
+ if((pos = fsp->conn->vfs_ops.lseek(fsp->fd,0,SEEK_CUR)) == -1)
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+
+ delete_pending = fsp->delete_on_close;
}
- pos = sys_lseek(fsp->fd_ptr->fd,0,SEEK_CUR);
} else {
/* qpathinfo */
info_level = SVAL(params,0);
+
+ DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
+
fname = &fname1[0];
pstrcpy(fname,¶ms[6]);
+
+ RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+
unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && dos_stat(fname,&sbuf))) {
+ if (!check_name(fname,conn) ||
+ (!VALID_STAT(sbuf) && conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf))) {
DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
if((errno == ENOENT) && bad_path)
{
}
return(UNIXERROR(ERRDOS,ERRbadpath));
}
- pos = 0;
}
/* from now on we only want the part after the / */
fname = p;
- params = *pparams = Realloc(*pparams,2); bzero(params,2);
- data_size = 1024;
+ params = *pparams = Realloc(*pparams,2);
+ memset((char *)params,'\0',2);
+ data_size = max_data_bytes + 1024;
pdata = *ppdata = Realloc(*ppdata, data_size);
if (total_data > 0 && IVAL(pdata,0) == total_data) {
return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
}
- bzero(pdata,data_size);
+ memset((char *)pdata,'\0',data_size);
switch (info_level)
{
put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
SIVAL(pdata,l1_cbFile,(uint32)size);
- SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
+ SIVAL(pdata,l1_cbFileAlloc,SMB_ROUNDUP(size,1024));
SSVAL(pdata,l1_attrFile,mode);
SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
break;
put_dos_date2(pdata,4,sbuf.st_atime);
put_dos_date2(pdata,8,sbuf.st_mtime);
SIVAL(pdata,12,(uint32)size);
- SIVAL(pdata,16,ROUNDUP(size,1024));
+ SIVAL(pdata,16,SMB_ROUNDUP(size,1024));
SIVAL(pdata,20,mode);
break;
/* Mangle if not already 8.3 */
if(!is_8_3(short_name, True))
{
- if(!name_map_mangle(short_name,True,SNUM(conn)))
+ if(!name_map_mangle(short_name,True,True,SNUM(conn)))
*short_name = '\0';
}
strupper(short_name);
l = strlen(short_name);
- PutUniCode(pdata + 4, short_name);
+ dos_PutUniCode(pdata + 4, unix_to_dos(short_name,False),sizeof(pstring), False);
data_size = 4 + (2*l);
SIVAL(pdata,0,2*l);
}
break;
case SMB_QUERY_FILE_NAME_INFO:
+ /*
+ * The first part of this code is essential
+ * to get security descriptors to work on mapped
+ * drives. Don't ask how I discovered this unless
+ * you like hearing about me suffering.... :-). JRA.
+ */
+ if(strequal(".", fname) && (global_client_caps & CAP_UNICODE)) {
+ l = l*2;
+ SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
+ dos_PutUniCode(pdata + 4, unix_to_dos("\\",False),sizeof(pstring), False);
+ } else {
+ pstrcpy(pdata+4,fname);
+ }
data_size = 4 + l;
SIVAL(pdata,0,l);
- pstrcpy(pdata+4,fname);
break;
case SMB_QUERY_FILE_ALLOCATION_INFO:
SOFF_T(pdata,0,size);
SOFF_T(pdata,8,size);
SIVAL(pdata,16,sbuf.st_nlink);
- CVAL(pdata,20) = 0;
+ CVAL(pdata,20) = delete_pending;
CVAL(pdata,21) = (mode&aDIR)?1:0;
pdata += 24;
+ SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);
pdata += 8; /* index number */
pdata += 4; /* EA info */
if (mode & aRONLY)
else
SIVAL(pdata,0,0xd01BF);
pdata += 4;
- SIVAL(pdata,0,pos); /* current offset */
+ SOFF_T(pdata,0,pos); /* current offset */
pdata += 8;
SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
pdata += 4;
char *fname;
int fd = -1;
BOOL bad_path = False;
+ files_struct *fsp = NULL;
if (!CAN_WRITE(conn))
return(ERROR(ERRSRV,ERRaccess));
if (tran_call == TRANSACT2_SETFILEINFO) {
- files_struct *fsp = file_fsp(params,0);
+ fsp = file_fsp(params,0);
info_level = SVAL(params,2);
- CHECK_FSP(fsp,conn);
- CHECK_ERROR(fsp);
+ if(fsp && (fsp->is_directory || fsp->stat_open)) {
+ /*
+ * This is actually a SETFILEINFO on a directory
+ * handle (returned from an NT SMB). NT5.0 seems
+ * to do this call. JRA.
+ */
+ fname = fsp->fsp_name;
+ unix_convert(fname,conn,0,&bad_path,&st);
+ if (!check_name(fname,conn) ||
+ (!VALID_STAT(st) && conn->vfs_ops.stat(dos_to_unix(fname,False),&st))) {
+ DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
+ return(UNIXERROR(ERRDOS,ERRbadpath));
+ }
+ } else {
+ /*
+ * Original code - this is an open file.
+ */
+ CHECK_FSP(fsp,conn);
+ CHECK_ERROR(fsp);
- fname = fsp->fsp_name;
- fd = fsp->fd_ptr->fd;
+ fname = fsp->fsp_name;
+ fd = fsp->fd;
- if(sys_fstat(fd,&st)!=0) {
- DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno)));
- return(ERROR(ERRDOS,ERRbadpath));
+ if (fsp->conn->vfs_ops.fstat(fd,&st) != 0) {
+ DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
+ return(UNIXERROR(ERRDOS,ERRbadfid));
+ }
}
} else {
/* set path info */
return(UNIXERROR(ERRDOS,ERRbadpath));
}
- if(!VALID_STAT(st) && dos_stat(fname,&st)!=0) {
+ if(!VALID_STAT(st) && conn->vfs_ops.stat(dos_to_unix(fname,False),&st)!=0) {
DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
if((errno == ENOENT) && bad_path)
{
tran_call,fname,info_level,total_data));
/* Realloc the parameter and data sizes */
- params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
+ params = *pparams = Realloc(*pparams,2);
if(params == NULL)
return(ERROR(ERRDOS,ERRnomem));
+ SSVAL(params,0,0);
+
size = st.st_size;
tvs.modtime = st.st_mtime;
tvs.actime = st.st_atime;
case SMB_SET_FILE_BASIC_INFO:
{
+ /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
+ time_t write_time;
+ time_t changed_time;
+
/* Ignore create time at offset pdata. */
/* access time */
tvs.actime = interpret_long_date(pdata+8);
- /* write time + changed time, combined. */
- tvs.modtime=MAX(interpret_long_date(pdata+16),
- interpret_long_date(pdata+24));
+ write_time = interpret_long_date(pdata+16);
+ changed_time = interpret_long_date(pdata+24);
+
+ tvs.modtime = MIN(write_time, changed_time);
+
+ /* Prefer a defined time to an undefined one. */
+ if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
+ tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
+ ? changed_time
+ : write_time);
#if 0 /* Needs more testing... */
/* Test from Luke to prevent Win95 from
break;
}
+ /*
+ * NT seems to use this call with a size of zero
+ * to mean truncate the file. JRA.
+ */
+
+ case SMB_SET_FILE_ALLOCATION_INFO:
+ {
+ SMB_OFF_T newsize = IVAL(pdata,0);
+#ifdef LARGE_SMB_OFF_T
+ newsize |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
+#else /* LARGE_SMB_OFF_T */
+ if (IVAL(pdata,4) != 0) /* more than 32 bits? */
+ return(ERROR(ERRDOS,ERRunknownlevel));
+#endif /* LARGE_SMB_OFF_T */
+ DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n", fname, (double)newsize ));
+ if(newsize == 0)
+ size = 0;
+ break;
+ }
+
case SMB_SET_FILE_END_OF_FILE_INFO:
{
size = IVAL(pdata,0);
if (IVAL(pdata,4) != 0) /* more than 32 bits? */
return(ERROR(ERRDOS,ERRunknownlevel));
#endif /* LARGE_SMB_OFF_T */
+ DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
break;
}
- case SMB_SET_FILE_ALLOCATION_INFO:
- break; /* We don't need to do anything for this call. */
-
case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
{
- if (tran_call == TRANSACT2_SETFILEINFO) {
- files_struct *fsp = file_fsp(params,0);
+ if ((tran_call == TRANSACT2_SETFILEINFO) && (fsp != NULL))
+ {
+ BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
+
if(fsp->is_directory)
- return(ERROR(ERRDOS,ERRnoaccess));
- /*
- * TODO - check here is this means set
- * this flag bit on all open files that
- * reference this particular dev/inode pair.
- * If so we'll need to search the open
- * file entries here and set this flag on
- * all of them that match. JRA.
- */
- fsp->delete_on_close = CVAL(pdata,0);
+ {
+ fsp->directory_delete_on_close = delete_on_close;
+ DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, directory %s\n",
+ delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
+
+ }
+ else if(fsp->stat_open)
+ {
+ DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, stat open %s\n",
+ delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
+ }
+ else
+ {
+
+ /*
+ * We can only set the delete on close flag if
+ * the share mode contained ALLOW_SHARE_DELETE
+ */
+
+ if(!GET_ALLOW_SHARE_DELETE(fsp->share_mode))
+ return(ERROR(ERRDOS,ERRnoaccess));
+
+ /*
+ * If the flag has been set then
+ * modify the share mode entry for all files we have open
+ * on this device and inode to tell other smbds we have
+ * changed the delete on close flag.
+ */
+
+ if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode))
+ {
+ int i;
+ files_struct *iterate_fsp;
+ SMB_DEV_T dev = fsp->dev;
+ SMB_INO_T inode = fsp->inode;
+ int num_share_modes;
+ share_mode_entry *current_shares = NULL;
+
+ if (lock_share_entry_fsp(fsp) == False)
+ return(ERROR(ERRDOS,ERRnoaccess));
+
+ /*
+ * Before we allow this we need to ensure that all current opens
+ * on the file have the GET_ALLOW_SHARE_DELETE flag set. If they
+ * do not then we deny this (as we are essentially deleting the
+ * file at this point.
+ */
+
+ num_share_modes = get_share_modes(conn, dev, inode, ¤t_shares);
+ for(i = 0; i < num_share_modes; i++)
+ {
+ if(!GET_ALLOW_SHARE_DELETE(current_shares[i].share_mode))
+ {
+ DEBUG(5,("call_trans2setfilepathinfo: refusing to set delete on close flag for fnum = %d, \
+file %s as a share exists that was not opened with FILE_DELETE access.\n",
+ fsp->fnum, fsp->fsp_name ));
+ /*
+ * Release the lock.
+ */
+
+ unlock_share_entry_fsp(fsp);
+
+ /*
+ * current_shares was malloced by get_share_modes - free it here.
+ */
+
+ free((char *)current_shares);
+
+ /*
+ * Even though share violation would be more appropriate here,
+ * return ERRnoaccess as that's what NT does.
+ */
+
+ return(ERROR(ERRDOS,ERRnoaccess));
+ }
+ }
+
+ /*
+ * current_shares was malloced by get_share_modes - free it here.
+ */
+
+ free((char *)current_shares);
+
+ DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n",
+ delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
+
+ /*
+ * Go through all files we have open on the same device and
+ * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG.
+ * Other smbd's that have this file open will have to fend for themselves. We
+ * take care of this (rare) case in close_file(). See the comment there.
+ */
+
+ for(iterate_fsp = file_find_di_first(dev, inode); iterate_fsp;
+ iterate_fsp = file_find_di_next(iterate_fsp))
+ {
+ int new_share_mode = (delete_on_close ?
+ (iterate_fsp->share_mode | DELETE_ON_CLOSE_FLAG) :
+ (iterate_fsp->share_mode & ~DELETE_ON_CLOSE_FLAG) );
+
+ DEBUG(10,("call_trans2setfilepathinfo: Changing share mode for fnum %d, file %s \
+dev = %x, inode = %.0f from %x to %x\n",
+ iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev,
+ (double)inode, iterate_fsp->share_mode, new_share_mode ));
+
+ if(modify_share_mode(iterate_fsp, new_share_mode, iterate_fsp->oplock_type)==False)
+ DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close for fnum %d, \
+dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode));
+ }
+
+ /*
+ * Set the delete on close flag in the reference
+ * counted struct. Delete when the last reference
+ * goes away.
+ */
+ fsp->delete_on_close = delete_on_close;
+
+ unlock_share_entry_fsp(fsp);
+
+ DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n",
+ delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
+
+ } /* end if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) */
+ } /* end if is_directory. */
} else
return(ERROR(ERRDOS,ERRunknownlevel));
break;
}
}
+ /* get some defaults (no modifications) if any info is zero or -1. */
+ if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
+ tvs.actime = st.st_atime;
+
+ if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
+ tvs.modtime = st.st_mtime;
+
DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
DEBUG(6,("size: %.0f ", (double)size));
DEBUG(6,("mode: %x\n" , mode));
- /* get some defaults (no modifications) if any info is zero. */
- if (!tvs.actime) tvs.actime = st.st_atime;
- if (!tvs.modtime) tvs.modtime = st.st_mtime;
- if (!size) size = st.st_size;
+ if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
+ (info_level == SMB_SET_FILE_ALLOCATION_INFO))) {
+ /*
+ * Only do this test if we are not explicitly
+ * changing the size of a file.
+ */
+ if (!size)
+ size = st.st_size;
+ }
/* Try and set the times, size and mode of this file -
if they are different from the current values
*/
- if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
- {
- if(file_utime(conn, fname, &tvs)!=0)
- {
- return(ERROR(ERRDOS,ERRnoaccess));
+ if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime) {
+ if(fsp != NULL) {
+ /*
+ * This was a setfileinfo on an open file.
+ * NT does this a lot. It's actually pointless
+ * setting the time here, as it will be overwritten
+ * on the next write, so we save the request
+ * away and will set it on file code. JRA.
+ */
+
+ if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
+ DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n",
+ ctime(&tvs.modtime) ));
+ fsp->pending_modtime = tvs.modtime;
+ }
+
+ } else {
+
+ DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
+
+ if(file_utime(conn, fname, &tvs)!=0)
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
}
}
/* check the mode isn't different, before changing it */
- if (mode != dos_mode(conn, fname, &st) && file_chmod(conn, fname, mode, NULL))
- {
- DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
- return(ERROR(ERRDOS,ERRnoaccess));
+ if ((mode != 0) && (mode != dos_mode(conn, fname, &st))) {
+
+ DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n",
+ fname, mode ));
+
+ if(file_chmod(conn, fname, mode, NULL)) {
+ DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
}
- if(size != st.st_size)
- {
- if (fd == -1)
- {
- fd = dos_open(fname,O_RDWR,0);
+ if(size != st.st_size) {
+
+ DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
+ fname, (double)size ));
+
+ if (fd == -1) {
+ fd = conn->vfs_ops.open(dos_to_unix(fname,False),O_RDWR,0);
if (fd == -1)
- {
- return(ERROR(ERRDOS,ERRbadpath));
- }
- set_filelen(fd, size);
- close(fd);
- }
- else
- {
- set_filelen(fd, size);
+ return(UNIXERROR(ERRDOS,ERRbadpath));
+ set_filelen(fd, size); /* tpot vfs */
+ conn->vfs_ops.close(fd);
+ } else {
+ set_filelen(fd, size); /* tpot vfs */
}
+
+ if(fsp)
+ set_filelen_write_cache(fsp, size);
}
SSVAL(params,0,0);
unix_convert(directory,conn,0,&bad_path,NULL);
if (check_name(directory,conn))
- ret = dos_mkdir(directory,unix_mode(conn,aDIR));
+ ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False),
+ unix_mode(conn,aDIR,directory));
if(ret < 0)
{
return(-1);
}
+/****************************************************************************
+ reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>
+****************************************************************************/
+static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
+ char* outbuf, int length, int bufsize,
+ char** pparams, char** ppdata)
+{
+ char *params = *pparams;
+ enum remote_arch_types ra_type = get_remote_arch();
+ BOOL NT_arch = ((ra_type == RA_WINNT) || (ra_type == RA_WIN2K));
+ pstring pathname;
+ int reply_size = 0;
+ int max_referral_level = SVAL(params,0);
+
+
+ DEBUG(10,("call_trans2getdfsreferral\n"));
+
+ if(!lp_host_msdfs())
+ return(ERROR(ERRDOS,ERRbadfunc));
+
+ /* if pathname is in UNICODE, convert to DOS */
+ /* NT always sends in UNICODE, may not set UNICODE flag */
+ if(NT_arch || (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS))
+ {
+ unistr_to_dos(pathname, ¶ms[2]);
+ DEBUG(10,("UNICODE referral for %s\n",pathname));
+ }
+ else
+ pstrcpy(pathname,¶ms[2]);
+
+ if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
+ return(ERROR(ERRDOS,ERRbadfile));
+
+ SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_UNICODE_STRINGS |
+ FLAGS2_DFS_PATHNAMES);
+ send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
+
+ return(-1);
+}
+
+
/****************************************************************************
reply to a SMBfindclose (stop trans2 directory search)
****************************************************************************/
char *inbuf,char *outbuf,int length,int bufsize)
{
int outsize = 0;
- int16 dptr_num=SVALS(inbuf,smb_vwv0);
+ int dptr_num=SVALS(inbuf,smb_vwv0);
DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
- dptr_close(dptr_num);
+ dptr_close(&dptr_num);
outsize = set_message(outbuf,0,0,True);
/* We need to send an interim response then receive the rest
of the parameter/data bytes */
outsize = set_message(outbuf,0,0,True);
- send_smb(Client,outbuf);
+ send_smb(smbd_server_fd(),outbuf);
while (num_data_sofar < total_data ||
num_params_sofar < total_params) {
outsize = call_trans2mkdir(conn, inbuf, outbuf, length,
bufsize, ¶ms, &data);
break;
+
+ case TRANSACT2_GET_DFS_REFERRAL:
+ outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length,
+ bufsize, ¶ms, &data);
+ break;
default:
/* Error in request */
DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));