mirror of
https://github.com/samba-team/samba.git
synced 2025-01-14 19:24:43 +03:00
e7c8c15888
1. Finally work with cascaded modules with private data storage per module 2. Convert VFS API to macro calls to simplify cascading 3. Add quota support to VFS layer (prepare to NT quota support) Patch by Stefan (metze) Metzemacher, with review of Jelmer and me Tested in past few weeks. Documentation to new VFS API for third-party developers to follow (This used to be commit 91984ef5caa2d13c5d52e1f535bd3bbbae1ec978)
271 lines
7.2 KiB
C
271 lines
7.2 KiB
C
/*
|
|
Unix SMB/CIFS implementation.
|
|
Manage connections_struct structures
|
|
Copyright (C) Andrew Tridgell 1998
|
|
Copyright (C) Alexander Bokovoy 2002
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#include "includes.h"
|
|
|
|
/* set these to define the limits of the server. NOTE These are on a
|
|
per-client basis. Thus any one machine can't connect to more than
|
|
MAX_CONNECTIONS services, but any number of machines may connect at
|
|
one time. */
|
|
#define MAX_CONNECTIONS 128
|
|
|
|
static connection_struct *Connections;
|
|
|
|
/* number of open connections */
|
|
static struct bitmap *bmap;
|
|
static int num_open;
|
|
|
|
/****************************************************************************
|
|
init the conn structures
|
|
****************************************************************************/
|
|
void conn_init(void)
|
|
{
|
|
bmap = bitmap_allocate(MAX_CONNECTIONS);
|
|
}
|
|
|
|
/****************************************************************************
|
|
return the number of open connections
|
|
****************************************************************************/
|
|
int conn_num_open(void)
|
|
{
|
|
return num_open;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
check if a snum is in use
|
|
****************************************************************************/
|
|
BOOL conn_snum_used(int snum)
|
|
{
|
|
connection_struct *conn;
|
|
for (conn=Connections;conn;conn=conn->next) {
|
|
if (conn->service == snum) {
|
|
return(True);
|
|
}
|
|
}
|
|
return(False);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
find a conn given a cnum
|
|
****************************************************************************/
|
|
connection_struct *conn_find(unsigned cnum)
|
|
{
|
|
int count=0;
|
|
connection_struct *conn;
|
|
|
|
for (conn=Connections;conn;conn=conn->next,count++) {
|
|
if (conn->cnum == cnum) {
|
|
if (count > 10) {
|
|
DLIST_PROMOTE(Connections, conn);
|
|
}
|
|
return conn;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
find first available connection slot, starting from a random position.
|
|
The randomisation stops problems with the server dieing and clients
|
|
thinking the server is still available.
|
|
****************************************************************************/
|
|
connection_struct *conn_new(void)
|
|
{
|
|
TALLOC_CTX *mem_ctx;
|
|
connection_struct *conn;
|
|
int i;
|
|
|
|
i = bitmap_find(bmap, 1);
|
|
|
|
if (i == -1) {
|
|
DEBUG(1,("ERROR! Out of connection structures\n"));
|
|
return NULL;
|
|
}
|
|
|
|
if ((mem_ctx=talloc_init("connection_struct"))==NULL) {
|
|
DEBUG(0,("talloc_init(connection_struct) failed!\n"));
|
|
return NULL;
|
|
}
|
|
|
|
if ((conn=(connection_struct *)talloc_zero(mem_ctx, sizeof(*conn)))==NULL) {
|
|
DEBUG(0,("talloc_zero() failed!\n"));
|
|
return NULL;
|
|
}
|
|
conn->mem_ctx = mem_ctx;
|
|
conn->cnum = i;
|
|
|
|
bitmap_set(bmap, i);
|
|
|
|
num_open++;
|
|
|
|
string_set(&conn->user,"");
|
|
string_set(&conn->dirpath,"");
|
|
string_set(&conn->connectpath,"");
|
|
string_set(&conn->origpath,"");
|
|
|
|
DLIST_ADD(Connections, conn);
|
|
|
|
return conn;
|
|
}
|
|
|
|
/****************************************************************************
|
|
close all conn structures
|
|
****************************************************************************/
|
|
void conn_close_all(void)
|
|
{
|
|
connection_struct *conn, *next;
|
|
for (conn=Connections;conn;conn=next) {
|
|
next=conn->next;
|
|
close_cnum(conn, conn->vuid);
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
Idle inactive connections.
|
|
****************************************************************************/
|
|
|
|
BOOL conn_idle_all(time_t t, int deadtime)
|
|
{
|
|
pipes_struct *plist = NULL;
|
|
BOOL allidle = True;
|
|
connection_struct *conn, *next;
|
|
|
|
for (conn=Connections;conn;conn=next) {
|
|
next=conn->next;
|
|
/* close dirptrs on connections that are idle */
|
|
if ((t-conn->lastused) > DPTR_IDLE_TIMEOUT)
|
|
dptr_idlecnum(conn);
|
|
|
|
if (conn->num_files_open > 0 ||
|
|
(t-conn->lastused)<deadtime)
|
|
allidle = False;
|
|
}
|
|
|
|
/*
|
|
* Check all pipes for any open handles. We cannot
|
|
* idle with a handle open.
|
|
*/
|
|
|
|
for (plist = get_first_internal_pipe(); plist; plist = get_next_internal_pipe(plist))
|
|
if (plist->pipe_handles && plist->pipe_handles->count)
|
|
allidle = False;
|
|
|
|
return allidle;
|
|
}
|
|
|
|
/****************************************************************************
|
|
clear a vuid out of the validity cache, and as the 'owner' of a connection.
|
|
****************************************************************************/
|
|
void conn_clear_vuid_cache(uint16 vuid)
|
|
{
|
|
connection_struct *conn;
|
|
unsigned int i;
|
|
|
|
for (conn=Connections;conn;conn=conn->next) {
|
|
if (conn->vuid == vuid) {
|
|
conn->vuid = UID_FIELD_INVALID;
|
|
}
|
|
|
|
for (i=0;i<conn->vuid_cache.entries && i< VUID_CACHE_SIZE;i++) {
|
|
if (conn->vuid_cache.list[i] == vuid) {
|
|
conn->vuid_cache.list[i] = UID_FIELD_INVALID;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
Free a conn structure.
|
|
****************************************************************************/
|
|
|
|
void conn_free(connection_struct *conn)
|
|
{
|
|
vfs_handle_struct *handle = NULL, *thandle = NULL;
|
|
TALLOC_CTX *mem_ctx = NULL;
|
|
|
|
/* Free vfs_connection_struct */
|
|
handle = conn->vfs_handles;
|
|
while(handle) {
|
|
DLIST_REMOVE(conn->vfs_handles, handle);
|
|
thandle = handle->next;
|
|
if (handle->free_data)
|
|
handle->free_data(&handle->data);
|
|
handle = thandle;
|
|
}
|
|
|
|
DLIST_REMOVE(Connections, conn);
|
|
|
|
if (conn->ngroups && conn->groups) {
|
|
SAFE_FREE(conn->groups);
|
|
conn->ngroups = 0;
|
|
}
|
|
|
|
free_namearray(conn->veto_list);
|
|
free_namearray(conn->hide_list);
|
|
free_namearray(conn->veto_oplock_list);
|
|
|
|
string_free(&conn->user);
|
|
string_free(&conn->dirpath);
|
|
string_free(&conn->connectpath);
|
|
string_free(&conn->origpath);
|
|
|
|
bitmap_clear(bmap, conn->cnum);
|
|
num_open--;
|
|
|
|
mem_ctx = conn->mem_ctx;
|
|
ZERO_STRUCTP(conn);
|
|
talloc_destroy(mem_ctx);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
receive a smbcontrol message to forcibly unmount a share
|
|
the message contains just a share name and all instances of that
|
|
share are unmounted
|
|
the special sharename '*' forces unmount of all shares
|
|
****************************************************************************/
|
|
void msg_force_tdis(int msg_type, pid_t pid, void *buf, size_t len)
|
|
{
|
|
connection_struct *conn, *next;
|
|
fstring sharename;
|
|
|
|
fstrcpy(sharename, buf);
|
|
|
|
if (strcmp(sharename, "*") == 0) {
|
|
DEBUG(1,("Forcing close of all shares\n"));
|
|
conn_close_all();
|
|
return;
|
|
}
|
|
|
|
for (conn=Connections;conn;conn=next) {
|
|
next=conn->next;
|
|
if (strequal(lp_servicename(conn->service), sharename)) {
|
|
DEBUG(1,("Forcing close of share %s cnum=%d\n",
|
|
sharename, conn->cnum));
|
|
close_cnum(conn, (uint16)-1);
|
|
}
|
|
}
|
|
}
|