From 4e1291a83f61a72989045879763d9ef05fd38f71 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 21 Dec 1999 09:25:59 +0000 Subject: 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 used to be commit e48c2d9937eea0667b8cd3332e49c06314ef31e7) --- source3/Makefile.in | 3 +- source3/include/proto.h | 21 +- source3/include/smb.h | 16 + source3/lib/util.c | 21 + source3/locking/locking.c | 423 +++++++++----- source3/locking/locking_shm.c | 711 ----------------------- source3/locking/locking_slow.c | 1144 ------------------------------------- source3/locking/shmem.c | 963 ------------------------------- source3/locking/shmem_sysv.c | 724 ----------------------- source3/rpc_client/cli_netlogon.c | 2 +- source3/smbd/close.c | 7 +- source3/smbd/connection.c | 27 +- source3/smbd/fileio.c | 6 +- source3/smbd/open.c | 33 +- source3/smbd/oplock.c | 15 +- source3/smbd/trans2.c | 11 +- source3/tdb/tdb.c | 65 ++- source3/utils/status.c | 33 +- source3/web/statuspage.c | 8 +- 19 files changed, 428 insertions(+), 3805 deletions(-) delete mode 100644 source3/locking/locking_shm.c delete mode 100644 source3/locking/locking_slow.c delete mode 100644 source3/locking/shmem.c delete mode 100644 source3/locking/shmem_sysv.c (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index ca85566703..5236274255 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -135,8 +135,7 @@ RPC_CLIENT_OBJ = \ rpc_client/cli_samr.o -LOCKING_OBJ = locking/locking.o locking/locking_shm.o locking/locking_slow.o \ - locking/shmem.o locking/shmem_sysv.o +LOCKING_OBJ = locking/locking.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 diff --git a/source3/include/proto.h b/source3/include/proto.h index 125ef3a27c..401a619110 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -299,6 +299,7 @@ BOOL reg_split_key(char *full_keyname, uint32 *reg_type, char *key_name); char *smbd_mktemp(char *template); void *memdup(void *p, size_t size); char *myhostname(void); +char *lock_path(char *name); /*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_end(void); 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, - 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 token, SMB_DEV_T dev, SMB_INO_T inode, + SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry **shares); -void del_share_mode(int token, files_struct *fsp); -BOOL set_share_mode(int token, files_struct *fsp, uint16 port, uint16 op_type); -BOOL remove_share_oplock(int token, files_struct *fsp); -BOOL downgrade_share_oplock(int token, files_struct *fsp); -BOOL modify_share_mode(int token, files_struct *fsp, int new_mode, uint16 new_oplock); +void del_share_mode(files_struct *fsp); +BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type); +BOOL remove_share_oplock(files_struct *fsp); +BOOL downgrade_share_oplock(files_struct *fsp); +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 *)); void share_status(FILE *f); @@ -2375,7 +2377,6 @@ void conn_free(connection_struct *conn); /*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); 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); @@ -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_writelock(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 */ diff --git a/source3/include/smb.h b/source3/include/smb.h index 6c3d7488c3..de269f1d7d 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -858,6 +858,22 @@ struct connections_data { 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 */ typedef enum { diff --git a/source3/lib/util.c b/source3/lib/util.c index 8f904d486d..d3a63691df 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -3213,3 +3213,24 @@ char *myhostname(void) } 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; +} diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 012d954e50..fc4ce725c5 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -1,8 +1,8 @@ /* Unix SMB/Netbios implementation. - Version 1.9. + Version 3.0 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 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 support. + rewrtten completely to use new tdb code. Tridge, Dec '99 */ #include "includes.h" 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 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)) { - /* - * Many UNIX's cannot get a write lock on a file opened read-only. - * Win32 locking semantics allow this. - * 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")); - return F_RDLCK; - } else if( (lock_type == F_RDLCK) && (fsp->fd_ptr->real_open_flags == O_WRONLY)) { - /* - * Ditto for read locks on write only files. - */ - DEBUG(10,("map_lock_type: Changing read lock to write due to write-only file.\n")); - return F_WRLCK; - } - - /* - * This return should be the most normal, as we attempt - * to always open files read/write. - */ - - return lock_type; + 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. + * Win32 locking semantics allow this. + * 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")); + return F_RDLCK; + } else if( (lock_type == F_RDLCK) && (fsp->fd_ptr->real_open_flags == O_WRONLY)) { + /* + * Ditto for read locks on write only files. + */ + DEBUG(10,("map_lock_type: Changing read lock to write due to write-only file.\n")); + return F_WRLCK; + } + + /* + * This return should be the most normal, as we attempt + * to always open files read/write. + */ + + 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) { int snum = SNUM(conn); - + if (count == 0) 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, int *eclass,uint32 *ecode) { - BOOL ok = False; - - if (!lp_locking(SNUM(conn))) - return(True); - - if (count == 0) { - *eclass = ERRDOS; - *ecode = ERRnoaccess; - 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 )); - - if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) - ok = fcntl_lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count, - map_lock_type(fsp,lock_type)); - - if (!ok) { - *eclass = ERRDOS; - *ecode = ERRlock; - return False; - } - return True; /* Got lock */ + BOOL ok = False; + + if (!lp_locking(SNUM(conn))) + return(True); + + if (count == 0) { + *eclass = ERRDOS; + *ecode = ERRnoaccess; + 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 )); + + if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) + ok = fcntl_lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count, + map_lock_type(fsp,lock_type)); + + if (!ok) { + *eclass = ERRDOS; + *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, SMB_OFF_T count,SMB_OFF_T offset,int *eclass,uint32 *ecode) { - BOOL ok = False; - - if (!lp_locking(SNUM(conn))) - return(True); - - DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for file %s\n", - (double)offset, (double)count, fsp->fsp_name )); - - if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) - ok = fcntl_lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count,F_UNLCK); + BOOL ok = False; + + if (!lp_locking(SNUM(conn))) + return(True); + + DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for file %s\n", + (double)offset, (double)count, fsp->fsp_name )); + + if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) + ok = fcntl_lock(fsp->fd_ptr->fd,SMB_F_SETLK,offset,count,F_UNLCK); - if (!ok) { - *eclass = ERRDOS; - *ecode = ERRlock; - return False; - } - return True; /* Did unlock */ + if (!ok) { + *eclass = ERRDOS; + *ecode = ERRlock; + return False; + } + return True; /* Did unlock */ } /**************************************************************************** Initialise the locking functions. ****************************************************************************/ - BOOL locking_init(int read_only) { - if (share_ops) - return True; + if (tdb) return True; -#ifdef FAST_SHARE_MODES - share_ops = locking_shm_init(read_only); - if (!share_ops && read_only && (getuid() == 0)) { - /* this may be the first time the share modes code has - 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 + tdb = tdb_open(lock_path("locking.tdb"), + 0, + read_only?O_RDONLY:O_RDWR|O_CREAT, + 0644); - if (!share_ops) { + if (!tdb) { DEBUG(0,("ERROR: Failed to initialise share modes\n")); return False; } @@ -181,110 +174,271 @@ BOOL locking_init(int read_only) /******************************************************************* Deinitialize the share_mode management. ******************************************************************/ - BOOL locking_end(void) { - if (share_ops) - return share_ops->stop_mgmt(); + if (tdb && tdb_close(tdb) != 0) return False; 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. ******************************************************************/ 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. ******************************************************************/ 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. ********************************************************************/ 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) { - 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 for this process +********************************************************************/ +void del_share_mode(files_struct *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;inum_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); } /******************************************************************* - Del the share mode of a file. +fill a share mode entry ********************************************************************/ -void del_share_mode(int token, files_struct *fsp) +static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_type) { - share_ops->del_entry(token, fsp); + 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. ********************************************************************/ -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;inum_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 below. ********************************************************************/ - static void remove_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode, void *param) { - DEBUG(10,("remove_share_oplock_fn: removing oplock info for entry dev=%x ino=%.0f\n", - (unsigned int)dev, (double)inode )); - /* Delete the oplock info. */ - entry->op_port = 0; - entry->op_type = NO_OPLOCK; + DEBUG(10,("remove_share_oplock_fn: removing oplock info for entry dev=%x ino=%.0f\n", + (unsigned int)dev, (double)inode )); + /* Delete the oplock info. */ + entry->op_port = 0; + entry->op_type = NO_OPLOCK; } /******************************************************************* Remove an oplock port and mode entry from a share mode. ********************************************************************/ - -BOOL remove_share_oplock(int token, files_struct *fsp) +BOOL remove_share_oplock(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 below. ********************************************************************/ - static void downgrade_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode, void *param) { - DEBUG(10,("downgrade_share_oplock_fn: downgrading oplock info for entry dev=%x ino=%.0f\n", - (unsigned int)dev, (double)inode )); - entry->op_type = LEVEL_II_OPLOCK; + DEBUG(10,("downgrade_share_oplock_fn: downgrading oplock info for entry dev=%x ino=%.0f\n", + (unsigned int)dev, (double)inode )); + entry->op_type = LEVEL_II_OPLOCK; } /******************************************************************* Downgrade a oplock type from exclusive to level II. ********************************************************************/ - -BOOL downgrade_share_oplock(int token, files_struct *fsp) +BOOL downgrade_share_oplock(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 below. ********************************************************************/ - struct mod_val { int new_share_mode; 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. Return False on fail, True on success. ********************************************************************/ - -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) { struct mod_val mv; 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); } -/******************************************************************* - Call the specified function on each entry under management by the - share mode system. -********************************************************************/ +static void (*traverse_callback)(share_mode_entry *, char *); -int share_mode_forall(void (*fn)(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) { - if (!share_ops) return 0; - return share_ops->forall(fn); + 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;inum_share_mode_entries;i++) { + traverse_callback(&shares[i], name); + } + return 0; } /******************************************************************* - Dump the state of the system. + Call the specified function on each entry under management by the + share mode system. ********************************************************************/ - -void share_status(FILE *f) +int share_mode_forall(void (*fn)(share_mode_entry *, char *)) { - share_ops->status(f); + if (!tdb) return 0; + traverse_callback = fn; + return tdb_traverse(tdb, traverse_fn); } diff --git a/source3/locking/locking_shm.c b/source3/locking/locking_shm.c deleted file mode 100644 index 174ad73e97..0000000000 --- a/source3/locking/locking_shm.c +++ /dev/null @@ -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 */ diff --git a/source3/locking/locking_slow.c b/source3/locking/locking_slow.c deleted file mode 100644 index 58673d2707..0000000000 --- a/source3/locking/locking_slow.c +++ /dev/null @@ -1,1144 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - slow (lockfile) 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" - -#ifndef FAST_SHARE_MODES - -extern int DEBUGLEVEL; - -/* - * Locking file header lengths & offsets. - */ -#define SMF_VERSION_OFFSET 0 -#define SMF_NUM_ENTRIES_OFFSET 4 -#define SMF_FILENAME_LEN_OFFSET 8 -#define SMF_HEADER_LENGTH 10 - -#define SMF_ENTRY_LENGTH 20 - -/* - * Share mode record offsets. - */ - -#define SME_SEC_OFFSET 0 -#define SME_USEC_OFFSET 4 -#define SME_SHAREMODE_OFFSET 8 -#define SME_PID_OFFSET 12 -#define SME_PORT_OFFSET 16 -#define SME_OPLOCK_TYPE_OFFSET 18 - -/* we need world read for smbstatus to function correctly */ -#ifdef SECURE_SHARE_MODES -#define SHARE_FILE_MODE 0600 -#else -#define SHARE_FILE_MODE 0644 -#endif - -static int read_only; - -/******************************************************************* - deinitialize share_mode management - ******************************************************************/ -static BOOL slow_stop_share_mode_mgmt(void) -{ - return True; -} - - -/******************************************************************* - name a share file - ******************************************************************/ -static BOOL share_name(connection_struct *conn, - SMB_DEV_T dev, SMB_INO_T inode, char *name) -{ - int len; - pstrcpy(name,lp_lockdir()); - trim_string(name,"","/"); - if (!*name) return(False); - len = strlen(name); - name += len; - -#ifdef LARGE_SMB_INO_T - slprintf(name, sizeof(pstring) - len - 1, "/share.%u.%.0f",(unsigned int)dev,(double)inode); -#else /* LARGE_SMB_INO_T */ - slprintf(name, sizeof(pstring) - len - 1, "/share.%u.%lu",(unsigned int)dev,(unsigned long)inode); -#endif /* LARGE_SMB_INO_T */ - return(True); -} - -/******************************************************************* -Force a share file to be deleted. -********************************************************************/ -static int delete_share_file(connection_struct *conn, char *fname ) -{ - if (read_only) return -1; - - /* the share file could be owned by anyone, so do this as root */ - become_root(False); - - if(unlink(fname) != 0) - { - DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n", - fname, strerror(errno))); - } - else - { - DEBUG(5,("delete_share_file: Deleted share file %s\n", fname)); - } - - /* return to our previous privilege level */ - unbecome_root(False); - - return 0; -} - -/******************************************************************* - lock a share mode file. - ******************************************************************/ -static BOOL slow_lock_share_entry(connection_struct *conn, - SMB_DEV_T dev, SMB_INO_T inode, int *ptok) -{ - pstring fname; - int fd; - int ret = True; - - *ptok = (int)-1; - - if(!share_name(conn, dev, inode, fname)) - return False; - - if (read_only) return True; - - /* we need to do this as root */ - become_root(False); - - { - BOOL gotlock = False; - /* - * There was a race condition in the original slow share mode code. - * A smbd could open a share mode file, and before getting - * the lock, another smbd could delete the last entry for - * the share mode file and delete the file entry from the - * directory. Thus this smbd would be left with a locked - * share mode fd attached to a file that no longer had a - * directory entry. Thus another smbd would think that - * there were no outstanding opens on the file. To fix - * this we now check we can do a stat() call on the filename - * before allowing the lock to proceed, and back out completely - * and try the open again if we cannot. - * Jeremy Allison (jallison@whistle.com). - */ - - do - { - SMB_STRUCT_STAT dummy_stat; - - fd = sys_open(fname,read_only?O_RDONLY:(O_RDWR|O_CREAT), SHARE_FILE_MODE); - - if(fd < 0) - { - DEBUG(0,("ERROR lock_share_entry: failed to open share file %s. Error was %s\n", - fname, strerror(errno))); - ret = False; - break; - } - - /* At this point we have an open fd to the share mode file. - Lock the first byte exclusively to signify a lock. */ - if(fcntl_lock(fd, SMB_F_SETLKW, 0, 1, F_WRLCK) == False) - { - DEBUG(0,("ERROR lock_share_entry: fcntl_lock on file %s failed with %s\n", - fname, strerror(errno))); - close(fd); - ret = False; - break; - } - - /* - * If we cannot stat the filename, the file was deleted between - * the open and the lock call. Back out and try again. - */ - - if(sys_stat(fname, &dummy_stat)!=0) - { - DEBUG(2,("lock_share_entry: Re-issuing open on %s to fix race. Error was %s\n", - fname, strerror(errno))); - close(fd); - } - else - gotlock = True; - } while(!gotlock); - - /* - * We have to come here if any of the above calls fail - * as we don't want to return and leave ourselves running - * as root ! - */ - } - - *ptok = (int)fd; - - /* return to our previous privilege level */ - unbecome_root(False); - - return ret; -} - -/******************************************************************* - unlock a share mode file. - ******************************************************************/ -static BOOL slow_unlock_share_entry(connection_struct *conn, - SMB_DEV_T dev, SMB_INO_T inode, int token) -{ - int fd = token; - int ret = True; - SMB_STRUCT_STAT sb; - pstring fname; - - if (read_only) return True; - - /* Fix for zero length share files from - Gerald Werner */ - - share_name(conn, dev, inode, fname); - - /* get the share mode file size */ - if(sys_fstat((int)token, &sb) != 0) - { - DEBUG(0,("ERROR: unlock_share_entry: Failed to do stat on share file %s (%s)\n", - fname, strerror(errno))); - sb.st_size = 1; - ret = False; - } - - /* If the file was zero length, we must delete before - doing the unlock to avoid a race condition (see - the code in lock_share_mode_entry for details. - */ - - /* remove the share file if zero length */ - if(sb.st_size == 0) - delete_share_file(conn, fname); - - /* token is the fd of the open share mode file. */ - /* Unlock the first byte. */ - if(fcntl_lock(fd, SMB_F_SETLKW, 0, 1, F_UNLCK) == False) - { - DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n", - strerror(errno))); - ret = False; - } - - close(fd); - return ret; -} - -/******************************************************************* -Read a share file into a buffer. -********************************************************************/ -static int read_share_file(connection_struct *conn, int fd, char *fname, char **out, BOOL *p_new_file) -{ - SMB_STRUCT_STAT sb; - char *buf; - SMB_OFF_T size; - - *out = 0; - *p_new_file = False; - - if(sys_fstat(fd, &sb) != 0) - { - DEBUG(0,("ERROR: read_share_file: Failed to do stat on share file %s (%s)\n", - fname, strerror(errno))); - return -1; - } - - if(sb.st_size == 0) - { - *p_new_file = True; - return 0; - } - - /* Allocate space for the file */ - if((buf = (char *)malloc((size_t)sb.st_size)) == NULL) - { - DEBUG(0,("read_share_file: malloc for file size %d fail !\n", - (int)sb.st_size)); - return -1; - } - - if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: read_share_file: Failed to reset position to 0 \ -for share file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return -1; - } - - if (read(fd,buf,(size_t)sb.st_size) != (size_t)sb.st_size) - { - DEBUG(0,("ERROR: read_share_file: Failed to read share file %s (%s)\n", - fname, strerror(errno))); - if(buf) - free(buf); - return -1; - } - - if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) { - DEBUG(0,("ERROR: read_share_file: share file %s has incorrect \ -locking version (was %d, should be %d).\n",fname, - IVAL(buf,SMF_VERSION_OFFSET), LOCKING_VERSION)); - if(buf) - free(buf); - delete_share_file(conn, fname); - return -1; - } - - /* Sanity check for file contents */ - size = sb.st_size; - size -= SMF_HEADER_LENGTH; /* Remove the header */ - - /* Remove the filename component. */ - size -= SVAL(buf, SMF_FILENAME_LEN_OFFSET); - - /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */ - if((size % SMF_ENTRY_LENGTH) != 0) - { - DEBUG(0,("ERROR: read_share_file: share file %s is an incorrect length - \ -deleting it.\n", fname)); - if(buf) - free(buf); - delete_share_file(conn, fname); - return -1; - } - - *out = buf; - return 0; -} - -/******************************************************************* -get all share mode entries in a share file for a dev/inode pair. -********************************************************************/ -static int slow_get_share_modes(connection_struct *conn, int token, - SMB_DEV_T dev, SMB_INO_T inode, - share_mode_entry **old_shares) -{ - int fd = token; - pstring fname; - int i; - int num_entries; - int num_entries_copied; - int newsize; - share_mode_entry *share_array; - char *buf = 0; - char *base = 0; - BOOL new_file; - - *old_shares = 0; - - /* Read the share file header - this is of the form: - 0 - locking version. - 4 - number of share mode entries. - 8 - 2 byte name length - [n bytes] file name (zero terminated). - - Followed by share mode entries of the form : - - 0 - tv_sec - 4 - tv_usec - 8 - share_mode - 12 - pid - 16 - oplock port (if oplocks in use) - 2 bytes. - */ - - share_name(conn, dev, inode, fname); - - if(read_share_file( conn, fd, fname, &buf, &new_file) != 0) - { - DEBUG(0,("ERROR: get_share_modes: Failed to read share file %s\n", - fname)); - return 0; - } - - if(new_file == True) - return 0; - - num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); - - DEBUG(5,("get_share_modes: share file %s has %d share mode entries.\n", - fname, num_entries)); - - /* PARANOIA TEST */ - if(num_entries < 0) - { - DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \ -for share file %s\n", num_entries, fname)); - return 0; - } - - 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 !\n")); - return 0; - } - } - else - { - /* No entries - just delete the file. */ - DEBUG(0,("get_share_modes: share file %s has no share mode entries - deleting.\n", - fname)); - if(buf) - free(buf); - delete_share_file(conn, fname); - return 0; - } - - num_entries_copied = 0; - base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - - for( i = 0; i < num_entries; i++) - { - pid_t pid; - char *p = base + (i*SMF_ENTRY_LENGTH); - - pid = (pid_t)IVAL(p,SME_PID_OFFSET); - - if(!process_exists(pid)) - { - DEBUG(0,("get_share_modes: process %d no longer exists and \ -it left a share mode entry with mode 0x%X in share file %s\n", - (int)pid, IVAL(p,SME_SHAREMODE_OFFSET), fname)); - continue; - } - share_array[num_entries_copied].time.tv_sec = IVAL(p,SME_SEC_OFFSET); - share_array[num_entries_copied].time.tv_usec = IVAL(p,SME_USEC_OFFSET); - share_array[num_entries_copied].share_mode = IVAL(p,SME_SHAREMODE_OFFSET); - share_array[num_entries_copied].pid = pid; - share_array[num_entries_copied].op_port = SVAL(p,SME_PORT_OFFSET); - share_array[num_entries_copied].op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); - - num_entries_copied++; - } - - if(num_entries_copied == 0) - { - /* Delete the whole file. */ - DEBUG(0,("get_share_modes: share file %s had no valid entries - deleting it !\n", - fname)); - if(*old_shares) - free((char *)*old_shares); - *old_shares = 0; - if(buf) - free(buf); - delete_share_file(conn, fname); - return 0; - } - - /* If we deleted some entries we need to re-write the whole number of - share mode entries back into the file. */ - - if(num_entries_copied != num_entries) - { - if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: get_share_modes: lseek failed to reset to \ -position 0 for share mode file %s (%s)\n", fname, strerror(errno))); - if(*old_shares) - free((char *)*old_shares); - *old_shares = 0; - if(buf) - free(buf); - return 0; - } - - SIVAL(buf, SMF_NUM_ENTRIES_OFFSET, num_entries_copied); - for( i = 0; i < num_entries_copied; i++) - { - char *p = base + (i*SMF_ENTRY_LENGTH); - - SIVAL(p,SME_PID_OFFSET,(uint32)share_array[i].pid); - SIVAL(p,SME_SHAREMODE_OFFSET,share_array[i].share_mode); - SIVAL(p,SME_SEC_OFFSET,share_array[i].time.tv_sec); - SIVAL(p,SME_USEC_OFFSET,share_array[i].time.tv_usec); - SSVAL(p,SME_PORT_OFFSET,share_array[i].op_port); - SSVAL(p,SME_OPLOCK_TYPE_OFFSET,share_array[i].op_type); - } - - newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries_copied); - if(write(fd, buf, newsize) != newsize) - { - DEBUG(0,("ERROR: get_share_modes: failed to re-write share \ -mode file %s (%s)\n", fname, strerror(errno))); - if(*old_shares) - free((char *)*old_shares); - *old_shares = 0; - if(buf) - free(buf); - return 0; - } - /* Now truncate the file at this point. */ -#ifdef FTRUNCATE_NEEDS_ROOT - become_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - - if(sys_ftruncate(fd, (SMB_OFF_T)newsize)!= 0) - { -#ifdef FTRUNCATE_NEEDS_ROOT - int saved_errno = errno; - unbecome_root(False); - errno = saved_errno; -#endif /* FTRUNCATE_NEEDS_ROOT */ - - DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \ -mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); - if(*old_shares) - free((char *)*old_shares); - *old_shares = 0; - if(buf) - free(buf); - return 0; - } - } - -#ifdef FTRUNCATE_NEEDS_ROOT - unbecome_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - - if(buf) - free(buf); - - DEBUG(5,("get_share_modes: Read share file %s returning %d entries\n",fname, - num_entries_copied)); - - return num_entries_copied; -} - -/******************************************************************* -del a share mode from a share mode file. -********************************************************************/ -static void slow_del_share_mode(int token, files_struct *fsp) -{ - pstring fname; - int fd = (int)token; - char *buf = 0; - char *base = 0; - int num_entries; - int newsize; - int i; - pid_t pid; - BOOL deleted = False; - BOOL new_file; - - share_name(fsp->conn, fsp->fd_ptr->dev, - fsp->fd_ptr->inode, fname); - - if(read_share_file( fsp->conn, fd, fname, &buf, &new_file) != 0) - { - DEBUG(0,("ERROR: del_share_mode: Failed to read share file %s\n", - fname)); - return; - } - - if(new_file == True) - { - DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n", - fname)); - delete_share_file(fsp->conn, fname); - return; - } - - num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); - - DEBUG(5,("del_share_mode: share file %s has %d share mode entries.\n", - fname, num_entries)); - - /* PARANOIA TEST */ - if(num_entries < 0) - { - DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \ -for share file %s\n", num_entries, fname)); - return; - } - - if(num_entries == 0) - { - /* No entries - just delete the file. */ - DEBUG(0,("del_share_mode: share file %s has no share mode entries - deleting.\n", - fname)); - if(buf) - free(buf); - delete_share_file(fsp->conn, fname); - return; - } - - pid = getpid(); - - /* Go through the entries looking for the particular one - we have set - delete it. - */ - - base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - - for(i = 0; i < num_entries; i++) - { - char *p = base + (i*SMF_ENTRY_LENGTH); - - if((IVAL(p,SME_SEC_OFFSET) != fsp->open_time.tv_sec) || - (IVAL(p,SME_USEC_OFFSET) != fsp->open_time.tv_usec) || - (IVAL(p,SME_SHAREMODE_OFFSET) != fsp->share_mode) || - (((pid_t)IVAL(p,SME_PID_OFFSET)) != pid)) - continue; - - DEBUG(5,("del_share_mode: deleting entry number %d (of %d) from the share file %s\n", - i, num_entries, fname)); - - /* Remove this entry. */ - if(i != num_entries - 1) - memcpy(p, p + SMF_ENTRY_LENGTH, (num_entries - i - 1)*SMF_ENTRY_LENGTH); - - deleted = True; - break; - } - - if(!deleted) - { - DEBUG(0,("del_share_mode: entry not found in share file %s\n", fname)); - if(buf) - free(buf); - return; - } - - num_entries--; - SIVAL(buf,SMF_NUM_ENTRIES_OFFSET, num_entries); - - if(num_entries == 0) - { - /* Deleted the last entry - remove the file. */ - DEBUG(5,("del_share_mode: removed last entry in share file - deleting share file %s\n", - fname)); - if(buf) - free(buf); - delete_share_file(fsp->conn,fname); - return; - } - - /* Re-write the file - and truncate it at the correct point. */ - if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: del_share_mode: lseek failed to reset to \ -position 0 for share mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return; - } - - newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries); - if(write(fd, buf, newsize) != newsize) - { - DEBUG(0,("ERROR: del_share_mode: failed to re-write share \ -mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return; - } - - /* Now truncate the file at this point. */ -#ifdef FTRUNCATE_NEEDS_ROOT - become_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - - if(sys_ftruncate(fd, (SMB_OFF_T)newsize) != 0) - { -#ifdef FTRUNCATE_NEEDS_ROOT - int saved_errno = errno; - unbecome_root(False); - errno = saved_errno; -#endif /* FTRUNCATE_NEEDS_ROOT */ - - - DEBUG(0,("ERROR: del_share_mode: failed to ftruncate share \ -mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); - if(buf) - free(buf); - return; - } - -#ifdef FTRUNCATE_NEEDS_ROOT - unbecome_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - -} - -/******************************************************************* -set the share mode of a file -********************************************************************/ -static BOOL slow_set_share_mode(int token,files_struct *fsp, uint16 port, uint16 op_type) -{ - pstring fname; - int fd = (int)token; - pid_t pid = getpid(); - SMB_STRUCT_STAT sb; - char *buf; - int num_entries; - int header_size; - char *p; - - share_name(fsp->conn, fsp->fd_ptr->dev, - fsp->fd_ptr->inode, fname); - - if(sys_fstat(fd, &sb) != 0) - { - DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n", - fname)); - return False; - } - - /* Sanity check for file contents (if it's not a new share file). */ - if(sb.st_size != 0) - { - SMB_OFF_T size = sb.st_size; - - /* Allocate space for the file plus one extra entry */ - if((buf = (char *)malloc((size_t)(sb.st_size + SMF_ENTRY_LENGTH))) == NULL) - { - DEBUG(0,("set_share_mode: malloc for file size %d fail !\n", - (int)(sb.st_size + SMF_ENTRY_LENGTH))); - return False; - } - - if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: set_share_mode: Failed to reset position \ -to 0 for share file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - if (read(fd,buf,(size_t)sb.st_size) != (size_t)sb.st_size) - { - DEBUG(0,("ERROR: set_share_mode: Failed to read share file %s (%s)\n", - fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) - { - DEBUG(0,("ERROR: set_share_mode: share file %s has incorrect \ -locking version (was %d, should be %d).\n",fname, IVAL(buf,SMF_VERSION_OFFSET), - LOCKING_VERSION)); - if(buf) - free(buf); - delete_share_file(fsp->conn, fname); - return False; - } - - size -= (SMF_HEADER_LENGTH + SVAL(buf, SMF_FILENAME_LEN_OFFSET)); /* Remove the header */ - - /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */ - if((size % SMF_ENTRY_LENGTH) != 0) - { - DEBUG(0,("ERROR: set_share_mode: share file %s is an incorrect length - \ -deleting it.\n", fname)); - if(buf) - free(buf); - delete_share_file(fsp->conn, fname); - return False; - } - - } - else - { - /* New file - just use a single_entry. */ - if((buf = (char *)malloc(SMF_HEADER_LENGTH + - strlen(fsp->fsp_name) + strlen(fsp->conn->connectpath) + 2 + SMF_ENTRY_LENGTH)) == NULL) - { - DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n")); - return False; - } - SIVAL(buf,SMF_VERSION_OFFSET,LOCKING_VERSION); - SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,0); - SSVAL(buf,SMF_FILENAME_LEN_OFFSET,strlen(fsp->fsp_name) + strlen(fsp->conn->connectpath) + 2); - pstrcpy(buf + SMF_HEADER_LENGTH, fsp->conn->connectpath); - pstrcat(buf + SMF_HEADER_LENGTH, "/"); - pstrcat(buf + SMF_HEADER_LENGTH, fsp->fsp_name); - } - - num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); - header_size = SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - p = buf + header_size + (num_entries * SMF_ENTRY_LENGTH); - SIVAL(p,SME_SEC_OFFSET,fsp->open_time.tv_sec); - SIVAL(p,SME_USEC_OFFSET,fsp->open_time.tv_usec); - SIVAL(p,SME_SHAREMODE_OFFSET,fsp->share_mode); - SIVAL(p,SME_PID_OFFSET,(uint32)pid); - SSVAL(p,SME_PORT_OFFSET,port); - SSVAL(p,SME_OPLOCK_TYPE_OFFSET,op_type); - - num_entries++; - - SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,num_entries); - - if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: set_share_mode: (1) Failed to reset position to \ -0 for share file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - if (write(fd,buf,header_size + (num_entries*SMF_ENTRY_LENGTH)) != - (header_size + (num_entries*SMF_ENTRY_LENGTH))) - { - DEBUG(2,("ERROR: set_share_mode: Failed to write share file %s - \ -deleting it (%s).\n",fname, strerror(errno))); - delete_share_file(fsp->conn, fname); - if(buf) - free(buf); - return False; - } - - /* Now truncate the file at this point - just for safety. */ - -#ifdef FTRUNCATE_NEEDS_ROOT - become_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - - if(sys_ftruncate(fd, (SMB_OFF_T)(header_size + (SMF_ENTRY_LENGTH*num_entries)))!= 0) - { - -#ifdef FTRUNCATE_NEEDS_ROOT - int saved_errno = errno; - unbecome_root(False); - errno = saved_errno; -#endif /* FTRUNCATE_NEEDS_ROOT */ - - DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \ -mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*num_entries), - strerror(errno))); - if(buf) - free(buf); - return False; - } - -#ifdef FTRUNCATE_NEEDS_ROOT - unbecome_root(False); -#endif /* FTRUNCATE_NEEDS_ROOT */ - - if(buf) - free(buf); - - DEBUG(3,("set_share_mode: Created share file %s with \ -mode 0x%X pid=%d\n",fname,fsp->share_mode,(int)pid)); - - return True; -} - -/******************************************************************* - Call a generic modify function for a share mode entry. -********************************************************************/ - -static BOOL slow_mod_share_entry(int token, files_struct *fsp, - void (*mod_fn)(share_mode_entry *, SMB_DEV_T, SMB_INO_T, void *), - void *param) -{ - pstring fname; - int fd = (int)token; - char *buf = 0; - char *base = 0; - int num_entries; - int fsize; - int i; - pid_t pid; - BOOL found = False; - BOOL new_file; - share_mode_entry entry; - - share_name(fsp->conn, fsp->fd_ptr->dev, - fsp->fd_ptr->inode, fname); - - if(read_share_file( fsp->conn, fd, fname, &buf, &new_file) != 0) - { - DEBUG(0,("ERROR: slow_mod_share_entry: Failed to read share file %s\n", - fname)); - return False; - } - - if(new_file == True) - { - DEBUG(0,("ERROR: slow_mod_share_entry: share file %s is new (size zero), \ -deleting it.\n", fname)); - delete_share_file(fsp->conn, fname); - return False; - } - - num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); - - DEBUG(5,("slow_mod_share_entry: share file %s has %d share mode entries.\n", - fname, num_entries)); - - /* PARANOIA TEST */ - if(num_entries < 0) - { - DEBUG(0,("PANIC ERROR:slow_mod_share_entry: num_share_mode_entries < 0 (%d) \ -for share file %s\n", num_entries, fname)); - return False; - } - - if(num_entries == 0) - { - /* No entries - just delete the file. */ - DEBUG(0,("slow_mod_share_entry: share file %s has no share mode entries - deleting.\n", - fname)); - if(buf) - free(buf); - delete_share_file(fsp->conn, fname); - return False; - } - - pid = getpid(); - - base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - - for(i = 0; i < num_entries; i++) - { - char *p = base + (i*SMF_ENTRY_LENGTH); - - if((IVAL(p,SME_SEC_OFFSET) != fsp->open_time.tv_sec) || - (IVAL(p,SME_USEC_OFFSET) != fsp->open_time.tv_usec) || - (IVAL(p,SME_SHAREMODE_OFFSET) != fsp->share_mode) || - (((pid_t)IVAL(p,SME_PID_OFFSET)) != pid)) - continue; - - DEBUG(5,("slow_mod_share_entry: Calling generic function to modify entry number %d (of %d) \ -from the share file %s\n", i, num_entries, fname)); - - /* - * Copy into the share_mode_entry structure and then call - * the generic function with the given parameter. - */ - - entry.pid = (pid_t)IVAL(p,SME_PID_OFFSET); - entry.op_port = SVAL(p,SME_PORT_OFFSET); - entry.op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); - entry.share_mode = IVAL(p,SME_SHAREMODE_OFFSET); - entry.time.tv_sec = IVAL(p,SME_SEC_OFFSET); - entry.time.tv_usec = IVAL(p,SME_USEC_OFFSET); - - (*mod_fn)( &entry, fsp->fd_ptr->dev, fsp->fd_ptr->inode, param); - - /* - * Now copy any changes the function made back into the buffer. - */ - - SIVAL(p,SME_PID_OFFSET, (uint32)entry.pid); - SSVAL(p,SME_PORT_OFFSET,entry.op_port); - SSVAL(p,SME_OPLOCK_TYPE_OFFSET,entry.op_type); - SIVAL(p,SME_SHAREMODE_OFFSET,entry.share_mode); - SIVAL(p,SME_SEC_OFFSET,entry.time.tv_sec); - SIVAL(p,SME_USEC_OFFSET,entry.time.tv_usec); - - found = True; - break; - } - - if(!found) - { - DEBUG(0,("slow_mod_share_entry: entry not found in share file %s\n", fname)); - if(buf) - free(buf); - return False; - } - - /* Re-write the file - and truncate it at the correct point. */ - if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: slow_mod_share_entry: lseek failed to reset to \ -position 0 for share mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - fsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries); - if(write(fd, buf, fsize) != fsize) - { - DEBUG(0,("ERROR: slow_mod_share_entry: failed to re-write share \ -mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - return True; -} - - - -/******************************************************************* -call the specified function on each entry under management by the -share mode system -********************************************************************/ -static int slow_share_forall(void (*fn)(share_mode_entry *, char *)) -{ - int i, count=0; - DIR *dir; - char *s; - share_mode_entry e; - - dir = opendir(lp_lockdir()); - if (!dir) { - return(0); - } - - while ((s=readdirname(dir))) { - char *buf; - char *base; - int fd; - pstring lname; - SMB_DEV_T dev; - SMB_INO_T inode; - BOOL new_file; - pstring fname; - -#ifdef LARGE_SMB_INO_T - double inode_ascii; - if (sscanf(s,"share.%u.%lf",&dev,&inode_ascii)!=2) continue; - inode = (SMB_INO_T)inode_ascii; -#else /* LARGE_SMB_INO_T */ - unsigned long inode_long; - if (sscanf(s,"share.%u.%lu",&dev,&inode_long)!=2) continue; - inode = (SMB_INO_T)inode_long; -#endif /* LARGE_SMB_INO_T */ - - pstrcpy(lname,lp_lockdir()); - trim_string(lname,NULL,"/"); - pstrcat(lname,"/"); - pstrcat(lname,s); - - fd = sys_open(lname,read_only?O_RDONLY:O_RDWR,0); - if (fd < 0) { - continue; - } - - /* Lock the share mode file while we read it. */ - if(!read_only && - fcntl_lock(fd, SMB_F_SETLKW, 0, 1, F_WRLCK) == False) { - close(fd); - continue; - } - - if(read_share_file( 0, fd, lname, &buf, &new_file)) { - close(fd); - continue; - } - pstrcpy( fname, &buf[10]); - close(fd); - - base = buf + SMF_HEADER_LENGTH + - SVAL(buf,SMF_FILENAME_LEN_OFFSET); - for( i = 0; i < IVAL(buf, SMF_NUM_ENTRIES_OFFSET); i++) { - char *p = base + (i*SMF_ENTRY_LENGTH); - e.pid = (pid_t)IVAL(p,SME_PID_OFFSET); - e.share_mode = IVAL(p,SME_SHAREMODE_OFFSET); - e.time.tv_sec = IVAL(p,SME_SEC_OFFSET); - e.time.tv_usec = IVAL(p,SME_USEC_OFFSET); - e.op_port = SVAL(p,SME_PORT_OFFSET); - e.op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); - - if (process_exists(e.pid)) { - fn(&e, fname); - count++; - } - } /* end for i */ - - if(buf) - free(buf); - base = 0; - } /* end while */ - closedir(dir); - - return count; -} - - -/******************************************************************* -dump the state of the system -********************************************************************/ -static void slow_share_status(FILE *f) -{ - -} - - -static struct share_ops share_ops = { - slow_stop_share_mode_mgmt, - slow_lock_share_entry, - slow_unlock_share_entry, - slow_get_share_modes, - slow_del_share_mode, - slow_set_share_mode, - slow_mod_share_entry, - slow_share_forall, - slow_share_status, -}; - -/******************************************************************* - initialize the slow share_mode management - ******************************************************************/ -struct share_ops *locking_slow_init(int ronly) -{ - - read_only = ronly; - - if (!directory_exist(lp_lockdir(),NULL)) { - if (!read_only) - mkdir(lp_lockdir(),0755); - if (!directory_exist(lp_lockdir(),NULL)) - return NULL; - } - - return &share_ops; -} -#else - int locking_slow_dummy_procedure(void); - int locking_slow_dummy_procedure(void) {return 0;} -#endif /* !FAST_SHARE_MODES */ diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c deleted file mode 100644 index bf2802c9ec..0000000000 --- a/source3/locking/shmem.c +++ /dev/null @@ -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 */ diff --git a/source3/locking/shmem_sysv.c b/source3/locking/shmem_sysv.c deleted file mode 100644 index 04a2e74460..0000000000 --- a/source3/locking/shmem_sysv.c +++ /dev/null @@ -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 - * 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 diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index 8202960089..583b4bb4b8 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -628,7 +628,7 @@ BOOL change_trust_account_password( char *domain, char *remote_machine_list) unsigned char old_trust_passwd_hash[16]; unsigned char new_trust_passwd_hash[16]; time_t lct; - BOOL res; + BOOL res = False; if(!get_trust_account_password( old_trust_passwd_hash, &lct)) { DEBUG(0,("change_trust_account_password: unable to read the machine \ diff --git a/source3/smbd/close.c b/source3/smbd/close.c index d06cb3b5bb..bfef7c5235 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -94,7 +94,6 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) { SMB_DEV_T dev = fsp->fd_ptr->dev; SMB_INO_T inode = fsp->fd_ptr->inode; - int token; BOOL last_reference = False; BOOL delete_on_close = fsp->fd_ptr->delete_on_close; connection_struct *conn = fsp->conn; @@ -109,8 +108,8 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) #endif if (lp_share_modes(SNUM(conn))) { - lock_share_entry(conn, dev, inode, &token); - del_share_mode(token, fsp); + lock_share_entry(conn, dev, inode); + del_share_mode(fsp); } 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; 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 */ if (normal_close && fsp->print_file) diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index f88d707983..5b5ab005c8 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -26,27 +26,6 @@ extern fstring remote_machine; 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 ****************************************************************************/ @@ -56,7 +35,8 @@ BOOL yield_connection(connection_struct *conn,char *name,int max_connections) TDB_DATA kbuf; 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)); @@ -100,7 +80,8 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO if (max_connections <= 0) 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)); diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 8b48a921fd..fa04e671f8 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -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 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 )); } - 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++) { 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); - unlock_share_entry(fsp->conn, dev, inode, token); + unlock_share_entry(fsp->conn, dev, inode); } /* Paranoia check... */ diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 4491082b2c..a940eda85d 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -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. */ if (*share_locked && lp_share_modes(SNUM(conn))) unlock_share_entry( conn, fsp->fd_ptr->dev, - fsp->fd_ptr->inode, token); + fsp->fd_ptr->inode); close_file(fsp,False); /* Share mode no longer locked. */ *share_locked = False; @@ -858,9 +858,9 @@ void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int { dev = sbuf.st_dev; inode = sbuf.st_ino; - lock_share_entry(conn, dev, inode, &token); + lock_share_entry(conn, dev, inode); 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)); /* Oplock break.... */ - unlock_share_entry(conn, dev, inode, token); + unlock_share_entry(conn, dev, inode); if(request_oplock_break(share_entry, dev, inode) == False) { 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; return; } - lock_share_entry(conn, dev, inode, &token); + lock_share_entry(conn, dev, inode); broke_oplock = True; all_current_opens_are_level_II = False; 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) { free((char *)old_shares); - unlock_share_entry(conn, dev, inode, token); + unlock_share_entry(conn, dev, inode); errno = EACCES; return; } @@ -932,7 +932,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou if(broke_oplock) { 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++; } } 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. */ dev = fsp->fd_ptr->dev; inode = fsp->fd_ptr->inode; - lock_share_entry(conn, dev, inode, &token); + lock_share_entry(conn, dev, inode); 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; } - set_share_mode(token, fsp, port, oplock_request); + set_share_mode(fsp, port, oplock_request); } 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))) - 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; int num_share_modes; SMB_STRUCT_STAT sbuf; - int token; pid_t pid = getpid(); SMB_DEV_T dev; SMB_INO_T inode; @@ -1237,8 +1236,8 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op) dev = sbuf.st_dev; inode = sbuf.st_ino; - lock_share_entry(conn, dev, inode, &token); - num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares); + lock_share_entry(conn, dev, inode); + num_share_modes = get_share_modes(conn, dev, inode, &old_shares); /* * 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)); /* Oplock break.... */ - unlock_share_entry(conn, dev, inode, token); + unlock_share_entry(conn, dev, inode); if(request_oplock_break(share_entry, dev, inode) == False) { 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; } - lock_share_entry(conn, dev, inode, &token); + lock_share_entry(conn, dev, inode); broke_oplock = True; break; } @@ -1345,7 +1344,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou if(broke_oplock) { 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); } @@ -1364,7 +1363,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou free_and_exit: - unlock_share_entry(conn, dev, inode, token); + unlock_share_entry(conn, dev, inode); if(old_shares != NULL) free((char *)old_shares); return(ret); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index a64dd2d0ef..c5cab8c225 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -406,13 +406,12 @@ static void downgrade_file_oplock(files_struct *fsp) BOOL remove_oplock(files_struct *fsp) { - int token; SMB_DEV_T dev = fsp->fd_ptr->dev; SMB_INO_T inode = fsp->fd_ptr->inode; BOOL ret = True; /* 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", fsp->fsp_name )); ret = False; @@ -424,7 +423,7 @@ BOOL remove_oplock(files_struct *fsp) * 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, \ dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double)inode)); 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. */ - 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, \ dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double)inode)); ret = False; @@ -447,7 +446,7 @@ dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double) downgrade_file_oplock(fsp); } - unlock_share_entry(fsp->conn, dev, inode, token); + unlock_share_entry(fsp->conn, dev, inode); 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. */ - 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 )); } else { 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 )); } 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; level_II_oplocks_open--; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 5a8db7efda..bbbfda7468 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1800,7 +1800,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) { - int token; int i; files_struct *iterate_fsp; SMB_DEV_T dev = fsp->fd_ptr->dev; @@ -1808,7 +1807,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, int num_share_modes; 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)); /* @@ -1818,7 +1817,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, * file at this point. */ - num_share_modes = get_share_modes(conn, token, dev, inode, ¤t_shares); + num_share_modes = get_share_modes(conn, dev, inode, ¤t_shares); for(i = 0; i < num_share_modes; i++) { if(!GET_ALLOW_SHARE_DELETE(current_shares[i].share_mode)) @@ -1830,7 +1829,7 @@ file %s as a share exists that was not opened with FILE_DELETE access.\n", * 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. @@ -1875,7 +1874,7 @@ dev = %x, inode = %.0f from %x to %x\n", iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev, (double)inode, iterate_fsp->share_mode, new_share_mode )); - if(modify_share_mode(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, \ 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; - 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", delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name )); diff --git a/source3/tdb/tdb.c b/source3/tdb/tdb.c index 01d2e740f7..70880b5345 100644 --- a/source3/tdb/tdb.c +++ b/source3/tdb/tdb.c @@ -75,6 +75,26 @@ static char *memdup(char *d, int size) } #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 This is based on the hash agorithm from gdbm */ 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 */ int tdb_writelock(TDB_CONTEXT *tdb) { -#if !NOLOCK - 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; + return tdb_brlock(tdb, 0, 1); } -/* unlock the database. If we don't have it locked then return -1 */ +/* unlock the database. */ int tdb_writeunlock(TDB_CONTEXT *tdb) { -#if !NOLOCK - struct flock fl; - - if (!tdb->write_locked) return -1; + return tdb_brlock(tdb, 0, 0); +} - fl.l_type = F_UNLCK; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 1; - fl.l_pid = 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); +} - if (fcntl(tdb->fd, F_SETLK, &fl) != 0) return -1; - tdb->write_locked = 0; -#endif - return 0; +/* 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); } - diff --git a/source3/utils/status.c b/source3/utils/status.c index 594783bd39..8f3461c082 100644 --- a/source3/utils/status.c +++ b/source3/utils/status.c @@ -165,7 +165,6 @@ static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf) static pid_t last_pid; struct session_record *ptr; struct connections_data crec; - static int doneone; 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 (!doneone) { - printf("\nSamba version %s\n",VERSION); - printf("PID Username Machine Time logged in\n"); - printf("-------------------------------------------------------------------\n"); - doneone = 1; - } - ptr=srecs; while (ptr!=NULL) { 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; } } else { - if (!doneone) { - printf("\nSamba version %s\n",VERSION); - printf("Service uid gid pid machine\n"); - printf("----------------------------------------------\n"); - doneone = 1; - } - Ucrit_addPid(crec.pid); if (processes_only) { if (last_pid != crec.pid) @@ -292,19 +277,13 @@ static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf) if (verbose) { printf("using configfile = %s\n", servicesf); - printf("lockdir = %s\n", *lp_lockdir() ? lp_lockdir() : "NULL"); } if (profile_only) { return profile_dump(); } - pstrcpy(fname,lp_lockdir()); - standard_sub_basic(fname); - trim_string(fname,"","/"); - pstrcat(fname,"/connections.tdb"); - - tdb = tdb_open(fname, 0, O_RDONLY, 0); + tdb = tdb_open(lock_path("connections.tdb"), 0, O_RDONLY, 0); if (!tdb) { printf("Couldn't open status file %s\n",fname); 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; + 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); locks: @@ -347,8 +334,6 @@ static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf) printf("\n"); - share_status(stdout); - locking_end(); } diff --git a/source3/web/statuspage.c b/source3/web/statuspage.c index 8b7108c0b5..e3e10f09d5 100644 --- a/source3/web/statuspage.c +++ b/source3/web/statuspage.c @@ -128,7 +128,6 @@ static int traverse_fn3(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf) /* show the current server status */ void status_page(void) { - pstring fname; char *v; int autorefresh=0; int refresh_interval=30; @@ -173,12 +172,7 @@ void status_page(void) refresh_interval = atoi(v); } - pstrcpy(fname,lp_lockdir()); - standard_sub_basic(fname); - trim_string(fname,"","/"); - pstrcat(fname,"/connections.tdb"); - - tdb = tdb_open(fname, 0, O_RDONLY, 0); + tdb = tdb_open(lock_path("connections.tdb"), 0, O_RDONLY, 0); if (tdb) tdb_traverse(tdb, traverse_fn1); printf("

Server Status

\n"); -- cgit