summaryrefslogtreecommitdiff
path: root/source3/modules
diff options
context:
space:
mode:
Diffstat (limited to 'source3/modules')
-rw-r--r--source3/modules/vfs_recycle.c161
1 files changed, 138 insertions, 23 deletions
diff --git a/source3/modules/vfs_recycle.c b/source3/modules/vfs_recycle.c
index b59cb92a28..74e034a77e 100644
--- a/source3/modules/vfs_recycle.c
+++ b/source3/modules/vfs_recycle.c
@@ -37,7 +37,7 @@ static const char *delimiter = "|"; /* delimiter for options */
typedef struct recycle_bin_struct
{
- TALLOC_CTX *ctx;
+ TALLOC_CTX *mem_ctx;
char *repository; /* name of the recycle bin directory */
BOOL keep_dir_tree; /* keep directory structure of deleted file in recycle bin */
BOOL versions; /* create versions of deleted files with identical name */
@@ -48,6 +48,19 @@ typedef struct recycle_bin_struct
SMB_OFF_T maxsize; /* maximum file size to be saved */
} recycle_bin_struct;
+typedef struct recycle_bin_connections {
+ int conn;
+ recycle_bin_struct *data;
+ struct recycle_bin_connections *next;
+} recycle_bin_connections;
+
+typedef struct recycle_bin_private_data {
+ TALLOC_CTX *mem_ctx;
+ recycle_bin_connections *conns;
+} recycle_bin_private_data;
+
+struct smb_vfs_handle_struct *recycle_bin_private_handle;
+
/* VFS operations */
static struct vfs_ops default_vfs_ops; /* For passthrough operation */
@@ -87,6 +100,8 @@ static BOOL check_bool_param(const char *value)
vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops,
struct smb_vfs_handle_struct *vfs_handle)
{
+ TALLOC_CTX *mem_ctx = NULL;
+
DEBUG(10, ("Initializing VFS module recycle\n"));
*vfs_version = SMB_VFS_INTERFACE_VERSION;
memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops));
@@ -98,6 +113,20 @@ vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops,
DEBUG(0, ("vfs_recycle: Debug class number of 'vfs_recycle': %d\n", vfs_recycle_debug_level));
}
+ recycle_bin_private_handle = vfs_handle;
+ if (!(mem_ctx = talloc_init_named("recycle bin data"))) {
+ DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n"));
+ return NULL;
+ }
+
+ recycle_bin_private_handle->data = talloc(mem_ctx, sizeof(recycle_bin_private_data));
+ if (recycle_bin_private_handle->data == NULL) {
+ DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n"));
+ return NULL;
+ }
+ ((recycle_bin_private_data *)(recycle_bin_private_handle->data))->mem_ctx = mem_ctx;
+ ((recycle_bin_private_data *)(recycle_bin_private_handle->data))->conns = NULL;
+
return recycle_ops;
}
@@ -105,34 +134,68 @@ vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops,
* VFS finalization function.
*
**/
-void vfs_done(connection_struct *conn)
+void vfs_done(void)
{
- DEBUG(10,("Called for connection %d\n", SNUM(conn)));
+ recycle_bin_private_data *recdata;
+ recycle_bin_connections *recconn;
+
+ DEBUG(10, ("Unloading/Cleaning VFS module recycle bin\n"));
+
+ if (recycle_bin_private_handle)
+ recdata = (recycle_bin_private_data *)(recycle_bin_private_handle->data);
+ else {
+ DEBUG(0, ("Recycle bin not initialized!\n"));
+ return;
+ }
+
+ if (recdata) {
+ if (recdata->conns) {
+ recconn = recdata->conns;
+ while (recconn) {
+ talloc_destroy(recconn->data->mem_ctx);
+ recconn = recconn->next;
+ }
+ }
+ if (recdata->mem_ctx) {
+ talloc_destroy(recdata->mem_ctx);
+ }
+ recdata = NULL;
+ }
}
static int recycle_connect(struct connection_struct *conn, const char *service, const char *user)
{
TALLOC_CTX *ctx = NULL;
recycle_bin_struct *recbin;
+ recycle_bin_connections *recconn;
+ recycle_bin_connections *recconnbase;
+ recycle_bin_private_data *recdata;
char *servicename;
char *tmp_str;
DEBUG(10, ("Called for service %s (%d) as user %s\n", service, SNUM(conn), user));
- if (!(ctx = talloc_init_named("recycle bin"))) {
+ if (recycle_bin_private_handle)
+ recdata = (recycle_bin_private_data *)(recycle_bin_private_handle->data);
+ else {
+ DEBUG(0, ("Recycle bin not initialized!\n"));
+ return -1;
+ }
+
+ if (!(ctx = talloc_init_named("recycle bin connection"))) {
DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n"));
- return 0;
+ return -1;
}
- recbin = talloc(ctx,sizeof(recycle_bin_struct));
- if ( recbin == NULL) {
+ recbin = talloc(ctx, sizeof(recycle_bin_struct));
+ if (recbin == NULL) {
DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n"));
return -1;
}
- recbin->ctx = ctx;
+ recbin->mem_ctx = ctx;
/* Set defaults */
- recbin->repository = talloc_strdup(ctx, ".recycle");
+ recbin->repository = talloc_strdup(recbin->mem_ctx, ".recycle");
ALLOC_CHECK(recbin->repository, error);
recbin->keep_dir_tree = False;
recbin->versions = False;
@@ -143,10 +206,10 @@ static int recycle_connect(struct connection_struct *conn, const char *service,
recbin->maxsize = 0;
/* parse configuration options */
- servicename = talloc_strdup(recbin->ctx, lp_servicename(SNUM(conn)));
+ servicename = talloc_strdup(recbin->mem_ctx, lp_servicename(SNUM(conn)));
DEBUG(10, ("servicename = %s\n",servicename));
if ((tmp_str = lp_parm_string(servicename, "vfs_recycle_bin", "repository")) != NULL) {
- recbin->repository = talloc_sub_conn(ctx, conn, tmp_str);
+ recbin->repository = talloc_sub_conn(recbin->mem_ctx, conn, tmp_str);
ALLOC_CHECK(recbin->repository, error);
trim_string(recbin->repository, "/", "/");
DEBUG(5, ("recycle.bin: repository = %s\n", recbin->repository));
@@ -176,22 +239,36 @@ static int recycle_connect(struct connection_struct *conn, const char *service,
}
}
if ((tmp_str = lp_parm_string(servicename, "vfs_recycle_bin", "exclude")) != NULL) {
- recbin->exclude = talloc_strdup(ctx, tmp_str);
+ recbin->exclude = talloc_strdup(recbin->mem_ctx, tmp_str);
ALLOC_CHECK(recbin->exclude, error);
DEBUG(5, ("recycle.bin: exclude = %s\n", recbin->exclude));
}
if ((tmp_str = lp_parm_string(servicename,"vfs_recycle_bin", "exclude_dir")) != NULL) {
- recbin->exclude_dir = talloc_strdup(ctx, tmp_str);
+ recbin->exclude_dir = talloc_strdup(recbin->mem_ctx, tmp_str);
ALLOC_CHECK(recbin->exclude_dir, error);
DEBUG(5, ("recycle.bin: exclude_dir = %s\n", recbin->exclude_dir));
}
if ((tmp_str = lp_parm_string(servicename,"vfs_recycle_bin", "noversions")) != NULL) {
- recbin->noversions = talloc_strdup(ctx, tmp_str);
+ recbin->noversions = talloc_strdup(recbin->mem_ctx, tmp_str);
ALLOC_CHECK(recbin->noversions, error);
DEBUG(5, ("recycle.bin: noversions = %s\n", recbin->noversions));
}
- conn->vfs_private = (void *)recbin;
+ recconn = talloc(recdata->mem_ctx, sizeof(recycle_bin_connections));
+ if (recconn == NULL) {
+ DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n"));
+ goto error;
+ }
+ recconn->conn = SNUM(conn);
+ recconn->data = recbin;
+ recconn->next = NULL;
+ if (recdata->conns) {
+ recconnbase = recdata->conns;
+ while (recconnbase->next != NULL) recconnbase = recconnbase->next;
+ recconnbase->next = recconn;
+ } else {
+ recdata->conns = recconn;
+ }
return default_vfs_ops.connect(conn, service, user);
error:
@@ -201,10 +278,35 @@ error:
static void recycle_disconnect(struct connection_struct *conn)
{
+ recycle_bin_private_data *recdata;
+ recycle_bin_connections *recconn;
+
DEBUG(10, ("Disconnecting VFS module recycle bin\n"));
- if (conn->vfs_private) {
- talloc_destroy(((recycle_bin_struct *)conn->vfs_private)->ctx);
- conn->vfs_private = NULL;
+
+ if (recycle_bin_private_handle)
+ recdata = (recycle_bin_private_data *)(recycle_bin_private_handle->data);
+ else {
+ DEBUG(0, ("Recycle bin not initialized!\n"));
+ return;
+ }
+
+ if (recdata) {
+ if (recdata->conns) {
+ if (recdata->conns->conn == SNUM(conn)) {
+ talloc_destroy(recdata->conns->data->mem_ctx);
+ recdata->conns = recdata->conns->next;
+ } else {
+ recconn = recdata->conns;
+ while (recconn->next) {
+ if (recconn->next->conn == SNUM(conn)) {
+ talloc_destroy(recconn->next->data->mem_ctx);
+ recconn->next = recconn->next->next;
+ break;
+ }
+ recconn = recconn->next;
+ }
+ }
+ }
}
default_vfs_ops.disconnect(conn);
}
@@ -391,6 +493,8 @@ static void recycle_touch(connection_struct *conn, const char *fname)
**/
static int recycle_unlink(connection_struct *conn, const char *inname)
{
+ recycle_bin_private_data *recdata;
+ recycle_bin_connections *recconn;
recycle_bin_struct *recbin;
char *file_name = NULL;
char *path_name = NULL;
@@ -398,17 +502,28 @@ static int recycle_unlink(connection_struct *conn, const char *inname)
char *final_name = NULL;
char *base;
int i;
- SMB_BIG_UINT dfree, dsize, bsize;
- SMB_OFF_T file_size, space_avail;
+/* SMB_BIG_UINT dfree, dsize, bsize; */
+ SMB_OFF_T file_size; /* space_avail; */
BOOL exist;
int rc = -1;
file_name = strdup(inname);
ALLOC_CHECK(file_name, done);
- if (conn->vfs_private)
- recbin = (recycle_bin_struct *)conn->vfs_private;
- else {
+ recbin = NULL;
+ if (recycle_bin_private_handle) {
+ recdata = (recycle_bin_private_data *)(recycle_bin_private_handle->data);
+ if (recdata) {
+ if (recdata->conns) {
+ recconn = recdata->conns;
+ while (recconn && recconn->conn != SNUM(conn)) recconn = recconn->next;
+ if (recconn != NULL) {
+ recbin = recconn->data;
+ }
+ }
+ }
+ }
+ if (recbin == NULL) {
DEBUG(0, ("Recycle bin not initialized!\n"));
rc = default_vfs_ops.unlink(conn, file_name);
goto done;