mirror of
https://github.com/samba-team/samba.git
synced 2025-02-28 01:58:17 +03:00
Makefile.in: Moved blocking lock code into smbd/blocking.c for link purposes.
include/includes.h: Added nterr.h. locking/locking.c: Moved blocking lock code into smbd/blocking.c for link purposes. smbd/close.c: Added blocking lock removal to file close. smbd/filename.c: Tidied up unix_convert() so I could read it (:-) in preparation for the stat_cache code. smbd/nttrans.c: Added WRITE_ATTRIBUTES check. smbd/reply.c: Fixed multibyte char problem in wildcard mask. Jeremy. (This used to be commit 148eaba3dadb1d0bd3ac3ef53da3d9811636e89a)
This commit is contained in:
parent
1e6837837a
commit
12de4034c7
@ -126,7 +126,7 @@ SMBD_OBJ1 = smbd/server.o smbd/files.o smbd/chgpasswd.o smbd/connection.o \
|
||||
smbd/groupname.o smbd/ipc.o smbd/mangle.o smbd/negprot.o \
|
||||
smbd/message.o smbd/nttrans.o smbd/pipes.o smbd/predict.o \
|
||||
smbd/quotas.o smbd/reply.o smbd/ssl.o smbd/trans2.o smbd/uid.o \
|
||||
smbd/dosmode.o smbd/filename.o smbd/open.o smbd/close.o \
|
||||
smbd/dosmode.o smbd/filename.o smbd/open.o smbd/close.o smbd/blocking.o \
|
||||
smbd/process.o smbd/oplock.o smbd/service.o smbd/error.o
|
||||
|
||||
PRINTING_OBJ = printing/pcap.o printing/print_svid.o printing/printing.o
|
||||
|
@ -329,6 +329,8 @@ extern int errno;
|
||||
#include "kanji.h"
|
||||
#include "charset.h"
|
||||
|
||||
#include "nterr.h"
|
||||
|
||||
#ifndef MAXCODEPAGELINES
|
||||
#define MAXCODEPAGELINES 256
|
||||
#endif
|
||||
|
@ -480,8 +480,6 @@ char *smb_errstr(char *inbuf);
|
||||
|
||||
/*The following definitions come from locking/locking.c */
|
||||
|
||||
BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num);
|
||||
void process_blocking_lock_queue(time_t t);
|
||||
BOOL is_locked(files_struct *fsp,connection_struct *conn,
|
||||
uint32 count,uint32 offset, int lock_type);
|
||||
BOOL do_lock(files_struct *fsp,connection_struct *conn,
|
||||
@ -1899,6 +1897,13 @@ uint32 lookup_user_rid(char *user_name, uint32 *rid);
|
||||
|
||||
BOOL api_wkssvc_rpc(pipes_struct *p, prs_struct *data);
|
||||
|
||||
/*The following definitions come from smbd/blocking.c */
|
||||
|
||||
BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num);
|
||||
void remove_pending_lock_requests_by_fid(files_struct *fsp);
|
||||
void remove_pending_lock_requests_by_mid(int mid);
|
||||
void process_blocking_lock_queue(time_t t);
|
||||
|
||||
/*The following definitions come from smbd/chgpasswd.c */
|
||||
|
||||
BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence, BOOL as_root);
|
||||
|
@ -33,299 +33,9 @@
|
||||
|
||||
#include "includes.h"
|
||||
extern int DEBUGLEVEL;
|
||||
extern int Client;
|
||||
|
||||
static struct share_ops *share_ops;
|
||||
|
||||
#if 0 /* JRATEST - blocking lock code - under development. */
|
||||
|
||||
/****************************************************************************
|
||||
This is the structure to queue to implement blocking locks.
|
||||
notify. It consists of the requesting SMB and the expiry time.
|
||||
*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
ubi_slNode msg_next;
|
||||
time_t expire_time;
|
||||
int lock_num;
|
||||
char *inbuf;
|
||||
int length;
|
||||
} blocking_lock_record;
|
||||
|
||||
static ubi_slList blocking_lock_queue = { NULL, (ubi_slNodePtr)&blocking_lock_queue, 0};
|
||||
|
||||
/****************************************************************************
|
||||
Function to push a blocking lockingX request onto the lock queue.
|
||||
****************************************************************************/
|
||||
|
||||
BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num)
|
||||
{
|
||||
blocking_lock_record *blr;
|
||||
files_struct *fsp = file_fsp(inbuf,smb_vwv2);
|
||||
|
||||
/*
|
||||
* Now queue an entry on the blocking lock queue. We setup
|
||||
* the expiration time here.
|
||||
*/
|
||||
|
||||
if((blr = (blocking_lock_record *)malloc(sizeof(blocking_lock_record))) == NULL) {
|
||||
DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" ));
|
||||
return False;
|
||||
}
|
||||
|
||||
if((blr->inbuf = (char *)malloc(length)) == NULL) {
|
||||
DEBUG(0,("push_blocking_lock_request: Malloc fail (2)!\n" ));
|
||||
free((char *)blr);
|
||||
return False;
|
||||
}
|
||||
|
||||
memcpy(blr->inbuf, inbuf, length);
|
||||
blr->length = length;
|
||||
blr->lock_num = lock_num;
|
||||
blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout;
|
||||
|
||||
ubi_slAddTail(&blocking_lock_queue, blr);
|
||||
|
||||
DEBUG(3,("push_blocking_lock_request: lock request blocked with expiry time %d \
|
||||
for fnum = %d, name = %s\n", blr->expire_time, fsp->fnum, fsp->name ));
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Return a blocking lock success SMB.
|
||||
*****************************************************************************/
|
||||
static void blocking_lock_reply_success(blocking_lock_record *blr)
|
||||
{
|
||||
extern int chain_size;
|
||||
extern char *OutBuffer;
|
||||
char *outbuf = OutBuffer;
|
||||
int bufsize = BUFFER_SIZE;
|
||||
char *inbuf = blr->inbuf;
|
||||
files_struct *fsp = file_fsp(inbuf,smb_vwv2);
|
||||
int outsize = 0;
|
||||
|
||||
construct_reply_common(inbuf, outbuf);
|
||||
set_message(outbuf,2,0,True);
|
||||
|
||||
/*
|
||||
* As this message is a lockingX call we must handle
|
||||
* any following chained message correctly.
|
||||
* This is normally handled in construct_reply(),
|
||||
* but as that calls switch_message, we can't use
|
||||
* that here and must set up the chain info manually.
|
||||
*/
|
||||
|
||||
chain_size = 0;
|
||||
|
||||
outsize = chain_reply(inbuf,outbuf,blr->length,bufsize);
|
||||
|
||||
outsize += chain_size;
|
||||
|
||||
if(outsize > 4)
|
||||
smb_setlen(outbuf,outsize - 4);
|
||||
|
||||
send_smb(Client,outbuf);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Return a lock fail error. Undo all the locks we have obtained first.
|
||||
*****************************************************************************/
|
||||
|
||||
static void blocking_lock_reply_error(blocking_lock_record *blr, int eclass, int32 ecode)
|
||||
{
|
||||
extern char *OutBuffer;
|
||||
char *outbuf = OutBuffer;
|
||||
int bufsize = BUFFER_SIZE;
|
||||
char *inbuf = blr->inbuf;
|
||||
files_struct *fsp = file_fsp(inbuf,smb_vwv2);
|
||||
uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
|
||||
uint16 num_locks = SVAL(inbuf,smb_vwv7);
|
||||
uint32 count, offset;
|
||||
int lock_num = blr->lock_num;
|
||||
char *data;
|
||||
int i;
|
||||
|
||||
data = smb_buf(inbuf) + 10*num_ulocks;
|
||||
|
||||
/*
|
||||
* Data now points at the beginning of the list
|
||||
* of smb_lkrng structs.
|
||||
*/
|
||||
|
||||
for(i = blr->lock_num; i >= 0; i--) {
|
||||
count = IVAL(data,SMB_LKLEN_OFFSET(i));
|
||||
offset = IVAL(data,SMB_LKOFF_OFFSET(i));
|
||||
do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
|
||||
}
|
||||
|
||||
construct_reply_common(inbuf, outbuf);
|
||||
ERROR(eclass,ecode);
|
||||
send_smb(Client,outbuf);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Attempt to finish off getting all pending blocking locks.
|
||||
Returns True if we want to be removed from the list.
|
||||
*****************************************************************************/
|
||||
|
||||
static BOOL blocking_lock_record_process(blocking_lock_record *blr)
|
||||
{
|
||||
char *inbuf = blr->inbuf;
|
||||
unsigned char locktype = CVAL(inbuf,smb_vwv3);
|
||||
files_struct *fsp = file_fsp(inbuf,smb_vwv2);
|
||||
uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
|
||||
uint16 num_locks = SVAL(inbuf,smb_vwv7);
|
||||
uint32 count, offset;
|
||||
int lock_num = blr->lock_num;
|
||||
char *data;
|
||||
int eclass=0;
|
||||
uint32 ecode=0;
|
||||
|
||||
data = smb_buf(inbuf) + 10*num_ulocks;
|
||||
|
||||
/*
|
||||
* Data now points at the beginning of the list
|
||||
* of smb_lkrng structs.
|
||||
*/
|
||||
|
||||
for(; blr->lock_num < num_locks; blr->lock_num++) {
|
||||
count = IVAL(data,SMB_LKLEN_OFFSET(blr->lock_num));
|
||||
offset = IVAL(data,SMB_LKOFF_OFFSET(blr->lock_num));
|
||||
if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK),
|
||||
&eclass, &ecode))
|
||||
break;
|
||||
}
|
||||
|
||||
if(blr->lock_num == num_locks) {
|
||||
|
||||
/*
|
||||
* Success - we got all the locks.
|
||||
*/
|
||||
|
||||
DEBUG(3,("blocking_lock_record_process fnum=%d type=%d num_locks=%d\n",
|
||||
fsp->fnum, (unsigned int)locktype, num_locks) );
|
||||
|
||||
blocking_lock_reply_success(blr);
|
||||
return True;
|
||||
|
||||
} else if((errno != EACCES) && (errno != EAGAIN)) {
|
||||
|
||||
/*
|
||||
* We have other than a "can't get lock" POSIX
|
||||
* error. Free any locks we had and return an error.
|
||||
* Return True so we get dequeued.
|
||||
*/
|
||||
|
||||
blocking_lock_reply_error(blr, eclass, ecode);
|
||||
return True;
|
||||
}
|
||||
|
||||
/*
|
||||
* Still can't get all the locks - keep waiting.
|
||||
*/
|
||||
|
||||
DEBUG(10,("blocking_lock_record_process: only got %d locks of %d needed for fnum = %d. \
|
||||
Waiting....\n", blr->lock_num, num_locks, fsp->fnum));
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Process the blocking lock queue. Note that this is only called as root.
|
||||
*****************************************************************************/
|
||||
|
||||
void process_blocking_lock_queue(time_t t)
|
||||
{
|
||||
blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue );
|
||||
blocking_lock_record *prev = NULL;
|
||||
|
||||
if(blr == NULL)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Go through the queue and see if we can get any of the locks.
|
||||
*/
|
||||
|
||||
while(blr != NULL) {
|
||||
files_struct *fsp = NULL;
|
||||
uint16 vuid;
|
||||
|
||||
/*
|
||||
* Ensure we don't have any old chain_fnum values
|
||||
* sitting around....
|
||||
*/
|
||||
file_chain_reset();
|
||||
|
||||
fsp = file_fsp(blr->inbuf,smb_vwv2);
|
||||
vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID :
|
||||
SVAL(blr->inbuf,smb_uid);
|
||||
|
||||
DEBUG(5,("process_blocking_lock_queue: examining pending lock fnum = %d for file %s\n",
|
||||
fsp->fnum, fsp->name ));
|
||||
|
||||
if((blr->expire_time != -1) && (blr->expire_time > t)) {
|
||||
/*
|
||||
* Lock expired - throw away all previously
|
||||
* obtained locks and return lock error.
|
||||
*/
|
||||
DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n",
|
||||
fsp->fnum, fsp->name ));
|
||||
|
||||
blocking_lock_reply_error(blr,ERRSRV,ERRaccess);
|
||||
free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
|
||||
blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue));
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!become_user(conn,vuid)) {
|
||||
DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n",
|
||||
vuid ));
|
||||
/*
|
||||
* Remove the entry and return an error to the client.
|
||||
*/
|
||||
blocking_lock_reply_error(blr,ERRSRV,ERRaccess);
|
||||
free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
|
||||
blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue));
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!become_service(conn,True)) {
|
||||
DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) ));
|
||||
/*
|
||||
* Remove the entry and return an error to the client.
|
||||
*/
|
||||
blocking_lock_reply_error(blr,ERRSRV,ERRaccess);
|
||||
free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
|
||||
blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue));
|
||||
unbecome_user();
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Go through the remaining locks and try and obtain them.
|
||||
* The call returns True if all locks were obtained successfully
|
||||
* and False if we still need to wait.
|
||||
*/
|
||||
|
||||
if(blocking_lock_record_process(blr)) {
|
||||
free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
|
||||
blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue));
|
||||
unbecome_user();
|
||||
continue;
|
||||
}
|
||||
|
||||
unbecome_user();
|
||||
|
||||
/*
|
||||
* Move to the next in the list.
|
||||
*/
|
||||
prev = blr;
|
||||
blr = (blocking_lock_record *)ubi_slNext(blr);
|
||||
}
|
||||
}
|
||||
#endif /* JRATEST */
|
||||
|
||||
/****************************************************************************
|
||||
Utility function to map a lock type correctly depending on the real open
|
||||
mode of a file.
|
||||
|
@ -142,6 +142,8 @@ void close_file(files_struct *fsp, BOOL normal_close)
|
||||
string_free(&fsp->fsp_name);
|
||||
}
|
||||
|
||||
remove_pending_lock_requests_by_fid(fsp);
|
||||
|
||||
file_free(fsp);
|
||||
}
|
||||
|
||||
@ -151,10 +153,6 @@ void close_file(files_struct *fsp, BOOL normal_close)
|
||||
|
||||
void close_directory(files_struct *fsp)
|
||||
{
|
||||
/* TODO - walk the list of pending
|
||||
change notify requests and free
|
||||
any pertaining to this fsp. */
|
||||
|
||||
remove_pending_change_notify_requests_by_fid(fsp);
|
||||
|
||||
/*
|
||||
|
@ -102,6 +102,7 @@ used to pick the correct error code to return between ENOENT and ENOTDIR
|
||||
as Windows applications depend on ERRbadpath being returned if a component
|
||||
of a pathname does not exist.
|
||||
****************************************************************************/
|
||||
|
||||
BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, BOOL *bad_path)
|
||||
{
|
||||
struct stat st;
|
||||
@ -115,17 +116,24 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component,
|
||||
if(saved_last_component)
|
||||
*saved_last_component = 0;
|
||||
|
||||
/* convert to basic unix format - removing \ chars and cleaning it up */
|
||||
/*
|
||||
* Convert to basic unix format - removing \ chars and cleaning it up.
|
||||
*/
|
||||
|
||||
unix_format(name);
|
||||
unix_clean_name(name);
|
||||
|
||||
/* names must be relative to the root of the service - trim any leading /.
|
||||
also trim trailing /'s */
|
||||
/*
|
||||
* Names must be relative to the root of the service - trim any leading /.
|
||||
* also trim trailing /'s.
|
||||
*/
|
||||
|
||||
trim_string(name,"/","/");
|
||||
|
||||
/*
|
||||
* Ensure saved_last_component is valid even if file exists.
|
||||
*/
|
||||
|
||||
if(saved_last_component) {
|
||||
end = strrchr(name, '/');
|
||||
if(end)
|
||||
@ -138,23 +146,30 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component,
|
||||
(!case_preserve || (is_8_3(name, False) && !short_case_preserve)))
|
||||
strnorm(name);
|
||||
|
||||
/* check if it's a printer file */
|
||||
if (conn->printer)
|
||||
{
|
||||
if ((! *name) || strchr(name,'/') || !is_8_3(name, True))
|
||||
{
|
||||
char *s;
|
||||
fstring name2;
|
||||
slprintf(name2,sizeof(name2)-1,"%.6s.XXXXXX",remote_machine);
|
||||
/* sanitise the name */
|
||||
for (s=name2 ; *s ; s++)
|
||||
if (!issafe(*s)) *s = '_';
|
||||
pstrcpy(name,(char *)mktemp(name2));
|
||||
}
|
||||
return(True);
|
||||
}
|
||||
/*
|
||||
* Check if it's a printer file.
|
||||
*/
|
||||
if (conn->printer) {
|
||||
if ((! *name) || strchr(name,'/') || !is_8_3(name, True)) {
|
||||
char *s;
|
||||
fstring name2;
|
||||
slprintf(name2,sizeof(name2)-1,"%.6s.XXXXXX",remote_machine);
|
||||
|
||||
/*
|
||||
* Sanitise the name.
|
||||
*/
|
||||
|
||||
for (s=name2 ; *s ; s++)
|
||||
if (!issafe(*s)) *s = '_';
|
||||
pstrcpy(name,(char *)mktemp(name2));
|
||||
}
|
||||
return(True);
|
||||
}
|
||||
|
||||
/*
|
||||
* stat the name - if it exists then we are all done!
|
||||
*/
|
||||
|
||||
/* stat the name - if it exists then we are all done! */
|
||||
if (sys_stat(name,&st) == 0)
|
||||
return(True);
|
||||
|
||||
@ -162,109 +177,144 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component,
|
||||
|
||||
DEBUG(5,("unix_convert(%s)\n",name));
|
||||
|
||||
/* a special case - if we don't have any mangling chars and are case
|
||||
sensitive then searching won't help */
|
||||
/*
|
||||
* A special case - if we don't have any mangling chars and are case
|
||||
* sensitive then searching won't help.
|
||||
*/
|
||||
|
||||
if (case_sensitive && !is_mangled(name) &&
|
||||
!lp_strip_dot() && !use_mangled_map && (saved_errno != ENOENT))
|
||||
return(False);
|
||||
|
||||
/* now we need to recursively match the name against the real
|
||||
directory structure */
|
||||
/*
|
||||
* Now we need to recursively match the name against the real
|
||||
* directory structure.
|
||||
*/
|
||||
|
||||
start = name;
|
||||
while (strncmp(start,"./",2) == 0)
|
||||
start += 2;
|
||||
|
||||
/* now match each part of the path name separately, trying the names
|
||||
as is first, then trying to scan the directory for matching names */
|
||||
for (;start;start = (end?end+1:(char *)NULL))
|
||||
{
|
||||
/* pinpoint the end of this section of the filename */
|
||||
/*
|
||||
* Match each part of the path name separately, trying the names
|
||||
* as is first, then trying to scan the directory for matching names.
|
||||
*/
|
||||
|
||||
for (;start;start = (end?end+1:(char *)NULL)) {
|
||||
/*
|
||||
* Pinpoint the end of this section of the filename.
|
||||
*/
|
||||
end = strchr(start, '/');
|
||||
|
||||
/* chop the name at this point */
|
||||
if (end) *end = 0;
|
||||
/*
|
||||
* Chop the name at this point.
|
||||
*/
|
||||
if (end)
|
||||
*end = 0;
|
||||
|
||||
if(saved_last_component != 0)
|
||||
pstrcpy(saved_last_component, end ? end + 1 : start);
|
||||
|
||||
/* check if the name exists up to this point */
|
||||
if (sys_stat(name, &st) == 0)
|
||||
{
|
||||
/* it exists. it must either be a directory or this must be
|
||||
the last part of the path for it to be OK */
|
||||
if (end && !(st.st_mode & S_IFDIR))
|
||||
{
|
||||
/* an intermediate part of the name isn't a directory */
|
||||
DEBUG(5,("Not a dir %s\n",start));
|
||||
*end = '/';
|
||||
return(False);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pstring rest;
|
||||
/*
|
||||
* Check if the name exists up to this point.
|
||||
*/
|
||||
if (sys_stat(name, &st) == 0) {
|
||||
/*
|
||||
* It exists. it must either be a directory or this must be
|
||||
* the last part of the path for it to be OK.
|
||||
*/
|
||||
if (end && !(st.st_mode & S_IFDIR)) {
|
||||
/*
|
||||
* An intermediate part of the name isn't a directory.
|
||||
*/
|
||||
DEBUG(5,("Not a dir %s\n",start));
|
||||
*end = '/';
|
||||
return(False);
|
||||
}
|
||||
} else {
|
||||
pstring rest;
|
||||
|
||||
*rest = 0;
|
||||
*rest = 0;
|
||||
|
||||
/* remember the rest of the pathname so it can be restored
|
||||
later */
|
||||
if (end) pstrcpy(rest,end+1);
|
||||
/*
|
||||
* Remember the rest of the pathname so it can be restored
|
||||
* later.
|
||||
*/
|
||||
|
||||
/* try to find this part of the path in the directory */
|
||||
if (strchr(start,'?') || strchr(start,'*') ||
|
||||
!scan_directory(dirpath, start, conn, end?True:False))
|
||||
{
|
||||
if (end)
|
||||
{
|
||||
/* an intermediate part of the name can't be found */
|
||||
DEBUG(5,("Intermediate not found %s\n",start));
|
||||
*end = '/';
|
||||
/* We need to return the fact that the intermediate
|
||||
name resolution failed. This is used to return an
|
||||
error of ERRbadpath rather than ERRbadfile. Some
|
||||
Windows applications depend on the difference between
|
||||
these two errors.
|
||||
*/
|
||||
*bad_path = True;
|
||||
return(False);
|
||||
}
|
||||
if (end)
|
||||
pstrcpy(rest,end+1);
|
||||
|
||||
/*
|
||||
* Try to find this part of the path in the directory.
|
||||
*/
|
||||
if (strchr(start,'?') || strchr(start,'*') ||
|
||||
!scan_directory(dirpath, start, conn, end?True:False)) {
|
||||
if (end) {
|
||||
/*
|
||||
* An intermediate part of the name can't be found.
|
||||
*/
|
||||
DEBUG(5,("Intermediate not found %s\n",start));
|
||||
*end = '/';
|
||||
|
||||
/*
|
||||
* We need to return the fact that the intermediate
|
||||
* name resolution failed. This is used to return an
|
||||
* error of ERRbadpath rather than ERRbadfile. Some
|
||||
* Windows applications depend on the difference between
|
||||
* these two errors.
|
||||
*/
|
||||
*bad_path = True;
|
||||
return(False);
|
||||
}
|
||||
|
||||
/* just the last part of the name doesn't exist */
|
||||
/* we may need to strupper() or strlower() it in case
|
||||
this conversion is being used for file creation
|
||||
purposes */
|
||||
/* if the filename is of mixed case then don't normalise it */
|
||||
if (!case_preserve &&
|
||||
(!strhasupper(start) || !strhaslower(start)))
|
||||
strnorm(start);
|
||||
/*
|
||||
* Just the last part of the name doesn't exist.
|
||||
* We may need to strupper() or strlower() it in case
|
||||
* this conversion is being used for file creation
|
||||
* purposes. If the filename is of mixed case then
|
||||
* don't normalise it.
|
||||
*/
|
||||
|
||||
/* check on the mangled stack to see if we can recover the
|
||||
base of the filename */
|
||||
if (is_mangled(start))
|
||||
check_mangled_cache( start );
|
||||
if (!case_preserve && (!strhasupper(start) || !strhaslower(start)))
|
||||
strnorm(start);
|
||||
|
||||
DEBUG(5,("New file %s\n",start));
|
||||
return(True);
|
||||
}
|
||||
/*
|
||||
* check on the mangled stack to see if we can recover the
|
||||
* base of the filename.
|
||||
*/
|
||||
|
||||
/* restore the rest of the string */
|
||||
if (end)
|
||||
{
|
||||
pstrcpy(start+strlen(start)+1,rest);
|
||||
end = start + strlen(start);
|
||||
}
|
||||
}
|
||||
if (is_mangled(start))
|
||||
check_mangled_cache( start );
|
||||
|
||||
/* add to the dirpath that we have resolved so far */
|
||||
if (*dirpath) pstrcat(dirpath,"/");
|
||||
DEBUG(5,("New file %s\n",start));
|
||||
return(True);
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore the rest of the string.
|
||||
*/
|
||||
if (end) {
|
||||
pstrcpy(start+strlen(start)+1,rest);
|
||||
end = start + strlen(start);
|
||||
}
|
||||
} /* end else */
|
||||
|
||||
/*
|
||||
* Add to the dirpath that we have resolved so far.
|
||||
*/
|
||||
if (*dirpath) pstrcat(dirpath,"/");
|
||||
pstrcat(dirpath,start);
|
||||
|
||||
/* restore the / that we wiped out earlier */
|
||||
if (end) *end = '/';
|
||||
}
|
||||
/*
|
||||
* Restore the / that we wiped out earlier.
|
||||
*/
|
||||
if (end)
|
||||
*end = '/';
|
||||
}
|
||||
|
||||
/* the name has been resolved */
|
||||
/*
|
||||
* The name has been resolved.
|
||||
*/
|
||||
DEBUG(5,("conversion finished %s\n",name));
|
||||
return(True);
|
||||
}
|
||||
|
@ -321,7 +321,7 @@ static int map_share_mode( uint32 desired_access, uint32 share_access, uint32 fi
|
||||
}
|
||||
|
||||
if (smb_open_mode == -1) {
|
||||
if(desired_access & DELETE_ACCESS)
|
||||
if(desired_access & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES))
|
||||
smb_open_mode = 2;
|
||||
else if( desired_access & FILE_EXECUTE)
|
||||
smb_open_mode = 0;
|
||||
@ -909,12 +909,11 @@ int reply_ntcancel(connection_struct *conn,
|
||||
{
|
||||
/*
|
||||
* Go through and cancel any pending change notifies.
|
||||
* TODO: When we add blocking locks we will add cancel
|
||||
* for them here too.
|
||||
*/
|
||||
|
||||
int mid = SVAL(inbuf,smb_mid);
|
||||
remove_pending_change_notify_requests_by_mid(mid);
|
||||
remove_pending_lock_requests_by_mid(mid);
|
||||
|
||||
DEBUG(3,("reply_ntcancel: cancel called on mid = %d.\n", mid));
|
||||
|
||||
|
@ -1051,14 +1051,24 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
|
||||
mask_convert(mask);
|
||||
|
||||
{
|
||||
for (p=mask; *p; p++)
|
||||
int skip;
|
||||
p = mask;
|
||||
while(*p)
|
||||
{
|
||||
if((skip = skip_multibyte_char( *p )) != 0 )
|
||||
{
|
||||
if (*p != '?' && *p != '*' && !isdoschar(*p))
|
||||
{
|
||||
DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
|
||||
*p = '?';
|
||||
}
|
||||
p += skip;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*p != '?' && *p != '*' && !isdoschar(*p))
|
||||
{
|
||||
DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
|
||||
*p = '?';
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!strchr(mask,'.') && strlen(mask)>8)
|
||||
@ -3569,8 +3579,8 @@ dev = %x, inode = %x\n",
|
||||
count = IVAL(data,SMB_LKLEN_OFFSET(i));
|
||||
offset = IVAL(data,SMB_LKOFF_OFFSET(i));
|
||||
if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK),
|
||||
&eclass, &ecode))
|
||||
#if 0 /* JRATEST - blocking lock code. */
|
||||
&eclass, &ecode)) {
|
||||
#if 0 /* JRATEST */
|
||||
if((ecode == ERRlock) && (lock_timeout != 0)) {
|
||||
/*
|
||||
* A blocking lock was requested. Package up
|
||||
@ -3579,8 +3589,10 @@ dev = %x, inode = %x\n",
|
||||
*/
|
||||
if(push_blocking_lock_request(inbuf, length, lock_timeout, i))
|
||||
return -1;
|
||||
}
|
||||
#endif /* JRATEST */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If any of the above locks failed, then we must unlock
|
||||
|
Loading…
x
Reference in New Issue
Block a user