mirror of
https://github.com/samba-team/samba.git
synced 2025-01-13 13:18:06 +03:00
0f1f0ceb95
Wed May 7 1997: Update for 1.9.17alpha1 release - 'browsefix release'
designed to make browsing across subnets work.
byteorder.h: Updated copyright to 1997.
charcnv.c: Updated copyright to 1997.
charset.c Updated copyright to 1997.
charset.h Updated copyright to 1997.
client.c Updated copyright to 1997.
clientutil.c Updated copyright to 1997.
dir.c Updated copyright to 1997.
fault.c Updated copyright to 1997.
includes.h Updated copyright to 1997.
interface.c Updated copyright to 1997.
ipc.c Updated copyright to 1997.
kanji.c Updated copyright to 1997.
kanji.h Updated copyright to 1997.
loadparm.c Updated copyright to 1997.
locking.c Updated copyright to 1997.
mangle.c Updated copyright to 1997.
message.c Updated copyright to 1997.
nameannounce.c
Made use of WINS subnet explicit.
Added reset_announce_timer() so announcement
can be made immediately when we become a master.
Expanded code to do sync with dmb.
namebrowse.c
Removed redundent checks for AM_MASTER in
sync code. Made use of WINS subnet explicit.
namedbname.c Made use of WINS subnet explicit.
namedbresp.c Made use of WINS subnet explicit.
namedbserver.c Made use of WINS subnet explicit.
namedbsubnet.c
Explicitly add workgroup to WINS subnet
when we become a dmb. Made use of WINS subnet explicit.
namedbwork.c
Made use of WINS subnet explicit. Removed
redundent check_work_servertype() function.
nameelect.c
Explicitly add workgroup to WINS subnet
when we become a master browser. Made use of WINS subnet explicit.
namelogon.c Updated copyright to 1997.
namepacket.c Updated copyright to 1997.
namequery.c Updated copyright to 1997.
nameresp.c
Made use of WINS subnet explicit. Made nmbd fail if
configured as master browser and one exists already.
nameserv.c
Made use of WINS subnet explicit. Remove redundent
logon server and domain master code.
nameserv.h Add emumerate subnet macros.
nameservreply.c Made use of WINS subnet explicit.
nameservresp.c Updated copyright to 1997.
namework.c
Made use of WINS subnet explicit. Updated code to
add sync browser entries to add subnet parameter.
nmbd.c
Added sanity check for misconfigured nmbd.
nmblib.c Updated copyright to 1997.
nmblookup.c Updated copyright to 1997.
nmbsync.c
Removed redundent AM_ANY_MASTER check.
params.c Updated copyright to 1997.
password.c Updated copyright to 1997.
pipes.c Updated copyright to 1997.
predict.c Updated copyright to 1997.
printing.c Updated copyright to 1997.
proto.h
Changed protos for new nmbd code.
quotas.c Updated copyright to 1997.
replace.c Updated copyright to 1997.
reply.c Updated copyright to 1997.
server.c Updated copyright to 1997.
shmem.c Updated copyright to 1997.
smb.h Updated copyright to 1997.
smbencrypt.c Updated copyright to 1997.
smbpasswd.c Updated copyright to 1997.
smbrun.c Updated copyright to 1997.
status.c Updated copyright to 1997.
system.c Updated copyright to 1997.
testparm.c Updated copyright to 1997.
testprns.c Updated copyright to 1997.
time.c Updated copyright to 1997.
trans2.c Updated copyright to 1997.
trans2.h Updated copyright to 1997.
uid.c Updated copyright to 1997.
username.c Updated copyright to 1997.
util.c Updated copyright to 1997.
version.h
Changed to 1.9.17alpha1.
(This used to be commit cf23a155a1
)
585 lines
14 KiB
C
585 lines
14 KiB
C
/*
|
|
Unix SMB/Netbios implementation.
|
|
Version 1.9.
|
|
Locking functions
|
|
Copyright (C) Andrew Tridgell 1992-1997
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
Revision History:
|
|
|
|
12 aug 96: Erik.Devriendt@te6.siemens.be
|
|
added support for shared memory implementation of share mode locking
|
|
*/
|
|
|
|
#include "includes.h"
|
|
extern int DEBUGLEVEL;
|
|
extern connection_struct Connections[];
|
|
extern files_struct Files[];
|
|
|
|
pstring share_del_pending="";
|
|
|
|
|
|
/****************************************************************************
|
|
utility function called to see if a file region is locked
|
|
****************************************************************************/
|
|
BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset)
|
|
{
|
|
int snum = SNUM(cnum);
|
|
|
|
if (count == 0)
|
|
return(False);
|
|
|
|
if (!lp_locking(snum) || !lp_strict_locking(snum))
|
|
return(False);
|
|
|
|
return(fcntl_lock(Files[fnum].fd_ptr->fd,F_GETLK,offset,count,
|
|
(Files[fnum].can_write?F_WRLCK:F_RDLCK)));
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
utility function called by locking requests
|
|
****************************************************************************/
|
|
BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode)
|
|
{
|
|
BOOL ok = False;
|
|
|
|
if (!lp_locking(SNUM(cnum)))
|
|
return(True);
|
|
|
|
if (count == 0) {
|
|
*eclass = ERRDOS;
|
|
*ecode = ERRnoaccess;
|
|
return False;
|
|
}
|
|
|
|
if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
|
|
ok = fcntl_lock(Files[fnum].fd_ptr->fd,F_SETLK,offset,count,
|
|
(Files[fnum].can_write?F_WRLCK:F_RDLCK));
|
|
|
|
if (!ok) {
|
|
*eclass = ERRDOS;
|
|
*ecode = ERRlock;
|
|
return False;
|
|
}
|
|
return True; /* Got lock */
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
utility function called by unlocking requests
|
|
****************************************************************************/
|
|
BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode)
|
|
{
|
|
BOOL ok = False;
|
|
|
|
if (!lp_locking(SNUM(cnum)))
|
|
return(True);
|
|
|
|
if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
|
|
ok = fcntl_lock(Files[fnum].fd_ptr->fd,F_SETLK,offset,count,F_UNLCK);
|
|
|
|
if (!ok) {
|
|
*eclass = ERRDOS;
|
|
*ecode = ERRlock;
|
|
return False;
|
|
}
|
|
return True; /* Did unlock */
|
|
}
|
|
|
|
#if FAST_SHARE_MODES
|
|
/*******************************************************************
|
|
initialize the shared memory for share_mode management
|
|
******************************************************************/
|
|
BOOL start_share_mode_mgmt(void)
|
|
{
|
|
pstring shmem_file_name;
|
|
|
|
strcpy(shmem_file_name,lp_lockdir());
|
|
if (!directory_exist(shmem_file_name,NULL))
|
|
mkdir(shmem_file_name,0755);
|
|
trim_string(shmem_file_name,"","/");
|
|
if (!*shmem_file_name) return(False);
|
|
strcat(shmem_file_name, "/SHARE_MEM_FILE");
|
|
return smb_shm_open(shmem_file_name, SHMEM_SIZE);
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
deinitialize the shared memory for share_mode management
|
|
******************************************************************/
|
|
BOOL stop_share_mode_mgmt(void)
|
|
{
|
|
return smb_shm_close();
|
|
}
|
|
|
|
#else
|
|
|
|
/* SHARE MODE LOCKS USING SLOW DESCRIPTION FILES */
|
|
|
|
/*******************************************************************
|
|
name a share file
|
|
******************************************************************/
|
|
static BOOL share_name(int cnum,struct stat *st,char *name)
|
|
{
|
|
strcpy(name,lp_lockdir());
|
|
standard_sub(cnum,name);
|
|
trim_string(name,"","/");
|
|
if (!*name) return(False);
|
|
name += strlen(name);
|
|
|
|
sprintf(name,"/share.%d.%d",(int)st->st_dev,(int)st->st_ino);
|
|
return(True);
|
|
}
|
|
|
|
/*******************************************************************
|
|
use the fnum to get the share file name
|
|
******************************************************************/
|
|
static BOOL share_name_fnum(int fnum,char *name)
|
|
{
|
|
struct stat st;
|
|
if (fstat(Files[fnum].fd_ptr->fd,&st) != 0) return(False);
|
|
return(share_name(Files[fnum].cnum,&st,name));
|
|
}
|
|
|
|
#endif
|
|
|
|
/*******************************************************************
|
|
get the share mode of a file using the fnum
|
|
******************************************************************/
|
|
int get_share_mode_by_fnum(int cnum,int fnum,int *pid)
|
|
{
|
|
struct stat sbuf;
|
|
if (fstat(Files[fnum].fd_ptr->fd,&sbuf) == -1) return(0);
|
|
return(get_share_mode(cnum,&sbuf,pid));
|
|
}
|
|
|
|
/*******************************************************************
|
|
get the share mode of a file using the files name
|
|
******************************************************************/
|
|
int get_share_mode_byname(int cnum,char *fname,int *pid)
|
|
{
|
|
struct stat sbuf;
|
|
if (stat(fname,&sbuf) == -1) return(0);
|
|
return(get_share_mode(cnum,&sbuf,pid));
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
get the share mode of a file
|
|
********************************************************************/
|
|
int get_share_mode(int cnum,struct stat *sbuf,int *pid)
|
|
{
|
|
#if FAST_SHARE_MODES
|
|
share_mode_record *scanner_p;
|
|
share_mode_record *prev_p;
|
|
int ret;
|
|
BOOL found = False;
|
|
|
|
*pid = 0;
|
|
|
|
if(!smb_shm_lock()) return (0);
|
|
|
|
scanner_p = (share_mode_record *)smb_shm_offset2addr(smb_shm_get_userdef_off());
|
|
prev_p = scanner_p;
|
|
while(scanner_p)
|
|
{
|
|
if( (scanner_p->st_dev == sbuf->st_dev) && (scanner_p->st_ino == sbuf->st_ino) )
|
|
{
|
|
found = True;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
prev_p = scanner_p ;
|
|
scanner_p = (share_mode_record *)smb_shm_offset2addr(scanner_p->next_offset);
|
|
}
|
|
}
|
|
|
|
if(!found)
|
|
{
|
|
smb_shm_unlock();
|
|
return (0);
|
|
}
|
|
|
|
if(scanner_p->locking_version != LOCKING_VERSION)
|
|
{
|
|
DEBUG(2,("Deleting old share mode record due to old locking version %d",scanner_p->locking_version));
|
|
if(prev_p == scanner_p)
|
|
smb_shm_set_userdef_off(scanner_p->next_offset);
|
|
else
|
|
prev_p->next_offset = scanner_p->next_offset;
|
|
smb_shm_free(smb_shm_addr2offset(scanner_p));
|
|
*pid = 0;
|
|
|
|
smb_shm_unlock();
|
|
return (0);
|
|
}
|
|
|
|
*pid = scanner_p->pid;
|
|
ret = scanner_p->share_mode;
|
|
|
|
if (*pid && !process_exists(*pid))
|
|
{
|
|
ret = 0;
|
|
*pid = 0;
|
|
}
|
|
|
|
if (! *pid)
|
|
{
|
|
if(prev_p == scanner_p)
|
|
smb_shm_set_userdef_off(scanner_p->next_offset);
|
|
else
|
|
prev_p->next_offset = scanner_p->next_offset;
|
|
smb_shm_free(smb_shm_addr2offset(scanner_p));
|
|
}
|
|
|
|
if (*pid)
|
|
DEBUG(5,("Read share mode record mode 0x%X pid=%d\n",ret,*pid));
|
|
|
|
if(!smb_shm_unlock()) return (0);
|
|
|
|
return(ret);
|
|
|
|
#else
|
|
pstring fname;
|
|
int fd2;
|
|
char buf[20];
|
|
int ret;
|
|
struct timeval t;
|
|
|
|
*pid = 0;
|
|
|
|
if (!share_name(cnum,sbuf,fname)) return(0);
|
|
|
|
fd2 = open(fname,O_RDONLY,0);
|
|
if (fd2 < 0) return(0);
|
|
|
|
if (read(fd2,buf,20) != 20) {
|
|
DEBUG(2,("Failed to read share file %s\n",fname));
|
|
close(fd2);
|
|
unlink(fname);
|
|
return(0);
|
|
}
|
|
close(fd2);
|
|
|
|
t.tv_sec = IVAL(buf,4);
|
|
t.tv_usec = IVAL(buf,8);
|
|
ret = IVAL(buf,12);
|
|
*pid = IVAL(buf,16);
|
|
|
|
if (IVAL(buf,0) != LOCKING_VERSION) {
|
|
if (!unlink(fname)) DEBUG(2,("Deleted old locking file %s",fname));
|
|
*pid = 0;
|
|
return(0);
|
|
}
|
|
|
|
if (*pid && !process_exists(*pid)) {
|
|
ret=0;
|
|
*pid = 0;
|
|
}
|
|
|
|
if (! *pid) unlink(fname); /* XXXXX race, race */
|
|
|
|
if (*pid)
|
|
DEBUG(5,("Read share file %s mode 0x%X pid=%d\n",fname,ret,*pid));
|
|
|
|
return(ret);
|
|
#endif
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
del the share mode of a file, if we set it last
|
|
********************************************************************/
|
|
void del_share_mode(int fnum)
|
|
{
|
|
#if FAST_SHARE_MODES
|
|
struct stat st;
|
|
struct timeval t;
|
|
int pid=0;
|
|
BOOL del = False;
|
|
share_mode_record *scanner_p;
|
|
share_mode_record *prev_p;
|
|
BOOL found = False;
|
|
|
|
t.tv_sec = t.tv_usec = 0;
|
|
|
|
if (fstat(Files[fnum].fd_ptr->fd,&st) != 0) return;
|
|
|
|
if (!smb_shm_lock()) return;
|
|
|
|
scanner_p = (share_mode_record *)smb_shm_offset2addr(smb_shm_get_userdef_off());
|
|
prev_p = scanner_p;
|
|
while(scanner_p)
|
|
{
|
|
if( (scanner_p->st_dev == st.st_dev) && (scanner_p->st_ino == st.st_ino) )
|
|
{
|
|
found = True;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
prev_p = scanner_p ;
|
|
scanner_p = (share_mode_record *)smb_shm_offset2addr(scanner_p->next_offset);
|
|
}
|
|
}
|
|
|
|
if(!found)
|
|
{
|
|
smb_shm_unlock();
|
|
return;
|
|
}
|
|
|
|
t.tv_sec = scanner_p->time.tv_sec;
|
|
t.tv_usec = scanner_p->time.tv_usec;
|
|
pid = scanner_p->pid;
|
|
|
|
if( (scanner_p->locking_version != LOCKING_VERSION) || !pid || !process_exists(pid))
|
|
del = True;
|
|
|
|
if (!del && (memcmp(&t,&Files[fnum].open_time,sizeof(t)) == 0)
|
|
&& pid==(int)getpid())
|
|
del = True;
|
|
|
|
if (del)
|
|
{
|
|
DEBUG(2,("Deleting share mode record\n"));
|
|
if(prev_p == scanner_p)
|
|
smb_shm_set_userdef_off(scanner_p->next_offset);
|
|
else
|
|
prev_p->next_offset = scanner_p->next_offset;
|
|
smb_shm_free(smb_shm_addr2offset(scanner_p));
|
|
|
|
}
|
|
|
|
smb_shm_unlock();
|
|
return;
|
|
|
|
#else
|
|
pstring fname;
|
|
int fd2;
|
|
char buf[20];
|
|
struct timeval t;
|
|
int pid=0;
|
|
BOOL del = False;
|
|
|
|
t.tv_sec = t.tv_usec = 0;
|
|
if (!share_name_fnum(fnum,fname)) return;
|
|
|
|
fd2 = open(fname,O_RDONLY,0);
|
|
if (fd2 < 0) return;
|
|
if (read(fd2,buf,20) != 20)
|
|
del = True;
|
|
close(fd2);
|
|
|
|
if (!del) {
|
|
t.tv_sec = IVAL(buf,4);
|
|
t.tv_usec = IVAL(buf,8);
|
|
pid = IVAL(buf,16);
|
|
}
|
|
|
|
if (!del)
|
|
if (IVAL(buf,0) != LOCKING_VERSION || !pid || !process_exists(pid))
|
|
del = True;
|
|
|
|
if (!del && (memcmp(&t,&Files[fnum].open_time,sizeof(t)) == 0) && (pid==(int)getpid()))
|
|
del = True;
|
|
|
|
if (del) {
|
|
if (!unlink(fname))
|
|
DEBUG(2,("Deleted share file %s\n",fname));
|
|
else {
|
|
DEBUG(3,("Pending delete share file %s\n",fname));
|
|
if (*share_del_pending) DEBUG(0,("Share del clash!\n"));
|
|
strcpy(share_del_pending,fname);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
set the share mode of a file
|
|
********************************************************************/
|
|
BOOL set_share_mode(int fnum,int mode)
|
|
{
|
|
#if FAST_SHARE_MODES
|
|
int pid = (int)getpid();
|
|
struct stat st;
|
|
smb_shm_offset_t new_off;
|
|
share_mode_record *new_p;
|
|
|
|
|
|
if (fstat(Files[fnum].fd_ptr->fd,&st) != 0) return(False);
|
|
|
|
if (!smb_shm_lock()) return (False);
|
|
new_off = smb_shm_alloc(sizeof(share_mode_record) + strlen(Files[fnum].name) );
|
|
if (new_off == NULL_OFFSET) return (False);
|
|
new_p = (share_mode_record *)smb_shm_offset2addr(new_off);
|
|
new_p->locking_version = LOCKING_VERSION;
|
|
new_p->share_mode = mode;
|
|
new_p->time.tv_sec = Files[fnum].open_time.tv_sec;
|
|
new_p->time.tv_usec = Files[fnum].open_time.tv_usec;
|
|
new_p->pid = pid;
|
|
new_p->st_dev = st.st_dev;
|
|
new_p->st_ino = st.st_ino;
|
|
strcpy(new_p->file_name,Files[fnum].name);
|
|
new_p->next_offset = smb_shm_get_userdef_off();
|
|
smb_shm_set_userdef_off(new_off);
|
|
|
|
|
|
DEBUG(3,("Created share record for %s with mode 0x%X pid=%d\n",Files[fnum].name,mode,pid));
|
|
|
|
if (!smb_shm_unlock()) return (False);
|
|
return(True);
|
|
|
|
#else
|
|
pstring fname;
|
|
int fd2;
|
|
char buf[20];
|
|
int pid = (int)getpid();
|
|
|
|
if (!share_name_fnum(fnum,fname)) return(False);
|
|
|
|
{
|
|
int old_umask = umask(0);
|
|
fd2 = open(fname,O_WRONLY|O_CREAT|O_TRUNC,0644);
|
|
umask(old_umask);
|
|
}
|
|
if (fd2 < 0) {
|
|
DEBUG(2,("Failed to create share file %s\n",fname));
|
|
return(False);
|
|
}
|
|
|
|
SIVAL(buf,0,LOCKING_VERSION);
|
|
SIVAL(buf,4,Files[fnum].open_time.tv_sec);
|
|
SIVAL(buf,8,Files[fnum].open_time.tv_usec);
|
|
SIVAL(buf,12,mode);
|
|
SIVAL(buf,16,pid);
|
|
|
|
if (write(fd2,buf,20) != 20) {
|
|
DEBUG(2,("Failed to write share file %s\n",fname));
|
|
close(fd2);
|
|
unlink(fname);
|
|
return(False);
|
|
}
|
|
|
|
write(fd2,Files[fnum].name,strlen(Files[fnum].name)+1);
|
|
|
|
close(fd2);
|
|
|
|
DEBUG(3,("Created share file %s with mode 0x%X pid=%d\n",fname,mode,pid));
|
|
|
|
return(True);
|
|
#endif
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
cleanup any stale share files
|
|
********************************************************************/
|
|
void clean_share_modes(void)
|
|
{
|
|
#ifdef USE_SHMEM
|
|
share_mode_record *scanner_p;
|
|
share_mode_record *prev_p;
|
|
int pid;
|
|
|
|
if (!smb_shm_lock()) return;
|
|
|
|
scanner_p = (share_mode_record *)smb_shm_offset2addr(smb_shm_get_userdef_off());
|
|
prev_p = scanner_p;
|
|
while(scanner_p)
|
|
{
|
|
pid = scanner_p->pid;
|
|
|
|
if( (scanner_p->locking_version != LOCKING_VERSION) || !process_exists(pid))
|
|
{
|
|
DEBUG(2,("Deleting stale share mode record"));
|
|
if(prev_p == scanner_p)
|
|
{
|
|
smb_shm_set_userdef_off(scanner_p->next_offset);
|
|
smb_shm_free(smb_shm_addr2offset(scanner_p));
|
|
scanner_p = (share_mode_record *)smb_shm_offset2addr(smb_shm_get_userdef_off());
|
|
prev_p = scanner_p;
|
|
}
|
|
else
|
|
{
|
|
prev_p->next_offset = scanner_p->next_offset;
|
|
smb_shm_free(smb_shm_addr2offset(scanner_p));
|
|
scanner_p = (share_mode_record *)smb_shm_offset2addr(prev_p->next_offset);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
prev_p = scanner_p ;
|
|
scanner_p = (share_mode_record *)smb_shm_offset2addr(scanner_p->next_offset);
|
|
}
|
|
}
|
|
|
|
|
|
smb_shm_unlock();
|
|
return;
|
|
|
|
#else
|
|
char *lockdir = lp_lockdir();
|
|
void *dir;
|
|
char *s;
|
|
|
|
if (!*lockdir) return;
|
|
|
|
dir = opendir(lockdir);
|
|
if (!dir) return;
|
|
|
|
while ((s=readdirname(dir))) {
|
|
char buf[20];
|
|
int pid;
|
|
int fd;
|
|
pstring lname;
|
|
int dev,inode;
|
|
|
|
if (sscanf(s,"share.%d.%d",&dev,&inode)!=2) continue;
|
|
|
|
strcpy(lname,lp_lockdir());
|
|
trim_string(lname,NULL,"/");
|
|
strcat(lname,"/");
|
|
strcat(lname,s);
|
|
|
|
fd = open(lname,O_RDONLY,0);
|
|
if (fd < 0) continue;
|
|
|
|
if (read(fd,buf,20) != 20) {
|
|
close(fd);
|
|
if (!unlink(lname))
|
|
printf("Deleted corrupt share file %s\n",s);
|
|
continue;
|
|
}
|
|
close(fd);
|
|
|
|
pid = IVAL(buf,16);
|
|
|
|
if (IVAL(buf,0) != LOCKING_VERSION || !process_exists(pid)) {
|
|
if (!unlink(lname))
|
|
printf("Deleted stale share file %s\n",s);
|
|
}
|
|
}
|
|
|
|
closedir(dir);
|
|
#endif
|
|
}
|