mirror of
https://github.com/samba-team/samba.git
synced 2025-10-28 03:33:13 +03:00
make vfs recycle use vfs facilities correctly!
WARNING: every vfs module maintainer should look at these changes to understand how to properly write a vfs module in head!!
also make installmodules work correctly when the directory structure is not yet in place.
Simo.
(This used to be commit 6dfa460986)
This commit is contained in:
@@ -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"))) {
|
||||
DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n"));
|
||||
return 0;
|
||||
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;
|
||||
}
|
||||
|
||||
recbin = talloc(ctx,sizeof(recycle_bin_struct));
|
||||
if ( recbin == NULL) {
|
||||
if (!(ctx = talloc_init_named("recycle bin connection"))) {
|
||||
DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n"));
|
||||
return -1;
|
||||
}
|
||||
recbin->ctx = ctx;
|
||||
|
||||
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->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;
|
||||
|
||||
Reference in New Issue
Block a user