1
0
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:
Jeremy Allison 1998-08-19 01:49:34 +00:00
parent 1e6837837a
commit 12de4034c7
8 changed files with 180 additions and 404 deletions

View File

@ -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

View File

@ -329,6 +329,8 @@ extern int errno;
#include "kanji.h"
#include "charset.h"
#include "nterr.h"
#ifndef MAXCODEPAGELINES
#define MAXCODEPAGELINES 256
#endif

View File

@ -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);

View File

@ -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.

View 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);
/*

View File

@ -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);
}

View File

@ -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));

View File

@ -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