summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/include/includes.h3
-rw-r--r--source3/include/proto.h25
-rw-r--r--source3/include/smb.h50
-rw-r--r--source3/lib/util.c5
-rw-r--r--source3/locking/locking.c1323
-rw-r--r--source3/locking/shmem.c261
-rw-r--r--source3/nameannounce.c21
-rw-r--r--source3/nameconf.c6
-rw-r--r--source3/namedbname.c7
-rw-r--r--source3/namedbserver.c3
-rw-r--r--source3/namedbsubnet.c194
-rw-r--r--source3/namedbwork.c6
-rw-r--r--source3/nameelect.c248
-rw-r--r--source3/nameresp.c8
-rw-r--r--source3/nameserv.c42
-rw-r--r--source3/nameservreply.c3
-rw-r--r--source3/namework.c5
-rw-r--r--source3/nmbd/nmbd.c15
-rw-r--r--source3/param/loadparm.c38
-rw-r--r--source3/smbd/dir.c7
-rw-r--r--source3/smbd/ipc.c13
-rw-r--r--source3/smbd/pipes.c3
-rw-r--r--source3/smbd/reply.c3
-rw-r--r--source3/smbd/server.c288
-rw-r--r--source3/smbd/trans2.c4
-rw-r--r--source3/utils/status.c260
26 files changed, 1925 insertions, 916 deletions
diff --git a/source3/include/includes.h b/source3/include/includes.h
index e1ed3a5816..265e838be0 100644
--- a/source3/include/includes.h
+++ b/source3/include/includes.h
@@ -481,6 +481,7 @@ char *mktemp(char *); /* No standard include */
#ifdef FreeBSD
+#include <arpa/inet.h>
#include <strings.h>
#include <netinet/tcp.h>
#include <netinet/in_systm.h>
@@ -970,7 +971,7 @@ typedef int mode_t;
end of the platform specific sections
********************************************************************/
-#if defined(USE_MMAP) || FAST_SHARE_MODES
+#if defined(USE_MMAP) || defined(FAST_SHARE_MODES)
#include <sys/mman.h>
#endif
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 973b1a15f3..1fa8c1d95e 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -149,6 +149,7 @@ char *lp_socket_address(void);
char *lp_nis_home_map_name(void);
BOOL lp_wins_support(void);
BOOL lp_wins_proxy(void);
+BOOL lp_local_master(void);
BOOL lp_domain_master(void);
BOOL lp_domain_logons(void);
BOOL lp_preferred_master(void);
@@ -176,6 +177,8 @@ int lp_maxpacket(void);
int lp_keepalive(void);
int lp_passwordlevel(void);
int lp_readsize(void);
+int lp_shmem_size(void);
+int lp_shmem_hash_size(void);
int lp_deadtime(void);
int lp_maxprotocol(void);
int lp_security(void);
@@ -266,12 +269,12 @@ BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ec
BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode);
BOOL start_share_mode_mgmt(void);
BOOL stop_share_mode_mgmt(void);
-int get_share_mode_by_fnum(int cnum,int fnum,int *pid);
-int get_share_mode_byname(int cnum,char *fname,int *pid);
-int get_share_mode(int cnum,struct stat *sbuf,int *pid);
-void del_share_mode(int fnum);
-BOOL set_share_mode(int fnum,int mode);
-void clean_share_modes(void);
+BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *);
+BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token);
+int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode,
+ min_share_mode_entry **old_shares);
+void del_share_mode(share_lock_token token, int fnum);
+BOOL set_share_mode(share_lock_token token, int fnum);
/*The following definitions come from mangle.c */
@@ -309,7 +312,7 @@ void do_announce_host(int command,
char *to_name , int to_type , struct in_addr to_ip,
time_t announce_interval,
char *server_name, int server_type, char *server_comment);
-void remove_my_servers(void);
+void announce_my_servers_removed(void);
void announce_server(struct subnet_record *d, struct work_record *work,
char *name, char *comment, time_t ttl, int server_type);
void announce_host(time_t t);
@@ -394,7 +397,7 @@ void expire_servers(time_t t);
struct subnet_record *find_subnet(struct in_addr bcast_ip);
struct subnet_record *find_req_subnet(struct in_addr ip, BOOL bcast);
struct subnet_record *find_subnet_all(struct in_addr bcast_ip);
-void add_subnet_interfaces(void);
+void add_workgroup_to_subnet( struct subnet_record *d, char *group);
void add_my_subnets(char *group);
void write_browse_list(time_t t);
@@ -406,7 +409,6 @@ struct work_record *remove_workgroup(struct subnet_record *d,
struct work_record *find_workgroupstruct(struct subnet_record *d,
fstring name, BOOL add);
void dump_workgroups(void);
-int check_work_servertype(const char *work_name, int type_mask);
/*The following definitions come from nameelect.c */
@@ -724,6 +726,11 @@ BOOL smb_shm_set_userdef_off(smb_shm_offset_t userdef_off);
void * smb_shm_offset2addr(smb_shm_offset_t offset);
BOOL smb_shm_lock(void);
BOOL smb_shm_unlock(void);
+smb_shm_offset_t smb_shm_alloc(int size);
+smb_shm_offset_t smb_shm_addr2offset(void *addr);
+smb_shm_offset_t smb_shm_get_userdef_off(void);
+BOOL smb_shm_lock_hash_entry( unsigned int entry);
+BOOL smb_shm_unlock_hash_entry( unsigned int entry );
BOOL smb_shm_get_usage(int *bytes_free,
int *bytes_used,
int *bytes_overhead);
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 7cd2f5b0fe..e0c08183db 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -36,11 +36,16 @@
#define BUFFER_SIZE (0xFFFF)
#define SAFETY_MARGIN 1024
-/* size of shared memory used for share mode locking */
+/* Default size of shared memory used for share mode locking */
#ifndef SHMEM_SIZE
#define SHMEM_SIZE 102400
#endif
+/* Default number of hash buckets used in shared memory share mode */
+#ifndef SHMEM_HASH_SIZE
+#define SHMEM_HASH_SIZE 113
+#endif
+
#define NMB_PORT 137
#define DGRAM_PORT 138
#define SMB_PORT 139
@@ -295,8 +300,8 @@ typedef struct
typedef struct
{
uint16 ref_count;
- int32 dev;
- int32 inode;
+ uint32 dev;
+ uint32 inode;
int fd;
int fd_readonly;
int fd_writeonly;
@@ -320,7 +325,6 @@ typedef struct
BOOL can_read;
BOOL can_write;
BOOL share_mode;
- BOOL share_pending;
BOOL print_file;
BOOL modified;
char *name;
@@ -420,19 +424,40 @@ struct interface
struct in_addr nmask;
};
-/* share mode record in shared memory */
+/* share mode record pointed to in shared memory hash bucket */
typedef struct
{
- smb_shm_offset_t next_offset; /* offset of next record in list in shared mem */
+ smb_shm_offset_t next_offset; /* offset of next record in chain from hash bucket */
int locking_version;
+ int32 st_dev;
+ int32 st_ino;
+ int num_share_mode_entries;
+ smb_shm_offset_t 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
+{
+ smb_shm_offset_t next_share_mode_entry;
+ int pid;
int share_mode;
struct timeval time;
+} share_mode_entry;
+
+/* struct returned by get_share_modes */
+typedef struct
+{
int pid;
- dev_t st_dev;
- ino_t st_ino;
- char file_name[1]; /* dynamically allocated with correct size */
-} share_mode_record;
+ int share_mode;
+ struct timeval time;
+} min_share_mode_entry;
+
+/* Token returned by lock_share_entry (actually ignored by FAST_SHARE_MODES code) */
+typedef int share_lock_token;
+/* Conversion to hash entry index from device and inode numbers. */
+#define HASH_ENTRY(dev,ino) ((( (uint32)(dev) )* ( (uint32)(ino) )) % lp_shmem_hash_size())
/* this is used for smbstatus */
struct connect_record
@@ -798,12 +823,15 @@ char *Strstr(char *s, char *p);
#define SV_TYPE_DOMAIN_ENUM 0x80000000
#define SV_TYPE_ALL 0xFFFFFFFF
-/* What server type are we currently - JHT Says we ARE 4.20 */
+/* what server type are we currently - JHT Says we ARE 4.20 */
+/* this was set by JHT in liaison with Jeremy Allison early 1997 */
+/* setting to 4.20 at same time as announcing ourselves as NT Server */
/* History: */
/* Version 4.0 - never made public */
/* Version 4.10 - New to 1.9.16p2, lost in space 1.9.16p3 to 1.9.16p9 */
/* - Reappeared in 1.9.16p11 with fixed smbd services */
/* Version 4.20 - To indicate that nmbd and browsing now works better */
+
#define MAJOR_VERSION 0x04
#define MINOR_VERSION 0x02
diff --git a/source3/lib/util.c b/source3/lib/util.c
index 3315f1a41a..0ed08405ba 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -73,6 +73,7 @@ pstring myhostname="";
pstring user_socket_options="";
pstring sesssetup_user="";
pstring myname = "";
+fstring myworkgroup = "";
int smb_read_error = 0;
@@ -3431,7 +3432,7 @@ BOOL is_vetoed_name(char *name)
nameptr++;
continue;
}
- if(name_end = strchr(nameptr,'/'))
+ if((name_end = strchr(nameptr,'/'))!=NULL)
{
*name_end = 0;
}
@@ -3472,7 +3473,7 @@ BOOL is_vetoed_path(char *name)
nameptr++;
continue;
}
- if(name_end = strchr(nameptr,'/'))
+ if((name_end = strchr(nameptr,'/'))!=NULL)
{
*name_end = 0;
}
diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index 7c23e5b3ca..e63e347a26 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -22,6 +22,9 @@
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.
*/
#include "includes.h"
@@ -29,9 +32,6 @@ extern int DEBUGLEVEL;
extern connection_struct Connections[];
extern files_struct Files[];
-pstring share_del_pending="";
-
-
/****************************************************************************
utility function called to see if a file region is locked
****************************************************************************/
@@ -100,7 +100,7 @@ BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *
return True; /* Did unlock */
}
-#if FAST_SHARE_MODES
+#ifdef FAST_SHARE_MODES
/*******************************************************************
initialize the shared memory for share_mode management
******************************************************************/
@@ -114,7 +114,7 @@ BOOL start_share_mode_mgmt(void)
trim_string(shmem_file_name,"","/");
if (!*shmem_file_name) return(False);
strcat(shmem_file_name, "/SHARE_MEM_FILE");
- return smb_shm_open(shmem_file_name, SHMEM_SIZE);
+ return smb_shm_open(shmem_file_name, lp_shmem_size());
}
@@ -126,459 +126,1118 @@ BOOL stop_share_mode_mgmt(void)
return smb_shm_close();
}
-#else
-
-/* SHARE MODE LOCKS USING SLOW DESCRIPTION FILES */
-
-/*******************************************************************
- name a share file
- ******************************************************************/
-static BOOL share_name(int cnum,struct stat *st,char *name)
-{
- strcpy(name,lp_lockdir());
- standard_sub(cnum,name);
- trim_string(name,"","/");
- if (!*name) return(False);
- name += strlen(name);
-
- sprintf(name,"/share.%d.%d",(int)st->st_dev,(int)st->st_ino);
- return(True);
-}
-
/*******************************************************************
- use the fnum to get the share file name
+ lock a hash bucket entry in shared memory for share_mode management
******************************************************************/
-static BOOL share_name_fnum(int fnum,char *name)
+BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok)
{
- struct stat st;
- if (fstat(Files[fnum].fd_ptr->fd,&st) != 0) return(False);
- return(share_name(Files[fnum].cnum,&st,name));
+ return smb_shm_lock_hash_entry(HASH_ENTRY(dev, inode));
}
-#endif
-
/*******************************************************************
- get the share mode of a file using the fnum
+ unlock a hash bucket entry in shared memory for share_mode management
******************************************************************/
-int get_share_mode_by_fnum(int cnum,int fnum,int *pid)
+BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token)
{
- struct stat sbuf;
- if (fstat(Files[fnum].fd_ptr->fd,&sbuf) == -1) return(0);
- return(get_share_mode(cnum,&sbuf,pid));
+ return smb_shm_unlock_hash_entry(HASH_ENTRY(dev, inode));
}
/*******************************************************************
- get the share mode of a file using the files name
- ******************************************************************/
-int get_share_mode_byname(int cnum,char *fname,int *pid)
-{
- struct stat sbuf;
- if (stat(fname,&sbuf) == -1) return(0);
- return(get_share_mode(cnum,&sbuf,pid));
-}
-
-
-/*******************************************************************
-get the share mode of a file
+get all share mode entries in shared memory for a dev/inode pair.
********************************************************************/
-int get_share_mode(int cnum,struct stat *sbuf,int *pid)
+int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode,
+ min_share_mode_entry **old_shares)
{
-#if FAST_SHARE_MODES
- share_mode_record *scanner_p;
- share_mode_record *prev_p;
- int ret;
+ smb_shm_offset_t *mode_array;
+ unsigned int hash_entry = HASH_ENTRY(dev, inode);
+ share_mode_record *file_scanner_p;
+ share_mode_record *file_prev_p;
+ share_mode_entry *entry_scanner_p;
+ share_mode_entry *entry_prev_p;
+ int num_entries;
+ int num_entries_copied;
BOOL found = False;
+ min_share_mode_entry *share_array = (min_share_mode_entry *)0;
- *pid = 0;
+ *old_shares = 0;
- if(!smb_shm_lock()) return (0);
+ if(hash_entry > lp_shmem_hash_size() )
+ {
+ DEBUG(0,
+ ("PANIC ERROR : get_share_modes (FAST_SHARE_MODES): hash_entry %d too large \
+(max = %d)\n",
+ hash_entry, lp_shmem_hash_size() ));
+ abort();
+ }
- scanner_p = (share_mode_record *)smb_shm_offset2addr(smb_shm_get_userdef_off());
- prev_p = scanner_p;
- while(scanner_p)
+ mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
+
+ if(mode_array[hash_entry] == NULL_OFFSET)
{
- if( (scanner_p->st_dev == sbuf->st_dev) && (scanner_p->st_ino == sbuf->st_ino) )
+ DEBUG(5,("get_share_modes (FAST_SHARE_MODES): hash bucket %d empty\n", hash_entry));
+ return 0;
+ }
+
+ file_scanner_p = (share_mode_record *)smb_shm_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
{
- prev_p = scanner_p ;
- scanner_p = (share_mode_record *)smb_shm_offset2addr(scanner_p->next_offset);
+ file_prev_p = file_scanner_p ;
+ file_scanner_p = (share_mode_record *)smb_shm_offset2addr(
+ file_scanner_p->next_offset);
}
}
if(!found)
{
- smb_shm_unlock();
+ DEBUG(5,("get_share_modes (FAST_SHARE_MODES): no entry for \
+file dev = %d, ino = %d in hash_bucket %d\n", dev, inode, hash_entry));
return (0);
}
- if(scanner_p->locking_version != LOCKING_VERSION)
+ if(file_scanner_p->locking_version != LOCKING_VERSION)
{
- DEBUG(2,("Deleting old share mode record due to old locking version %d",scanner_p->locking_version));
- if(prev_p == scanner_p)
- smb_shm_set_userdef_off(scanner_p->next_offset);
+ DEBUG(0,("ERROR:get_share_modes (FAST_SHARE_MODES): Deleting old share mode \
+record due to old locking version %d for file dev = %d, inode = %d in hash \
+bucket %d",file_scanner_p->locking_version, dev, inode, hash_entry));
+ if(file_prev_p == file_scanner_p)
+ mode_array[hash_entry] = file_scanner_p->next_offset;
else
- prev_p->next_offset = scanner_p->next_offset;
- smb_shm_free(smb_shm_addr2offset(scanner_p));
- *pid = 0;
-
- smb_shm_unlock();
+ file_prev_p->next_offset = file_scanner_p->next_offset;
+ smb_shm_free(smb_shm_addr2offset(file_scanner_p));
return (0);
}
-
- *pid = scanner_p->pid;
- ret = scanner_p->share_mode;
- if (*pid && !process_exists(*pid))
+ /* Allocate the old_shares array */
+ num_entries = file_scanner_p->num_share_mode_entries;
+ if(num_entries)
{
- ret = 0;
- *pid = 0;
+ *old_shares = share_array = (min_share_mode_entry *)
+ malloc(num_entries * sizeof(min_share_mode_entry));
+ if(*old_shares == 0)
+ {
+ DEBUG(0,("get_share_modes (FAST_SHARE_MODES): malloc fail !\n"));
+ return 0;
+ }
}
+
+ num_entries_copied = 0;
- if (! *pid)
+ entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr(
+ file_scanner_p->share_mode_entries);
+ entry_prev_p = entry_scanner_p;
+ while(entry_scanner_p)
{
- if(prev_p == scanner_p)
- smb_shm_set_userdef_off(scanner_p->next_offset);
- else
- prev_p->next_offset = scanner_p->next_offset;
- smb_shm_free(smb_shm_addr2offset(scanner_p));
+ int pid = entry_scanner_p->pid;
+
+ if (pid && !process_exists(pid))
+ {
+ /* Delete this share mode entry */
+ 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 = (share_mode_entry*)smb_shm_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 = (share_mode_entry*)
+ smb_shm_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 (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \
+for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries,
+ dev, inode, hash_entry));
+ abort();
+ }
+
+ DEBUG(0,("get_share_modes (FAST_SHARE_MODES): process %d no longer exists and \
+it left a share mode entry with mode 0x%X for file dev = %d, ino = %d in hash \
+bucket (number of entries now = %d)\n",
+ pid, entry_scanner_p->share_mode, dev, inode, hash_entry,
+ file_scanner_p->num_share_mode_entries));
+
+ smb_shm_free(smb_shm_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->pid;
+ share_array[num_entries_copied].share_mode = entry_scanner_p->share_mode;
+ memcpy(&share_array[num_entries_copied].time, &entry_scanner_p->time,
+ sizeof(struct timeval));
+ num_entries_copied++;
+ DEBUG(5,("get_share_modes (FAST_SHARE_MODES): Read share mode \
+record mode 0x%X pid=%d\n", entry_scanner_p->share_mode, entry_scanner_p->pid));
+ entry_prev_p = entry_scanner_p;
+ entry_scanner_p = (share_mode_entry *)
+ smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry);
+ }
}
- if (*pid)
- DEBUG(5,("Read share mode record mode 0x%X pid=%d\n",ret,*pid));
+ /* If no valid share mode entries were found then this record shouldn't exist ! */
+ if(num_entries_copied == 0)
+ {
+ DEBUG(0,("get_share_modes (FAST_SHARE_MODES): file with dev %d, inode %d in \
+hash bucket %d has a share mode record but no entries - deleting\n",
+ dev, inode, hash_entry));
+ 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;
+ smb_shm_free(smb_shm_addr2offset(file_scanner_p));
+ }
- if(!smb_shm_unlock()) return (0);
-
- return(ret);
-
-#else
- pstring fname;
- int fd2;
- char buf[20];
- int ret;
- struct timeval t;
+ DEBUG(5,("get_share_modes (FAST_SHARE_MODES): file with dev %d, inode %d in \
+hash bucket %d returning %d entries\n", dev, inode, hash_entry,
+ num_entries_copied));
+
+ return(num_entries_copied);
+}
- *pid = 0;
+/*******************************************************************
+del the share mode of a file.
+********************************************************************/
+void del_share_mode(share_lock_token token, int fnum)
+{
+ uint32 dev, inode;
+ smb_shm_offset_t *mode_array;
+ unsigned int hash_entry;
+ share_mode_record *file_scanner_p;
+ share_mode_record *file_prev_p;
+ share_mode_entry *entry_scanner_p;
+ share_mode_entry *entry_prev_p;
+ BOOL found = False;
+ int pid = getpid();
- if (!share_name(cnum,sbuf,fname)) return(0);
+ dev = Files[fnum].fd_ptr->dev;
+ inode = Files[fnum].fd_ptr->inode;
- fd2 = open(fname,O_RDONLY,0);
- if (fd2 < 0) return(0);
+ hash_entry = HASH_ENTRY(dev, inode);
- if (read(fd2,buf,20) != 20) {
- DEBUG(2,("Failed to read share file %s\n",fname));
- close(fd2);
- unlink(fname);
- return(0);
+ if(hash_entry > lp_shmem_hash_size() )
+ {
+ DEBUG(0,
+ ("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash_entry %d too large \
+(max = %d)\n",
+ hash_entry, lp_shmem_hash_size() ));
+ abort();
}
- close(fd2);
- t.tv_sec = IVAL(buf,4);
- t.tv_usec = IVAL(buf,8);
- ret = IVAL(buf,12);
- *pid = IVAL(buf,16);
+ mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
+
+ if(mode_array[hash_entry] == NULL_OFFSET)
+ {
+ DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash bucket %d empty\n",
+ hash_entry));
+ abort();
+ }
- if (IVAL(buf,0) != LOCKING_VERSION) {
- if (!unlink(fname)) DEBUG(2,("Deleted old locking file %s",fname));
- *pid = 0;
- return(0);
- }
+ file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]);
+ file_prev_p = file_scanner_p;
- if (*pid && !process_exists(*pid)) {
- ret=0;
- *pid = 0;
+ 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 *)
+ smb_shm_offset2addr(file_scanner_p->next_offset);
+ }
+ }
+
+ if(!found)
+ {
+ DEBUG(0,("ERROR:del_share_mode (FAST_SHARE_MODES): no entry found for dev %d, \
+inode %d in hash bucket %d\n", dev, inode, hash_entry));
+ return;
+ }
+
+ if(file_scanner_p->locking_version != LOCKING_VERSION)
+ {
+ DEBUG(0,("ERROR: del_share_modes (FAST_SHARE_MODES): Deleting old share mode \
+record due to old locking version %d for file dev %d, inode %d hash bucket %d\n",
+ file_scanner_p->locking_version, dev, inode, hash_entry ));
+ 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;
+ smb_shm_free(smb_shm_addr2offset(file_scanner_p));
+ return;
}
- if (! *pid) unlink(fname); /* XXXXX race, race */
+ found = False;
+ entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr(
+ file_scanner_p->share_mode_entries);
+ entry_prev_p = entry_scanner_p;
+ while(entry_scanner_p)
+ {
+ if( (pid == entry_scanner_p->pid) &&
+ (memcmp(&entry_scanner_p->time,
+ &Files[fnum].open_time,sizeof(struct timeval)) == 0) )
+ {
+ found = True;
+ break;
+ }
+ else
+ {
+ entry_prev_p = entry_scanner_p;
+ entry_scanner_p = (share_mode_entry *)
+ smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry);
+ }
+ }
- if (*pid)
- DEBUG(5,("Read share file %s mode 0x%X pid=%d\n",fname,ret,*pid));
+ if (found)
+ {
+ /* Decrement the number of entries in the record. */
+ file_scanner_p->num_share_mode_entries -= 1;
+
+ DEBUG(2,("del_share_modes (FAST_SHARE_MODES): \
+Deleting share mode entry dev = %d, inode = %d in hash bucket %d (num entries now = %d)\n",
+ dev, inode, hash_entry, file_scanner_p->num_share_mode_entries));
+ 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;
+ smb_shm_free(smb_shm_addr2offset(entry_scanner_p));
+
+ /* PARANOIA TEST */
+ if(file_scanner_p->num_share_mode_entries < 0)
+ {
+ DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \
+for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries,
+ dev, inode, hash_entry));
+ abort();
+ }
- return(ret);
-#endif
+ /* 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 (FAST_SHARE_MODES): num entries = 0, deleting share_mode \
+record dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry));
+ 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;
+ smb_shm_free(smb_shm_addr2offset(file_scanner_p));
+ }
+ }
+ else
+ {
+ DEBUG(0,("ERROR: del_share_modes (FAST_SHARE_MODES): No share mode record found \
+dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry));
+ }
}
-
/*******************************************************************
-del the share mode of a file, if we set it last
+set the share mode of a file. Return False on fail, True on success.
********************************************************************/
-void del_share_mode(int fnum)
+BOOL set_share_mode(share_lock_token token, int fnum)
{
-#if FAST_SHARE_MODES
- struct stat st;
- struct timeval t;
- int pid=0;
- BOOL del = False;
- share_mode_record *scanner_p;
- share_mode_record *prev_p;
+ files_struct *fs_p = &Files[fnum];
+ int32 dev, inode;
+ smb_shm_offset_t *mode_array;
+ unsigned int hash_entry;
+ share_mode_record *file_scanner_p;
+ share_mode_record *file_prev_p;
+ share_mode_entry *new_entry_p;
+ smb_shm_offset_t new_entry_offset;
BOOL found = False;
- t.tv_sec = t.tv_usec = 0;
-
- if (fstat(Files[fnum].fd_ptr->fd,&st) != 0) return;
-
- if (!smb_shm_lock()) return;
+ dev = fs_p->fd_ptr->dev;
+ inode = fs_p->fd_ptr->inode;
+
+ hash_entry = HASH_ENTRY(dev, inode);
+ if(hash_entry > lp_shmem_hash_size() )
+ {
+ DEBUG(0,
+ ("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): hash_entry %d too large \
+(max = %d)\n",
+ hash_entry, lp_shmem_hash_size() ));
+ abort();
+ }
+
+ mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
+
+ file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]);
+ file_prev_p = file_scanner_p;
- scanner_p = (share_mode_record *)smb_shm_offset2addr(smb_shm_get_userdef_off());
- prev_p = scanner_p;
- while(scanner_p)
+ while(file_scanner_p)
{
- if( (scanner_p->st_dev == st.st_dev) && (scanner_p->st_ino == st.st_ino) )
+ if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
{
- found = True;
- break;
+ found = True;
+ break;
}
else
{
- prev_p = scanner_p ;
- scanner_p = (share_mode_record *)smb_shm_offset2addr(scanner_p->next_offset);
+ file_prev_p = file_scanner_p ;
+ file_scanner_p = (share_mode_record *)
+ smb_shm_offset2addr(file_scanner_p->next_offset);
}
}
-
+
if(!found)
{
- smb_shm_unlock();
- return;
+ /* We must create a share_mode_record */
+ share_mode_record *new_mode_p = NULL;
+ smb_shm_offset_t new_offset = smb_shm_alloc( sizeof(share_mode_record) +
+ strlen(fs_p->name) + 1);
+ if(new_offset == NULL_OFFSET)
+ {
+ DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): smb_shm_alloc fail !\n"));
+ return False;
+ }
+ new_mode_p = smb_shm_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 = NULL_OFFSET;
+ strcpy(new_mode_p->file_name, fs_p->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 (FAST_SHARE_MODES): Created share record for %s (dev %d \
+inode %d in hash bucket %d\n", fs_p->name, dev, inode, hash_entry));
+ }
+
+ /* Now create the share mode entry */
+ new_entry_offset = smb_shm_alloc( sizeof(share_mode_entry));
+ if(new_entry_offset == NULL_OFFSET)
+ {
+ smb_shm_offset_t delete_offset = mode_array[hash_entry];
+ DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): smb_shm_alloc fail 1!\n"));
+ /* Unlink the damaged record */
+ mode_array[hash_entry] = file_scanner_p->next_offset;
+ /* And delete it */
+ smb_shm_free( delete_offset );
+ return False;
}
-
- t.tv_sec = scanner_p->time.tv_sec;
- t.tv_usec = scanner_p->time.tv_usec;
- pid = scanner_p->pid;
-
- if( (scanner_p->locking_version != LOCKING_VERSION) || !pid || !process_exists(pid))
- del = True;
- if (!del && (memcmp(&t,&Files[fnum].open_time,sizeof(t)) == 0)
- && pid==(int)getpid())
- del = True;
+ new_entry_p = smb_shm_offset2addr(new_entry_offset);
- if (del)
+ new_entry_p->pid = getpid();
+ new_entry_p->share_mode = fs_p->share_mode;
+ memcpy( (char *)&new_entry_p->time, (char *)&fs_p->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(2,("Deleting share mode record\n"));
- if(prev_p == scanner_p)
- smb_shm_set_userdef_off(scanner_p->next_offset);
- else
- prev_p->next_offset = scanner_p->next_offset;
- smb_shm_free(smb_shm_addr2offset(scanner_p));
-
+ DEBUG(0,("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \
+for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries,
+ dev, inode, hash_entry));
+ abort();
}
- smb_shm_unlock();
- return;
+ /* Increment the share_mode_entries counter */
+ file_scanner_p->num_share_mode_entries += 1;
+
+ DEBUG(3,("set_share_mode (FAST_SHARE_MODES): Created share entry for %s with mode \
+0x%X pid=%d (num_entries now = %d)\n",fs_p->name, fs_p->share_mode, new_entry_p->pid,
+ file_scanner_p->num_share_mode_entries));
+
+ return(True);
+}
+
+#else /* FAST_SHARE_MODES */
+
+/* SHARE MODE LOCKS USING SLOW DESCRIPTION FILES */
-#else
+/*******************************************************************
+ name a share file
+ ******************************************************************/
+static BOOL share_name(int cnum, uint32 dev, uint32 inode, char *name)
+{
+ strcpy(name,lp_lockdir());
+ standard_sub(cnum,name);
+ trim_string(name,"","/");
+ if (!*name) return(False);
+ name += strlen(name);
+
+ sprintf(name,"/share.%u.%u",dev,inode);
+ return(True);
+}
+
+/*******************************************************************
+ lock a share mode file.
+ ******************************************************************/
+BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok)
+{
pstring fname;
- int fd2;
- char buf[20];
- struct timeval t;
- int pid=0;
- BOOL del = False;
-
- t.tv_sec = t.tv_usec = 0;
- if (!share_name_fnum(fnum,fname)) return;
-
- fd2 = open(fname,O_RDONLY,0);
- if (fd2 < 0) return;
- if (read(fd2,buf,20) != 20)
- del = True;
- close(fd2);
-
- if (!del) {
- t.tv_sec = IVAL(buf,4);
- t.tv_usec = IVAL(buf,8);
- pid = IVAL(buf,16);
- }
-
- if (!del)
- if (IVAL(buf,0) != LOCKING_VERSION || !pid || !process_exists(pid))
- del = True;
-
- if (!del && (memcmp(&t,&Files[fnum].open_time,sizeof(t)) == 0) && (pid==(int)getpid()))
- del = True;
-
- if (del) {
- if (!unlink(fname))
- DEBUG(2,("Deleted share file %s\n",fname));
- else {
- DEBUG(3,("Pending delete share file %s\n",fname));
- if (*share_del_pending) DEBUG(0,("Share del clash!\n"));
- strcpy(share_del_pending,fname);
+ int fd;
+
+ *ptok = (share_lock_token)-1;
+
+ if(!share_name(cnum, dev, inode, fname))
+ return False;
+
+ {
+ int old_umask;
+ unbecome_user();
+ old_umask = umask(0);
+#ifdef SECURE_SHARE_MODES
+ fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0600);
+#else /* SECURE_SHARE_MODES */
+ fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0644);
+#endif /* SECURE_SHARE_MODES */
+ umask(old_umask);
+ if(!become_user(cnum,Connections[cnum].vuid))
+ {
+ DEBUG(0,("lock_share_entry: Can't become connected user!\n"));
+ close(fd);
+ return False;
+ }
+ /* We need to change directory back to the connection root. */
+ if (ChDir(Connections[cnum].connectpath) != 0)
+ {
+ DEBUG(0,("lock_share_entry: Can't change directory to %s (%s)\n",
+ Connections[cnum].connectpath, strerror(errno)));
+ close(fd);
+ return False;
}
}
-#endif
+
+ /* 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, F_SETLKW, 0, 1, F_WRLCK) == False)
+ {
+ DEBUG(0,("ERROR lock_share_entry: fcntl_lock failed with %s\n",
+ strerror(errno)));
+ close(fd);
+ return False;
+ }
+
+ *ptok = (share_lock_token)fd;
+ return True;
}
-
/*******************************************************************
-set the share mode of a file
+ unlock a share mode file.
+ ******************************************************************/
+BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token)
+{
+ int fd = (int)token;
+ int ret = True;
+
+ /* token is the fd of the open share mode file. */
+ /* Unlock the first byte. */
+ if(fcntl_lock(fd, F_SETLKW, 0, 1, F_UNLCK) == False)
+ {
+ DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n",
+ strerror(errno)));
+ ret = False;
+ }
+
+ close((int)token);
+ return ret;
+}
+
+/*******************************************************************
+Force a share file to be deleted.
********************************************************************/
-BOOL set_share_mode(int fnum,int mode)
+
+static int delete_share_file( int cnum, char *fname )
{
-#if FAST_SHARE_MODES
- int pid = (int)getpid();
- struct stat st;
- smb_shm_offset_t new_off;
- share_mode_record *new_p;
+ unbecome_user();
+ if(unlink(fname) != 0)
+ {
+ DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n",
+ fname, strerror(errno)));
+ }
+
+ DEBUG(5,("delete_share_file: Deleted share file %s\n", fname));
+
+ if(!become_user(cnum,Connections[cnum].vuid))
+ {
+ DEBUG(0,("delete_share_file: Can't become connected user!\n"));
+ return -1;
+ }
+ /* We need to change directory back to the connection root. */
+ if (ChDir(Connections[cnum].connectpath) != 0)
+ {
+ DEBUG(0,("delete_share_file: Can't change directory to %s (%s)\n",
+ Connections[cnum].connectpath, strerror(errno)));
+ return -1;
+ }
+ return 0;
+}
+
+/*******************************************************************
+Read a share file into a buffer.
+********************************************************************/
+
+static int read_share_file(int cnum, int fd, char *fname, char **out, BOOL *p_new_file)
+{
+ struct stat sb;
+ char *buf;
+ int size;
+
+ *out = 0;
+ *p_new_file = False;
+
+ if(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(sb.st_size)) == NULL)
+ {
+ DEBUG(0,("read_share_file: malloc for file size %d fail !\n", sb.st_size));
+ return -1;
+ }
+ if(lseek(fd, 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 (fstat(Files[fnum].fd_ptr->fd,&st) != 0) return(False);
+ if (read(fd,buf,sb.st_size) != 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 (!smb_shm_lock()) return (False);
- new_off = smb_shm_alloc(sizeof(share_mode_record) + strlen(Files[fnum].name) );
- if (new_off == NULL_OFFSET) return (False);
- new_p = (share_mode_record *)smb_shm_offset2addr(new_off);
- new_p->locking_version = LOCKING_VERSION;
- new_p->share_mode = mode;
- new_p->time.tv_sec = Files[fnum].open_time.tv_sec;
- new_p->time.tv_usec = Files[fnum].open_time.tv_usec;
- new_p->pid = pid;
- new_p->st_dev = st.st_dev;
- new_p->st_ino = st.st_ino;
- strcpy(new_p->file_name,Files[fnum].name);
- new_p->next_offset = smb_shm_get_userdef_off();
- smb_shm_set_userdef_off(new_off);
-
-
- DEBUG(3,("Created share record for %s with mode 0x%X pid=%d\n",Files[fnum].name,mode,pid));
-
- if (!smb_shm_unlock()) return (False);
- return(True);
+ if (IVAL(buf,0) != LOCKING_VERSION) {
+ DEBUG(0,("ERROR: read_share_file: share file %s has incorrect \
+locking version (was %d, should be %d).\n",fname, IVAL(buf,0), LOCKING_VERSION));
+ if(buf)
+ free(buf);
+ delete_share_file(cnum, fname);
+ return -1;
+ }
+
+ /* Sanity check for file contents */
+ size = sb.st_size;
+ size -= 10; /* Remove the header */
+
+ /* Remove the filename component. */
+ size -= SVAL(buf, 8);
+
+ /* The remaining size must be a multiple of 16 - error if not. */
+ if((size % 16) != 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(cnum, fname);
+ return -1;
+ }
-#else
+ *out = buf;
+ return 0;
+}
+
+/*******************************************************************
+get all share mode entries in a share file for a dev/inode pair.
+********************************************************************/
+int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode,
+ min_share_mode_entry **old_shares)
+{
+ int fd = (int)token;
pstring fname;
- int fd2;
- char buf[20];
- int pid = (int)getpid();
+ int i;
+ int num_entries;
+ int num_entries_copied;
+ int newsize;
+ min_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).
- if (!share_name_fnum(fnum,fname)) return(False);
+ Followed by <n> share mode entries of the form :
+ 0 - tv_sec
+ 4 - tv_usec
+ 8 - share_mode
+ 12 - pid
+
+ */
+
+ share_name(cnum, dev, inode, fname);
+
+ if(read_share_file( cnum, fd, fname, &buf, &new_file) != 0)
{
- int old_umask = umask(0);
- fd2 = open(fname,O_WRONLY|O_CREAT|O_TRUNC,0644);
- umask(old_umask);
+ DEBUG(0,("ERROR: get_share_modes: Failed to read share file %s\n",
+ fname));
+ return 0;
}
- if (fd2 < 0) {
- DEBUG(2,("Failed to create share file %s\n",fname));
- return(False);
+
+ if(new_file == True)
+ return 0;
+
+ num_entries = IVAL(buf,4);
+
+ 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 %d\n", num_entries, fname));
+ abort();
}
- SIVAL(buf,0,LOCKING_VERSION);
- SIVAL(buf,4,Files[fnum].open_time.tv_sec);
- SIVAL(buf,8,Files[fnum].open_time.tv_usec);
- SIVAL(buf,12,mode);
- SIVAL(buf,16,pid);
+ if(num_entries)
+ {
+ *old_shares = share_array = (min_share_mode_entry *)
+ malloc(num_entries * sizeof(min_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(cnum, fname);
+ return 0;
+ }
- if (write(fd2,buf,20) != 20) {
- DEBUG(2,("Failed to write share file %s\n",fname));
- close(fd2);
- unlink(fname);
- return(False);
+ num_entries_copied = 0;
+ base = buf + 10 + SVAL(buf,8);
+
+ for( i = 0; i < num_entries; i++)
+ {
+ int pid;
+ char *p = base + (i*16);
+
+ pid = IVAL(p,12);
+
+ 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",
+ pid, IVAL(p,8), fname));
+ continue;
+ }
+ share_array[num_entries_copied].time.tv_sec = IVAL(p,0);
+ share_array[num_entries_copied].time.tv_usec = IVAL(p,4);
+ share_array[num_entries_copied].share_mode = IVAL(p,8);
+ share_array[num_entries_copied].pid = pid;
+
+ num_entries_copied++;
}
- write(fd2,Files[fnum].name,strlen(Files[fnum].name)+1);
+ 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);
+ if(buf)
+ free(buf);
+ delete_share_file(cnum, fname);
+ return 0;
+ }
- close(fd2);
+ /* If we deleted some entries we need to re-write the whole number of
+ share mode entries back into the file. */
- DEBUG(3,("Created share file %s with mode 0x%X pid=%d\n",fname,mode,pid));
+ if(num_entries_copied != num_entries)
+ {
+ if(lseek(fd, 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);
+ if(buf)
+ free(buf);
+ return 0;
+ }
- return(True);
-#endif
+ SIVAL(buf, 4, num_entries_copied);
+ for( i = 0; i < num_entries_copied; i++)
+ {
+ char *p = base + (i*16);
+
+ SIVAL(p,12,share_array[i].pid);
+ SIVAL(p,8,share_array[i].share_mode);
+ SIVAL(p,0,share_array[i].time.tv_sec);
+ SIVAL(p,4,share_array[i].time.tv_usec);
+ }
+
+ newsize = (base - buf) + (16*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);
+ if(buf)
+ free(buf);
+ return 0;
+ }
+ /* Now truncate the file at this point. */
+ if(ftruncate(fd, newsize)!= 0)
+ {
+ 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);
+ if(buf)
+ free(buf);
+ return 0;
+ }
+ }
+
+ 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;
}
-
/*******************************************************************
-cleanup any stale share files
+del a share mode from a share mode file.
********************************************************************/
-void clean_share_modes(void)
+void del_share_mode(share_lock_token token, int fnum)
{
-#ifdef USE_SHMEM
- share_mode_record *scanner_p;
- share_mode_record *prev_p;
+ pstring fname;
+ int fd = (int)token;
+ char *buf = 0;
+ char *base = 0;
+ int num_entries;
+ int newsize;
+ int i;
+ files_struct *fs_p = &Files[fnum];
int pid;
-
- if (!smb_shm_lock()) return;
-
- scanner_p = (share_mode_record *)smb_shm_offset2addr(smb_shm_get_userdef_off());
- prev_p = scanner_p;
- while(scanner_p)
+ BOOL deleted = False;
+ BOOL new_file;
+
+ share_name(fs_p->cnum, fs_p->fd_ptr->dev,
+ fs_p->fd_ptr->inode, fname);
+
+ if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0)
{
- pid = scanner_p->pid;
-
- if( (scanner_p->locking_version != LOCKING_VERSION) || !process_exists(pid))
- {
- DEBUG(2,("Deleting stale share mode record"));
- if(prev_p == scanner_p)
- {
- smb_shm_set_userdef_off(scanner_p->next_offset);
- smb_shm_free(smb_shm_addr2offset(scanner_p));
- scanner_p = (share_mode_record *)smb_shm_offset2addr(smb_shm_get_userdef_off());
- prev_p = scanner_p;
- }
- else
- {
- prev_p->next_offset = scanner_p->next_offset;
- smb_shm_free(smb_shm_addr2offset(scanner_p));
- scanner_p = (share_mode_record *)smb_shm_offset2addr(prev_p->next_offset);
- }
-
- }
- else
- {
- prev_p = scanner_p ;
- scanner_p = (share_mode_record *)smb_shm_offset2addr(scanner_p->next_offset);
- }
+ DEBUG(0,("ERROR: del_share_mode: Failed to read share file %s\n",
+ fname));
+ return;
}
-
- smb_shm_unlock();
- return;
-
-#else
- char *lockdir = lp_lockdir();
- void *dir;
- char *s;
+ if(new_file == True)
+ {
+ DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n",
+ fname));
+ delete_share_file(fs_p->cnum, fname);
+ return;
+ }
- if (!*lockdir) return;
+ num_entries = IVAL(buf,4);
- dir = opendir(lockdir);
- if (!dir) return;
+ DEBUG(5,("del_share_mode: share file %s has %d share mode entries.\n",
+ fname, num_entries));
- while ((s=readdirname(dir))) {
- char buf[20];
- int pid;
- int fd;
- pstring lname;
- int dev,inode;
+ /* PARANOIA TEST */
+ if(num_entries < 0)
+ {
+ DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \
+for share file %d\n", num_entries, fname));
+ abort();
+ }
- if (sscanf(s,"share.%d.%d",&dev,&inode)!=2) continue;
+ 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(fs_p->cnum, fname);
+ return;
+ }
- strcpy(lname,lp_lockdir());
- trim_string(lname,NULL,"/");
- strcat(lname,"/");
- strcat(lname,s);
+ pid = getpid();
- fd = open(lname,O_RDONLY,0);
- if (fd < 0) continue;
+ /* Go through the entries looking for the particular one
+ we have set - delete it.
+ */
- if (read(fd,buf,20) != 20) {
- close(fd);
- if (!unlink(lname))
- printf("Deleted corrupt share file %s\n",s);
+ base = buf + 10 + SVAL(buf,8);
+
+ for(i = 0; i < num_entries; i++)
+ {
+ char *p = base + (i*16);
+
+ if((IVAL(p,0) != fs_p->open_time.tv_sec) || (IVAL(p,4) != fs_p->open_time.tv_usec) ||
+ (IVAL(p,8) != fs_p->share_mode) || (IVAL(p,12) != 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 + 16, (num_entries - i - 1)*16);
+
+ 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,4, 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(fs_p->cnum,fname);
+ return;
+ }
+
+ /* Re-write the file - and truncate it at the correct point. */
+ if(lseek(fd, 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;
}
- close(fd);
- pid = IVAL(buf,16);
+ newsize = (base - buf) + (16*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. */
+ if(ftruncate(fd, newsize) != 0)
+ {
+ 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;
+ }
+}
+
+/*******************************************************************
+set the share mode of a file
+********************************************************************/
+BOOL set_share_mode(share_lock_token token,int fnum)
+{
+ files_struct *fs_p = &Files[fnum];
+ pstring fname;
+ int fd = (int)token;
+ int pid = (int)getpid();
+ struct stat sb;
+ char *buf;
+ int num_entries;
+ int header_size;
+ char *p;
+
+ share_name(fs_p->cnum, fs_p->fd_ptr->dev,
+ fs_p->fd_ptr->inode, fname);
+
+ if(fstat(fd, &sb) != 0)
+ {
+ DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n",
+ fname));
+ return False;
+ }
- if (IVAL(buf,0) != LOCKING_VERSION || !process_exists(pid)) {
- if (!unlink(lname))
- printf("Deleted stale share file %s\n",s);
+ /* Sanity check for file contents (if it's not a new share file). */
+ if(sb.st_size != 0)
+ {
+ int size = sb.st_size;
+
+ /* Allocate space for the file plus one extra entry */
+ if((buf = (char *)malloc(sb.st_size + 16)) == NULL)
+ {
+ DEBUG(0,("set_share_mode: malloc for file size %d fail !\n", sb.st_size + 16));
+ return False;
+ }
+
+ if(lseek(fd, 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,sb.st_size) != 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,0) != LOCKING_VERSION)
+ {
+ DEBUG(0,("ERROR: set_share_mode: share file %s has incorrect \
+locking version (was %d, should be %d).\n",fname, IVAL(buf,0), LOCKING_VERSION));
+ if(buf)
+ free(buf);
+ delete_share_file(fs_p->cnum, fname);
+ return False;
+ }
+
+ size -= (10 + SVAL(buf, 8)); /* Remove the header */
+
+ /* The remaining size must be a multiple of 16 - error if not. */
+ if((size % 16) != 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(fs_p->cnum, fname);
+ return False;
+ }
+
}
+ else
+ {
+ /* New file - just use a single_entry. */
+ if((buf = (char *)malloc(10 + strlen(fs_p->name) + 1 + 16)) == NULL)
+ {
+ DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n"));
+ return False;
+ }
+ SIVAL(buf,0,LOCKING_VERSION);
+ SIVAL(buf,4,0);
+ SSVAL(buf,8,strlen(fs_p->name) + 1);
+ strcpy(buf + 10, fs_p->name);
+ }
+
+ num_entries = IVAL(buf,4);
+ header_size = 10 + SVAL(buf,8);
+ p = buf + header_size + (num_entries * 16);
+ SIVAL(p,0,fs_p->open_time.tv_sec);
+ SIVAL(p,4,fs_p->open_time.tv_usec);
+ SIVAL(p,8,fs_p->share_mode);
+ SIVAL(p,12,pid);
+
+ num_entries++;
+
+ SIVAL(buf,4,num_entries);
+
+ if(lseek(fd, 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*16)) != (header_size + (num_entries*16)))
+ {
+ DEBUG(2,("ERROR: set_share_mode: Failed to write share file %s - \
+deleting it (%s).\n",fname, strerror(errno)));
+ delete_share_file(fs_p->cnum, fname);
+ if(buf)
+ free(buf);
+ return False;
+ }
+
+ /* Now truncate the file at this point - just for safety. */
+ if(ftruncate(fd, header_size + (16*num_entries))!= 0)
+ {
+ DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \
+mode file %s to size %d (%s)\n", fname, header_size + (16*num_entries), strerror(errno)));
+ if(buf)
+ free(buf);
+ return False;
+ }
+
+ if(buf)
+ free(buf);
+
+ DEBUG(3,("set_share_mode: Created share file %s with \
+mode 0x%X pid=%d\n",fname,fs_p->share_mode,pid));
- closedir(dir);
-#endif
+ return True;
}
+#endif /* FAST_SHARE_MODES */
diff --git a/source3/locking/shmem.c b/source3/locking/shmem.c
index 2c02982d04..9d4e62bdd7 100644
--- a/source3/locking/shmem.c
+++ b/source3/locking/shmem.c
@@ -23,7 +23,7 @@
#include "includes.h"
-#if FAST_SHARE_MODES
+#ifdef FAST_SHARE_MODES
extern int DEBUGLEVEL;
@@ -32,7 +32,7 @@ extern int DEBUGLEVEL;
#define SMB_SHM_MAGIC 0x53484100
/* = "SHM" in hex */
-#define SMB_SHM_VERSION 1
+#define SMB_SHM_VERSION 2
/* WARNING : offsets are used because mmap() does not guarantee that all processes have the
shared memory mapped to the same address */
@@ -73,15 +73,109 @@ 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 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(2,("smb_shm_global_lock : locked %d times\n",smb_shm_times_locked));
+ return True;
+ }
+
+ /* Do an exclusive wait lock on the first byte of the file */
+ if (fcntl_lock(smb_shm_fd, F_SETLKW, 0, 1, F_WRLCK) == False)
+ {
+ DEBUG(0,("ERROR smb_shm_global_lock : fcntl_lock failed with code %d\n",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",smb_shm_fd));
+ return False;
+ }
+
+ smb_shm_times_locked--;
+
+ if(smb_shm_times_locked > 0)
+ {
+ DEBUG(2,("smb_shm_global_unlock : still locked %d times\n",smb_shm_times_locked));
+ return True;
+ }
+
+ /* Do a wait unlock on the first byte of the file */
+ if (fcntl_lock(smb_shm_fd, F_SETLKW, 0, 1, F_UNLCK) == False)
+ {
+ DEBUG(0,("ERROR smb_shm_global_unlock : fcntl_lock failed with code %d\n",errno));
+ smb_shm_times_locked++;
+ return False;
+ }
+
+ return True;
+
+}
+
+/*
+ * Function to create the hash table for the share mode entries. Called
+ * when smb shared memory is global locked.
+ */
+
+BOOL smb_shm_create_hash_table( unsigned int size )
+{
+ size *= sizeof(smb_shm_offset_t);
+
+ smb_shm_global_lock();
+ smb_shm_header_p->userdef_off = smb_shm_alloc( size );
+
+ if(smb_shm_header_p->userdef_off == NULL_OFFSET)
+ {
+ 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;
+ int seek_back = -sizeof(other_pid);
int free_slot = -1;
int erased_slot;
+#ifndef SECURE_SHARE_MODES
smb_shm_processes_fd = open(processreg_file, O_RDWR | O_CREAT, 0666);
+#else /* SECURE_SHARE_MODES */
+ smb_shm_processes_fd = open(processreg_file, O_RDWR | O_CREAT, 0600);
+#endif /* SECURE_SHARE_MODES */
if ( smb_shm_processes_fd < 0 )
{
DEBUG(0,("ERROR smb_shm_register_process : processreg_file open failed with code %d\n",errno));
@@ -99,9 +193,10 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth
else
{
/* erase old pid */
- DEBUG(2,("smb_shm_register_process : erasing stale record for pid %d\n",other_pid));
+ DEBUG(2,("smb_shm_register_process : erasing stale record for pid %d (seek_back = %d)\n",
+ other_pid, seek_back));
other_pid = (pid_t)0;
- erased_slot = lseek(smb_shm_processes_fd, -sizeof(other_pid), SEEK_CUR);
+ erased_slot = lseek(smb_shm_processes_fd, seek_back, SEEK_CUR);
write(smb_shm_processes_fd, &other_pid, sizeof(other_pid));
if(free_slot < 0)
free_slot = erased_slot;
@@ -109,7 +204,7 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth
}
else
if(free_slot < 0)
- free_slot = lseek(smb_shm_processes_fd, -sizeof(other_pid), SEEK_CUR);
+ free_slot = lseek(smb_shm_processes_fd, seek_back, SEEK_CUR);
}
if (nb_read < 0)
{
@@ -141,6 +236,7 @@ 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;
+ int seek_back = -sizeof(other_pid);
int erased_slot;
BOOL found = False;
@@ -156,12 +252,14 @@ static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid)
while ((nb_read = read(smb_shm_processes_fd, &other_pid, sizeof(other_pid))) > 0)
{
+ DEBUG(2,("smb_shm_unregister_process : read record for pid %d\n",other_pid));
if(other_pid == pid)
{
/* erase pid */
- DEBUG(2,("smb_shm_unregister_process : erasing record for pid %d\n",other_pid));
+ DEBUG(2,("smb_shm_unregister_process : erasing record for pid %d (seek_val = %d)\n",
+ other_pid, seek_back));
other_pid = (pid_t)0;
- erased_slot = lseek(smb_shm_processes_fd, -sizeof(other_pid), SEEK_CUR);
+ erased_slot = lseek(smb_shm_processes_fd, seek_back, SEEK_CUR);
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 %d\n",errno));
@@ -257,6 +355,8 @@ static BOOL smb_shm_initialize(int size)
smb_shm_header_p->consistent = True;
+ smb_shm_initialize_called = True;
+
return True;
}
@@ -291,7 +391,11 @@ BOOL smb_shm_open( char *file_name, int size)
DEBUG(2,("smb_shm_open : using shmem file %s to be of size %d\n",file_name,size));
old_umask = umask(0);
+#ifndef SECURE_SHARE_MODES
smb_shm_fd = open(file_name, O_RDWR | O_CREAT, 0666);
+#else /* SECURE_SHARE_MODES */
+ smb_shm_fd = open(file_name, O_RDWR | O_CREAT, 0600);
+#endif /* SECURE_SHARE_MODE */
umask(old_umask);
if ( smb_shm_fd < 0 )
{
@@ -299,16 +403,16 @@ BOOL smb_shm_open( char *file_name, int size)
return False;
}
- if (!smb_shm_lock())
+ if (!smb_shm_global_lock())
{
- DEBUG(0,("ERROR smb_shm_open : can't do smb_shm_lock\n"));
+ DEBUG(0,("ERROR smb_shm_open : can't do smb_shm_global_lock\n"));
return False;
}
if( (filesize = lseek(smb_shm_fd, 0, SEEK_END)) < 0)
{
DEBUG(0,("ERROR smb_shm_open : lseek failed with code %d\n",errno));
- smb_shm_unlock();
+ smb_shm_global_unlock();
close(smb_shm_fd);
return False;
}
@@ -332,7 +436,7 @@ BOOL smb_shm_open( char *file_name, int size)
if (! smb_shm_register_process(smb_shm_processreg_name, getpid(), &other_processes))
{
- smb_shm_unlock();
+ smb_shm_global_unlock();
close(smb_shm_fd);
return False;
}
@@ -344,7 +448,7 @@ BOOL smb_shm_open( char *file_name, int size)
{
DEBUG(0,("ERROR smb_shm_open : ftruncate failed with code %d\n",errno));
smb_shm_unregister_process(smb_shm_processreg_name, getpid());
- smb_shm_unlock();
+ smb_shm_global_unlock();
close(smb_shm_fd);
return False;
}
@@ -369,7 +473,7 @@ BOOL smb_shm_open( char *file_name, int size)
{
DEBUG(0,("ERROR smb_shm_open : mmap failed with code %d\n",errno));
smb_shm_unregister_process(smb_shm_processreg_name, getpid());
- smb_shm_unlock();
+ smb_shm_global_unlock();
close(smb_shm_fd);
return False;
}
@@ -378,6 +482,8 @@ BOOL smb_shm_open( char *file_name, int size)
if (created_new || !other_processes)
{
smb_shm_initialize(size);
+ /* Create the hash buckets for the share file entries. */
+ smb_shm_create_hash_table( lp_shmem_hash_size() );
}
else if (!smb_shm_validate_header(size) )
{
@@ -385,12 +491,12 @@ BOOL smb_shm_open( char *file_name, int size)
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_unlock();
+ smb_shm_global_unlock();
close(smb_shm_fd);
return False;
}
- smb_shm_unlock();
+ smb_shm_global_unlock();
return True;
}
@@ -399,17 +505,22 @@ BOOL smb_shm_open( char *file_name, int size)
BOOL smb_shm_close( void )
{
+ if(smb_shm_initialize_called == False)
+ return True;
+
DEBUG(2,("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 ( munmap((caddr_t)smb_shm_header_p, smb_shm_header_p->total_size) < 0)
+ 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 %d\n",errno));
}
- smb_shm_lock();
+ smb_shm_global_lock();
+ DEBUG(2,("calling smb_shm_unregister_process(%s, %d)\n", smb_shm_processreg_name, getpid()));
smb_shm_unregister_process(smb_shm_processreg_name, getpid());
- smb_shm_unlock();
+ smb_shm_global_unlock();
close(smb_shm_fd);
@@ -438,9 +549,12 @@ smb_shm_offset_t smb_shm_alloc(int size)
return NULL_OFFSET;
}
+ 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 NULL_OFFSET;
}
@@ -463,6 +577,7 @@ smb_shm_offset_t smb_shm_alloc(int size)
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 (NULL_OFFSET);
}
@@ -516,6 +631,7 @@ smb_shm_offset_t smb_shm_alloc(int size)
DEBUG(2,("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 );
}
@@ -534,9 +650,12 @@ BOOL smb_shm_free(smb_shm_offset_t offset)
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;
}
@@ -545,6 +664,7 @@ BOOL smb_shm_free(smb_shm_offset_t offset)
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;
}
@@ -577,6 +697,7 @@ BOOL smb_shm_free(smb_shm_offset_t offset)
smb_shm_solve_neighbors( header_p ); /* if neighbors then link them */
smb_shm_header_p->consistent = True;
+ smb_shm_global_unlock();
return True;
}
else
@@ -590,6 +711,7 @@ BOOL smb_shm_free(smb_shm_offset_t offset)
smb_shm_solve_neighbors(prev_p) ;
smb_shm_header_p->consistent = True;
+ smb_shm_global_unlock();
return True;
}
}
@@ -633,68 +755,71 @@ smb_shm_offset_t smb_shm_addr2offset(void *addr)
return (smb_shm_offset_t)((char *)addr - (char *)smb_shm_header_p);
}
-BOOL smb_shm_lock(void)
+/*******************************************************************
+ Lock a particular hash bucket entry.
+ ******************************************************************/
+
+BOOL smb_shm_lock_hash_entry( unsigned int entry)
{
- if (smb_shm_fd < 0)
- {
- DEBUG(0,("ERROR smb_shm_lock : bad smb_shm_fd (%d)\n",smb_shm_fd));
+ int start = (smb_shm_header_p->userdef_off + (entry * sizeof(smb_shm_offset_t)));
+
+ if (smb_shm_fd < 0)
+ {
+ DEBUG(0,("ERROR smb_shm_lock_hash_entry : bad smb_shm_fd (%d)\n",smb_shm_fd));
return False;
- }
-
- smb_shm_times_locked++;
-
- if(smb_shm_times_locked > 1)
- {
- DEBUG(2,("smb_shm_lock : locked %d times\n",smb_shm_times_locked));
- return True;
- }
-
- if (lockf(smb_shm_fd, F_LOCK, 0) < 0)
- {
- DEBUG(0,("ERROR smb_shm_lock : lockf failed with code %d\n",errno));
- smb_shm_times_locked--;
+ }
+
+ if(entry >= lp_shmem_hash_size())
+ {
+ DEBUG(0,("ERROR smb_shm_lock_hash_entry : hash entry size too big (%d)\n", entry));
return False;
- }
-
- return True;
-
+ }
+
+ /* Do an exclusive wait lock on the 4 byte region mapping into this entry */
+ if (fcntl_lock(smb_shm_fd, F_SETLKW, start, sizeof(smb_shm_offset_t), F_WRLCK) == False)
+ {
+ DEBUG(0,("ERROR smb_shm_lock_hash_entry : fcntl_lock failed with code %d\n",errno));
+ return False;
+ }
+
+ DEBUG(9,("smb_shm_lock_hash_entry: locked hash bucket %d\n", entry));
+ return True;
}
+/*******************************************************************
+ Unlock a particular hash bucket entry.
+ ******************************************************************/
-
-BOOL smb_shm_unlock(void)
+BOOL smb_shm_unlock_hash_entry( unsigned int entry )
{
- if (smb_shm_fd < 0)
- {
- DEBUG(0,("ERROR smb_shm_unlock : bad smb_shm_fd (%d)\n",smb_shm_fd));
+ int start = (smb_shm_header_p->userdef_off + (entry * sizeof(smb_shm_offset_t)));
+
+ 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(smb_shm_times_locked == 0)
- {
- DEBUG(0,("ERROR smb_shm_unlock : shmem not locked\n",smb_shm_fd));
+ if(entry >= lp_shmem_hash_size())
+ {
+ DEBUG(0,("ERROR smb_shm_unlock_hash_entry : hash entry size too big (%d)\n", entry));
return False;
- }
-
- smb_shm_times_locked--;
-
- if(smb_shm_times_locked > 0)
- {
- DEBUG(2,("smb_shm_unlock : still locked %d times\n",smb_shm_times_locked));
- return True;
- }
-
- if (lockf(smb_shm_fd, F_ULOCK, 0) < 0)
- {
- DEBUG(0,("ERROR smb_shm_unlock : lockf failed with code %d\n",errno));
- smb_shm_times_locked++;
+ }
+
+ /* Do a wait lock on the 4 byte region mapping into this entry */
+ if (fcntl_lock(smb_shm_fd, F_SETLKW, start, sizeof(smb_shm_offset_t), F_UNLCK) == False)
+ {
+ DEBUG(0,("ERROR smb_shm_unlock_hash_entry : fcntl_lock failed with code %d\n",errno));
return False;
- }
-
- return True;
-
+ }
+
+ DEBUG(9,("smb_shm_unlock_hash_entry: unlocked hash bucket %d\n", entry));
+ return True;
}
+/*******************************************************************
+ Gather statistics on shared memory usage.
+ ******************************************************************/
BOOL smb_shm_get_usage(int *bytes_free,
int *bytes_used,
@@ -716,4 +841,4 @@ BOOL smb_shm_get_usage(int *bytes_free,
#else /* FAST_SHARE_MODES */
int shmem_dummy_procedure(void)
{return 0;}
-#endif
+#endif /* FAST_SHARE_MODES */
diff --git a/source3/nameannounce.c b/source3/nameannounce.c
index b46436168c..7d7a95334c 100644
--- a/source3/nameannounce.c
+++ b/source3/nameannounce.c
@@ -35,6 +35,7 @@ extern BOOL CanRecurse;
extern struct in_addr ipzero;
extern pstring myname;
+extern fstring myworkgroup;
extern int ClientDGRAM;
extern int ClientNMB;
@@ -185,9 +186,9 @@ void do_announce_host(int command,
/****************************************************************************
- remove all samba's server entries
- ****************************************************************************/
-void remove_my_servers(void)
+announce all samba's server entries as 'gone'.
+****************************************************************************/
+void announce_my_servers_removed(void)
{
struct subnet_record *d;
for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
@@ -372,7 +373,7 @@ static time_t announce_timer_last=0;
void reset_announce_timer()
{
- announce_timer_last = 0;
+ announce_timer_last = time(NULL) - (CHECK_TIME_MST_ANNOUNCE * 60);
}
/****************************************************************************
@@ -396,7 +397,7 @@ void announce_master(time_t t)
return;
}
- if(wins_subnet == 0)
+ if(wins_subnet == NULL)
{
DEBUG(10,("announce_master: no wins subnet, ignoring.\n"));
return;
@@ -412,19 +413,19 @@ void announce_master(time_t t)
if (AM_MASTER(work))
{
am_master = True;
+ DEBUG(4,( "announce_master: am_master = %d for \
+workgroup %s\n", am_master, work->work_group));
}
}
}
- DEBUG(4,( "announce_master: am_master = %d for workgroup %s\n", am_master, lp_workgroup()));
-
if (!am_master) return; /* only proceed if we are a master browser */
/* Note that we don't do this if we are domain master browser
and that we *only* do this on the WINS subnet. */
/* Try and find our workgroup on the WINS subnet */
- work = find_workgroupstruct(wins_subnet, lp_workgroup(), False);
+ work = find_workgroupstruct(wins_subnet, myworkgroup, False);
if (work)
{
@@ -488,7 +489,7 @@ in our own WINS database.\n", work->work_group));
/* Check that this isn't one of our addresses (ie. we are not domain master
ourselves) */
- if(ismyip(nr->ip_flgs[0].ip))
+ if(ismyip(nr->ip_flgs[0].ip) || ip_equal(nr->ip_flgs[0].ip, ipzero))
{
DEBUG(4, ("announce_master: domain master ip found (%s) for workgroup %s \
is one of our interfaces.\n", work->work_group, inet_ntoa(nr->ip_flgs[0].ip) ));
@@ -535,7 +536,7 @@ void announce_remote(time_t t)
if (!*s) return;
comment = lp_serverstring();
- workgroup = lp_workgroup();
+ workgroup = myworkgroup;
for (ptr=s; next_token(&ptr,s2,NULL); ) {
/* the entries are of the form a.b.c.d/WORKGROUP with
diff --git a/source3/nameconf.c b/source3/nameconf.c
index 99951a3b0e..8f33419b9a 100644
--- a/source3/nameconf.c
+++ b/source3/nameconf.c
@@ -35,6 +35,8 @@
#include "includes.h"
extern int DEBUGLEVEL;
+extern fstring myworkgroup;
+
#if 0
struct smbbrowse_parms
{
@@ -104,7 +106,7 @@ static struct smbbrowse *new_workgroup(struct smbbrowse *model,
StrnCpy(new->work_name, workgroup_name, 15);
strupper(new->work_name);
- if (strequal(lp_workgroup(), workgroup_name))
+ if (strequal(myworkgroup, workgroup_name))
StrnCpy(new->browsing_alias, default_name, 15);
else
sprintf(new->browsing_alias, "%.14s%x", default_name, nexttoken);
@@ -289,7 +291,7 @@ static void default_smbbrowse_conf(char *default_name)
struct smbbrowse *w;
/* The workgroup specified in smb.conf */
- w = new_workgroup((struct smbbrowse *)NULL, lp_workgroup(), default_name);
+ w = new_workgroup((struct smbbrowse *)NULL, myworkgroup, default_name);
w->should_local_master = lp_preferred_master();
w->should_domain_master = lp_domain_master();
w->should_workgroup_member = True;
diff --git a/source3/namedbname.c b/source3/namedbname.c
index 2e0afc1497..aa41726450 100644
--- a/source3/namedbname.c
+++ b/source3/namedbname.c
@@ -153,11 +153,13 @@ struct name_record *find_name(struct name_record *n,
{
continue;
}
- DEBUG(9,("find_name: found name %s\n", name->name));
+ DEBUG(9,("find_name: found name %s(%02x)\n",
+ name->name, name->name_type));
return ret;
}
}
- DEBUG(9,("find_name: name %s NOT FOUND\n", name->name));
+ DEBUG(9,("find_name: name %s(%02x) NOT FOUND\n", name->name,
+ name->name_type));
return NULL;
}
@@ -528,7 +530,6 @@ struct name_record *dns_name_search(struct nmb_name *question, int Time)
{
int name_type = question->name_type;
char *qname = question->name;
- char *r;
BOOL dns_type = (name_type == 0x20 || name_type == 0);
struct in_addr dns_ip;
diff --git a/source3/namedbserver.c b/source3/namedbserver.c
index 9c7bb664ab..8cad8a3a11 100644
--- a/source3/namedbserver.c
+++ b/source3/namedbserver.c
@@ -37,6 +37,7 @@ extern int ClientDGRAM;
extern int DEBUGLEVEL;
extern pstring myname;
+extern fstring myworkgroup;
/* this is our domain/workgroup/server database */
extern struct subnet_record *subnetlist;
@@ -161,7 +162,7 @@ struct server_record *add_server_entry(struct subnet_record *d,
}
- if (strequal(lp_workgroup(),work->work_group))
+ if (strequal(myworkgroup,work->work_group))
{
if (servertype)
servertype |= SV_TYPE_LOCAL_LIST_ONLY;
diff --git a/source3/namedbsubnet.c b/source3/namedbsubnet.c
index 25c369ab1c..393db363d8 100644
--- a/source3/namedbsubnet.c
+++ b/source3/namedbsubnet.c
@@ -40,6 +40,7 @@ extern struct in_addr wins_ip;
extern struct in_addr ipzero;
extern pstring myname;
+extern fstring myworkgroup;
BOOL updatedlists = True;
int updatecount = 0;
@@ -52,15 +53,10 @@ struct subnet_record *subnetlist = NULL;
/* WINS subnet - keep this separate so enumeration code doesn't
run onto it by mistake. */
-struct subnet_record *wins_subnet = 0;
+struct subnet_record *wins_subnet = NULL;
extern uint16 nb_type; /* samba's NetBIOS name type */
-/* Forward references. */
-static struct subnet_record *add_subnet_entry(struct in_addr bcast_ip,
- struct in_addr mask_ip,
- char *name, BOOL add, BOOL lmhosts);
-
/****************************************************************************
add a domain into the list
**************************************************************************/
@@ -129,6 +125,7 @@ struct subnet_record *find_subnet_all(struct in_addr bcast_ip)
struct subnet_record *d = find_subnet(bcast_ip);
if(!d)
return wins_subnet;
+ return d;
}
/****************************************************************************
@@ -156,121 +153,122 @@ static struct subnet_record *make_subnet(struct in_addr bcast_ip, struct in_addr
return d;
}
-
/****************************************************************************
- add the remote interfaces from lp_interfaces()
- to the netbios subnet database.
+ add a domain entry. creates a workgroup, if necessary, and adds the domain
+ to the named a workgroup.
****************************************************************************/
-void add_subnet_interfaces(void)
+static struct subnet_record *add_subnet_entry(struct in_addr bcast_ip,
+ struct in_addr mask_ip, char *name,
+ BOOL create_subnets, BOOL add)
{
- struct interface *i;
+ struct subnet_record *d = NULL;
- /* loop on all local interfaces */
- for (i = local_interfaces; i; i = i->next)
- {
- /* add the interface into our subnet database */
- if (!find_subnet(i->bcast))
- {
- make_subnet(i->bcast,i->nmask, True);
- }
- }
+ if (zero_ip(bcast_ip))
+ bcast_ip = *iface_bcast(bcast_ip);
+
+ /* Note that we should also add into the WINS subnet as add_subnet_entry
+ should be called to add NetBIOS names and server entries on all
+ interfaces, including the WINS interface
+ */
- /* add the pseudo-ip interface for WINS: 255.255.255.255 */
- if (lp_wins_support() || (*lp_wins_server()))
+ if(create_subnets == True)
+ {
+ /* Create new subnets. */
+ if((d = make_subnet(bcast_ip, mask_ip, add)) == NULL)
{
- struct in_addr wins_bcast = wins_ip;
- struct in_addr wins_nmask = ipzero;
- wins_subnet = make_subnet(wins_bcast, wins_nmask, False);
+ DEBUG(0,("add_subnet_entry: Unable to create subnet %s\n",
+ inet_ntoa(bcast_ip) ));
+ return NULL;
}
+ return d;
+ }
+ if(ip_equal(bcast_ip, wins_ip))
+ return wins_subnet;
+ return find_subnet(bcast_ip);
}
-
-
/****************************************************************************
- add the default workgroup into the subnet lists.
- **************************************************************************/
-void add_my_subnets(char *group)
+ Add a workgroup into a subnet, and if it's our primary workgroup,
+ add the required names to it.
+**************************************************************************/
+
+void add_workgroup_to_subnet( struct subnet_record *d, char *group)
{
- struct interface *i;
+ struct work_record *w = NULL;
- /* add or find domain on our local subnet, in the default workgroup */
-
- if (*group == '*') return;
+ DEBUG(5,("add_workgroup_to_subnet: Adding workgroup %s to subnet %s\n",
+ group, inet_ntoa(d->bcast_ip)));
- /* the coding choice is up to you, andrew: i can see why you don't want
- global access to the local_interfaces structure: so it can't get
- messed up! */
- for (i = local_interfaces; i; i = i->next)
- {
- add_subnet_entry(i->bcast,i->nmask,group, True, False);
- }
+ /* This next statement creates the workgroup struct if it doesn't
+ already exist.
+ */
+ if((w = find_workgroupstruct(d, group, True)) == NULL)
+ {
+ DEBUG(0,("add_workgroup_to_subnet: Unable to add workgroup %s to subnet %s\n",
+ group, inet_ntoa(d->bcast_ip) ));
+ return;
+ }
- /* If we are setup as a domain master browser, and are using
- WINS, then we must add the workgroup to the WINS subnet. This
- is used as a place to keep collated server lists. */
-
- if(lp_domain_master() && (lp_wins_support() || lp_wins_server()))
- if(find_workgroupstruct(wins_subnet, group, True) == 0)
- DEBUG(0, ("add_my_subnets: Failed to add workgroup %s to \
-WINS subnet.\n", group));
- else
- DEBUG(3,("add_my_subnets: Added workgroup %s to WINS subnet.\n",
- group));
+ /* add WORKGROUP(1e) and WORKGROUP(00) entries into name database
+ or register with WINS server, if it's our workgroup
+ */
+ if (strequal(myworkgroup, group))
+ {
+ add_my_name_entry(d,group,0x1e,nb_type|NB_ACTIVE|NB_GROUP);
+ add_my_name_entry(d,group,0x0 ,nb_type|NB_ACTIVE|NB_GROUP);
+ /* add samba server name to workgroup list. */
+ add_server_entry(d,w,myname,w->ServerType,0,lp_serverstring(),True);
+ DEBUG(3,("add_workgroup_to_subnet: Added server name entry %s to subnet %s\n",
+ myname, inet_ntoa(d->bcast_ip)));
+ }
}
-
/****************************************************************************
- add a domain entry. creates a workgroup, if necessary, and adds the domain
- to the named a workgroup.
- ****************************************************************************/
-static struct subnet_record *add_subnet_entry(struct in_addr bcast_ip,
- struct in_addr mask_ip,
- char *name, BOOL add, BOOL lmhosts)
-{
- struct subnet_record *d;
+ create subnet / workgroup / server entries
+
+ - add or create the subnet lists
+ - add or create the workgroup entries in each subnet entry
+ - register appropriate NetBIOS names for the workgroup entries
+
+**************************************************************************/
+void add_my_subnets(char *group)
+{
+ static BOOL create_subnets = True;
+ struct subnet_record *d = NULL;
+ struct interface *i = NULL;
- /* XXXX andrew: struct in_addr ip appears not to be referenced at all except
- in the DEBUG comment. i assume that the DEBUG comment below actually
- intends to refer to bcast_ip? i don't know.
+ if (*group == '*') return;
- struct in_addr ip = wins_ip;
+ /* Create subnets from all the local interfaces and thread them onto
+ the linked list.
+ */
+ for (i = local_interfaces; i; i = i->next)
+ {
+ add_subnet_entry(i->bcast,i->nmask,group, create_subnets, True);
+ }
- */
+ /* If we are using WINS, then we must add the workgroup to the WINS
+ subnet. This is used as a place to keep collated server lists.
+ */
- if (zero_ip(bcast_ip))
- bcast_ip = *iface_bcast(bcast_ip);
-
- /* add the domain into our domain database */
- /* Note that we never add into the WINS subnet as add_subnet_entry
- is only called to add our local interfaces. */
- if ((d = find_subnet(bcast_ip)) ||
- (d = make_subnet(bcast_ip, mask_ip, True)))
- {
- struct work_record *w = find_workgroupstruct(d, name, add);
-
- if (!w) return NULL;
+ /* Create the WINS subnet if we are using WINS - but don't thread it
+ onto the linked subnet list.
+ */
+ if (lp_wins_support() || lp_wins_server())
+ {
+ struct in_addr wins_nmask = ipzero;
+ wins_subnet = add_subnet_entry(wins_ip, wins_nmask, group, create_subnets, False);
+ }
- /* add WORKGROUP(1e) and WORKGROUP(00) entries into name database
- or register with WINS server, if it's our workgroup */
- if (strequal(lp_workgroup(), name))
- {
- add_my_name_entry(d,name,0x1e,nb_type|NB_ACTIVE|NB_GROUP);
- add_my_name_entry(d,name,0x0 ,nb_type|NB_ACTIVE|NB_GROUP);
- }
- /* add samba server name to workgroup list. don't add
- lmhosts server entries to local interfaces */
- if (strequal(lp_workgroup(), name))
- {
- add_server_entry(d,w,myname,w->ServerType,0,lp_serverstring(),True);
- DEBUG(3,("Added server name entry %s at %s\n",
- name,inet_ntoa(bcast_ip)));
- }
-
- return d;
- }
- return NULL;
-}
+ /* Ensure we only create the subnets once. */
+ create_subnets = False;
+ /* Now we have created all the subnets - we can add the names
+ that make us a client member in the workgroup.
+ */
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
+ add_workgroup_to_subnet(d, group);
+}
/*******************************************************************
write out browse.dat
diff --git a/source3/namedbwork.c b/source3/namedbwork.c
index 8c249cc82c..d752916815 100644
--- a/source3/namedbwork.c
+++ b/source3/namedbwork.c
@@ -40,6 +40,8 @@ extern struct subnet_record *subnetlist;
extern struct in_addr wins_ip;
+extern fstring myworkgroup;
+
int workgroup_count = 0; /* unique index key: one for each workgroup */
@@ -192,8 +194,8 @@ struct work_record *find_workgroupstruct(struct subnet_record *d,
if ((work = make_workgroup(name)))
{
if (!ip_equal(d->bcast_ip, wins_ip) &&
- lp_preferred_master() &&
- strequal(lp_workgroup(), name))
+ lp_preferred_master() && lp_local_master() &&
+ strequal(myworkgroup, name))
{
DEBUG(3, ("preferred master startup for %s\n", work->work_group));
work->needelection = True;
diff --git a/source3/nameelect.c b/source3/nameelect.c
index 02fda9f817..82cebd3e6c 100644
--- a/source3/nameelect.c
+++ b/source3/nameelect.c
@@ -40,6 +40,7 @@ extern int DEBUGLEVEL;
extern pstring scope;
extern pstring myname;
+extern fstring myworkgroup;
extern struct in_addr ipzero;
extern struct in_addr wins_ip;
@@ -57,55 +58,59 @@ extern uint16 nb_type; /* samba's NetBIOS name type */
******************************************************************/
void check_master_browser(time_t t)
{
- static time_t lastrun=0;
- struct subnet_record *d;
+ static time_t lastrun=0;
+ struct subnet_record *d;
- if (!lastrun) lastrun = t;
- if (t < lastrun + CHECK_TIME_MST_BROWSE * 60) return;
+ if (!lastrun) lastrun = t;
+ if (t < lastrun + CHECK_TIME_MST_BROWSE * 60) return;
- lastrun = t;
+ lastrun = t;
- dump_workgroups();
+ dump_workgroups();
- for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
- {
- struct work_record *work;
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
+ {
+ struct work_record *work;
- for (work = d->workgrouplist; work; work = work->next)
- {
- if (strequal(work->work_group, lp_workgroup()) && !AM_MASTER(work))
- {
- if (lp_preferred_master())
- {
- /* preferred master - not a master browser. force
- becoming a master browser, hence the log message.
- */
-
- DEBUG(0,("%s preferred master for %s %s - force election\n",
- timestring(), work->work_group,
- inet_ntoa(d->bcast_ip)));
-
- browser_gone(work->work_group, d->bcast_ip);
- }
- else
- {
- /* if we are not the browse master of a workgroup,
- and we can't find a browser on the subnet, do
- something about it.
- */
-
- queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_MST_CHK,
- work->work_group,0x1d,0,0,0,NULL,NULL,
- True,False,d->bcast_ip,d->bcast_ip);
- }
- }
- }
- }
+ for (work = d->workgrouplist; work; work = work->next)
+ {
+ if (strequal(work->work_group, myworkgroup) && !AM_MASTER(work))
+ {
+ if (lp_local_master())
+ {
+ /* potential master browser - not a master browser. force
+ becoming a master browser, hence the log message.
+ */
+
+ DEBUG(0,("%s potential master for %s %s - force election\n",
+ timestring(), work->work_group,
+ inet_ntoa(d->bcast_ip)));
+
+ browser_gone(work->work_group, d->bcast_ip);
+ }
+ else
+ {
+ /* if we are not the browse master of a workgroup,
+ and we can't find a browser on the subnet, do
+ something about it.
+ */
+
+ queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_MST_CHK,
+ work->work_group,0x1d,0,0,0,NULL,NULL,
+ True,False,d->bcast_ip,d->bcast_ip);
+ }
+ }
+ }
+ }
}
/*******************************************************************
- what to do if a master browser DOESN't exist
+ what to do if a master browser DOESN't exist.
+
+ option 1: force an election, and participate in it
+ option 2: force an election, and let everyone else participate.
+
******************************************************************/
void browser_gone(char *work_name, struct in_addr ip)
{
@@ -119,24 +124,37 @@ void browser_gone(char *work_name, struct in_addr ip)
if (ip_equal(d->bcast_ip,wins_ip))
return;
- if (strequal(work->work_group, lp_workgroup()))
+ if (strequal(work->work_group, myworkgroup))
{
+ if (lp_local_master())
+ {
+ /* we have discovered that there is no local master
+ browser, and we are configured to initiate
+ an election under exactly such circumstances.
+ */
DEBUG(2,("Forcing election on %s %s\n",
work->work_group,inet_ntoa(d->bcast_ip)));
/* we can attempt to become master browser */
work->needelection = True;
- }
- else
- {
- /* local interfaces: force an election */
- send_election(d, work->work_group, 0, 0, myname);
-
- /* only removes workgroup completely on a local interface
- persistent lmhosts entries on a local interface _will_ be removed).
- */
- remove_workgroup(d, work,True);
+ }
+ else
+ {
+ /* we need to force an election, because we are configured
+ not to _become_ the local master, but we still _need_ one,
+ having detected that one doesn't exist.
+ */
+
+ /* local interfaces: force an election */
+ send_election(d, work->work_group, 0, 0, myname);
+
+ /* only removes workgroup completely on a local interface
+ persistent lmhosts entries on a local interface _will_ be removed).
+ */
+ remove_workgroup(d, work,True);
+ add_workgroup_to_subnet(d, work->work_group);
+ }
}
}
@@ -199,15 +217,15 @@ void name_unregister_work(struct subnet_record *d, char *name, int name_type)
{
remove_type_local |= SV_TYPE_MASTER_BROWSER;
}
- if (AM_MASTER(work) && strequal(name, lp_workgroup()) && name_type == 0x1d)
+ if (AM_MASTER(work) && strequal(name, myworkgroup) && name_type == 0x1d)
{
remove_type_local |= SV_TYPE_MASTER_BROWSER;
}
- if (AM_DOMMST(work) && strequal(name, lp_workgroup()) && name_type == 0x1b)
+ if (AM_DOMMST(work) && strequal(name, myworkgroup) && name_type == 0x1b)
{
remove_type_domain |= SV_TYPE_DOMAIN_MASTER;
}
- if (AM_DOMMEM(work) && strequal(name, lp_workgroup()) && name_type == 0x1c)
+ if (AM_DOMMEM(work) && strequal(name, myworkgroup) && name_type == 0x1c)
{
remove_type_logon|= SV_TYPE_DOMAIN_MEMBER;
}
@@ -228,47 +246,48 @@ void name_unregister_work(struct subnet_record *d, char *name, int name_type)
void name_register_work(struct subnet_record *d, char *name, int name_type,
int nb_flags, time_t ttl, struct in_addr ip, BOOL bcast)
{
- enum name_source source = (ismyip(ip) || ip_equal(ip, ipzero)) ?
+ enum name_source source = (ismyip(ip) || ip_equal(ip, ipzero)) ?
SELF : REGISTER;
- if (source == SELF)
- {
- struct work_record *work = find_workgroupstruct(d, lp_workgroup(), False);
+ if (source == SELF)
+ {
+ struct work_record *work = find_workgroupstruct(d,
+ myworkgroup, False);
- add_netbios_entry(d,name,name_type,nb_flags,ttl,source,ip,True,!bcast);
+ add_netbios_entry(d,name,name_type,nb_flags,ttl,source,ip,True,!bcast);
- if (work)
- {
- int add_type_local = False;
- int add_type_domain = False;
- int add_type_logon = False;
-
- DEBUG(4,("checking next stage: name_register_work %s\n", name));
-
- /* work out what to become, from the name type being added */
-
- if (ms_browser_name(name, name_type))
- {
- add_type_local = True;
- }
- if (strequal(name, lp_workgroup()) && name_type == 0x1d)
- {
- add_type_local = True;
- }
- if (strequal(name, lp_workgroup()) && name_type == 0x1b)
- {
- add_type_domain = True;
- }
- if (strequal(name, lp_workgroup()) && name_type == 0x1c)
- {
- add_type_logon = True;
- }
-
- if (add_type_local ) become_local_master (d, work);
- if (add_type_domain) become_domain_master(d, work);
- if (add_type_logon ) become_logon_server (d, work);
- }
- }
+ if (work)
+ {
+ int add_type_local = False;
+ int add_type_domain = False;
+ int add_type_logon = False;
+
+ DEBUG(4,("checking next stage: name_register_work %s\n", name));
+
+ /* work out what to become, from the name type being added */
+
+ if (ms_browser_name(name, name_type))
+ {
+ add_type_local = True;
+ }
+ if (strequal(name, myworkgroup) && name_type == 0x1d)
+ {
+ add_type_local = True;
+ }
+ if (strequal(name, myworkgroup) && name_type == 0x1b)
+ {
+ add_type_domain = True;
+ }
+ if (strequal(name, myworkgroup) && name_type == 0x1c)
+ {
+ add_type_logon = True;
+ }
+
+ if (add_type_local ) become_local_master (d, work);
+ if (add_type_domain) become_domain_master(d, work);
+ if (add_type_logon ) become_logon_server (d, work);
+ }
+ }
}
@@ -303,17 +322,18 @@ void become_local_master(struct subnet_record *d, struct work_record *work)
*/
uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT;
- if (!work || !d) return;
+ if (!work || !d)
+ return;
DEBUG(2,("Becoming master for %s %s (currently at stage %d)\n",
- work->work_group,inet_ntoa(d->bcast_ip),work->mst_state));
+ work->work_group,inet_ntoa(d->bcast_ip),work->mst_state));
switch (work->mst_state)
{
case MST_POTENTIAL: /* while we were nothing but a server... */
{
DEBUG(3,("go to first stage: register ^1^2__MSBROWSE__^2^1\n"));
- work->mst_state = MST_BACK; /* ... an election win was successful */
+ work->mst_state = MST_BACK; /* an election win was successful */
work->ElectionCriterion |= 0x5;
@@ -322,7 +342,7 @@ void become_local_master(struct subnet_record *d, struct work_record *work)
add_server_entry(d,work,myname,work->ServerType,0,lp_serverstring(),True);
/* add special browser name */
- add_my_name_entry(d,MSBROWSE ,0x01,nb_type|NB_ACTIVE|NB_GROUP);
+ add_my_name_entry(d,MSBROWSE,0x01,nb_type|NB_ACTIVE|NB_GROUP);
/* DON'T do anything else after calling add_my_name_entry() */
break;
@@ -331,7 +351,7 @@ void become_local_master(struct subnet_record *d, struct work_record *work)
case MST_BACK: /* while nothing had happened except we won an election... */
{
DEBUG(3,("go to second stage: register as master browser\n"));
- work->mst_state = MST_MSB; /* ... registering MSBROWSE was successful */
+ work->mst_state = MST_MSB; /* registering MSBROWSE was successful */
/* add server entry on successful registration of MSBROWSE */
add_server_entry(d,work,work->work_group,domain_type,0,myname,True);
@@ -346,49 +366,33 @@ void become_local_master(struct subnet_record *d, struct work_record *work)
case MST_MSB: /* while we were still only registered MSBROWSE state... */
{
DEBUG(3,("2nd stage complete: registered as master browser\n"));
- work->mst_state = MST_BROWSER; /* ... registering WORKGROUP(1d) succeeded */
+ work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */
/* update our server status */
work->ServerType |= SV_TYPE_MASTER_BROWSER;
- DEBUG(3,("become_local_master: updating our server %s to type %x\n", myname, work->ServerType));
+ DEBUG(3,("become_local_master: updating our server %s to type %x\n",
+ myname, work->ServerType));
add_server_entry(d,work,myname,work->ServerType,0,lp_serverstring(),True);
if (work->serverlist == NULL) /* no servers! */
{
/* ask all servers on our local net to announce to us */
- /* XXXX OOPS! add_server_entry will always add one entry - our own. */
+ /* XXXX OOPS! add_server_entry always adds one entry - ours. */
announce_request(work, d->bcast_ip);
}
- /* If we have WINS support or are a WINS server we must add
- the workgroup we just became master browser for to the
- WINS subnet. This is needed so we have somewhere to save
- server lists when we do browser synchronization. */
- if(wins_subnet != 0)
- {
- if(find_workgroupstruct(wins_subnet, work->work_group, True) == 0)
- DEBUG(0, ("become_local_master: \
-Failed to add workgroup %s to WINS subnet.\n",
- work->work_group));
- else
- DEBUG(3, ("become_local_master: Added workgroup %s to WINS subnet.\n",
- work->work_group));
-
- /* Reset the announce master timer so that we do an announce as soon as possible
- now we are a master. */
- reset_announce_timer();
- }
+ /* Reset the announce master timer so that we do an announce as soon as possible
+ now we are a master. */
+ reset_announce_timer();
break;
-
}
case MST_BROWSER:
{
/* don't have to do anything: just report success */
DEBUG(3,("3rd stage: become master browser!\n"));
-
break;
}
}
@@ -438,7 +442,7 @@ void become_domain_master(struct subnet_record *d, struct work_record *work)
work->dom_state = DOMAIN_WAIT;
/* XXXX the 0x1b is domain master browser name */
- add_my_name_entry(d, lp_workgroup(),0x1b,nb_type|NB_ACTIVE|NB_GROUP);
+ add_my_name_entry(d, myworkgroup,0x1b,nb_type|NB_ACTIVE|NB_GROUP);
/* DON'T do anything else after calling add_my_name_entry() */
break;
@@ -505,7 +509,7 @@ void become_logon_server(struct subnet_record *d, struct work_record *work)
work->log_state = LOGON_WAIT;
/* XXXX the 0x1c is apparently something to do with domain logons */
- add_my_name_entry(d, lp_workgroup(),0x1c,nb_type|NB_ACTIVE|NB_GROUP);
+ add_my_name_entry(d, myworkgroup,0x1c,nb_type|NB_ACTIVE|NB_GROUP);
/* DON'T do anything else after calling add_my_name_entry() */
break;
@@ -749,7 +753,7 @@ void process_election(struct packet_struct *p,char *buf)
for (work = d->workgrouplist; work; work = work->next)
{
- if (!strequal(work->work_group, lp_workgroup()))
+ if (!strequal(work->work_group, myworkgroup))
continue;
if (win_election(work, version,criterion,timeup,name)) {
diff --git a/source3/nameresp.c b/source3/nameresp.c
index f2b3ba167a..27796ec07c 100644
--- a/source3/nameresp.c
+++ b/source3/nameresp.c
@@ -263,13 +263,13 @@ struct response_record *queue_netbios_pkt_wins(
if ((!lp_wins_support()) && (*lp_wins_server()))
{
/* samba is not a WINS server, and we are using a WINS server */
- struct in_addr wins_ip;
- wins_ip = *interpret_addr2(lp_wins_server());
+ struct in_addr real_wins_ip;
+ real_wins_ip = *interpret_addr2(lp_wins_server());
- if (!zero_ip(wins_ip))
+ if (!zero_ip(real_wins_ip))
{
bcast = False;
- send_ip = wins_ip;
+ send_ip = real_wins_ip;
}
else
{
diff --git a/source3/nameserv.c b/source3/nameserv.c
index 022b5521a2..9163642896 100644
--- a/source3/nameserv.c
+++ b/source3/nameserv.c
@@ -37,6 +37,7 @@ extern int DEBUGLEVEL;
extern pstring scope;
extern pstring myname;
+extern fstring myworkgroup;
extern struct in_addr ipzero;
extern struct in_addr wins_ip;
@@ -141,6 +142,9 @@ void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags)
}
else
{
+ DEBUG(4,("add_my_name_entry registering name %s with WINS server.\n",
+ name));
+
/* a time-to-live allows us to refresh this name with the WINS server. */
queue_netbios_pkt_wins(ClientNMB,
re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER,
@@ -179,33 +183,32 @@ void add_domain_names(time_t t)
for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
{
- work = find_workgroupstruct(d, lp_workgroup(), False);
+ work = find_workgroupstruct(d, myworkgroup, False);
if (lp_domain_logons() && work && work->log_state == LOGON_NONE)
{
- make_nmb_name(&n,lp_workgroup(),0x1c,scope);
+ make_nmb_name(&n,myworkgroup,0x1c,scope);
if (!find_name(d->namelist, &n, FIND_SELF))
{
/* logon servers are group names - we don't expect this to fail. */
DEBUG(0,("%s attempting to become logon server for %s %s\n",
- timestring(), lp_workgroup(), inet_ntoa(d->bcast_ip)));
+ timestring(), myworkgroup, inet_ntoa(d->bcast_ip)));
become_logon_server(d, work);
}
}
}
- if(wins_subnet != 0)
- work = find_workgroupstruct(wins_subnet, lp_workgroup(), False);
-
- if (lp_domain_master() && work && work->dom_state == DOMAIN_NONE)
- {
-
- DEBUG(0,("add_domain_names:Checking for domain master on workgroup %s\n", lp_workgroup()));
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
+ {
+ work = find_workgroupstruct(d, myworkgroup, True);
- make_nmb_name(&n,lp_workgroup(),0x1b,scope);
- if (!find_name(wins_subnet->namelist, &n, FIND_SELF))
+ if (lp_domain_master() && work && work->dom_state == DOMAIN_NONE)
+ {
+ make_nmb_name(&n,myworkgroup,0x1b,scope);
+ if (!find_name(d->namelist, &n, FIND_SELF))
{
- DEBUG(0,("add_domain_names: attempting to become domain master browser on workgroup %s\n",
- lp_workgroup()));
+ DEBUG(0,("%s add_domain_names: attempting to become domain master \
+browser on workgroup %s %s\n",
+ timestring(), myworkgroup, inet_ntoa(d->bcast_ip)));
if (lp_wins_support())
{
@@ -216,8 +219,8 @@ void add_domain_names(time_t t)
*/
DEBUG(1,("%s initiating becoming domain master for %s\n",
- timestring(), lp_workgroup()));
- become_domain_master(wins_subnet, work);
+ timestring(), myworkgroup));
+ become_domain_master(d, work);
}
else
{
@@ -228,15 +231,17 @@ void add_domain_names(time_t t)
NetBIOS name 0x1b.
*/
- DEBUG(0,("add_domain_names:querying WINS for domain master on workgroup %s\n", lp_workgroup()));
+ DEBUG(0,("add_domain_names:querying WINS for domain master \
+on workgroup %s\n", myworkgroup));
queue_netbios_pkt_wins(ClientNMB,NMB_QUERY,NAME_QUERY_DOMAIN,
- lp_workgroup(), 0x1b,
+ myworkgroup, 0x1b,
0, 0,0,NULL,NULL,
False, False, ipzero, ipzero);
}
}
}
+ }
}
@@ -255,7 +260,6 @@ void add_my_names(void)
for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
{
BOOL wins = (lp_wins_support() && (d == wins_subnet));
- struct work_record *work = find_workgroupstruct(d, lp_workgroup(), False);
add_my_name_entry(d, myname,0x20,nb_type|NB_ACTIVE);
add_my_name_entry(d, myname,0x03,nb_type|NB_ACTIVE);
diff --git a/source3/nameservreply.c b/source3/nameservreply.c
index e1738007df..00e940df67 100644
--- a/source3/nameservreply.c
+++ b/source3/nameservreply.c
@@ -528,7 +528,8 @@ void reply_name_query(struct packet_struct *p)
}
}
- DEBUG(3,("Name query "));
+ DEBUG(3,("Name query from %s for name %s<0x%x>\n",
+ inet_ntoa(p->ip), question->name, question->name_type));
if (search == 0)
{
diff --git a/source3/namework.c b/source3/namework.c
index 218a7a349e..23d48d9ced 100644
--- a/source3/namework.c
+++ b/source3/namework.c
@@ -37,6 +37,7 @@ extern pstring scope;
extern BOOL CanRecurse;
extern pstring myname;
+extern fstring myworkgroup;
extern int ClientNMB;
extern int ClientDGRAM;
@@ -603,7 +604,7 @@ static void process_reset_browser(struct packet_struct *p,char *buf)
struct work_record *work;
for (work=d->workgrouplist;work;work=remove_workgroup(d,work,True));
}
- add_my_subnets(lp_workgroup());
+ add_my_subnets(myworkgroup);
}
/* stop browsing altogether. i don't think this is a good idea! */
@@ -639,7 +640,7 @@ static void process_announce_request(struct packet_struct *p,char *buf)
this workgroup before announcing, particularly as we only
respond on local interfaces anyway.
- if (strequal(dgram->dest_name, lp_workgroup()) return; ???
+ if (strequal(dgram->dest_name, myworkgroup) return; ???
*/
if (!d)
diff --git a/source3/nmbd/nmbd.c b/source3/nmbd/nmbd.c
index 550f3198f7..11f005b785 100644
--- a/source3/nmbd/nmbd.c
+++ b/source3/nmbd/nmbd.c
@@ -40,6 +40,7 @@ int ClientDGRAM = -1;
extern pstring myhostname;
static pstring host_file;
extern pstring myname;
+extern fstring myworkgroup;
/* are we running as a daemon ? */
static BOOL is_daemon = False;
@@ -67,7 +68,7 @@ static int sig_term()
/* announce all server entries as 0 time-to-live, 0 type */
/* XXXX don't care if we never receive a response back... yet */
- remove_my_servers();
+ announce_my_servers_removed();
/* XXXX other things: if we are a master browser, force an election? */
@@ -203,9 +204,6 @@ BOOL reload_services(BOOL test)
reload_services(True);
}
- load_interfaces();
- add_subnet_interfaces();
-
/* Do a sanity check for a misconfigured nmbd */
if(lp_wins_support() && *lp_wins_server()) {
DEBUG(0,("ERROR: both 'wins support = true' and 'wins server = <server>' \
@@ -502,6 +500,8 @@ static void usage(char *pname)
reload_services(True);
+ strcpy(myworkgroup, lp_workgroup());
+
set_samba_nb_type();
if (!is_daemon && !is_a_socket(0)) {
@@ -549,15 +549,16 @@ static void usage(char *pname)
DEBUG(3,("Loaded hosts file\n"));
}
+ load_interfaces();
+ add_my_subnets(myworkgroup);
+
add_my_names();
- if (strequal(lp_workgroup(),"*")) {
+ if (strequal(myworkgroup,"*")) {
DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
exit(1);
}
- add_my_subnets(lp_workgroup());
-
DEBUG(3,("Checked names\n"));
load_netbios_names();
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index 40611e4c3a..af0b05bb5d 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -152,8 +152,11 @@ typedef struct
int os_level;
int max_ttl;
int ReadSize;
+ int shmem_size;
+ int shmem_hash_size;
BOOL bWINSsupport;
BOOL bWINSproxy;
+ BOOL bLocalMaster;
BOOL bPreferredMaster;
BOOL bDomainMaster;
BOOL bDomainLogons;
@@ -427,6 +430,8 @@ struct parm_struct
{"deadtime", P_INTEGER, P_GLOBAL, &Globals.deadtime, NULL},
{"time offset", P_INTEGER, P_GLOBAL, &extra_time_offset, NULL},
{"read size", P_INTEGER, P_GLOBAL, &Globals.ReadSize, NULL},
+ {"shared mem size", P_INTEGER, P_GLOBAL, &Globals.shmem_size, NULL},
+ {"shared file entries", P_INTEGER, P_GLOBAL, &Globals.shmem_hash_size, NULL},
#ifdef KANJI
{"coding system", P_INTEGER, P_GLOBAL, &coding_system, handle_coding_system},
#endif /* KANJI */
@@ -437,6 +442,7 @@ struct parm_struct
{"wins server", P_STRING, P_GLOBAL, &Globals.szWINSserver, NULL},
{"preferred master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL},
{"prefered master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL},
+ {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL},
{"domain master", P_BOOL, P_GLOBAL, &Globals.bDomainMaster, NULL},
{"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL},
{"browse list", P_BOOL, P_GLOBAL, &Globals.bBrowseList, NULL},
@@ -601,15 +607,11 @@ static void init_globals(void)
Globals.bSyslogOnly = False;
Globals.os_level = 0;
Globals.max_ttl = 60*60*4; /* 2 hours default */
- Globals.bPreferredMaster = True;
- Globals.bDomainMaster = False;
- Globals.bDomainLogons = False;
- Globals.bBrowseList = True;
- Globals.bWINSsupport = False;
- Globals.bWINSproxy = False;
Globals.ReadSize = 16*1024;
+ Globals.shmem_size = SHMEM_SIZE;
+ Globals.shmem_hash_size = SHMEM_HASH_SIZE;
Globals.bUnixRealname = False;
-#ifdef NETGROUP
+#if (defined(NETGROUP) && defined(AUTOMOUNT))
Globals.bNISHomeMap = False;
string_set(&Globals.szNISHomeMapName, "auto.home");
#endif
@@ -617,6 +619,25 @@ static void init_globals(void)
coding_system = interpret_coding_system (KANJI, SJIS_CODE);
#endif /* KANJI */
+/* these parameters are set to defaults that are more appropriate
+ for the increasing samba install base:
+
+ as a member of the workgroup, that will possibly become a
+ _local_ master browser (lm = True). this is opposed to a forced
+ local master browser startup (pm = True).
+
+ doesn't provide WINS server service by default (wsupp = False),
+ and doesn't provide domain master browser services by default, either.
+
+*/
+
+ Globals.bPreferredMaster = False;
+ Globals.bLocalMaster = True;
+ Globals.bDomainMaster = False;
+ Globals.bDomainLogons = False;
+ Globals.bBrowseList = True;
+ Globals.bWINSsupport = False;
+ Globals.bWINSproxy = False;
}
/***************************************************************************
@@ -771,6 +792,7 @@ FN_GLOBAL_STRING(lp_nis_home_map_name,&Globals.szNISHomeMapName)
FN_GLOBAL_BOOL(lp_wins_support,&Globals.bWINSsupport)
FN_GLOBAL_BOOL(lp_wins_proxy,&Globals.bWINSproxy)
+FN_GLOBAL_BOOL(lp_local_master,&Globals.bLocalMaster)
FN_GLOBAL_BOOL(lp_domain_master,&Globals.bDomainMaster)
FN_GLOBAL_BOOL(lp_domain_logons,&Globals.bDomainLogons)
FN_GLOBAL_BOOL(lp_preferred_master,&Globals.bPreferredMaster)
@@ -799,6 +821,8 @@ FN_GLOBAL_INTEGER(lp_maxpacket,&Globals.max_packet)
FN_GLOBAL_INTEGER(lp_keepalive,&keepalive)
FN_GLOBAL_INTEGER(lp_passwordlevel,&Globals.pwordlevel)
FN_GLOBAL_INTEGER(lp_readsize,&Globals.ReadSize)
+FN_GLOBAL_INTEGER(lp_shmem_size,&Globals.shmem_size)
+FN_GLOBAL_INTEGER(lp_shmem_hash_size,&Globals.shmem_hash_size)
FN_GLOBAL_INTEGER(lp_deadtime,&Globals.deadtime)
FN_GLOBAL_INTEGER(lp_maxprotocol,&Globals.maxprotocol)
FN_GLOBAL_INTEGER(lp_security,&Globals.security)
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
index 2437b8b17e..bc099dd1e8 100644
--- a/source3/smbd/dir.c
+++ b/source3/smbd/dir.c
@@ -433,6 +433,7 @@ BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mo
BOOL isrootdir;
pstring filename;
BOOL matched;
+ BOOL needslash;
*path = *pathreal = *filename = 0;
@@ -440,6 +441,9 @@ BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mo
strequal(Connections[cnum].dirpath,".") ||
strequal(Connections[cnum].dirpath,"/"));
+ needslash =
+ ( Connections[cnum].dirpath[strlen(Connections[cnum].dirpath) -1] != '/');
+
if (!Connections[cnum].dirptr)
return(False);
@@ -467,7 +471,8 @@ BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mo
strcpy(fname,filename);
*path = 0;
strcpy(path,Connections[cnum].dirpath);
- strcat(path,"/");
+ if(needslash)
+ strcat(path,"/");
strcpy(pathreal,path);
strcat(path,fname);
strcat(pathreal,dname);
diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c
index 1f1ac8600a..8b9fb485ae 100644
--- a/source3/smbd/ipc.c
+++ b/source3/smbd/ipc.c
@@ -37,6 +37,7 @@ extern files_struct Files[];
extern connection_struct Connections[];
extern fstring local_machine;
+extern fstring myworkgroup;
#define NERR_Success 0
#define NERR_badpass 86
@@ -812,7 +813,7 @@ static int get_server_info(uint32 servertype,
if (!next_token(&ptr,s->comment, NULL)) continue;
if (!next_token(&ptr,s->domain , NULL)) {
/* this allows us to cope with an old nmbd */
- strcpy(s->domain,lp_workgroup());
+ strcpy(s->domain,myworkgroup);
}
if (sscanf(stype,"%X",&s->type) != 1) {
@@ -982,7 +983,7 @@ static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
if (strcmp(str1, "WrLehDz") == 0) {
StrnCpy(domain, p, sizeof(fstring)-1);
} else {
- StrnCpy(domain, lp_workgroup(), sizeof(fstring)-1);
+ StrnCpy(domain, myworkgroup, sizeof(fstring)-1);
}
if (lp_browse_list())
@@ -1668,7 +1669,7 @@ static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
strcpy(comment,lp_serverstring());
- if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
+ if ((count=get_server_info(SV_TYPE_ALL,&servers,myworkgroup))>0) {
for (i=0;i<count;i++)
if (strequal(servers[i].name,local_machine))
{
@@ -1754,7 +1755,7 @@ static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
p += 4;
SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
- strcpy(p2,lp_workgroup());
+ strcpy(p2,myworkgroup);
strupper(p2);
p2 = skip_string(p2,1);
p += 4;
@@ -1764,7 +1765,7 @@ static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
p += 2;
SIVAL(p,0,PTR_DIFF(p2,*rdata));
- strcpy(p2,lp_workgroup()); /* don't know. login domain?? */
+ strcpy(p2,myworkgroup); /* don't know. login domain?? */
p2 = skip_string(p2,1);
p += 4;
@@ -2228,7 +2229,7 @@ static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
strupper(mypath);
PACKS(&desc,"z",mypath); /* computer */
}
- PACKS(&desc,"z",lp_workgroup());/* domain */
+ PACKS(&desc,"z",myworkgroup);/* domain */
PACKS(&desc,"z",lp_logon_script()); /* script path */
PACKI(&desc,"D",0x00000000); /* reserved */
}
diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c
index 634d7af7f4..a294ee4f49 100644
--- a/source3/smbd/pipes.c
+++ b/source3/smbd/pipes.c
@@ -42,6 +42,7 @@ extern files_struct Files[];
extern BOOL case_sensitive;
extern pstring sesssetup_user;
extern int Client;
+extern fstring myworkgroup;
/* this macro should always be used to extract an fnum (smb_fid) from
a packet to ensure chaining works correctly */
@@ -250,7 +251,7 @@ static void LsarpcTNP3(char *data,char **rdata, int *rdata_len)
{
uint32 dword1;
uint16 word1;
- char * workgroup = lp_workgroup();
+ char * workgroup = myworkgroup;
int wglen = strlen(workgroup);
int i;
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index bb75211deb..639c386c2f 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -40,6 +40,7 @@ extern BOOL case_sensitive;
extern BOOL case_preserve;
extern BOOL short_case_preserve;
extern pstring sesssetup_user;
+extern fstring myworkgroup;
extern int Client;
/* this macro should always be used to extract an fnum (smb_fid) from
@@ -480,7 +481,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
p = smb_buf(outbuf);
strcpy(p,"Unix"); p = skip_string(p,1);
strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
- strcpy(p,lp_workgroup()); p = skip_string(p,1);
+ strcpy(p,myworkgroup); p = skip_string(p,1);
set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
/* perhaps grab OS version here?? */
}
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index 0f72efc478..fe0868b34a 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -25,6 +25,7 @@
pstring servicesf = CONFIGFILE;
extern pstring debugf;
extern pstring sesssetup_user;
+extern fstring myworkgroup;
char *InBuffer = NULL;
char *OutBuffer = NULL;
@@ -33,8 +34,6 @@ char *last_inbuf = NULL;
int am_parent = 1;
int atexit_set = 0;
-BOOL share_mode_pending = False;
-
/* the last message the was processed */
int last_message = -1;
@@ -113,6 +112,7 @@ static int find_free_connection(int hash);
void *dflt_sig(void)
{
exit_server("caught signal");
+ return 0; /* Keep -Wall happy :-) */
}
/****************************************************************************
Send a SIGTERM to our process group.
@@ -837,8 +837,8 @@ file_fd_struct *fd_get_already_open(struct stat *sbuf)
for(i = 0; i <= max_file_fd_used; i++) {
fd_ptr = &FileFd[i];
if((fd_ptr->ref_count > 0) &&
- (((int32)sbuf->st_dev) == fd_ptr->dev) &&
- (((int32)sbuf->st_ino) == fd_ptr->inode)) {
+ (((uint32)sbuf->st_dev) == fd_ptr->dev) &&
+ (((uint32)sbuf->st_ino) == fd_ptr->inode)) {
fd_ptr->ref_count++;
DEBUG(3,
("Re-used file_fd_struct %d, dev = %x, inode = %x, ref_count = %d\n",
@@ -861,8 +861,8 @@ file_fd_struct *fd_get_new()
for(i = 0; i < MAX_OPEN_FILES; i++) {
fd_ptr = &FileFd[i];
if(fd_ptr->ref_count == 0) {
- fd_ptr->dev = (int32)-1;
- fd_ptr->inode = (int32)-1;
+ fd_ptr->dev = (uint32)-1;
+ fd_ptr->inode = (uint32)-1;
fd_ptr->fd = -1;
fd_ptr->fd_readonly = -1;
fd_ptr->fd_writeonly = -1;
@@ -927,8 +927,8 @@ int fd_attempt_close(file_fd_struct *fd_ptr)
fd_ptr->fd_readonly = -1;
fd_ptr->fd_writeonly = -1;
fd_ptr->real_open_flags = -1;
- fd_ptr->dev = -1;
- fd_ptr->inode = -1;
+ fd_ptr->dev = (uint32)-1;
+ fd_ptr->inode = (uint32)-1;
}
}
return fd_ptr->ref_count;
@@ -1124,8 +1124,8 @@ void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *s
sbuf = &statbuf;
}
/* Set the correct entries in fd_ptr. */
- fd_ptr->dev = (int32)sbuf->st_dev;
- fd_ptr->inode = (int32)sbuf->st_ino;
+ fd_ptr->dev = (uint32)sbuf->st_dev;
+ fd_ptr->inode = (uint32)sbuf->st_ino;
Files[fnum].fd_ptr = fd_ptr;
Connections[cnum].num_files_open++;
@@ -1141,7 +1141,6 @@ void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *s
Files[fnum].can_read = ((flags & O_WRONLY)==0);
Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
Files[fnum].share_mode = 0;
- Files[fnum].share_pending = False;
Files[fnum].print_file = Connections[cnum].printer;
Files[fnum].modified = False;
Files[fnum].cnum = cnum;
@@ -1241,38 +1240,49 @@ close a file - possibly invalidating the read prediction
****************************************************************************/
void close_file(int fnum)
{
- int cnum = Files[fnum].cnum;
- invalidate_read_prediction(Files[fnum].fd_ptr->fd);
- Files[fnum].open = False;
+ files_struct *fs_p = &Files[fnum];
+ int cnum = fs_p->cnum;
+ uint32 dev = fs_p->fd_ptr->dev;
+ uint32 inode = fs_p->fd_ptr->inode;
+ share_lock_token token;
+
+ invalidate_read_prediction(fs_p->fd_ptr->fd);
+ fs_p->open = False;
Connections[cnum].num_files_open--;
- if(Files[fnum].wbmpx_ptr)
+ if(fs_p->wbmpx_ptr)
{
- free((char *)Files[fnum].wbmpx_ptr);
- Files[fnum].wbmpx_ptr = NULL;
+ free((char *)fs_p->wbmpx_ptr);
+ fs_p->wbmpx_ptr = NULL;
}
#if USE_MMAP
- if(Files[fnum].mmap_ptr)
+ if(fs_p->mmap_ptr)
{
- munmap(Files[fnum].mmap_ptr,Files[fnum].mmap_size);
- Files[fnum].mmap_ptr = NULL;
+ munmap(fs_p->mmap_ptr,fs_p->mmap_size);
+ fs_p->mmap_ptr = NULL;
}
#endif
if (lp_share_modes(SNUM(cnum)))
- del_share_mode(fnum);
+ {
+ lock_share_entry( cnum, dev, inode, &token);
+ del_share_mode(token, fnum);
+ }
+
+ fd_attempt_close(fs_p->fd_ptr);
- fd_attempt_close(Files[fnum].fd_ptr);
+ if (lp_share_modes(SNUM(cnum)))
+ unlock_share_entry( cnum, dev, inode, token);
/* NT uses smbclose to start a print - weird */
- if (Files[fnum].print_file)
+ if (fs_p->print_file)
print_file(fnum);
/* check for magic scripts */
check_magic(fnum,cnum);
DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
- timestring(),Connections[cnum].user,Files[fnum].name,
+ timestring(),Connections[cnum].user,fs_p->name,
Connections[cnum].num_files_open));
}
@@ -1334,17 +1344,44 @@ return True if sharing doesn't prevent the operation
********************************************************************/
BOOL check_file_sharing(int cnum,char *fname)
{
- int pid=0;
- int share_mode = get_share_mode_byname(cnum,fname,&pid);
+ int i;
+ int ret = False;
+ min_share_mode_entry *old_shares = 0;
+ int num_share_modes;
+ struct stat sbuf;
+ share_lock_token token;
+ int pid = getpid();
- if (!pid || !share_mode) return(True);
-
- if (share_mode == DENY_DOS)
- return(pid == getpid());
+ if(!lp_share_modes(SNUM(cnum)))
+ return True;
+
+ if (stat(fname,&sbuf) == -1) return(True);
+
+ lock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &token);
+ num_share_modes = get_share_modes(cnum, token,
+ (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &old_shares);
+
+ for( i = 0; i < num_share_modes; i++)
+ {
+ if (old_shares[i].share_mode != DENY_DOS)
+ goto free_and_exit;
+
+ if(old_shares[i].pid != pid);
+ goto free_and_exit;
+ }
/* XXXX exactly what share mode combinations should be allowed for
deleting/renaming? */
- return(False);
+ /* If we got here then either there were no share modes or
+ all share modes were DENY_DOS and the pid == getpid() */
+ ret = True;
+
+free_and_exit:
+
+ unlock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, token);
+ if(old_shares != NULL)
+ free((char *)old_shares);
+ return(ret);
}
/****************************************************************************
@@ -1373,25 +1410,31 @@ open a file with a share mode
void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
int mode,int *Access,int *action)
{
+ files_struct *fs_p = &Files[fnum];
int flags=0;
int flags2=0;
int deny_mode = (share_mode>>4)&7;
struct stat sbuf;
BOOL file_existed = file_exist(fname,&sbuf);
+ BOOL share_locked = False;
BOOL fcbopen = False;
- int share_pid=0;
+ share_lock_token token;
+ uint32 dev = 0;
+ uint32 inode = 0;
- Files[fnum].open = False;
- Files[fnum].fd_ptr = 0;
+ fs_p->open = False;
+ fs_p->fd_ptr = 0;
/* this is for OS/2 EAs - try and say we don't support them */
- if (strstr(fname,".+,;=[].")) {
+ if (strstr(fname,".+,;=[]."))
+ {
unix_ERR_class = ERRDOS;
unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
return;
}
- if ((ofun & 0x3) == 0 && file_existed) {
+ if ((ofun & 0x3) == 0 && file_existed)
+ {
errno = EEXIST;
return;
}
@@ -1405,7 +1448,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
append does not mean the same thing under dos and unix */
switch (share_mode&0xF)
- {
+ {
case 1:
flags = O_WRONLY;
break;
@@ -1419,18 +1462,21 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
default:
flags = O_RDONLY;
break;
- }
+ }
if (flags != O_RDONLY && file_existed &&
- (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf)))) {
- if (!fcbopen) {
+ (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf))))
+ {
+ if (!fcbopen)
+ {
errno = EACCES;
return;
}
flags = O_RDONLY;
}
- if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) {
+ if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB)
+ {
DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
errno = EINVAL;
return;
@@ -1438,21 +1484,36 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
- if (lp_share_modes(SNUM(cnum))) {
- int old_share=0;
+ if (lp_share_modes(SNUM(cnum)))
+ {
+ int num_shares = 0;
+ int i;
+ min_share_mode_entry *old_shares = 0;
+
if (file_existed)
- old_share = get_share_mode(cnum,&sbuf,&share_pid);
+ {
+ dev = (uint32)sbuf.st_dev;
+ inode = (uint32)sbuf.st_ino;
+ lock_share_entry(cnum, dev, inode, &token);
+ share_locked = True;
+ num_shares = get_share_modes(cnum, token, dev, inode, &old_shares);
+ }
- if (share_pid) {
+ for(i = 0; i < num_shares; i++)
+ {
/* someone else has a share lock on it, check to see
if we can too */
- int old_open_mode = old_share&0xF;
- int old_deny_mode = (old_share>>4)&7;
+ int old_open_mode = old_shares[i].share_mode &0xF;
+ int old_deny_mode = (old_shares[i].share_mode >>4)&7;
- if (deny_mode > 4 || old_deny_mode > 4 || old_open_mode > 2) {
+ if (deny_mode > 4 || old_deny_mode > 4 || old_open_mode > 2)
+ {
DEBUG(2,("Invalid share mode (%d,%d,%d) on file %s\n",
deny_mode,old_deny_mode,old_open_mode,fname));
+ free((char *)old_shares);
+ if(share_locked)
+ unlock_share_entry(cnum, dev, inode, token);
errno = EACCES;
unix_ERR_class = ERRDOS;
unix_ERR_code = ERRbadshare;
@@ -1461,21 +1522,25 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
{
int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
- share_pid,fname);
+ old_shares[i].pid,fname);
if ((access_allowed == AFAIL) ||
(!fcbopen && (access_allowed == AREAD && flags == O_RDWR)) ||
(access_allowed == AREAD && flags == O_WRONLY) ||
- (access_allowed == AWRITE && flags == O_RDONLY)) {
+ (access_allowed == AWRITE && flags == O_RDONLY))
+ {
DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
deny_mode,old_deny_mode,old_open_mode,
- share_pid,fname,
+ old_shares[i].pid,fname,
access_allowed));
+ free((char *)old_shares);
+ if(share_locked)
+ unlock_share_entry(cnum, dev, inode, token);
errno = EACCES;
unix_ERR_class = ERRDOS;
unix_ERR_code = ERRbadshare;
return;
- }
+ }
if (access_allowed == AREAD)
flags = O_RDONLY;
@@ -1484,76 +1549,69 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
flags = O_WRONLY;
}
}
+ if(old_shares != 0)
+ free((char *)old_shares);
}
DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
flags,flags2,mode));
open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0);
- if (!Files[fnum].open && flags==O_RDWR && errno!=ENOENT && fcbopen) {
+ if (!fs_p->open && flags==O_RDWR && errno!=ENOENT && fcbopen)
+ {
flags = O_RDONLY;
open_file(fnum,cnum,fname,flags,mode,file_existed ? &sbuf : 0 );
}
- if (Files[fnum].open) {
+ if (fs_p->open)
+ {
int open_mode=0;
- switch (flags) {
- case O_RDONLY:
- open_mode = 0;
- break;
- case O_RDWR:
- open_mode = 2;
- break;
- case O_WRONLY:
- open_mode = 1;
- break;
+
+ if((share_locked == False) && lp_share_modes(SNUM(cnum)))
+ {
+ /* We created the file - thus we must now lock the share entry before creating it. */
+ dev = fs_p->fd_ptr->dev;
+ inode = fs_p->fd_ptr->inode;
+ lock_share_entry(cnum, dev, inode, &token);
+ share_locked = True;
}
- Files[fnum].share_mode = (deny_mode<<4) | open_mode;
- Files[fnum].share_pending = True;
+ switch (flags)
+ {
+ case O_RDONLY:
+ open_mode = 0;
+ break;
+ case O_RDWR:
+ open_mode = 2;
+ break;
+ case O_WRONLY:
+ open_mode = 1;
+ break;
+ }
+
+ fs_p->share_mode = (deny_mode<<4) | open_mode;
- if (Access) {
+ if (Access)
(*Access) = open_mode;
- }
-
- if (action) {
+
+ if (action)
+ {
if (file_existed && !(flags2 & O_TRUNC)) *action = 1;
if (!file_existed) *action = 2;
if (file_existed && (flags2 & O_TRUNC)) *action = 3;
}
- if (!share_pid)
- share_mode_pending = True;
-
if ((flags2&O_TRUNC) && file_existed)
truncate_unless_locked(fnum,cnum);
- }
-}
-
+ if (lp_share_modes(SNUM(cnum)))
+ set_share_mode(token, fnum);
+ }
-/*******************************************************************
-check for files that we should now set our share modes on
-********************************************************************/
-static void check_share_modes(void)
-{
- int i;
- for (i=0;i<MAX_OPEN_FILES;i++)
- if(Files[i].open && Files[i].share_pending) {
- if (lp_share_modes(SNUM(Files[i].cnum))) {
- int pid=0;
- get_share_mode_by_fnum(Files[i].cnum,i,&pid);
- if (!pid) {
- set_share_mode(i,Files[i].share_mode);
- Files[i].share_pending = False;
- }
- } else {
- Files[i].share_pending = False;
- }
- }
+ if (share_locked && lp_share_modes(SNUM(cnum)))
+ unlock_share_entry( cnum, dev, inode, token);
}
-
/****************************************************************************
seek a file. Try to avoid the seek if possible
****************************************************************************/
@@ -2694,18 +2752,18 @@ int reply_nt1(char *outbuf)
*/
encrypt_len = doencrypt?challenge_len:0;
#if UNICODE
- data_len = encrypt_len + 2*(strlen(lp_workgroup())+1);
+ data_len = encrypt_len + 2*(strlen(myworkgroup)+1);
#else
- data_len = encrypt_len + strlen(lp_workgroup()) + 1;
+ data_len = encrypt_len + strlen(myworkgroup) + 1;
#endif
set_message(outbuf,17,data_len,True);
#if UNICODE
/* put the OEM'd domain name */
- PutUniCode(smb_buf(outbuf)+encrypt_len,lp_workgroup());
+ PutUniCode(smb_buf(outbuf)+encrypt_len,myworkgroup);
#else
- strcpy(smb_buf(outbuf)+encrypt_len, lp_workgroup());
+ strcpy(smb_buf(outbuf)+encrypt_len, myworkgroup);
#endif
CVAL(outbuf,smb_vwv1) = secword;
@@ -3258,9 +3316,9 @@ void exit_server(char *reason)
#endif
}
-#if FAST_SHARE_MODES
+#ifdef FAST_SHARE_MODES
stop_share_mode_mgmt();
-#endif
+#endif /* FAST_SHARE_MODES */
DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:""));
exit(0);
@@ -3738,24 +3796,6 @@ static void process(void)
if (lp_readprediction())
do_read_prediction();
- {
- extern pstring share_del_pending;
- if (*share_del_pending) {
- unbecome_user();
- if (!unlink(share_del_pending))
- DEBUG(3,("Share file deleted %s\n",share_del_pending));
- else
- DEBUG(2,("Share del failed of %s\n",share_del_pending));
- share_del_pending[0] = 0;
- }
- }
-
- if (share_mode_pending) {
- unbecome_user();
- check_share_modes();
- share_mode_pending=False;
- }
-
errno = 0;
for (counter=SMBD_SELECT_LOOP;
@@ -3787,6 +3827,7 @@ static void process(void)
if (!(counter%SMBD_RELOAD_CHECK))
reload_services(True);
+#if 0 /* JRA */
/* check the share modes every 10 secs */
if (!(counter%SHARE_MODES_CHECK))
check_share_modes();
@@ -3794,6 +3835,7 @@ static void process(void)
/* clean the share modes every 5 minutes */
if (!(counter%SHARE_MODES_CLEAN))
clean_share_modes();
+#endif /* JRA */
/* automatic timeout if all connections are closed */
if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) {
@@ -4082,6 +4124,8 @@ static void usage(char *pname)
if (!reload_services(False))
return(-1);
+ strcpy(myworkgroup, lp_workgroup());
+
#ifndef NO_SIGNAL_TEST
signal(SIGHUP,SIGNAL_CAST sig_hup);
#endif
@@ -4128,10 +4172,10 @@ static void usage(char *pname)
if (!open_sockets(is_daemon,port))
exit(1);
-#if FAST_SHARE_MODES
+#ifdef FAST_SHARE_MODES
if (!start_share_mode_mgmt())
exit(1);
-#endif
+#endif /* FAST_SHARE_MODES */
/* possibly reload the services file. */
reload_services(True);
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 38c7031b66..1d9977c66e 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -277,6 +277,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l
strequal(Connections[cnum].dirpath,"/"));
BOOL was_8_3;
int nt_extmode; /* Used for NT connections instead of mode */
+ BOOL needslash = ( Connections[cnum].dirpath[strlen(Connections[cnum].dirpath) -1] != '/');
*fname = 0;
*out_of_space = False;
@@ -323,7 +324,8 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l
continue;
strcpy(pathreal,Connections[cnum].dirpath);
- strcat(pathreal,"/");
+ if(needslash)
+ strcat(pathreal,"/");
strcat(pathreal,fname);
if (sys_stat(pathreal,&sbuf) != 0)
{
diff --git a/source3/utils/status.c b/source3/utils/status.c
index e8e57b3dd7..b439741e6c 100644
--- a/source3/utils/status.c
+++ b/source3/utils/status.c
@@ -53,6 +53,81 @@ int Ucrit_pid[100]; /* Ugly !!! */ /* added by OH */
int Ucrit_MaxPid=0; /* added by OH */
unsigned int Ucrit_IsActive = 0; /* added by OH */
+#ifndef FAST_SHARE_MODES
+static char *read_share_file(int fd, char *fname, char *progname)
+{
+ struct stat sb;
+ char *buf;
+ int size;
+
+ if(fstat(fd, &sb) != 0)
+ {
+ printf("%s: ERROR: read_share_file: Failed to do stat on share file %s (%s)\n",
+ progname, fname, strerror(errno));
+ return 0;
+ }
+
+ if(sb.st_size == 0)
+ {
+ return 0;
+ }
+
+ /* Allocate space for the file */
+ if((buf = (char *)malloc(sb.st_size)) == NULL)
+ {
+ printf("%s: read_share_file: malloc for file size %d fail !\n",
+ progname, (int)sb.st_size);
+ return 0;
+ }
+
+ if(lseek(fd, 0, SEEK_SET) != 0)
+ {
+ printf("%s: ERROR: read_share_file: Failed to reset position to 0 \
+for share file %s (%s)\n", progname, fname, strerror(errno));
+ if(buf)
+ free(buf);
+ return 0;
+ }
+
+ if (read(fd,buf,sb.st_size) != sb.st_size)
+ {
+ printf("%s: ERROR: read_share_file: Failed to read share file %s (%s)\n",
+ progname, fname, strerror(errno));
+ if(buf)
+ free(buf);
+ return 0;
+ }
+
+ if (IVAL(buf,0) != LOCKING_VERSION) {
+ printf("%s: ERROR: read_share_file: share file %s has incorrect \
+locking version (was %d, should be %d).\n",fname,
+ progname, IVAL(buf,0), LOCKING_VERSION);
+ if(buf)
+ free(buf);
+ return 0;
+ }
+
+ /* Sanity check for file contents */
+ size = sb.st_size;
+ size -= 10; /* Remove the header */
+
+ /* Remove the filename component. */
+ size -= SVAL(buf, 8);
+
+ /* The remaining size must be a multiple of 16 - error if not. */
+ if((size % 16) != 0)
+ {
+ printf("%s: ERROR: read_share_file: share file %s is an incorrect length.\n",
+ progname, fname);
+ if(buf)
+ free(buf);
+ return 0;
+ }
+
+ return buf;
+}
+#endif /* FAST_SHARE_MODES */
+
int main(int argc, char *argv[])
{
FILE *f;
@@ -64,16 +139,16 @@ unsigned int Ucrit_IsActive = 0; /* added by OH */
BOOL firstopen=True;
BOOL processes_only=False;
int last_pid=0;
-#if FAST_SHARE_MODES
+#ifdef FAST_SHARE_MODES
pstring shmem_file_name;
- share_mode_record *scanner_p;
- share_mode_record *prev_p;
+ share_mode_record *file_scanner_p;
+ smb_shm_offset_t *mode_array;
int bytes_free, bytes_used, bytes_overhead, bytes_total;
-#else
- int n;
+#else /* FAST_SHARE_MODES */
void *dir;
char *s;
-#endif
+#endif /* FAST_SHARE_MODES */
+ int i;
struct session_record *ptr;
@@ -226,101 +301,110 @@ unsigned int Ucrit_IsActive = 0; /* added by OH */
printf("\n");
-#if FAST_SHARE_MODES
+#ifdef FAST_SHARE_MODES
/*******************************************************************
initialize the shared memory for share_mode management
******************************************************************/
-
strcpy(shmem_file_name,lp_lockdir());
trim_string(shmem_file_name,"","/");
if (!*shmem_file_name) exit(-1);
strcat(shmem_file_name, "/SHARE_MEM_FILE");
- if(!smb_shm_open(shmem_file_name, SHMEM_SIZE)) exit(-1);
+ if(!smb_shm_open(shmem_file_name, lp_shmem_size())) exit(-1);
- if(!smb_shm_lock())
+ mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
+ if(mode_array == NULL)
{
- smb_shm_close();
- exit (-1);
+ printf("%s: base of shared memory hash array == 0! Exiting.\n", argv[0]);
+ smb_shm_close();
+ exit(-1);
}
- scanner_p = (share_mode_record *)smb_shm_offset2addr(smb_shm_get_userdef_off());
- prev_p = scanner_p;
- while(scanner_p)
+ for( i = 0; i < lp_shmem_hash_size(); i++)
{
- int pid,mode;
- struct timeval t;
-
- pid = scanner_p->pid;
-
- if ( !Ucrit_checkPid(pid) )
- {
- prev_p = scanner_p ;
- scanner_p = (share_mode_record *)smb_shm_offset2addr(scanner_p->next_offset);
- continue;
- }
+ smb_shm_lock_hash_entry(i);
+ if(mode_array[i] == NULL_OFFSET)
+ {
+ smb_shm_unlock_hash_entry(i);
+ continue;
+ }
+ file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[i]);
+ while((file_scanner_p != 0) && (file_scanner_p->num_share_mode_entries != 0))
+ {
+ share_mode_entry *entry_scanner_p =
+ (share_mode_entry *)smb_shm_offset2addr(
+ file_scanner_p->share_mode_entries);
+
+ while(entry_scanner_p != 0)
+ {
+ struct timeval t;
+ int pid = entry_scanner_p->pid;
+ int mode = entry_scanner_p->share_mode;
- if( (scanner_p->locking_version != LOCKING_VERSION) || !process_exists(pid))
+ t.tv_sec = entry_scanner_p->time.tv_sec;
+ t.tv_usec = entry_scanner_p->time.tv_usec;
+ strcpy(fname, file_scanner_p->file_name);
+#else /* FAST_SHARE_MODES */
+
+ /* For slow share modes go through all the files in
+ the share mode directory and read the entries in
+ each.
+ */
+
+ dir = opendir(lp_lockdir());
+ if (!dir)
{
- DEBUG(2,("Deleting stale share mode record"));
- if(prev_p == scanner_p)
- {
- smb_shm_set_userdef_off(scanner_p->next_offset);
- smb_shm_free(smb_shm_addr2offset(scanner_p));
- scanner_p = (share_mode_record *)smb_shm_offset2addr(smb_shm_get_userdef_off());
- prev_p = scanner_p;
- }
- else
- {
- prev_p->next_offset = scanner_p->next_offset;
- smb_shm_free(smb_shm_addr2offset(scanner_p));
- scanner_p = (share_mode_record *)smb_shm_offset2addr(prev_p->next_offset);
- }
- continue;
+ printf("%s: Unable to open lock directory %s.\n", argv[0], lp_lockdir());
+ return(0);
}
- t.tv_sec = scanner_p->time.tv_sec;
- t.tv_usec = scanner_p->time.tv_usec;
- mode = scanner_p->share_mode;
- strcpy(fname, scanner_p->file_name);
-#else
- dir = opendir(lp_lockdir());
- if (!dir) return(0);
while ((s=readdirname(dir))) {
- char buf[20];
- int pid,mode;
- struct timeval t;
+ char *buf;
+ char *base;
int fd;
pstring lname;
- int dev,inode;
+ uint32 dev,inode;
- if (sscanf(s,"share.%d.%d",&dev,&inode)!=2) continue;
+ if (sscanf(s,"share.%u.%u",&dev,&inode)!=2) continue;
strcpy(lname,lp_lockdir());
trim_string(lname,NULL,"/");
strcat(lname,"/");
strcat(lname,s);
- fd = open(lname,O_RDONLY,0);
- if (fd < 0) continue;
- if (read(fd,buf,20) != 20) continue;
- n = read(fd,fname,sizeof(fname));
- fname[MAX(n,0)]=0;
- close(fd);
-
- t.tv_sec = IVAL(buf,4);
- t.tv_usec = IVAL(buf,8);
- mode = IVAL(buf,12);
- pid = IVAL(buf,16);
-
- if ( !Ucrit_checkPid(pid) ) /* added by OH */
- continue;
-
- if (IVAL(buf,0) != LOCKING_VERSION || !process_exists(pid)) {
- if (unlink(lname)==0)
- printf("Deleted stale share file %s\n",s);
- continue;
+ fd = open(lname,O_RDWR,0);
+ if (fd < 0)
+ {
+ printf("%s: Unable to open share file %s.\n", argv[0], lname);
+ continue;
}
-#endif
+
+ /* Lock the share mode file while we read it. */
+ if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False)
+ {
+ printf("%s: Unable to lock open share file %s.\n", argv[0], lname);
+ close(fd);
+ continue;
+ }
+
+ if(( buf = read_share_file( fd, lname, argv[0] )) == NULL)
+ {
+ close(fd);
+ continue;
+ }
+ strcpy( fname, &buf[10]);
+ close(fd);
+
+ base = buf + 10 + SVAL(buf,8);
+ for( i = 0; i < IVAL(buf, 4); i++)
+ {
+ char *p = base + (i*16);
+ struct timeval t;
+ int pid = IVAL(p,12);
+ int mode = IVAL(p,8);
+
+ t.tv_sec = IVAL(p,0);
+ t.tv_usec = IVAL(p,4);
+#endif /* FAST_SHARE_MODES */
fname[sizeof(fname)-1] = 0;
@@ -349,28 +433,38 @@ unsigned int Ucrit_IsActive = 0; /* added by OH */
}
printf(" %s %s",fname,asctime(LocalTime((time_t *)&t.tv_sec)));
-#if FAST_SHARE_MODES
- prev_p = scanner_p ;
- scanner_p = (share_mode_record *)smb_shm_offset2addr(scanner_p->next_offset);
- } /* end while */
+#ifdef FAST_SHARE_MODES
+
+ entry_scanner_p = (share_mode_entry *)smb_shm_offset2addr(
+ entry_scanner_p->next_share_mode_entry);
+ } /* end while entry_scanner_p */
+ file_scanner_p = (share_mode_record *)smb_shm_offset2addr(
+ file_scanner_p->next_offset);
+ } /* end while file_scanner_p */
+ smb_shm_unlock_hash_entry(i);
+ } /* end for */
smb_shm_get_usage(&bytes_free, &bytes_used, &bytes_overhead);
bytes_total = bytes_free + bytes_used + bytes_overhead;
- smb_shm_unlock();
/*******************************************************************
deinitialize the shared memory for share_mode management
******************************************************************/
smb_shm_close();
-#else
+#else /* FAST_SHARE_MODES */
+ } /* end for i */
+
+ if(buf)
+ free(buf);
+ base = 0;
} /* end while */
closedir(dir);
-#endif
+#endif /* FAST_SHARE_MODES */
if (firstopen)
printf("No locked files\n");
-#if FAST_SHARE_MODES
+#ifdef FAST_SHARE_MODES
printf("\nShare mode memory usage (bytes):\n");
printf(" %d(%d%%) free + %d(%d%%) used + %d(%d%%) overhead = %d(100%%) total\n",
bytes_free, (bytes_free * 100)/bytes_total,
@@ -378,7 +472,7 @@ unsigned int Ucrit_IsActive = 0; /* added by OH */
bytes_overhead, (bytes_overhead * 100)/bytes_total,
bytes_total);
-#endif
+#endif /* FAST_SHARE_MODES */
return (0);
}