diff options
Diffstat (limited to 'source3/modules')
-rw-r--r-- | source3/modules/vfs_recycle.c | 161 |
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; |