1
0
mirror of https://github.com/samba-team/samba.git synced 2025-12-16 00:23:52 +03:00

converted all our existing shared memory code to use a tdb database

instead of either sysv or mmap shared memory or lock files.

this means we can now completely remove
	locking_shm.c
	locking_slow.c
	shmem.c
	shmem_sysv.c
and lots of other things also got simpler

locking.c got a bit larger, but is much better compartmentalised now
This commit is contained in:
Andrew Tridgell
-
parent 4951755413
commit e48c2d9937
19 changed files with 427 additions and 3804 deletions

View File

@@ -135,8 +135,7 @@ RPC_CLIENT_OBJ = \
rpc_client/cli_samr.o rpc_client/cli_samr.o
LOCKING_OBJ = locking/locking.o locking/locking_shm.o locking/locking_slow.o \ LOCKING_OBJ = locking/locking.o
locking/shmem.o locking/shmem_sysv.o
PASSDB_OBJ = passdb/passdb.o passdb/smbpassfile.o passdb/smbpass.o \ PASSDB_OBJ = passdb/passdb.o passdb/smbpassfile.o passdb/smbpass.o \
passdb/pass_check.o passdb/ldap.o passdb/nispass.o passdb/smbpasschange.o passdb/pass_check.o passdb/ldap.o passdb/nispass.o passdb/smbpasschange.o

View File

@@ -299,6 +299,7 @@ BOOL reg_split_key(char *full_keyname, uint32 *reg_type, char *key_name);
char *smbd_mktemp(char *template); char *smbd_mktemp(char *template);
void *memdup(void *p, size_t size); void *memdup(void *p, size_t size);
char *myhostname(void); char *myhostname(void);
char *lock_path(char *name);
/*The following definitions come from lib/util_file.c */ /*The following definitions come from lib/util_file.c */
@@ -618,17 +619,18 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn,
BOOL locking_init(int read_only); BOOL locking_init(int read_only);
BOOL locking_end(void); BOOL locking_end(void);
BOOL lock_share_entry(connection_struct *conn, BOOL lock_share_entry(connection_struct *conn,
SMB_DEV_T dev, SMB_INO_T inode, int *ptok); SMB_DEV_T dev, SMB_INO_T inode);
BOOL unlock_share_entry(connection_struct *conn, BOOL unlock_share_entry(connection_struct *conn,
SMB_DEV_T dev, SMB_INO_T inode, int token); SMB_DEV_T dev, SMB_INO_T inode);
int get_share_modes(connection_struct *conn, int get_share_modes(connection_struct *conn,
int token, SMB_DEV_T dev, SMB_INO_T inode, SMB_DEV_T dev, SMB_INO_T inode,
share_mode_entry **shares); share_mode_entry **shares);
void del_share_mode(int token, files_struct *fsp); void del_share_mode(files_struct *fsp);
BOOL set_share_mode(int token, files_struct *fsp, uint16 port, uint16 op_type); BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type);
BOOL remove_share_oplock(int token, files_struct *fsp); BOOL remove_share_oplock(files_struct *fsp);
BOOL downgrade_share_oplock(int token, files_struct *fsp); BOOL downgrade_share_oplock(files_struct *fsp);
BOOL modify_share_mode(int token, files_struct *fsp, int new_mode, uint16 new_oplock); BOOL modify_share_mode(files_struct *fsp, int new_mode, uint16 new_oplock);
int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf);
int share_mode_forall(void (*fn)(share_mode_entry *, char *)); int share_mode_forall(void (*fn)(share_mode_entry *, char *));
void share_status(FILE *f); void share_status(FILE *f);
@@ -2375,7 +2377,6 @@ void conn_free(connection_struct *conn);
/*The following definitions come from smbd/connection.c */ /*The following definitions come from smbd/connection.c */
TDB_CONTEXT *open_db(char *name);
BOOL yield_connection(connection_struct *conn,char *name,int max_connections); BOOL yield_connection(connection_struct *conn,char *name,int max_connections);
int delete_dead(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf); int delete_dead(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf);
BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOOL Clear); BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOOL Clear);
@@ -2809,6 +2810,8 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int flags, mode_t mode);
int tdb_close(TDB_CONTEXT *tdb); int tdb_close(TDB_CONTEXT *tdb);
int tdb_writelock(TDB_CONTEXT *tdb); int tdb_writelock(TDB_CONTEXT *tdb);
int tdb_writeunlock(TDB_CONTEXT *tdb); int tdb_writeunlock(TDB_CONTEXT *tdb);
int tdb_lockchain(TDB_CONTEXT *tdb, TDB_DATA key);
int tdb_unlockchain(TDB_CONTEXT *tdb, TDB_DATA key);
/*The following definitions come from utils/nbio.c */ /*The following definitions come from utils/nbio.c */

View File

@@ -858,6 +858,22 @@ struct connections_data {
time_t start; time_t start;
}; };
/* key and data records in the tdb locking database */
struct locking_key {
SMB_DEV_T dev;
SMB_INO_T inode;
};
struct locking_data {
int num_share_mode_entries;
/* the following two entries are implicit
share_mode_entry modes[num_share_mode_entries];
char file_name[];
*/
};
/* the following are used by loadparm for option lists */ /* the following are used by loadparm for option lists */
typedef enum typedef enum
{ {

View File

@@ -3213,3 +3213,24 @@ char *myhostname(void)
} }
return ret; return ret;
} }
/*****************************************************************
a useful function for returning a path in the Samba lock directory
*****************************************************************/
char *lock_path(char *name)
{
static pstring fname;
pstrcpy(fname,lp_lockdir());
trim_string(fname,"","/");
if (!directory_exist(fname,NULL)) {
mkdir(fname,0755);
}
pstrcat(fname,"/");
pstrcat(fname,name);
return fname;
}

View File

@@ -1,8 +1,8 @@
/* /*
Unix SMB/Netbios implementation. Unix SMB/Netbios implementation.
Version 1.9. Version 3.0
Locking functions Locking functions
Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Andrew Tridgell 1992-1999
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@@ -29,42 +29,43 @@
September 1997. Jeremy Allison (jallison@whistle.com). Added oplock September 1997. Jeremy Allison (jallison@whistle.com). Added oplock
support. support.
rewrtten completely to use new tdb code. Tridge, Dec '99
*/ */
#include "includes.h" #include "includes.h"
extern int DEBUGLEVEL; extern int DEBUGLEVEL;
static struct share_ops *share_ops; /* the locking database handle */
static TDB_CONTEXT *tdb;
/**************************************************************************** /****************************************************************************
Utility function to map a lock type correctly depending on the real open Utility function to map a lock type correctly depending on the real open
mode of a file. mode of a file.
****************************************************************************/ ****************************************************************************/
static int map_lock_type(files_struct *fsp, int lock_type)
static int map_lock_type( files_struct *fsp, int lock_type)
{ {
if((lock_type == F_WRLCK) && (fsp->fd_ptr->real_open_flags == O_RDONLY)) { if((lock_type == F_WRLCK) && (fsp->fd_ptr->real_open_flags == O_RDONLY)) {
/* /*
* Many UNIX's cannot get a write lock on a file opened read-only. * Many UNIX's cannot get a write lock on a file opened read-only.
* Win32 locking semantics allow this. * Win32 locking semantics allow this.
* Do the best we can and attempt a read-only lock. * Do the best we can and attempt a read-only lock.
*/ */
DEBUG(10,("map_lock_type: Downgrading write lock to read due to read-only file.\n")); DEBUG(10,("map_lock_type: Downgrading write lock to read due to read-only file.\n"));
return F_RDLCK; return F_RDLCK;
} else if( (lock_type == F_RDLCK) && (fsp->fd_ptr->real_open_flags == O_WRONLY)) { } else if( (lock_type == F_RDLCK) && (fsp->fd_ptr->real_open_flags == O_WRONLY)) {
/* /*
* Ditto for read locks on write only files. * Ditto for read locks on write only files.
*/ */
DEBUG(10,("map_lock_type: Changing read lock to write due to write-only file.\n")); DEBUG(10,("map_lock_type: Changing read lock to write due to write-only file.\n"));
return F_WRLCK; return F_WRLCK;
} }
/* /*
* This return should be the most normal, as we attempt * This return should be the most normal, as we attempt
* to always open files read/write. * to always open files read/write.
*/ */
return lock_type; return lock_type;
} }
/**************************************************************************** /****************************************************************************
@@ -74,7 +75,7 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn,
SMB_OFF_T count,SMB_OFF_T offset, int lock_type) SMB_OFF_T count,SMB_OFF_T offset, int lock_type)
{ {
int snum = SNUM(conn); int snum = SNUM(conn);
if (count == 0) if (count == 0)
return(False); return(False);
@@ -98,30 +99,30 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn,
SMB_OFF_T count,SMB_OFF_T offset,int lock_type, SMB_OFF_T count,SMB_OFF_T offset,int lock_type,
int *eclass,uint32 *ecode) int *eclass,uint32 *ecode)
{ {
BOOL ok = False; BOOL ok = False;
if (!lp_locking(SNUM(conn))) if (!lp_locking(SNUM(conn)))
return(True); return(True);
if (count == 0) { if (count == 0) {
*eclass = ERRDOS; *eclass = ERRDOS;
*ecode = ERRnoaccess; *ecode = ERRnoaccess;
return False; return False;
} }
DEBUG(10,("do_lock: lock type %d start=%.0f len=%.0f requested for file %s\n",
lock_type, (double)offset, (double)count, fsp->fsp_name ));
DEBUG(10,("do_lock: lock type %d start=%.0f len=%.0f requested for file %s\n", if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn))
lock_type, (double)offset, (double)count, fsp->fsp_name )); ok = fcntl_lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count,
map_lock_type(fsp,lock_type));
if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) if (!ok) {
ok = fcntl_lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count, *eclass = ERRDOS;
map_lock_type(fsp,lock_type)); *ecode = ERRlock;
return False;
if (!ok) { }
*eclass = ERRDOS; return True; /* Got lock */
*ecode = ERRlock;
return False;
}
return True; /* Got lock */
} }
@@ -131,46 +132,38 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn,
BOOL do_unlock(files_struct *fsp,connection_struct *conn, BOOL do_unlock(files_struct *fsp,connection_struct *conn,
SMB_OFF_T count,SMB_OFF_T offset,int *eclass,uint32 *ecode) SMB_OFF_T count,SMB_OFF_T offset,int *eclass,uint32 *ecode)
{ {
BOOL ok = False; BOOL ok = False;
if (!lp_locking(SNUM(conn))) if (!lp_locking(SNUM(conn)))
return(True); return(True);
DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for file %s\n", DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for file %s\n",
(double)offset, (double)count, fsp->fsp_name )); (double)offset, (double)count, fsp->fsp_name ));
if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn))
ok = fcntl_lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count,F_UNLCK); ok = fcntl_lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count,F_UNLCK);
if (!ok) { if (!ok) {
*eclass = ERRDOS; *eclass = ERRDOS;
*ecode = ERRlock; *ecode = ERRlock;
return False; return False;
} }
return True; /* Did unlock */ return True; /* Did unlock */
} }
/**************************************************************************** /****************************************************************************
Initialise the locking functions. Initialise the locking functions.
****************************************************************************/ ****************************************************************************/
BOOL locking_init(int read_only) BOOL locking_init(int read_only)
{ {
if (share_ops) if (tdb) return True;
return True;
#ifdef FAST_SHARE_MODES tdb = tdb_open(lock_path("locking.tdb"),
share_ops = locking_shm_init(read_only); 0,
if (!share_ops && read_only && (getuid() == 0)) { read_only?O_RDONLY:O_RDWR|O_CREAT,
/* this may be the first time the share modes code has 0644);
been run. Initialise it now by running it read-write */
share_ops = locking_shm_init(0);
}
#else
share_ops = locking_slow_init(read_only);
#endif
if (!share_ops) { if (!tdb) {
DEBUG(0,("ERROR: Failed to initialise share modes\n")); DEBUG(0,("ERROR: Failed to initialise share modes\n"));
return False; return False;
} }
@@ -181,110 +174,271 @@ BOOL locking_init(int read_only)
/******************************************************************* /*******************************************************************
Deinitialize the share_mode management. Deinitialize the share_mode management.
******************************************************************/ ******************************************************************/
BOOL locking_end(void) BOOL locking_end(void)
{ {
if (share_ops) if (tdb && tdb_close(tdb) != 0) return False;
return share_ops->stop_mgmt();
return True; return True;
} }
/*******************************************************************
form a static locking key for a dev/inode pair
******************************************************************/
static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode)
{
static struct locking_key key;
TDB_DATA kbuf;
key.dev = dev;
key.inode = inode;
kbuf.dptr = (char *)&key;
kbuf.dsize = sizeof(key);
return kbuf;
}
static TDB_DATA locking_key_fsp(files_struct *fsp)
{
return locking_key(fsp->fd_ptr->dev, fsp->fd_ptr->inode);
}
/******************************************************************* /*******************************************************************
Lock a hash bucket entry. Lock a hash bucket entry.
******************************************************************/ ******************************************************************/
BOOL lock_share_entry(connection_struct *conn, BOOL lock_share_entry(connection_struct *conn,
SMB_DEV_T dev, SMB_INO_T inode, int *ptok) SMB_DEV_T dev, SMB_INO_T inode)
{ {
return share_ops->lock_entry(conn, dev, inode, ptok); return tdb_lockchain(tdb, locking_key(dev, inode)) == 0;
} }
/******************************************************************* /*******************************************************************
Unlock a hash bucket entry. Unlock a hash bucket entry.
******************************************************************/ ******************************************************************/
BOOL unlock_share_entry(connection_struct *conn, BOOL unlock_share_entry(connection_struct *conn,
SMB_DEV_T dev, SMB_INO_T inode, int token) SMB_DEV_T dev, SMB_INO_T inode)
{ {
return share_ops->unlock_entry(conn, dev, inode, token); return tdb_unlockchain(tdb, locking_key(dev, inode)) == 0;
} }
/******************************************************************* /*******************************************************************
Get all share mode entries for a dev/inode pair. Get all share mode entries for a dev/inode pair.
********************************************************************/ ********************************************************************/
int get_share_modes(connection_struct *conn, int get_share_modes(connection_struct *conn,
int token, SMB_DEV_T dev, SMB_INO_T inode, SMB_DEV_T dev, SMB_INO_T inode,
share_mode_entry **shares) share_mode_entry **shares)
{ {
return share_ops->get_entries(conn, token, dev, inode, shares); TDB_DATA dbuf;
struct locking_data *data;
int ret;
dbuf = tdb_fetch(tdb, locking_key(dev, inode));
if (!dbuf.dptr) return 0;
data = (struct locking_data *)dbuf.dptr;
ret = data->num_share_mode_entries;
*shares = (share_mode_entry *)memdup(dbuf.dptr + sizeof(*data), ret * sizeof(**shares));
free(dbuf.dptr);
if (! *shares) return 0;
return ret;
} }
/******************************************************************* /*******************************************************************
Del the share mode of a file. Del the share mode of a file for this process
********************************************************************/ ********************************************************************/
void del_share_mode(int token, files_struct *fsp) void del_share_mode(files_struct *fsp)
{ {
share_ops->del_entry(token, fsp); TDB_DATA dbuf;
struct locking_data *data;
int i, del_count=0;
share_mode_entry *shares;
pid_t pid = getpid();
/* read in the existing share modes */
dbuf = tdb_fetch(tdb, locking_key_fsp(fsp));
if (!dbuf.dptr) return;
data = (struct locking_data *)dbuf.dptr;
shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
/* find any with our pid and delete it by overwriting with the rest of the data
from the record */
for (i=0;i<data->num_share_mode_entries;) {
if (shares[i].pid == pid &&
memcmp(&shares[i].time,
&fsp->open_time,sizeof(struct timeval)) == 0) {
data->num_share_mode_entries--;
memmove(&shares[i], &shares[i+1],
dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares)));
del_count++;
} else {
i++;
}
}
/* the record has shrunk a bit */
dbuf.dsize -= del_count * sizeof(*shares);
/* store it back in the database */
tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE);
free(dbuf.dptr);
}
/*******************************************************************
fill a share mode entry
********************************************************************/
static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_type)
{
share_mode_entry *e = (share_mode_entry *)p;
e->pid = getpid();
e->share_mode = fsp->share_mode;
e->op_port = port;
e->op_type = op_type;
memcpy((char *)&e->time, (char *)&fsp->open_time, sizeof(struct timeval));
} }
/******************************************************************* /*******************************************************************
Set the share mode of a file. Return False on fail, True on success. Set the share mode of a file. Return False on fail, True on success.
********************************************************************/ ********************************************************************/
BOOL set_share_mode(int token, files_struct *fsp, uint16 port, uint16 op_type) BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type)
{ {
return share_ops->set_entry(token, fsp, port, op_type); TDB_DATA dbuf;
struct locking_data *data;
share_mode_entry *shares;
char *p=NULL;
int size;
/* read in the existing share modes if any */
dbuf = tdb_fetch(tdb, locking_key_fsp(fsp));
if (!dbuf.dptr) {
/* we'll need to create a new record */
pstring fname;
pstrcpy(fname, fsp->conn->connectpath);
pstrcat(fname, "/");
pstrcat(fname, fsp->fsp_name);
size = sizeof(*data) + sizeof(*shares) + strlen(fname) + 1;
p = (char *)malloc(size);
data = (struct locking_data *)p;
shares = (share_mode_entry *)(p + sizeof(*data));
data->num_share_mode_entries = 1;
pstrcpy(p + sizeof(*data) + sizeof(*shares), fname);
fill_share_mode(p + sizeof(*data), fsp, port, op_type);
dbuf.dptr = p;
dbuf.dsize = size;
tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE);
free(p);
return True;
}
/* we're adding to an existing entry - this is a bit fiddly */
data = (struct locking_data *)dbuf.dptr;
shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
data->num_share_mode_entries++;
size = dbuf.dsize + sizeof(*shares);
p = malloc(size);
memcpy(p, dbuf.dptr, sizeof(*data));
fill_share_mode(p + sizeof(*data), fsp, port, op_type);
memcpy(p + sizeof(*data) + sizeof(*shares), dbuf.dptr + sizeof(*data),
dbuf.dsize - sizeof(*data));
free(dbuf.dptr);
dbuf.dptr = p;
dbuf.dsize = size;
tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE);
free(p);
return True;
} }
/*******************************************************************
a generic in-place modification call for share mode entries
********************************************************************/
static BOOL mod_share_mode(files_struct *fsp,
void (*mod_fn)(share_mode_entry *, SMB_DEV_T, SMB_INO_T, void *),
void *param)
{
TDB_DATA dbuf;
struct locking_data *data;
int i;
share_mode_entry *shares;
pid_t pid = getpid();
int need_store=0;
/* read in the existing share modes */
dbuf = tdb_fetch(tdb, locking_key_fsp(fsp));
if (!dbuf.dptr) return False;
data = (struct locking_data *)dbuf.dptr;
shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
/* find any with our pid and call the supplied function */
for (i=0;i<data->num_share_mode_entries;i++) {
if (pid == shares[i].pid &&
shares[i].share_mode == fsp->share_mode &&
memcmp(&shares[i].time,
&fsp->open_time,sizeof(struct timeval)) == 0) {
mod_fn(&shares[i], fsp->fd_ptr->dev, fsp->fd_ptr->inode, param);
need_store=1;
}
}
/* if the mod fn was called then store it back */
if (need_store) {
tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE);
}
free(dbuf.dptr);
return need_store;
}
/******************************************************************* /*******************************************************************
Static function that actually does the work for the generic function Static function that actually does the work for the generic function
below. below.
********************************************************************/ ********************************************************************/
static void remove_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode, static void remove_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode,
void *param) void *param)
{ {
DEBUG(10,("remove_share_oplock_fn: removing oplock info for entry dev=%x ino=%.0f\n", DEBUG(10,("remove_share_oplock_fn: removing oplock info for entry dev=%x ino=%.0f\n",
(unsigned int)dev, (double)inode )); (unsigned int)dev, (double)inode ));
/* Delete the oplock info. */ /* Delete the oplock info. */
entry->op_port = 0; entry->op_port = 0;
entry->op_type = NO_OPLOCK; entry->op_type = NO_OPLOCK;
} }
/******************************************************************* /*******************************************************************
Remove an oplock port and mode entry from a share mode. Remove an oplock port and mode entry from a share mode.
********************************************************************/ ********************************************************************/
BOOL remove_share_oplock(files_struct *fsp)
BOOL remove_share_oplock(int token, files_struct *fsp)
{ {
return share_ops->mod_entry(token, fsp, remove_share_oplock_fn, NULL); return mod_share_mode(fsp, remove_share_oplock_fn, NULL);
} }
/******************************************************************* /*******************************************************************
Static function that actually does the work for the generic function Static function that actually does the work for the generic function
below. below.
********************************************************************/ ********************************************************************/
static void downgrade_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode, static void downgrade_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode,
void *param) void *param)
{ {
DEBUG(10,("downgrade_share_oplock_fn: downgrading oplock info for entry dev=%x ino=%.0f\n", DEBUG(10,("downgrade_share_oplock_fn: downgrading oplock info for entry dev=%x ino=%.0f\n",
(unsigned int)dev, (double)inode )); (unsigned int)dev, (double)inode ));
entry->op_type = LEVEL_II_OPLOCK; entry->op_type = LEVEL_II_OPLOCK;
} }
/******************************************************************* /*******************************************************************
Downgrade a oplock type from exclusive to level II. Downgrade a oplock type from exclusive to level II.
********************************************************************/ ********************************************************************/
BOOL downgrade_share_oplock(files_struct *fsp)
BOOL downgrade_share_oplock(int token, files_struct *fsp)
{ {
return share_ops->mod_entry(token, fsp, downgrade_share_oplock_fn, NULL); return mod_share_mode(fsp, downgrade_share_oplock_fn, NULL);
} }
/******************************************************************* /*******************************************************************
Static function that actually does the work for the generic function Static function that actually does the work for the generic function
below. below.
********************************************************************/ ********************************************************************/
struct mod_val { struct mod_val {
int new_share_mode; int new_share_mode;
uint16 new_oplock; uint16 new_oplock;
@@ -308,33 +462,46 @@ static void modify_share_mode_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO
Modify a share mode on a file. Used by the delete open file code. Modify a share mode on a file. Used by the delete open file code.
Return False on fail, True on success. Return False on fail, True on success.
********************************************************************/ ********************************************************************/
BOOL modify_share_mode(files_struct *fsp, int new_mode, uint16 new_oplock)
BOOL modify_share_mode(int token, files_struct *fsp, int new_mode, uint16 new_oplock)
{ {
struct mod_val mv; struct mod_val mv;
mv.new_share_mode = new_mode; mv.new_share_mode = new_mode;
mv.new_oplock = new_oplock; mv.new_oplock = new_oplock;
return share_ops->mod_entry(token, fsp, modify_share_mode_fn, (void *)&mv); return mod_share_mode(fsp, modify_share_mode_fn, (void *)&mv);
}
static void (*traverse_callback)(share_mode_entry *, char *);
/****************************************************************************
traverse the whole database with this function, calling traverse_callback
on each share mode
****************************************************************************/
int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf)
{
struct locking_data *data;
share_mode_entry *shares;
char *name;
int i;
data = (struct locking_data *)dbuf.dptr;
shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
name = dbuf.dptr + sizeof(*data) + data->num_share_mode_entries*sizeof(*shares);
for (i=0;i<data->num_share_mode_entries;i++) {
traverse_callback(&shares[i], name);
}
return 0;
} }
/******************************************************************* /*******************************************************************
Call the specified function on each entry under management by the Call the specified function on each entry under management by the
share mode system. share mode system.
********************************************************************/ ********************************************************************/
int share_mode_forall(void (*fn)(share_mode_entry *, char *)) int share_mode_forall(void (*fn)(share_mode_entry *, char *))
{ {
if (!share_ops) return 0; if (!tdb) return 0;
return share_ops->forall(fn); traverse_callback = fn;
} return tdb_traverse(tdb, traverse_fn);
/*******************************************************************
Dump the state of the system.
********************************************************************/
void share_status(FILE *f)
{
share_ops->status(f);
} }

View File

@@ -1,711 +0,0 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
shared memory locking implementation
Copyright (C) Andrew Tridgell 1992-1998
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
May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode
locking to deal with multiple share modes per open file.
September 1997. Jeremy Allison (jallison@whistle.com). Added oplock
support.
October 1997 - split into separate file (tridge)
*/
#include "includes.h"
#ifdef FAST_SHARE_MODES
extern int DEBUGLEVEL;
static struct shmem_ops *shmops;
/* share mode record pointed to in shared memory hash bucket */
typedef struct
{
int next_offset; /* offset of next record in chain from hash bucket */
int locking_version;
SMB_DEV_T st_dev;
SMB_INO_T st_ino;
int num_share_mode_entries;
int share_mode_entries; /* Chain of share mode entries for this file */
char file_name[1];
} share_mode_record;
/* share mode entry pointed to by share_mode_record struct */
typedef struct
{
int next_share_mode_entry;
share_mode_entry e;
} shm_share_mode_entry;
static int read_only;
/* Conversion to hash entry index from device and inode numbers. */
#define HASH_ENTRY(dev,ino) ((unsigned int)(((dev) ^ (ino)) % shmops->hash_size()))
/*******************************************************************
deinitialize the shared memory for share_mode management
******************************************************************/
static BOOL shm_stop_share_mode_mgmt(void)
{
return shmops->shm_close();
}
/*******************************************************************
lock a hash bucket entry in shared memory for share_mode management
******************************************************************/
static BOOL shm_lock_share_entry(connection_struct *conn,
SMB_DEV_T dev, SMB_INO_T inode, int *ptok)
{
*ptok = 0; /* For purify... */
return shmops->lock_hash_entry(HASH_ENTRY(dev, inode));
}
/*******************************************************************
unlock a hash bucket entry in shared memory for share_mode management
******************************************************************/
static BOOL shm_unlock_share_entry(connection_struct *conn,
SMB_DEV_T dev, SMB_INO_T inode, int token)
{
return shmops->unlock_hash_entry(HASH_ENTRY(dev, inode));
}
/*******************************************************************
get all share mode entries in shared memory for a dev/inode pair.
********************************************************************/
static int shm_get_share_modes(connection_struct *conn,
int token, SMB_DEV_T dev, SMB_INO_T inode,
share_mode_entry **old_shares)
{
int *mode_array;
unsigned int hash_entry = HASH_ENTRY(dev, inode);
share_mode_record *file_scanner_p;
share_mode_record *file_prev_p;
shm_share_mode_entry *entry_scanner_p;
shm_share_mode_entry *entry_prev_p;
int num_entries;
int num_entries_copied;
BOOL found = False;
share_mode_entry *share_array = (share_mode_entry *)0;
*old_shares = 0;
mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off());
if(mode_array[hash_entry] == 0)
{
DEBUG(5,("get_share_modes hash bucket %d empty\n", hash_entry));
return 0;
}
file_scanner_p = (share_mode_record *)shmops->offset2addr(mode_array[hash_entry]);
file_prev_p = file_scanner_p;
while(file_scanner_p)
{
if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
{
found = True;
break;
}
else
{
file_prev_p = file_scanner_p ;
file_scanner_p = (share_mode_record *)shmops->offset2addr(
file_scanner_p->next_offset);
}
}
if(!found)
{
DEBUG(5,("get_share_modes no entry for file dev = %x ino = %.0f\n",
(unsigned int)dev, (double)inode));
return (0);
}
if(file_scanner_p->locking_version != LOCKING_VERSION)
{
DEBUG(0,("ERROR: get_share_modes Deleting old share mode v1 %d dev=%x ino=%.0f\n",
file_scanner_p->locking_version, (unsigned int)dev, (double)inode));
if(file_prev_p == file_scanner_p)
mode_array[hash_entry] = file_scanner_p->next_offset;
else
file_prev_p->next_offset = file_scanner_p->next_offset;
shmops->shm_free(shmops->addr2offset(file_scanner_p));
return (0);
}
/* Allocate the old_shares array */
num_entries = file_scanner_p->num_share_mode_entries;
if(num_entries)
{
*old_shares = share_array = (share_mode_entry *)
malloc(num_entries * sizeof(share_mode_entry));
if(*old_shares == 0)
{
DEBUG(0,("get_share_modes: malloc fail for size 0x%x!\n", (unsigned int)(num_entries * sizeof(share_mode_entry))));
return 0;
}
}
num_entries_copied = 0;
entry_scanner_p = (shm_share_mode_entry*)shmops->offset2addr(
file_scanner_p->share_mode_entries);
entry_prev_p = entry_scanner_p;
while(entry_scanner_p)
{
pid_t pid = entry_scanner_p->e.pid;
if (pid && !process_exists(pid))
{
/* Delete this share mode entry */
shm_share_mode_entry *delete_entry_p = entry_scanner_p;
if(entry_prev_p == entry_scanner_p)
{
/* We are at start of list */
file_scanner_p->share_mode_entries = entry_scanner_p->next_share_mode_entry;
entry_scanner_p = (shm_share_mode_entry*)shmops->offset2addr(
file_scanner_p->share_mode_entries);
entry_prev_p = entry_scanner_p;
}
else
{
entry_prev_p->next_share_mode_entry = entry_scanner_p->next_share_mode_entry;
entry_scanner_p = (shm_share_mode_entry*)
shmops->offset2addr(entry_scanner_p->next_share_mode_entry);
}
/* Decrement the number of share mode entries on this share mode record */
file_scanner_p->num_share_mode_entries -= 1;
/* PARANOIA TEST */
if(file_scanner_p->num_share_mode_entries < 0)
{
DEBUG(0,("PANIC ERROR: get_share_mode: entries=%d dev=%x ino=%.0f\n",
file_scanner_p->num_share_mode_entries, (unsigned int)dev, (double)inode));
return 0;
}
DEBUG(0,("get_share_modes: process %d no longer exists\n", (int)pid));
shmops->shm_free(shmops->addr2offset(delete_entry_p));
}
else
{
/* This is a valid share mode entry and the process that
created it still exists. Copy it into the output array.
*/
share_array[num_entries_copied].pid = entry_scanner_p->e.pid;
share_array[num_entries_copied].share_mode = entry_scanner_p->e.share_mode;
share_array[num_entries_copied].op_port = entry_scanner_p->e.op_port;
share_array[num_entries_copied].op_type = entry_scanner_p->e.op_type;
memcpy(&share_array[num_entries_copied].time, &entry_scanner_p->e.time,
sizeof(struct timeval));
num_entries_copied++;
DEBUG(5,("get_share_modes Read share mode 0x%X pid=%d\n",
entry_scanner_p->e.share_mode, (int)entry_scanner_p->e.pid));
entry_prev_p = entry_scanner_p;
entry_scanner_p = (shm_share_mode_entry *)
shmops->offset2addr(entry_scanner_p->next_share_mode_entry);
}
}
/* If no valid share mode entries were found then this record shouldn't exist ! */
if(num_entries_copied == 0)
{
DEBUG(0,("get_share_modes: file with dev %x inode %.0f empty\n",
(unsigned int)dev, (double)inode));
if(*old_shares)
free((char *)*old_shares);
*old_shares = 0;
if(file_prev_p == file_scanner_p)
mode_array[hash_entry] = file_scanner_p->next_offset;
else
file_prev_p->next_offset = file_scanner_p->next_offset;
shmops->shm_free(shmops->addr2offset(file_scanner_p));
}
DEBUG(5,("get_share_modes: file with dev %x inode %.0f -> %d entries\n",
(unsigned int)dev, (double)inode, num_entries_copied));
return(num_entries_copied);
}
/*******************************************************************
del the share mode of a file.
********************************************************************/
static void shm_del_share_mode(int token, files_struct *fsp)
{
SMB_DEV_T dev;
SMB_INO_T inode;
int *mode_array;
unsigned int hash_entry;
share_mode_record *file_scanner_p;
share_mode_record *file_prev_p;
shm_share_mode_entry *entry_scanner_p;
shm_share_mode_entry *entry_prev_p;
BOOL found = False;
pid_t pid = getpid();
dev = fsp->fd_ptr->dev;
inode = fsp->fd_ptr->inode;
hash_entry = HASH_ENTRY(dev, inode);
mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off());
if(mode_array[hash_entry] == 0)
{
DEBUG(0,("PANIC ERROR:del_share_mode hash bucket %d empty\n",
hash_entry));
return;
}
file_scanner_p = (share_mode_record *)shmops->offset2addr(mode_array[hash_entry]);
file_prev_p = file_scanner_p;
while(file_scanner_p)
{
if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
{
found = True;
break;
}
else
{
file_prev_p = file_scanner_p ;
file_scanner_p = (share_mode_record *)
shmops->offset2addr(file_scanner_p->next_offset);
}
}
if(!found)
{
DEBUG(0,("ERROR: del_share_mode no entry for dev %x inode %.0f\n",
(unsigned int)dev, (double)inode));
return;
}
if(file_scanner_p->locking_version != LOCKING_VERSION)
{
DEBUG(0,("ERROR: del_share_modes Deleting old share mode v1 %d dev=%x ino=%.0f\n",
file_scanner_p->locking_version, (unsigned int)dev, (double)inode));
if(file_prev_p == file_scanner_p)
mode_array[hash_entry] = file_scanner_p->next_offset;
else
file_prev_p->next_offset = file_scanner_p->next_offset;
shmops->shm_free(shmops->addr2offset(file_scanner_p));
return;
}
found = False;
entry_scanner_p = (shm_share_mode_entry*)shmops->offset2addr(
file_scanner_p->share_mode_entries);
entry_prev_p = entry_scanner_p;
while(entry_scanner_p)
{
if( (pid == entry_scanner_p->e.pid) &&
(memcmp(&entry_scanner_p->e.time,
&fsp->open_time,sizeof(struct timeval)) == 0) )
{
found = True;
break;
}
else
{
entry_prev_p = entry_scanner_p;
entry_scanner_p = (shm_share_mode_entry *)
shmops->offset2addr(entry_scanner_p->next_share_mode_entry);
}
}
if (found)
{
/* Decrement the number of entries in the record. */
file_scanner_p->num_share_mode_entries -= 1;
DEBUG(2,("del_share_modes Deleting share mode entry dev=%x ino=%.0f\n",
(unsigned int)dev, (double)inode));
if(entry_prev_p == entry_scanner_p)
/* We are at start of list */
file_scanner_p->share_mode_entries = entry_scanner_p->next_share_mode_entry;
else
entry_prev_p->next_share_mode_entry = entry_scanner_p->next_share_mode_entry;
shmops->shm_free(shmops->addr2offset(entry_scanner_p));
/* PARANOIA TEST */
if(file_scanner_p->num_share_mode_entries < 0)
{
DEBUG(0,("PANIC ERROR:del_share_mode num_share_mode_entries=%d\n",
file_scanner_p->num_share_mode_entries));
return;
}
/* If we deleted the last share mode entry then remove the share mode record. */
if(file_scanner_p->num_share_mode_entries == 0)
{
DEBUG(2,("del_share_modes num entries = 0, deleting share_mode dev=%x ino=%.0f\n",
(unsigned int)dev, (double)inode));
if(file_prev_p == file_scanner_p)
mode_array[hash_entry] = file_scanner_p->next_offset;
else
file_prev_p->next_offset = file_scanner_p->next_offset;
shmops->shm_free(shmops->addr2offset(file_scanner_p));
}
}
else
{
DEBUG(0,("ERROR: del_share_modes No share mode dev=%x ino=%.0f\n",
(unsigned int)dev, (double)inode));
}
}
/*******************************************************************
set the share mode of a file. Return False on fail, True on success.
********************************************************************/
static BOOL shm_set_share_mode(int token, files_struct *fsp, uint16 port, uint16 op_type)
{
SMB_DEV_T dev;
SMB_INO_T inode;
int *mode_array;
unsigned int hash_entry;
share_mode_record *file_scanner_p;
shm_share_mode_entry *new_entry_p;
int new_entry_offset;
BOOL found = False;
dev = fsp->fd_ptr->dev;
inode = fsp->fd_ptr->inode;
hash_entry = HASH_ENTRY(dev, inode);
mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off());
file_scanner_p = (share_mode_record *)shmops->offset2addr(mode_array[hash_entry]);
while(file_scanner_p)
{
if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
{
found = True;
break;
}
else
{
file_scanner_p = (share_mode_record *)
shmops->offset2addr(file_scanner_p->next_offset);
}
}
if(!found)
{
/* We must create a share_mode_record */
share_mode_record *new_mode_p = NULL;
int new_offset = shmops->shm_alloc(sizeof(share_mode_record) +
strlen(fsp->fsp_name) + strlen(fsp->conn->connectpath) + 2);
if(new_offset == 0) {
DEBUG(0,("ERROR:set_share_mode shmops->shm_alloc fail!\n"));
return False;
}
new_mode_p = shmops->offset2addr(new_offset);
new_mode_p->locking_version = LOCKING_VERSION;
new_mode_p->st_dev = dev;
new_mode_p->st_ino = inode;
new_mode_p->num_share_mode_entries = 0;
new_mode_p->share_mode_entries = 0;
pstrcpy(new_mode_p->file_name, fsp->conn->connectpath);
pstrcat(new_mode_p->file_name, "/");
pstrcat(new_mode_p->file_name, fsp->fsp_name);
/* Chain onto the start of the hash chain (in the hope we will be used first). */
new_mode_p->next_offset = mode_array[hash_entry];
mode_array[hash_entry] = new_offset;
file_scanner_p = new_mode_p;
DEBUG(3,("set_share_mode: Created share record for %s (dev %x inode %.0f)\n",
fsp->fsp_name, (unsigned int)dev, (double)inode));
}
/* Now create the share mode entry */
new_entry_offset = shmops->shm_alloc(sizeof(shm_share_mode_entry));
if(new_entry_offset == 0) {
int delete_offset = mode_array[hash_entry];
DEBUG(0,("ERROR:set_share_mode: shmops->shm_alloc fail 1!\n"));
/* Unlink the damaged record */
mode_array[hash_entry] = file_scanner_p->next_offset;
/* And delete it */
shmops->shm_free( delete_offset );
return False;
}
new_entry_p = shmops->offset2addr(new_entry_offset);
new_entry_p->e.pid = getpid();
new_entry_p->e.share_mode = fsp->share_mode;
new_entry_p->e.op_port = port;
new_entry_p->e.op_type = op_type;
memcpy( (char *)&new_entry_p->e.time, (char *)&fsp->open_time, sizeof(struct timeval));
/* Chain onto the share_mode_record */
new_entry_p->next_share_mode_entry = file_scanner_p->share_mode_entries;
file_scanner_p->share_mode_entries = new_entry_offset;
/* PARANOIA TEST */
if(file_scanner_p->num_share_mode_entries < 0)
{
DEBUG(0,("PANIC ERROR:set_share_mode num_share_mode_entries=%d\n",
file_scanner_p->num_share_mode_entries));
return False;
}
/* Increment the share_mode_entries counter */
file_scanner_p->num_share_mode_entries += 1;
DEBUG(3,("set_share_mode: Created share entry for %s with mode 0x%X pid=%d\n",
fsp->fsp_name, fsp->share_mode, (int)new_entry_p->e.pid));
return(True);
}
/*******************************************************************
Call a generic modify function for a share mode entry.
********************************************************************/
static BOOL shm_mod_share_entry(int token, files_struct *fsp,
void (*mod_fn)(share_mode_entry *, SMB_DEV_T, SMB_INO_T, void *),
void *param)
{
SMB_DEV_T dev;
SMB_INO_T inode;
int *mode_array;
unsigned int hash_entry;
share_mode_record *file_scanner_p;
share_mode_record *file_prev_p;
shm_share_mode_entry *entry_scanner_p;
BOOL found = False;
pid_t pid = getpid();
dev = fsp->fd_ptr->dev;
inode = fsp->fd_ptr->inode;
hash_entry = HASH_ENTRY(dev, inode);
mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off());
if(mode_array[hash_entry] == 0)
{
DEBUG(0,("PANIC ERROR:modify_share_entry: hash bucket %d empty\n",
hash_entry));
return False;
}
file_scanner_p = (share_mode_record *)shmops->offset2addr(mode_array[hash_entry]);
file_prev_p = file_scanner_p;
while(file_scanner_p)
{
if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
{
found = True;
break;
}
else
{
file_prev_p = file_scanner_p ;
file_scanner_p = (share_mode_record *)
shmops->offset2addr(file_scanner_p->next_offset);
}
}
if(!found)
{
DEBUG(0,("ERROR:modify_share_entry: no entry found for dev=%x ino=%.0f\n",
(unsigned int)dev, (double)inode));
return False;
}
if(file_scanner_p->locking_version != LOCKING_VERSION)
{
DEBUG(0,("ERROR: modify_share_entry: Deleting old share mode v1=%d dev=%x ino=%.0f\n",
file_scanner_p->locking_version, (unsigned int)dev, (double)inode));
if(file_prev_p == file_scanner_p)
mode_array[hash_entry] = file_scanner_p->next_offset;
else
file_prev_p->next_offset = file_scanner_p->next_offset;
shmops->shm_free(shmops->addr2offset(file_scanner_p));
return False;
}
found = False;
entry_scanner_p = (shm_share_mode_entry*)shmops->offset2addr(
file_scanner_p->share_mode_entries);
while(entry_scanner_p)
{
if( (pid == entry_scanner_p->e.pid) &&
(entry_scanner_p->e.share_mode == fsp->share_mode) &&
(memcmp(&entry_scanner_p->e.time,
&fsp->open_time,sizeof(struct timeval)) == 0) )
{
/*
* Call the generic function with the given parameter.
*/
DEBUG(5,("modify_share_entry: Calling generic function to modify entry for dev=%x ino=%.0f\n",
(unsigned int)dev, (double)inode));
(*mod_fn)( &entry_scanner_p->e, dev, inode, param);
found = True;
break;
}
else
{
entry_scanner_p = (shm_share_mode_entry *)
shmops->offset2addr(entry_scanner_p->next_share_mode_entry);
}
}
if(!found)
{
DEBUG(0,("ERROR: modify_share_entry: No entry found for dev=%x ino=%.0f\n",
(unsigned int)dev, (double)inode));
return False;
}
return True;
}
/*******************************************************************
call the specified function on each entry under management by the
share mode system
********************************************************************/
static int shm_share_forall(void (*fn)(share_mode_entry *, char *))
{
int i, count=0;
int *mode_array;
share_mode_record *file_scanner_p;
mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off());
for( i = 0; i < shmops->hash_size(); i++) {
shmops->lock_hash_entry(i);
if(mode_array[i] == 0) {
shmops->unlock_hash_entry(i);
continue;
}
file_scanner_p = (share_mode_record *)shmops->offset2addr(mode_array[i]);
while((file_scanner_p != 0) &&
(file_scanner_p->num_share_mode_entries != 0)) {
shm_share_mode_entry *entry_scanner_p =
(shm_share_mode_entry *)
shmops->offset2addr(file_scanner_p->share_mode_entries);
while(entry_scanner_p != 0) {
if (process_exists(entry_scanner_p->e.pid)) {
fn(&entry_scanner_p->e,
file_scanner_p->file_name);
count++;
}
entry_scanner_p =
(shm_share_mode_entry *)
shmops->offset2addr(
entry_scanner_p->next_share_mode_entry);
} /* end while entry_scanner_p */
file_scanner_p = (share_mode_record *)
shmops->offset2addr(file_scanner_p->next_offset);
} /* end while file_scanner_p */
shmops->unlock_hash_entry(i);
} /* end for */
return count;
}
/*******************************************************************
dump the state of the system
********************************************************************/
static void shm_share_status(FILE *f)
{
int bytes_free, bytes_used, bytes_overhead, bytes_total;
shmops->get_usage(&bytes_free, &bytes_used, &bytes_overhead);
bytes_total = bytes_free + bytes_used + bytes_overhead;
fprintf(f, "Share mode memory usage (bytes):\n");
fprintf(f, " %d(%d%%) free + %d(%d%%) used + %d(%d%%) overhead = %d(100%%) total\n",
bytes_free, (bytes_free * 100)/bytes_total,
bytes_used, (bytes_used * 100)/bytes_total,
bytes_overhead, (bytes_overhead * 100)/bytes_total,
bytes_total);
}
static struct share_ops share_ops = {
shm_stop_share_mode_mgmt,
shm_lock_share_entry,
shm_unlock_share_entry,
shm_get_share_modes,
shm_del_share_mode,
shm_set_share_mode,
shm_mod_share_entry,
shm_share_forall,
shm_share_status,
};
/*******************************************************************
initialize the shared memory for share_mode management
******************************************************************/
struct share_ops *locking_shm_init(int ronly)
{
read_only = ronly;
#ifdef USE_SYSV_IPC
shmops = sysv_shm_open(read_only);
if (shmops) return &share_ops;
#endif
#ifdef USE_SHARED_MMAP
shmops = smb_shm_open(read_only);
if (shmops) return &share_ops;
#endif
return NULL;
}
#else
int locking_shm_dummy_procedure(void)
{return 0;}
#endif /* FAST_SHARE_MODES */

File diff suppressed because it is too large Load Diff

View File

@@ -1,963 +0,0 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
Shared memory functions
Copyright (C) Erik Devriendt 1996-1998
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.
*/
#include "includes.h"
#ifdef USE_SHARED_MMAP
extern int DEBUGLEVEL;
#define SMB_SHM_MAGIC 0x53484100
/* = "SHM" in hex */
#define SMB_SHM_VERSION 2
/* we need world read for smbstatus to function correctly */
#ifdef SECURE_SHARE_MODES
#define SHM_FILE_MODE 0600
#else
#define SHM_FILE_MODE 0644
#endif
#define SHMEM_HASH_SIZE 13
/* WARNING : offsets are used because mmap() does not guarantee that all processes have the
shared memory mapped to the same address */
struct SmbShmHeader
{
int smb_shm_magic;
int smb_shm_version;
int total_size; /* in bytes */
BOOL consistent;
int first_free_off;
int userdef_off; /* a userdefined offset. can be used to store root of tree or list */
struct { /* a cell is a range of bytes of sizeof(struct SmbShmBlockDesc) size */
int cells_free;
int cells_used;
int cells_system; /* number of cells used as allocated block descriptors */
} statistics;
};
#define SMB_SHM_NOT_FREE_OFF (-1)
struct SmbShmBlockDesc
{
int next; /* offset of next block in the free list or SMB_SHM_NOT_FREE_OFF when block in use */
int size; /* user size in BlockDescSize units */
};
#define EOList_Addr (struct SmbShmBlockDesc *)( 0 )
#define EOList_Off 0
#define CellSize sizeof(struct SmbShmBlockDesc)
/* HeaderSize aligned on 8 byte boundary */
#define AlignedHeaderSize ((sizeof(struct SmbShmHeader)+7) & ~7)
static int smb_shm_fd = -1;
static pstring smb_shm_processreg_name = "";
static struct SmbShmHeader *smb_shm_header_p = (struct SmbShmHeader *)0;
static int smb_shm_times_locked = 0;
static BOOL smb_shm_initialize_called = False;
static int read_only;
static BOOL smb_shm_global_lock(void)
{
if (smb_shm_fd < 0)
{
DEBUG(0,("ERROR smb_shm_global_lock : bad smb_shm_fd (%d)\n",smb_shm_fd));
return False;
}
smb_shm_times_locked++;
if(smb_shm_times_locked > 1)
{
DEBUG(5,("smb_shm_global_lock : locked %d times\n",smb_shm_times_locked));
return True;
}
if (read_only)
return True;
/* Do an exclusive wait lock on the first byte of the file */
if (fcntl_lock(smb_shm_fd, SMB_F_SETLKW, 0, 1, F_WRLCK) == False)
{
DEBUG(0,("ERROR smb_shm_global_lock : fcntl_lock failed with code %s\n",strerror(errno)));
smb_shm_times_locked--;
return False;
}
return True;
}
static BOOL smb_shm_global_unlock(void)
{
if (smb_shm_fd < 0)
{
DEBUG(0,("ERROR smb_shm_global_unlock : bad smb_shm_fd (%d)\n",smb_shm_fd));
return False;
}
if(smb_shm_times_locked == 0)
{
DEBUG(0,("ERROR smb_shm_global_unlock : shmem not locked\n"));
return False;
}
smb_shm_times_locked--;
if(smb_shm_times_locked > 0)
{
DEBUG(5,("smb_shm_global_unlock : still locked %d times\n",smb_shm_times_locked));
return True;
}
if (read_only)
return True;
/* Do a wait unlock on the first byte of the file */
if (fcntl_lock(smb_shm_fd, SMB_F_SETLKW, 0, 1, F_UNLCK) == False)
{
DEBUG(0,("ERROR smb_shm_global_unlock : fcntl_lock failed with code %s\n",strerror(errno)));
smb_shm_times_locked++;
return False;
}
return True;
}
static void *smb_shm_offset2addr(int offset)
{
if (offset == 0 )
return (void *)(0);
if (!smb_shm_header_p)
return (void *)(0);
return (void *)((char *)smb_shm_header_p + offset );
}
static int smb_shm_addr2offset(void *addr)
{
if (!addr)
return 0;
if (!smb_shm_header_p)
return 0;
return (int)((char *)addr - (char *)smb_shm_header_p);
}
static int smb_shm_alloc(int size)
{
unsigned num_cells ;
struct SmbShmBlockDesc *scanner_p;
struct SmbShmBlockDesc *prev_p;
struct SmbShmBlockDesc *new_p;
int result_offset;
if( !smb_shm_header_p )
{
/* not mapped yet */
DEBUG(0,("ERROR smb_shm_alloc : shmem not mapped\n"));
return 0;
}
smb_shm_global_lock();
if( !smb_shm_header_p->consistent)
{
DEBUG(0,("ERROR smb_shm_alloc : shmem not consistent\n"));
smb_shm_global_unlock();
return 0;
}
/* calculate the number of cells */
num_cells = (size + CellSize -1) / CellSize;
/* set start of scan */
prev_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(smb_shm_header_p->first_free_off);
scanner_p = prev_p ;
/* scan the free list to find a matching free space */
while ( ( scanner_p != EOList_Addr ) && ( scanner_p->size < num_cells ) )
{
prev_p = scanner_p;
scanner_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(scanner_p->next);
}
/* at this point scanner point to a block header or to the end of the list */
if ( scanner_p == EOList_Addr )
{
DEBUG(0,("ERROR smb_shm_alloc : alloc of %d bytes failed, no free space found\n",size));
smb_shm_global_unlock();
return (0);
}
/* going to modify shared mem */
smb_shm_header_p->consistent = False;
/* if we found a good one : scanner == the good one */
if ( scanner_p->size <= num_cells + 2 )
{
/* there is no use in making a new one, it will be too small anyway
* we will link out scanner
*/
if ( prev_p == scanner_p )
{
smb_shm_header_p->first_free_off = scanner_p->next ;
}
else
{
prev_p->next = scanner_p->next ;
}
smb_shm_header_p->statistics.cells_free -= scanner_p->size;
smb_shm_header_p->statistics.cells_used += scanner_p->size;
}
else
{
/* Make a new one */
new_p = scanner_p + 1 + num_cells;
new_p->size = scanner_p->size - num_cells - 1;
new_p->next = scanner_p->next;
scanner_p->size = num_cells;
scanner_p->next = smb_shm_addr2offset(new_p);
if ( prev_p != scanner_p )
{
prev_p->next = smb_shm_addr2offset(new_p) ;
}
else
{
smb_shm_header_p->first_free_off = smb_shm_addr2offset(new_p) ;
}
smb_shm_header_p->statistics.cells_free -= num_cells+1;
smb_shm_header_p->statistics.cells_used += num_cells;
smb_shm_header_p->statistics.cells_system += 1;
}
result_offset = smb_shm_addr2offset( &(scanner_p[1]) );
scanner_p->next = SMB_SHM_NOT_FREE_OFF ;
/* end modification of shared mem */
smb_shm_header_p->consistent = True;
DEBUG(6,("smb_shm_alloc : request for %d bytes, allocated %d bytes at offset %d\n",size,scanner_p->size*CellSize,result_offset ));
smb_shm_global_unlock();
return ( result_offset );
}
/*
* Function to create the hash table for the share mode entries. Called
* when smb shared memory is global locked.
*/
static BOOL smb_shm_create_hash_table( unsigned int size )
{
size *= sizeof(int);
smb_shm_global_lock();
smb_shm_header_p->userdef_off = smb_shm_alloc( size );
if(smb_shm_header_p->userdef_off == 0)
{
DEBUG(0,("smb_shm_create_hash_table: Failed to create hash table of size %d\n",size));
smb_shm_global_unlock();
return False;
}
/* Clear hash buckets. */
memset( smb_shm_offset2addr(smb_shm_header_p->userdef_off), '\0', size);
smb_shm_global_unlock();
return True;
}
static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *other_processes)
{
int smb_shm_processes_fd = -1;
int nb_read;
pid_t other_pid;
SMB_OFF_T seek_back = -((SMB_OFF_T)sizeof(other_pid));
SMB_OFF_T free_slot = -1;
SMB_OFF_T erased_slot;
smb_shm_processes_fd = sys_open(processreg_file,
read_only?O_RDONLY:(O_RDWR|O_CREAT),
SHM_FILE_MODE);
if ( smb_shm_processes_fd < 0 )
{
DEBUG(0, ("ERROR smb_shm_register_process : processreg_file \
open failed with code %s\n",strerror(errno)));
return False;
}
*other_processes = False;
while ((nb_read = read(smb_shm_processes_fd, &other_pid, sizeof(other_pid))) > 0)
{
if(other_pid)
{
if(process_exists(other_pid))
*other_processes = True;
else
{
/* erase old pid */
DEBUG(5,("smb_shm_register_process : erasing stale record \
for pid %d (seek_back = %.0f)\n", (int)other_pid, (double)seek_back));
other_pid = (pid_t)0;
if((erased_slot = sys_lseek(smb_shm_processes_fd,
seek_back, SEEK_CUR)) == -1)
{
DEBUG(0, ("ERROR smb_shm_register_process : sys_lseek failed \
with error %s\n", strerror(errno)));
close(smb_shm_processes_fd);
return False;
}
if(write(smb_shm_processes_fd, &other_pid, sizeof(other_pid)) == -1)
{
DEBUG(0, ("ERROR smb_shm_register_process : write failed \
with error %s\n", strerror(errno)));
close(smb_shm_processes_fd);
return False;
}
if(free_slot < 0)
free_slot = erased_slot;
}
}
else
{
if(free_slot < 0)
{
if((free_slot = sys_lseek(smb_shm_processes_fd,
seek_back, SEEK_CUR))==-1)
{
DEBUG(0, ("ERROR smb_shm_register_process : sys_lseek \
failed with error %s\n", strerror(errno)));
close(smb_shm_processes_fd);
return False;
}
} /* end if free_slot */
} /* end else */
} /* end if other_pid */
if (nb_read < 0)
{
DEBUG(0,("ERROR smb_shm_register_process : processreg_file read \
failed with code %s\n",strerror(errno)));
close(smb_shm_processes_fd);
return False;
}
if(free_slot < 0)
{
if((free_slot = sys_lseek(smb_shm_processes_fd, 0, SEEK_END)) == -1)
{
DEBUG(0,("ERROR smb_shm_register_process : sys_lseek failed with code %s\n",strerror(errno)));
close(smb_shm_processes_fd);
return False;
}
}
DEBUG(5,("smb_shm_register_process : writing record for pid %d at offset %.0f\n",
(int)pid, (double)free_slot));
if(sys_lseek(smb_shm_processes_fd, free_slot, SEEK_SET) == -1)
{
DEBUG(0,("ERROR smb_shm_register_process : sys_lseek failed with code %s\n",strerror(errno)));
close(smb_shm_processes_fd);
return False;
}
if(write(smb_shm_processes_fd, &pid, sizeof(pid)) == -1)
{
DEBUG(0,("ERROR smb_shm_register_process : processreg_file write failed with code %s\n",strerror(errno)));
close(smb_shm_processes_fd);
return False;
}
close(smb_shm_processes_fd);
return True;
}
static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid)
{
int smb_shm_processes_fd = -1;
int nb_read;
pid_t other_pid;
SMB_OFF_T seek_back = -((SMB_OFF_T)sizeof(other_pid));
BOOL found = False;
smb_shm_processes_fd = sys_open(processreg_file, O_RDWR, 0);
if ( smb_shm_processes_fd < 0 )
{
DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file open failed with code %s\n",strerror(errno)));
return False;
}
while ((nb_read = read(smb_shm_processes_fd, &other_pid, sizeof(other_pid))) > 0)
{
DEBUG(5,("smb_shm_unregister_process : read record for pid %d\n",(int)other_pid));
if(other_pid == pid)
{
/* erase pid */
DEBUG(5,("smb_shm_unregister_process : erasing record for pid %d (seek_val = %.0f)\n",
(int)other_pid, (double)seek_back));
other_pid = (pid_t)0;
if(sys_lseek(smb_shm_processes_fd, seek_back, SEEK_CUR) == -1)
{
DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file sys_lseek failed with code %s\n",strerror(errno)));
close(smb_shm_processes_fd);
return False;
}
if(write(smb_shm_processes_fd, &other_pid, sizeof(other_pid)) < 0)
{
DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file write failed with code %s\n",strerror(errno)));
close(smb_shm_processes_fd);
return False;
}
found = True;
break;
}
}
if (nb_read < 0)
{
DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file read failed with code %s\n",strerror(errno)));
close(smb_shm_processes_fd);
return False;
}
if(!found)
{
DEBUG(0,("ERROR smb_shm_unregister_process : couldn't find pid %d in file %s\n",
(int)pid,processreg_file));
close(smb_shm_processes_fd);
return False;
}
close(smb_shm_processes_fd);
return True;
}
static BOOL smb_shm_validate_header(int size)
{
if( !smb_shm_header_p )
{
/* not mapped yet */
DEBUG(0,("ERROR smb_shm_validate_header : shmem not mapped\n"));
return False;
}
if(smb_shm_header_p->smb_shm_magic != SMB_SHM_MAGIC)
{
DEBUG(0,("ERROR smb_shm_validate_header : bad magic\n"));
return False;
}
if(smb_shm_header_p->smb_shm_version != SMB_SHM_VERSION)
{
DEBUG(0,("ERROR smb_shm_validate_header : bad version %X\n",smb_shm_header_p->smb_shm_version));
return False;
}
if(smb_shm_header_p->total_size != size)
{
DEBUG(0,("ERROR smb_shm_validate_header : shmem size mismatch (old = %d, new = %d)\n",smb_shm_header_p->total_size,size));
return False;
}
if(!smb_shm_header_p->consistent)
{
DEBUG(0,("ERROR smb_shm_validate_header : shmem not consistent\n"));
return False;
}
return True;
}
static BOOL smb_shm_initialize(int size)
{
struct SmbShmBlockDesc * first_free_block_p;
DEBUG(5,("smb_shm_initialize : initializing shmem file of size %d\n",size));
if( !smb_shm_header_p )
{
/* not mapped yet */
DEBUG(0,("ERROR smb_shm_initialize : shmem not mapped\n"));
return False;
}
smb_shm_header_p->smb_shm_magic = SMB_SHM_MAGIC;
smb_shm_header_p->smb_shm_version = SMB_SHM_VERSION;
smb_shm_header_p->total_size = size;
smb_shm_header_p->first_free_off = AlignedHeaderSize;
smb_shm_header_p->userdef_off = 0;
first_free_block_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(smb_shm_header_p->first_free_off);
first_free_block_p->next = EOList_Off;
first_free_block_p->size = ( size - AlignedHeaderSize - CellSize ) / CellSize ;
smb_shm_header_p->statistics.cells_free = first_free_block_p->size;
smb_shm_header_p->statistics.cells_used = 0;
smb_shm_header_p->statistics.cells_system = 1;
smb_shm_header_p->consistent = True;
smb_shm_initialize_called = True;
return True;
}
static void smb_shm_solve_neighbors(struct SmbShmBlockDesc *head_p )
{
struct SmbShmBlockDesc *next_p;
/* Check if head_p and head_p->next are neighbors and if so join them */
if ( head_p == EOList_Addr ) return ;
if ( head_p->next == EOList_Off ) return ;
next_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(head_p->next);
if ( ( head_p + head_p->size + 1 ) == next_p)
{
head_p->size += next_p->size +1 ; /* adapt size */
head_p->next = next_p->next ; /* link out */
smb_shm_header_p->statistics.cells_free += 1;
smb_shm_header_p->statistics.cells_system -= 1;
}
}
static BOOL smb_shm_close( void )
{
if(smb_shm_initialize_called == False)
return True;
DEBUG(5,("smb_shm_close\n"));
if(smb_shm_times_locked > 0)
DEBUG(0,("WARNING smb_shm_close : shmem was still locked %d times\n",smb_shm_times_locked));;
if ((smb_shm_header_p != NULL) &&
(munmap((caddr_t)smb_shm_header_p, smb_shm_header_p->total_size) < 0))
{
DEBUG(0,("ERROR smb_shm_close : munmap failed with code %s\n",strerror(errno)));
}
smb_shm_global_lock();
DEBUG(5,("calling smb_shm_unregister_process(%s, %d)\n",
smb_shm_processreg_name, (int)getpid()));
smb_shm_unregister_process(smb_shm_processreg_name, getpid());
smb_shm_global_unlock();
close(smb_shm_fd);
smb_shm_fd = -1;
smb_shm_processreg_name[0] = '\0';
smb_shm_header_p = (struct SmbShmHeader *)0;
smb_shm_times_locked = 0;
return True;
}
static BOOL smb_shm_free(int offset)
{
struct SmbShmBlockDesc *header_p ; /* pointer to header of block to free */
struct SmbShmBlockDesc *scanner_p ; /* used to scan the list */
struct SmbShmBlockDesc *prev_p ; /* holds previous in the list */
if( !smb_shm_header_p )
{
/* not mapped yet */
DEBUG(0,("ERROR smb_shm_free : shmem not mapped\n"));
return False;
}
smb_shm_global_lock();
if( !smb_shm_header_p->consistent)
{
DEBUG(0,("ERROR smb_shm_free : shmem not consistent\n"));
smb_shm_global_unlock();
return False;
}
header_p = ( (struct SmbShmBlockDesc *)smb_shm_offset2addr(offset) - 1); /* make pointer to header of block */
if (header_p->next != SMB_SHM_NOT_FREE_OFF)
{
DEBUG(0,("ERROR smb_shm_free : bad offset (%d)\n",offset));
smb_shm_global_unlock();
return False;
}
/* find a place in the free_list to put the header in */
/* set scanner and previous pointer to start of list */
prev_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(smb_shm_header_p->first_free_off);
scanner_p = prev_p ;
while ( ( scanner_p != EOList_Addr) && (scanner_p < header_p) ) /* while we didn't scan past its position */
{
prev_p = scanner_p ;
scanner_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(scanner_p->next);
}
smb_shm_header_p->consistent = False;
DEBUG(6,("smb_shm_free : freeing %d bytes at offset %d\n",header_p->size*CellSize,offset));
/* zero the area being freed - this allows us to find bugs faster */
memset(smb_shm_offset2addr(offset), 0, header_p->size*CellSize);
if ( scanner_p == prev_p )
{
smb_shm_header_p->statistics.cells_free += header_p->size;
smb_shm_header_p->statistics.cells_used -= header_p->size;
/* we must free it at the beginning of the list */
smb_shm_header_p->first_free_off = smb_shm_addr2offset(header_p); /* set the free_list_pointer to this block_header */
/* scanner is the one that was first in the list */
header_p->next = smb_shm_addr2offset(scanner_p);
smb_shm_solve_neighbors( header_p ); /* if neighbors then link them */
smb_shm_header_p->consistent = True;
smb_shm_global_unlock();
return True;
}
else
{
smb_shm_header_p->statistics.cells_free += header_p->size;
smb_shm_header_p->statistics.cells_used -= header_p->size;
prev_p->next = smb_shm_addr2offset(header_p);
header_p->next = smb_shm_addr2offset(scanner_p);
smb_shm_solve_neighbors(header_p) ;
smb_shm_solve_neighbors(prev_p) ;
smb_shm_header_p->consistent = True;
smb_shm_global_unlock();
return True;
}
}
static int smb_shm_get_userdef_off(void)
{
if (!smb_shm_header_p)
return 0;
else
return smb_shm_header_p->userdef_off;
}
/*******************************************************************
Lock a particular hash bucket entry.
******************************************************************/
static BOOL smb_shm_lock_hash_entry( unsigned int entry)
{
int start = (smb_shm_header_p->userdef_off + (entry * sizeof(int)));
if (smb_shm_fd < 0)
{
DEBUG(0,("ERROR smb_shm_lock_hash_entry : bad smb_shm_fd (%d)\n",smb_shm_fd));
return False;
}
if (read_only)
return True;
/* Do an exclusive wait lock on the 4 byte region mapping into this entry */
if (fcntl_lock(smb_shm_fd, SMB_F_SETLKW, start, sizeof(int), F_WRLCK) == False)
{
DEBUG(0,("ERROR smb_shm_lock_hash_entry : fcntl_lock failed with code %s\n",strerror(errno)));
return False;
}
DEBUG(9,("smb_shm_lock_hash_entry: locked hash bucket %d\n", entry));
return True;
}
/*******************************************************************
Unlock a particular hash bucket entry.
******************************************************************/
static BOOL smb_shm_unlock_hash_entry( unsigned int entry )
{
int start = (smb_shm_header_p->userdef_off + (entry * sizeof(int)));
if (smb_shm_fd < 0)
{
DEBUG(0,("ERROR smb_shm_unlock_hash_entry : bad smb_shm_fd (%d)\n",smb_shm_fd));
return False;
}
if (read_only)
return True;
/* Do a wait lock on the 4 byte region mapping into this entry */
if (fcntl_lock(smb_shm_fd, SMB_F_SETLKW, start, sizeof(int), F_UNLCK) == False)
{
DEBUG(0,("ERROR smb_shm_unlock_hash_entry : fcntl_lock failed with code %s\n",strerror(errno)));
return False;
}
DEBUG(9,("smb_shm_unlock_hash_entry: unlocked hash bucket %d\n", entry));
return True;
}
/*******************************************************************
Gather statistics on shared memory usage.
******************************************************************/
static BOOL smb_shm_get_usage(int *bytes_free,
int *bytes_used,
int *bytes_overhead)
{
if( !smb_shm_header_p )
{
/* not mapped yet */
DEBUG(0,("ERROR smb_shm_free : shmem not mapped\n"));
return False;
}
*bytes_free = smb_shm_header_p->statistics.cells_free * CellSize;
*bytes_used = smb_shm_header_p->statistics.cells_used * CellSize;
*bytes_overhead = smb_shm_header_p->statistics.cells_system * CellSize + AlignedHeaderSize;
return True;
}
/*******************************************************************
hash a number into a hash_entry
******************************************************************/
static unsigned smb_shm_hash_size(void)
{
return SHMEM_HASH_SIZE;
}
static struct shmem_ops shmops = {
smb_shm_close,
smb_shm_alloc,
smb_shm_free,
smb_shm_get_userdef_off,
smb_shm_offset2addr,
smb_shm_addr2offset,
smb_shm_lock_hash_entry,
smb_shm_unlock_hash_entry,
smb_shm_get_usage,
smb_shm_hash_size,
};
/*******************************************************************
open the shared memory
******************************************************************/
struct shmem_ops *smb_shm_open(int ronly)
{
pstring file_name;
SMB_OFF_T filesize;
BOOL created_new = False;
BOOL other_processes = True;
SMB_OFF_T size = (SMB_OFF_T)lp_shmem_size();
read_only = ronly;
pstrcpy(file_name,lp_lockdir());
if (!directory_exist(file_name,NULL)) {
if (read_only)
return NULL;
mkdir(file_name,0755);
}
trim_string(file_name,"","/");
if (!*file_name)
return(False);
pstrcat(file_name, "/SHARE_MEM_FILE");
DEBUG(5,("smb_shm_open : using shmem file %s to be of size %.0f\n",
file_name,(double)size));
smb_shm_fd = sys_open(file_name, read_only?O_RDONLY:(O_RDWR|O_CREAT),
SHM_FILE_MODE);
if ( smb_shm_fd < 0 )
{
DEBUG(0,("ERROR smb_shm_open : open failed with code %s\n",strerror(errno)));
return NULL;
}
if (!smb_shm_global_lock())
{
DEBUG(0,("ERROR smb_shm_open : can't do smb_shm_global_lock\n"));
return NULL;
}
if( (filesize = sys_lseek(smb_shm_fd, 0, SEEK_END)) == -1)
{
DEBUG(0,("ERROR smb_shm_open : sys_lseek failed with code %s\n",
strerror(errno)));
smb_shm_global_unlock();
close(smb_shm_fd);
return NULL;
}
/*
* Return the file offset to 0 to save on later seeks.
*/
if(sys_lseek(smb_shm_fd,0,SEEK_SET) == -1)
{
DEBUG(0,("ERROR smb_shm_open : sys_lseek failed with code %s\n",
strerror(errno)));
smb_shm_global_unlock();
close(smb_shm_fd);
return NULL;
}
if (filesize == 0)
{
/*
* We just created a new one.
*/
created_new = True;
}
/*
* To find out if some other process is already mapping the file,
* we use a registration file containing the processids of the file
* mapping processes.
*/
/* construct processreg file name */
pstrcpy(smb_shm_processreg_name, file_name);
pstrcat(smb_shm_processreg_name, ".processes");
if (!read_only && !smb_shm_register_process(smb_shm_processreg_name,
getpid(), &other_processes))
{
smb_shm_global_unlock();
close(smb_shm_fd);
return NULL;
}
if (!read_only && (created_new || !other_processes))
{
/* we just created a new one, or are the first opener, lets set it size */
if( sys_ftruncate(smb_shm_fd, size) <0)
{
DEBUG(0,("ERROR smb_shm_open : ftruncate failed with code %s\n",
strerror(errno)));
smb_shm_unregister_process(smb_shm_processreg_name, getpid());
smb_shm_global_unlock();
close(smb_shm_fd);
return NULL;
}
/* paranoia */
if(sys_lseek(smb_shm_fd,0,SEEK_SET) == -1)
{
DEBUG(0,("ERROR smb_shm_open : sys_lseek failed with code %s\n",
strerror(errno)));
smb_shm_unregister_process(smb_shm_processreg_name, getpid());
smb_shm_global_unlock();
close(smb_shm_fd);
return NULL;
}
filesize = size;
}
if (size != filesize )
{
/* the existing file has a different size and we are not the first opener.
Since another process is still using it, we will use the file size */
DEBUG(0,("WARNING smb_shm_open : filesize (%.0f) != expected \
size (%.0f), using filesize\n", (double)filesize, (double)size));
size = filesize;
}
smb_shm_header_p = (struct SmbShmHeader *)sys_mmap(NULL, size,
read_only?PROT_READ: (PROT_READ | PROT_WRITE),
MAP_FILE | MAP_SHARED, smb_shm_fd, (SMB_OFF_T)0);
/*
* WARNING, smb_shm_header_p can be different for different
* processes mapping the same file !
*/
if (smb_shm_header_p == (struct SmbShmHeader *)(-1))
{
DEBUG(0,("ERROR smb_shm_open : mmap failed with code %s\n",strerror(errno)));
smb_shm_unregister_process(smb_shm_processreg_name, getpid());
smb_shm_global_unlock();
close(smb_shm_fd);
return NULL;
}
if (!read_only && (created_new || !other_processes))
{
smb_shm_initialize(size);
/* Create the hash buckets for the share file entries. */
smb_shm_create_hash_table(SHMEM_HASH_SIZE);
}
else if (!smb_shm_validate_header(size) )
{
/* existing file is corrupt, samba admin should remove it by hand */
DEBUG(0,("ERROR smb_shm_open : corrupt shared mem file, remove it manually\n"));
munmap((caddr_t)smb_shm_header_p, size);
smb_shm_unregister_process(smb_shm_processreg_name, getpid());
smb_shm_global_unlock();
close(smb_shm_fd);
return NULL;
}
smb_shm_global_unlock();
return &shmops;
}
#else /* HAVE_SHARED_MMAP */
int shmem_dummy_procedure(void)
{return 0;}
#endif /* HAVE_SHARED_MMAP */

View File

@@ -1,724 +0,0 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
Shared memory functions - SYSV IPC implementation
Copyright (C) Andrew Tridgell 1997-1998
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.
*/
#include "includes.h"
#ifdef USE_SYSV_IPC
extern int DEBUGLEVEL;
#define SHMEM_KEY ((key_t)0x280267)
#define SEMAPHORE_KEY (SHMEM_KEY+2)
#define SHM_MAGIC 0x53484100
#define SHM_VERSION 2
#ifdef SHM_R
#define IPC_PERMS ((SHM_R | SHM_W) | (SHM_R>>3) | (SHM_R>>6))
#else
#define IPC_PERMS 0644
#endif
#ifdef SECURE_SEMAPHORES
/* secure semaphores are slow because we have to do a become_root()
on every call! */
#define SEMAPHORE_PERMS IPC_PERMS
#else
#define SEMAPHORE_PERMS 0666
#endif
#define SHMEM_HASH_SIZE 13
#define MIN_SHM_SIZE 0x1000
static int shm_id;
static int sem_id;
static int shm_size;
static int hash_size;
static int global_lock_count;
struct ShmHeader {
int shm_magic;
int shm_version;
int total_size; /* in bytes */
BOOL consistent;
int first_free_off;
int userdef_off; /* a userdefined offset. can be used to store
root of tree or list */
struct { /* a cell is a range of bytes of sizeof(struct
ShmBlockDesc) size */
int cells_free;
int cells_used;
int cells_system; /* number of cells used as allocated
block descriptors */
} statistics;
};
#define SHM_NOT_FREE_OFF (-1)
struct ShmBlockDesc
{
int next; /* offset of next block in the free list or
SHM_NOT_FREE_OFF when block in use */
int size; /* user size in BlockDescSize units */
};
#define EOList_Addr NULL
#define EOList_Off (0)
#define CellSize sizeof(struct ShmBlockDesc)
/* HeaderSize aligned on a 8 byte boundary */
#define AlignedHeaderSize ((sizeof(struct ShmHeader)+7) & ~7)
static struct ShmHeader *shm_header_p = NULL;
static int read_only;
static BOOL sem_change(int i, int op)
{
#ifdef SECURE_SEMAPHORES
extern struct current_user current_user;
int became_root=0;
#endif
struct sembuf sb;
int ret;
if (read_only) return True;
#ifdef SECURE_SEMAPHORES
if (current_user.uid != 0) {
become_root(0);
became_root = 1;
}
#endif
sb.sem_num = i;
sb.sem_op = op;
sb.sem_flg = 0;
ret = semop(sem_id, &sb, 1);
if (ret != 0) {
DEBUG(0,("ERROR: sem_change(%d,%d) failed (%s)\n",
i, op, strerror(errno)));
}
#ifdef SECURE_SEMAPHORES
if (became_root) {
unbecome_root(0);
}
#endif
return ret == 0;
}
static BOOL global_lock(void)
{
global_lock_count++;
if (global_lock_count == 1)
return sem_change(0, -1);
return True;
}
static BOOL global_unlock(void)
{
global_lock_count--;
if (global_lock_count == 0)
return sem_change(0, 1);
return True;
}
static void *shm_offset2addr(int offset)
{
if (offset == 0 )
return (void *)(0);
if (!shm_header_p)
return (void *)(0);
return (void *)((char *)shm_header_p + offset);
}
static int shm_addr2offset(void *addr)
{
if (!addr)
return 0;
if (!shm_header_p)
return 0;
return (int)((char *)addr - (char *)shm_header_p);
}
static int shm_alloc(int size)
{
unsigned num_cells ;
struct ShmBlockDesc *scanner_p;
struct ShmBlockDesc *prev_p;
struct ShmBlockDesc *new_p;
int result_offset;
if (!shm_header_p) {
/* not mapped yet */
DEBUG(0,("ERROR shm_alloc : shmem not mapped\n"));
return 0;
}
global_lock();
if (!shm_header_p->consistent) {
DEBUG(0,("ERROR shm_alloc : shmem not consistent\n"));
global_unlock();
return 0;
}
/* calculate the number of cells */
num_cells = (size + (CellSize-1)) / CellSize;
/* set start of scan */
prev_p = (struct ShmBlockDesc *)shm_offset2addr(shm_header_p->first_free_off);
scanner_p = prev_p ;
/* scan the free list to find a matching free space */
while ((scanner_p != EOList_Addr) && (scanner_p->size < num_cells)) {
prev_p = scanner_p;
scanner_p = (struct ShmBlockDesc *)shm_offset2addr(scanner_p->next);
}
/* at this point scanner point to a block header or to the end of
the list */
if (scanner_p == EOList_Addr) {
DEBUG(0,("ERROR shm_alloc : alloc of %d bytes failed\n",size));
global_unlock();
return (0);
}
/* going to modify shared mem */
shm_header_p->consistent = False;
/* if we found a good one : scanner == the good one */
if (scanner_p->size > num_cells + 2) {
/* Make a new one */
new_p = scanner_p + 1 + num_cells;
new_p->size = scanner_p->size - (num_cells + 1);
new_p->next = scanner_p->next;
scanner_p->size = num_cells;
scanner_p->next = shm_addr2offset(new_p);
shm_header_p->statistics.cells_free -= 1;
shm_header_p->statistics.cells_system += 1;
}
/* take it from the free list */
if (prev_p == scanner_p) {
shm_header_p->first_free_off = scanner_p->next;
} else {
prev_p->next = scanner_p->next;
}
shm_header_p->statistics.cells_free -= scanner_p->size;
shm_header_p->statistics.cells_used += scanner_p->size;
result_offset = shm_addr2offset(&(scanner_p[1]));
scanner_p->next = SHM_NOT_FREE_OFF;
/* end modification of shared mem */
shm_header_p->consistent = True;
global_unlock();
DEBUG(6,("shm_alloc : allocated %d bytes at offset %d\n",
size,result_offset));
return result_offset;
}
static void shm_solve_neighbors(struct ShmBlockDesc *head_p )
{
struct ShmBlockDesc *next_p;
/* Check if head_p and head_p->next are neighbors and if so
join them */
if ( head_p == EOList_Addr ) return ;
if ( head_p->next == EOList_Off ) return ;
next_p = (struct ShmBlockDesc *)shm_offset2addr(head_p->next);
if ((head_p + head_p->size + 1) == next_p) {
head_p->size += next_p->size + 1; /* adapt size */
head_p->next = next_p->next; /* link out */
shm_header_p->statistics.cells_free += 1;
shm_header_p->statistics.cells_system -= 1;
}
}
static BOOL shm_free(int offset)
{
struct ShmBlockDesc *header_p; /* pointer to header of
block to free */
struct ShmBlockDesc *scanner_p; /* used to scan the list */
struct ShmBlockDesc *prev_p; /* holds previous in the
list */
if (!shm_header_p) {
/* not mapped yet */
DEBUG(0,("ERROR shm_free : shmem not mapped\n"));
return False;
}
global_lock();
if (!shm_header_p->consistent) {
DEBUG(0,("ERROR shm_free : shmem not consistent\n"));
global_unlock();
return False;
}
/* make pointer to header of block */
header_p = ((struct ShmBlockDesc *)shm_offset2addr(offset) - 1);
if (header_p->next != SHM_NOT_FREE_OFF) {
DEBUG(0,("ERROR shm_free : bad offset (%d)\n",offset));
global_unlock();
return False;
}
/* find a place in the free_list to put the header in */
/* set scanner and previous pointer to start of list */
prev_p = (struct ShmBlockDesc *)
shm_offset2addr(shm_header_p->first_free_off);
scanner_p = prev_p ;
while ((scanner_p != EOList_Addr) &&
(scanner_p < header_p)) {
/* while we didn't scan past its position */
prev_p = scanner_p ;
scanner_p = (struct ShmBlockDesc *)
shm_offset2addr(scanner_p->next);
}
shm_header_p->consistent = False;
DEBUG(6,("shm_free : freeing %d bytes at offset %d\n",
(int)(header_p->size*CellSize),(int)offset));
/* zero the area being freed - this allows us to find bugs faster */
memset(shm_offset2addr(offset), 0, header_p->size*CellSize);
if (scanner_p == prev_p) {
shm_header_p->statistics.cells_free += header_p->size;
shm_header_p->statistics.cells_used -= header_p->size;
/* we must free it at the beginning of the list */
shm_header_p->first_free_off = shm_addr2offset(header_p);
/* set the free_list_pointer to this block_header */
/* scanner is the one that was first in the list */
header_p->next = shm_addr2offset(scanner_p);
shm_solve_neighbors(header_p);
shm_header_p->consistent = True;
} else {
shm_header_p->statistics.cells_free += header_p->size;
shm_header_p->statistics.cells_used -= header_p->size;
prev_p->next = shm_addr2offset(header_p);
header_p->next = shm_addr2offset(scanner_p);
shm_solve_neighbors(header_p) ;
shm_solve_neighbors(prev_p) ;
shm_header_p->consistent = True;
}
global_unlock();
return True;
}
/*
* Function to create the hash table for the share mode entries. Called
* when smb shared memory is global locked.
*/
static BOOL shm_create_hash_table(unsigned int hash_entries)
{
int size = hash_entries * sizeof(int);
global_lock();
shm_header_p->userdef_off = shm_alloc(size);
if(shm_header_p->userdef_off == 0) {
DEBUG(0,("shm_create_hash_table: Failed to create hash table of size %d\n",
size));
global_unlock();
return False;
}
/* Clear hash buckets. */
memset(shm_offset2addr(shm_header_p->userdef_off), '\0', size);
global_unlock();
return True;
}
static BOOL shm_validate_header(int size)
{
if(!shm_header_p) {
/* not mapped yet */
DEBUG(0,("ERROR shm_validate_header : shmem not mapped\n"));
return False;
}
if(shm_header_p->shm_magic != SHM_MAGIC) {
DEBUG(0,("ERROR shm_validate_header : bad magic\n"));
return False;
}
if(shm_header_p->shm_version != SHM_VERSION) {
DEBUG(0,("ERROR shm_validate_header : bad version %X\n",
shm_header_p->shm_version));
return False;
}
if(shm_header_p->total_size != size) {
DEBUG(0,("ERROR shmem size mismatch (old = %d, new = %d)\n",
shm_header_p->total_size,size));
return False;
}
if(!shm_header_p->consistent) {
DEBUG(0,("ERROR shmem not consistent\n"));
return False;
}
return True;
}
static BOOL shm_initialize(int size)
{
struct ShmBlockDesc * first_free_block_p;
DEBUG(5,("shm_initialize : initializing shmem size %d\n",size));
if( !shm_header_p ) {
/* not mapped yet */
DEBUG(0,("ERROR shm_initialize : shmem not mapped\n"));
return False;
}
shm_header_p->shm_magic = SHM_MAGIC;
shm_header_p->shm_version = SHM_VERSION;
shm_header_p->total_size = size;
shm_header_p->first_free_off = AlignedHeaderSize;
shm_header_p->userdef_off = 0;
first_free_block_p = (struct ShmBlockDesc *)
shm_offset2addr(shm_header_p->first_free_off);
first_free_block_p->next = EOList_Off;
first_free_block_p->size =
(size - (AlignedHeaderSize+CellSize))/CellSize;
shm_header_p->statistics.cells_free = first_free_block_p->size;
shm_header_p->statistics.cells_used = 0;
shm_header_p->statistics.cells_system = 1;
shm_header_p->consistent = True;
return True;
}
static BOOL shm_close( void )
{
return True;
}
static int shm_get_userdef_off(void)
{
if (!shm_header_p)
return 0;
else
return shm_header_p->userdef_off;
}
/*******************************************************************
Lock a particular hash bucket entry.
******************************************************************/
static BOOL shm_lock_hash_entry(unsigned int entry)
{
return sem_change(entry+1, -1);
}
/*******************************************************************
Unlock a particular hash bucket entry.
******************************************************************/
static BOOL shm_unlock_hash_entry(unsigned int entry)
{
return sem_change(entry+1, 1);
}
/*******************************************************************
Gather statistics on shared memory usage.
******************************************************************/
static BOOL shm_get_usage(int *bytes_free,
int *bytes_used,
int *bytes_overhead)
{
if(!shm_header_p) {
/* not mapped yet */
DEBUG(0,("ERROR shm_free : shmem not mapped\n"));
return False;
}
*bytes_free = shm_header_p->statistics.cells_free * CellSize;
*bytes_used = shm_header_p->statistics.cells_used * CellSize;
*bytes_overhead = shm_header_p->statistics.cells_system * CellSize +
AlignedHeaderSize;
return True;
}
/*******************************************************************
hash a number into a hash_entry
******************************************************************/
static unsigned shm_hash_size(void)
{
return hash_size;
}
static struct shmem_ops shmops = {
shm_close,
shm_alloc,
shm_free,
shm_get_userdef_off,
shm_offset2addr,
shm_addr2offset,
shm_lock_hash_entry,
shm_unlock_hash_entry,
shm_get_usage,
shm_hash_size,
};
/*******************************************************************
open the shared memory
******************************************************************/
struct shmem_ops *sysv_shm_open(int ronly)
{
BOOL other_processes;
struct shmid_ds shm_ds;
struct semid_ds sem_ds;
union semun su;
int i;
pid_t pid;
struct passwd *root_pwd = sys_getpwuid((uid_t)0);
gid_t root_gid = root_pwd ? root_pwd->pw_gid : (gid_t)0;
read_only = ronly;
shm_size = lp_shmem_size();
DEBUG(4,("Trying sysv shmem open of size %d\n", shm_size));
/* first the semaphore */
sem_id = semget(SEMAPHORE_KEY, 0, 0);
if (sem_id == -1) {
if (read_only) return NULL;
hash_size = SHMEM_HASH_SIZE;
while (hash_size > 1) {
sem_id = semget(SEMAPHORE_KEY, hash_size+1,
IPC_CREAT|IPC_EXCL| SEMAPHORE_PERMS);
if (sem_id != -1 ||
(errno != EINVAL && errno != ENOSPC)) break;
hash_size -= 5;
}
if (sem_id == -1) {
DEBUG(0,("Can't create or use semaphore [1]. Error was %s\n",
strerror(errno)));
return NULL;
}
if (sem_id != -1) {
su.val = 1;
for (i=0;i<hash_size+1;i++) {
if (semctl(sem_id, i, SETVAL, su) != 0) {
DEBUG(1,("Failed to init semaphore %d. Error was %s\n",
i, strerror(errno)));
return NULL;
}
}
}
}
if (shm_id == -1) {
sem_id = semget(SEMAPHORE_KEY, 0, 0);
}
if (sem_id == -1) {
DEBUG(0,("Can't create or use semaphore [2]. Error was %s\n",
strerror(errno)));
return NULL;
}
su.buf = &sem_ds;
if (semctl(sem_id, 0, IPC_STAT, su) != 0) {
DEBUG(0,("ERROR semctl: can't IPC_STAT. Error was %s\n",
strerror(errno)));
return NULL;
}
hash_size = sem_ds.sem_nsems-1;
if (!read_only) {
if (sem_ds.sem_perm.cuid != 0 || ((sem_ds.sem_perm.cgid != root_gid) && (sem_ds.sem_perm.cgid != 0))) {
DEBUG(0,("ERROR: root did not create the semaphore: semgid=%u, rootgid=%u\n",
(unsigned int)sem_ds.sem_perm.cgid, (unsigned int)root_gid));
return NULL;
}
if (semctl(sem_id, 0, GETVAL, su) == 0 &&
!process_exists((pid=(pid_t)semctl(sem_id, 0, GETPID, su)))) {
DEBUG(0,("WARNING: clearing global IPC lock set by dead process %d\n",
(int)pid));
su.val = 1;
if (semctl(sem_id, 0, SETVAL, su) != 0) {
DEBUG(0,("ERROR: Failed to clear global lock. Error was %s\n",
strerror(errno)));
return NULL;
}
}
sem_ds.sem_perm.mode = SEMAPHORE_PERMS;
if (semctl(sem_id, 0, IPC_SET, su) != 0) {
DEBUG(0,("ERROR shmctl : can't IPC_SET. Error was %s\n",
strerror(errno)));
return NULL;
}
}
if (!global_lock())
return NULL;
for (i=1;i<hash_size+1;i++) {
if (semctl(sem_id, i, GETVAL, su) == 0 &&
!process_exists((pid=(pid_t)semctl(sem_id, i, GETPID, su)))) {
DEBUG(1,("WARNING: clearing IPC lock %d set by dead process %d\n",
i, (int)pid));
su.val = 1;
if (semctl(sem_id, i, SETVAL, su) != 0) {
DEBUG(0,("ERROR: Failed to clear IPC lock %d. Error was %s\n",
i, strerror(errno)));
global_unlock();
return NULL;
}
}
}
/*
* Try to use an existing key. Note that
* in order to use an existing key successfully
* size must be zero else shmget returns EINVAL.
* Thanks to Veselin Terzic <vterzic@systems.DHL.COM>
* for pointing this out.
*/
shm_id = shmget(SHMEM_KEY, 0, 0);
/* if that failed then create one */
if (shm_id == -1) {
if (read_only) return NULL;
while (shm_size > MIN_SHM_SIZE) {
shm_id = shmget(SHMEM_KEY, shm_size,
IPC_CREAT | IPC_EXCL | IPC_PERMS);
if (shm_id != -1 ||
(errno != EINVAL && errno != ENOSPC)) break;
shm_size *= 0.8;
}
}
if (shm_id == -1) {
DEBUG(0,("Can't create or use IPC area. Error was %s\n", strerror(errno)));
global_unlock();
return NULL;
}
shm_header_p = (struct ShmHeader *)shmat(shm_id, 0,
read_only?SHM_RDONLY:0);
if ((long)shm_header_p == -1) {
DEBUG(0,("Can't attach to IPC area. Error was %s\n", strerror(errno)));
global_unlock();
return NULL;
}
/* to find out if some other process is already mapping the file,
we use a registration file containing the processids of the file
mapping processes */
if (shmctl(shm_id, IPC_STAT, &shm_ds) != 0) {
DEBUG(0,("ERROR shmctl : can't IPC_STAT. Error was %s\n", strerror(errno)));
global_unlock();
return NULL;
}
if (!read_only) {
if (shm_ds.shm_perm.cuid != 0 || ((shm_ds.shm_perm.cgid != root_gid) && (shm_ds.shm_perm.cgid != 0))) {
DEBUG(0,("ERROR: root did not create the shmem\n"));
global_unlock();
return NULL;
}
}
shm_size = shm_ds.shm_segsz;
other_processes = (shm_ds.shm_nattch > 1);
if (!read_only && !other_processes) {
memset((char *)shm_header_p, 0, shm_size);
shm_initialize(shm_size);
shm_create_hash_table(hash_size);
DEBUG(3,("Initialised IPC area of size %d\n", shm_size));
} else if (!shm_validate_header(shm_size)) {
/* existing file is corrupt, samba admin should remove
it by hand */
DEBUG(0,("ERROR shm_open : corrupt IPC area - remove it!\n"));
global_unlock();
return NULL;
}
global_unlock();
return &shmops;
}
#else
int ipc_dummy_procedure(void)
{return 0;}
#endif

View File

@@ -628,7 +628,7 @@ BOOL change_trust_account_password( char *domain, char *remote_machine_list)
unsigned char old_trust_passwd_hash[16]; unsigned char old_trust_passwd_hash[16];
unsigned char new_trust_passwd_hash[16]; unsigned char new_trust_passwd_hash[16];
time_t lct; time_t lct;
BOOL res; BOOL res = False;
if(!get_trust_account_password( old_trust_passwd_hash, &lct)) { if(!get_trust_account_password( old_trust_passwd_hash, &lct)) {
DEBUG(0,("change_trust_account_password: unable to read the machine \ DEBUG(0,("change_trust_account_password: unable to read the machine \

View File

@@ -94,7 +94,6 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close)
{ {
SMB_DEV_T dev = fsp->fd_ptr->dev; SMB_DEV_T dev = fsp->fd_ptr->dev;
SMB_INO_T inode = fsp->fd_ptr->inode; SMB_INO_T inode = fsp->fd_ptr->inode;
int token;
BOOL last_reference = False; BOOL last_reference = False;
BOOL delete_on_close = fsp->fd_ptr->delete_on_close; BOOL delete_on_close = fsp->fd_ptr->delete_on_close;
connection_struct *conn = fsp->conn; connection_struct *conn = fsp->conn;
@@ -109,8 +108,8 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close)
#endif #endif
if (lp_share_modes(SNUM(conn))) { if (lp_share_modes(SNUM(conn))) {
lock_share_entry(conn, dev, inode, &token); lock_share_entry(conn, dev, inode);
del_share_mode(token, fsp); del_share_mode(fsp);
} }
if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
@@ -122,7 +121,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close)
fsp->fd_ptr = NULL; fsp->fd_ptr = NULL;
if (lp_share_modes(SNUM(conn))) if (lp_share_modes(SNUM(conn)))
unlock_share_entry(conn, dev, inode, token); unlock_share_entry(conn, dev, inode);
/* NT uses smbclose to start a print - weird */ /* NT uses smbclose to start a print - weird */
if (normal_close && fsp->print_file) if (normal_close && fsp->print_file)

View File

@@ -26,27 +26,6 @@ extern fstring remote_machine;
extern int DEBUGLEVEL; extern int DEBUGLEVEL;
/****************************************************************************
open the connections database
****************************************************************************/
TDB_CONTEXT *open_db(char *name)
{
pstring fname;
pstrcpy(fname,lp_lockdir());
trim_string(fname,"","/");
if (!directory_exist(fname,NULL)) {
mkdir(fname,0755);
}
pstrcat(fname,"/connections.tdb");
return tdb_open(fname, 0, O_RDWR | O_CREAT, 0644);
}
/**************************************************************************** /****************************************************************************
delete a connection record delete a connection record
****************************************************************************/ ****************************************************************************/
@@ -56,7 +35,8 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections)
TDB_DATA kbuf; TDB_DATA kbuf;
TDB_CONTEXT *tdb; TDB_CONTEXT *tdb;
if (!(tdb = open_db(name))) return False; tdb = tdb_open(lock_path("connections.tdb"), 0, O_RDWR | O_CREAT, 0644);
if (!tdb) return False;
DEBUG(3,("Yielding connection to %s\n",name)); DEBUG(3,("Yielding connection to %s\n",name));
@@ -100,7 +80,8 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO
if (max_connections <= 0) if (max_connections <= 0)
return(True); return(True);
if (!(tdb = open_db(name))) return False; tdb = tdb_open(lock_path("connections.tdb"), 0, O_RDWR | O_CREAT, 0644);
if (!tdb) return False;
DEBUG(5,("claiming %s %d\n",name,max_connections)); DEBUG(5,("claiming %s %d\n",name,max_connections));

View File

@@ -213,11 +213,11 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n)
int num_share_modes = 0; int num_share_modes = 0;
int i; int i;
if (lock_share_entry(fsp->conn, dev, inode, &token) == False) { if (lock_share_entry(fsp->conn, dev, inode) == False) {
DEBUG(0,("write_file: failed to lock share mode entry for file %s.\n", fsp->fsp_name )); DEBUG(0,("write_file: failed to lock share mode entry for file %s.\n", fsp->fsp_name ));
} }
num_share_modes = get_share_modes(fsp->conn, token, dev, inode, &share_list); num_share_modes = get_share_modes(fsp->conn, dev, inode, &share_list);
for(i = 0; i < num_share_modes; i++) { for(i = 0; i < num_share_modes; i++) {
share_mode_entry *share_entry = &share_list[i]; share_mode_entry *share_entry = &share_list[i];
@@ -268,7 +268,7 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n)
} }
free((char *)share_list); free((char *)share_list);
unlock_share_entry(fsp->conn, dev, inode, token); unlock_share_entry(fsp->conn, dev, inode);
} }
/* Paranoia check... */ /* Paranoia check... */

View File

@@ -602,7 +602,7 @@ static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, i
have the share entry locked. Unlock it before closing. */ have the share entry locked. Unlock it before closing. */
if (*share_locked && lp_share_modes(SNUM(conn))) if (*share_locked && lp_share_modes(SNUM(conn)))
unlock_share_entry( conn, fsp->fd_ptr->dev, unlock_share_entry( conn, fsp->fd_ptr->dev,
fsp->fd_ptr->inode, token); fsp->fd_ptr->inode);
close_file(fsp,False); close_file(fsp,False);
/* Share mode no longer locked. */ /* Share mode no longer locked. */
*share_locked = False; *share_locked = False;
@@ -858,9 +858,9 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int
{ {
dev = sbuf.st_dev; dev = sbuf.st_dev;
inode = sbuf.st_ino; inode = sbuf.st_ino;
lock_share_entry(conn, dev, inode, &token); lock_share_entry(conn, dev, inode);
share_locked = True; share_locked = True;
num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); num_share_modes = get_share_modes(conn, dev, inode, &old_shares);
} }
/* /*
@@ -896,7 +896,7 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int
dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode)); dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode));
/* Oplock break.... */ /* Oplock break.... */
unlock_share_entry(conn, dev, inode, token); unlock_share_entry(conn, dev, inode);
if(request_oplock_break(share_entry, dev, inode) == False) if(request_oplock_break(share_entry, dev, inode) == False)
{ {
free((char *)old_shares); free((char *)old_shares);
@@ -909,7 +909,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou
unix_ERR_code = ERRbadshare; unix_ERR_code = ERRbadshare;
return; return;
} }
lock_share_entry(conn, dev, inode, &token); lock_share_entry(conn, dev, inode);
broke_oplock = True; broke_oplock = True;
all_current_opens_are_level_II = False; all_current_opens_are_level_II = False;
break; break;
@@ -922,7 +922,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou
if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False) if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False)
{ {
free((char *)old_shares); free((char *)old_shares);
unlock_share_entry(conn, dev, inode, token); unlock_share_entry(conn, dev, inode);
errno = EACCES; errno = EACCES;
return; return;
} }
@@ -932,7 +932,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou
if(broke_oplock) if(broke_oplock)
{ {
free((char *)old_shares); free((char *)old_shares);
num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); num_share_modes = get_share_modes(conn, dev, inode, &old_shares);
oplock_contention_count++; oplock_contention_count++;
} }
} while(broke_oplock); } while(broke_oplock);
@@ -973,7 +973,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou
/* We created the file - thus we must now lock the share entry before creating it. */ /* We created the file - thus we must now lock the share entry before creating it. */
dev = fsp->fd_ptr->dev; dev = fsp->fd_ptr->dev;
inode = fsp->fd_ptr->inode; inode = fsp->fd_ptr->inode;
lock_share_entry(conn, dev, inode, &token); lock_share_entry(conn, dev, inode);
share_locked = True; share_locked = True;
} }
@@ -1028,7 +1028,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou
oplock_request = 0; oplock_request = 0;
} }
set_share_mode(token, fsp, port, oplock_request); set_share_mode(fsp, port, oplock_request);
} }
if ((flags2&O_TRUNC) && file_existed) if ((flags2&O_TRUNC) && file_existed)
@@ -1036,7 +1036,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou
} }
if (share_locked && lp_share_modes(SNUM(conn))) if (share_locked && lp_share_modes(SNUM(conn)))
unlock_share_entry( conn, dev, inode, token); unlock_share_entry( conn, dev, inode);
} }
/**************************************************************************** /****************************************************************************
@@ -1224,7 +1224,6 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op)
share_mode_entry *old_shares = 0; share_mode_entry *old_shares = 0;
int num_share_modes; int num_share_modes;
SMB_STRUCT_STAT sbuf; SMB_STRUCT_STAT sbuf;
int token;
pid_t pid = getpid(); pid_t pid = getpid();
SMB_DEV_T dev; SMB_DEV_T dev;
SMB_INO_T inode; SMB_INO_T inode;
@@ -1237,8 +1236,8 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op)
dev = sbuf.st_dev; dev = sbuf.st_dev;
inode = sbuf.st_ino; inode = sbuf.st_ino;
lock_share_entry(conn, dev, inode, &token); lock_share_entry(conn, dev, inode);
num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); num_share_modes = get_share_modes(conn, dev, inode, &old_shares);
/* /*
* Check if the share modes will give us access. * Check if the share modes will give us access.
@@ -1308,7 +1307,7 @@ batch oplocked file %s, dev = %x, inode = %.0f\n", fname, (unsigned int)dev, (do
dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode)); dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode));
/* Oplock break.... */ /* Oplock break.... */
unlock_share_entry(conn, dev, inode, token); unlock_share_entry(conn, dev, inode);
if(request_oplock_break(share_entry, dev, inode) == False) if(request_oplock_break(share_entry, dev, inode) == False)
{ {
free((char *)old_shares); free((char *)old_shares);
@@ -1318,7 +1317,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou
return False; return False;
} }
lock_share_entry(conn, dev, inode, &token); lock_share_entry(conn, dev, inode);
broke_oplock = True; broke_oplock = True;
break; break;
} }
@@ -1345,7 +1344,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou
if(broke_oplock) if(broke_oplock)
{ {
free((char *)old_shares); free((char *)old_shares);
num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); num_share_modes = get_share_modes(conn, dev, inode, &old_shares);
} }
} while(broke_oplock); } while(broke_oplock);
} }
@@ -1364,7 +1363,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou
free_and_exit: free_and_exit:
unlock_share_entry(conn, dev, inode, token); unlock_share_entry(conn, dev, inode);
if(old_shares != NULL) if(old_shares != NULL)
free((char *)old_shares); free((char *)old_shares);
return(ret); return(ret);

View File

@@ -406,13 +406,12 @@ static void downgrade_file_oplock(files_struct *fsp)
BOOL remove_oplock(files_struct *fsp) BOOL remove_oplock(files_struct *fsp)
{ {
int token;
SMB_DEV_T dev = fsp->fd_ptr->dev; SMB_DEV_T dev = fsp->fd_ptr->dev;
SMB_INO_T inode = fsp->fd_ptr->inode; SMB_INO_T inode = fsp->fd_ptr->inode;
BOOL ret = True; BOOL ret = True;
/* Remove the oplock flag from the sharemode. */ /* Remove the oplock flag from the sharemode. */
if (lock_share_entry(fsp->conn, dev, inode, &token) == False) { if (lock_share_entry(fsp->conn, dev, inode) == False) {
DEBUG(0,("remove_oplock: failed to lock share entry for file %s\n", DEBUG(0,("remove_oplock: failed to lock share entry for file %s\n",
fsp->fsp_name )); fsp->fsp_name ));
ret = False; ret = False;
@@ -424,7 +423,7 @@ BOOL remove_oplock(files_struct *fsp)
* Deal with a reply when a break-to-none was sent. * Deal with a reply when a break-to-none was sent.
*/ */
if(remove_share_oplock(token, fsp)==False) { if(remove_share_oplock(fsp)==False) {
DEBUG(0,("remove_oplock: failed to remove share oplock for file %s fnum %d, \ DEBUG(0,("remove_oplock: failed to remove share oplock for file %s fnum %d, \
dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double)inode)); dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double)inode));
ret = False; ret = False;
@@ -438,7 +437,7 @@ dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double)
* Deal with a reply when a break-to-level II was sent. * Deal with a reply when a break-to-level II was sent.
*/ */
if(downgrade_share_oplock(token, fsp)==False) { if(downgrade_share_oplock(fsp)==False) {
DEBUG(0,("remove_oplock: failed to downgrade share oplock for file %s fnum %d, \ DEBUG(0,("remove_oplock: failed to downgrade share oplock for file %s fnum %d, \
dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double)inode)); dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double)inode));
ret = False; ret = False;
@@ -447,7 +446,7 @@ dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double)
downgrade_file_oplock(fsp); downgrade_file_oplock(fsp);
} }
unlock_share_entry(fsp->conn, dev, inode, token); unlock_share_entry(fsp->conn, dev, inode);
return ret; return ret;
} }
@@ -792,18 +791,18 @@ BOOL oplock_break_level2(files_struct *fsp, BOOL local_request, int token)
* the existing lock on the shared memory area. * the existing lock on the shared memory area.
*/ */
if(!local_request && lock_share_entry(fsp->conn, dev, inode, &token) == False) { if(!local_request && lock_share_entry(fsp->conn, dev, inode) == False) {
DEBUG(0,("oplock_break_level2: unable to lock share entry for file %s\n", fsp->fsp_name )); DEBUG(0,("oplock_break_level2: unable to lock share entry for file %s\n", fsp->fsp_name ));
} else { } else {
got_lock = True; got_lock = True;
} }
if(remove_share_oplock(token, fsp)==False) { if(remove_share_oplock(fsp)==False) {
DEBUG(0,("oplock_break_level2: unable to remove level II oplock for file %s\n", fsp->fsp_name )); DEBUG(0,("oplock_break_level2: unable to remove level II oplock for file %s\n", fsp->fsp_name ));
} }
if (!local_request && got_lock) if (!local_request && got_lock)
unlock_share_entry(fsp->conn, dev, inode, token); unlock_share_entry(fsp->conn, dev, inode);
fsp->oplock_type = NO_OPLOCK; fsp->oplock_type = NO_OPLOCK;
level_II_oplocks_open--; level_II_oplocks_open--;

View File

@@ -1800,7 +1800,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode))
{ {
int token;
int i; int i;
files_struct *iterate_fsp; files_struct *iterate_fsp;
SMB_DEV_T dev = fsp->fd_ptr->dev; SMB_DEV_T dev = fsp->fd_ptr->dev;
@@ -1808,7 +1807,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
int num_share_modes; int num_share_modes;
share_mode_entry *current_shares = NULL; share_mode_entry *current_shares = NULL;
if(lock_share_entry(fsp->conn, dev, inode, &token) == False) if(lock_share_entry(fsp->conn, dev, inode) == False)
return(ERROR(ERRDOS,ERRnoaccess)); return(ERROR(ERRDOS,ERRnoaccess));
/* /*
@@ -1818,7 +1817,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
* file at this point. * file at this point.
*/ */
num_share_modes = get_share_modes(conn, token, dev, inode, &current_shares); num_share_modes = get_share_modes(conn, dev, inode, &current_shares);
for(i = 0; i < num_share_modes; i++) for(i = 0; i < num_share_modes; i++)
{ {
if(!GET_ALLOW_SHARE_DELETE(current_shares[i].share_mode)) if(!GET_ALLOW_SHARE_DELETE(current_shares[i].share_mode))
@@ -1830,7 +1829,7 @@ file %s as a share exists that was not opened with FILE_DELETE access.\n",
* Release the lock. * Release the lock.
*/ */
unlock_share_entry(fsp->conn, dev, inode, token); unlock_share_entry(fsp->conn, dev, inode);
/* /*
* current_shares was malloced by get_share_modes - free it here. * current_shares was malloced by get_share_modes - free it here.
@@ -1875,7 +1874,7 @@ dev = %x, inode = %.0f from %x to %x\n",
iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev, iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev,
(double)inode, iterate_fsp->share_mode, new_share_mode )); (double)inode, iterate_fsp->share_mode, new_share_mode ));
if(modify_share_mode(token, iterate_fsp, new_share_mode, iterate_fsp->oplock_type)==False) 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, \ 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)); dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode));
} }
@@ -1887,7 +1886,7 @@ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode))
*/ */
fsp->fd_ptr->delete_on_close = delete_on_close; fsp->fd_ptr->delete_on_close = delete_on_close;
unlock_share_entry(fsp->conn, dev, inode, token); unlock_share_entry(fsp->conn, dev, inode);
DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", 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 )); delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));

View File

@@ -75,6 +75,26 @@ static char *memdup(char *d, int size)
} }
#endif #endif
/* a byte range locking function - return 0 on success
this functions locks/unlocks 1 byte at the specified offset */
static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset, int set)
{
#if !NOLOCK
struct flock fl;
fl.l_type = set?F_WRLCK:F_UNLCK;
fl.l_whence = SEEK_SET;
fl.l_start = offset;
fl.l_len = 1;
fl.l_pid = 0;
if (fcntl(tdb->fd, F_SETLKW, &fl) != 0) return -1;
#endif
return 0;
}
/* the hash algorithm - turn a key into an integer /* the hash algorithm - turn a key into an integer
This is based on the hash agorithm from gdbm */ This is based on the hash agorithm from gdbm */
static unsigned tdb_hash(TDB_DATA *key) static unsigned tdb_hash(TDB_DATA *key)
@@ -991,42 +1011,25 @@ int tdb_close(TDB_CONTEXT *tdb)
/* lock the database. If we already have it locked then don't do anything */ /* lock the database. If we already have it locked then don't do anything */
int tdb_writelock(TDB_CONTEXT *tdb) int tdb_writelock(TDB_CONTEXT *tdb)
{ {
#if !NOLOCK return tdb_brlock(tdb, 0, 1);
struct flock fl;
if (tdb->write_locked) return 0;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 1;
fl.l_pid = 0;
if (fcntl(tdb->fd, F_SETLKW, &fl) != 0) return -1;
tdb->write_locked = 1;
#endif
return 0;
} }
/* unlock the database. If we don't have it locked then return -1 */ /* unlock the database. */
int tdb_writeunlock(TDB_CONTEXT *tdb) int tdb_writeunlock(TDB_CONTEXT *tdb)
{ {
#if !NOLOCK return tdb_brlock(tdb, 0, 0);
struct flock fl;
if (!tdb->write_locked) return -1;
fl.l_type = F_UNLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 1;
fl.l_pid = 0;
if (fcntl(tdb->fd, F_SETLK, &fl) != 0) return -1;
tdb->write_locked = 0;
#endif
return 0;
} }
/* lock one hash chain. This is meant to be used to reduce locking
contention - it cannot guarantee how many records will be locked */
int tdb_lockchain(TDB_CONTEXT *tdb, TDB_DATA key)
{
return tdb_brlock(tdb, tdb_hash_top(tdb, tdb_hash(&key)), 1);
}
/* unlock one hash chain */
int tdb_unlockchain(TDB_CONTEXT *tdb, TDB_DATA key)
{
return tdb_brlock(tdb, tdb_hash_top(tdb, tdb_hash(&key)), 0);
}

View File

@@ -165,7 +165,6 @@ static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf)
static pid_t last_pid; static pid_t last_pid;
struct session_record *ptr; struct session_record *ptr;
struct connections_data crec; struct connections_data crec;
static int doneone;
memcpy(&crec, dbuf.dptr, sizeof(crec)); memcpy(&crec, dbuf.dptr, sizeof(crec));
@@ -176,13 +175,6 @@ static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf)
} }
if (brief) { if (brief) {
if (!doneone) {
printf("\nSamba version %s\n",VERSION);
printf("PID Username Machine Time logged in\n");
printf("-------------------------------------------------------------------\n");
doneone = 1;
}
ptr=srecs; ptr=srecs;
while (ptr!=NULL) { while (ptr!=NULL) {
if ((ptr->pid==crec.pid)&&(strncmp(ptr->machine,crec.machine,30)==0)) { if ((ptr->pid==crec.pid)&&(strncmp(ptr->machine,crec.machine,30)==0)) {
@@ -203,13 +195,6 @@ static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf)
srecs=ptr; srecs=ptr;
} }
} else { } else {
if (!doneone) {
printf("\nSamba version %s\n",VERSION);
printf("Service uid gid pid machine\n");
printf("----------------------------------------------\n");
doneone = 1;
}
Ucrit_addPid(crec.pid); Ucrit_addPid(crec.pid);
if (processes_only) { if (processes_only) {
if (last_pid != crec.pid) if (last_pid != crec.pid)
@@ -292,19 +277,13 @@ static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf)
if (verbose) { if (verbose) {
printf("using configfile = %s\n", servicesf); printf("using configfile = %s\n", servicesf);
printf("lockdir = %s\n", *lp_lockdir() ? lp_lockdir() : "NULL");
} }
if (profile_only) { if (profile_only) {
return profile_dump(); return profile_dump();
} }
pstrcpy(fname,lp_lockdir()); tdb = tdb_open(lock_path("connections.tdb"), 0, O_RDONLY, 0);
standard_sub_basic(fname);
trim_string(fname,"","/");
pstrcat(fname,"/connections.tdb");
tdb = tdb_open(fname, 0, O_RDONLY, 0);
if (!tdb) { if (!tdb) {
printf("Couldn't open status file %s\n",fname); printf("Couldn't open status file %s\n",fname);
if (!lp_status(-1)) if (!lp_status(-1))
@@ -316,6 +295,14 @@ static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf)
if (locks_only) goto locks; if (locks_only) goto locks;
printf("\nSamba version %s\n",VERSION);
if (brief) {
printf("PID Username Machine Time logged in\n");
printf("-------------------------------------------------------------------\n");
} else {
printf("Service uid gid pid machine\n");
printf("----------------------------------------------\n");
}
tdb_traverse(tdb, traverse_fn1); tdb_traverse(tdb, traverse_fn1);
locks: locks:
@@ -347,8 +334,6 @@ static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf)
printf("\n"); printf("\n");
share_status(stdout);
locking_end(); locking_end();
} }

View File

@@ -128,7 +128,6 @@ static int traverse_fn3(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf)
/* show the current server status */ /* show the current server status */
void status_page(void) void status_page(void)
{ {
pstring fname;
char *v; char *v;
int autorefresh=0; int autorefresh=0;
int refresh_interval=30; int refresh_interval=30;
@@ -173,12 +172,7 @@ void status_page(void)
refresh_interval = atoi(v); refresh_interval = atoi(v);
} }
pstrcpy(fname,lp_lockdir()); tdb = tdb_open(lock_path("connections.tdb"), 0, O_RDONLY, 0);
standard_sub_basic(fname);
trim_string(fname,"","/");
pstrcat(fname,"/connections.tdb");
tdb = tdb_open(fname, 0, O_RDONLY, 0);
if (tdb) tdb_traverse(tdb, traverse_fn1); if (tdb) tdb_traverse(tdb, traverse_fn1);
printf("<H2>Server Status</H2>\n"); printf("<H2>Server Status</H2>\n");