summaryrefslogtreecommitdiff
path: root/source3/modules/vfs_recycle.c
diff options
context:
space:
mode:
authorAlexander Bokovoy <ab@samba.org>2003-05-11 23:34:18 +0000
committerAlexander Bokovoy <ab@samba.org>2003-05-11 23:34:18 +0000
commite7c8c15888454043c73967635deb4d3419a489e9 (patch)
treef876b48b107b0f1c3b05445f1198d4858a46aa24 /source3/modules/vfs_recycle.c
parent03589cf994e91a06a44e528d5864f2c85bcf8bef (diff)
downloadsamba-e7c8c15888454043c73967635deb4d3419a489e9.tar.gz
samba-e7c8c15888454043c73967635deb4d3419a489e9.tar.bz2
samba-e7c8c15888454043c73967635deb4d3419a489e9.zip
Fix VFS layer:
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)
Diffstat (limited to 'source3/modules/vfs_recycle.c')
-rw-r--r--source3/modules/vfs_recycle.c508
1 files changed, 198 insertions, 310 deletions
diff --git a/source3/modules/vfs_recycle.c b/source3/modules/vfs_recycle.c
index 87dea944ac..03e2c5eabc 100644
--- a/source3/modules/vfs_recycle.c
+++ b/source3/modules/vfs_recycle.c
@@ -6,6 +6,7 @@
* Copyright (C) 2002, Alexander Bokovoy - cascaded VFS adoption,
* Copyright (C) 2002, Juergen Hasch - added some options.
* Copyright (C) 2002, Simo Sorce
+ * Copyright (C) 2002, Stefan (metze) Metzmacher
*
* 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
@@ -30,45 +31,10 @@ static int vfs_recycle_debug_level = DBGC_VFS;
#undef DBGC_CLASS
#define DBGC_CLASS vfs_recycle_debug_level
-
-static const char *delimiter = "|"; /* delimiter for options */
-
-/* One per connection */
-
-typedef struct recycle_bin_struct
-{
- 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 */
- BOOL touch; /* touch access date of deleted file */
- char *exclude; /* which files to exclude */
- char *exclude_dir; /* which directories to exclude */
- char *noversions; /* which files to exclude from versioning */
- 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 */
-
-static int recycle_connect(struct connection_struct *conn, const char *service, const char *user);
-static void recycle_disconnect(struct connection_struct *conn);
-static int recycle_unlink(connection_struct *, const char *);
-
-#define VFS_OP(x) ((void *) x)
+
+static int recycle_connect(vfs_handle_struct *handle, connection_struct *conn, const char *service, const char *user);
+static void recycle_disconnect(vfs_handle_struct *handle, connection_struct *conn);
+static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *name);
static vfs_op_tuple recycle_ops[] = {
@@ -82,179 +48,116 @@ static vfs_op_tuple recycle_ops[] = {
{NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
};
-/**
- * VFS initialisation function.
- *
- * @retval initialised vfs_op_tuple array
- **/
-static vfs_op_tuple *recycle_init(const struct vfs_ops *def_vfs_ops,
- struct smb_vfs_handle_struct *vfs_handle)
+static int recycle_connect(vfs_handle_struct *handle, connection_struct *conn, const char *service, const char *user)
{
- TALLOC_CTX *mem_ctx = NULL;
+ DEBUG(10,("recycle_connect() connect to service[%s] as user[%s].\n",
+ service,user));
- DEBUG(10, ("Initializing VFS module recycle\n"));
- memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops));
- vfs_recycle_debug_level = debug_add_class("vfs_recycle_bin");
- if (vfs_recycle_debug_level == -1) {
- vfs_recycle_debug_level = DBGC_VFS;
- DEBUG(0, ("vfs_recycle: Couldn't register custom debugging class!\n"));
- } else {
- 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("recycle bin data"))) {
- DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n"));
- return NULL;
- }
+ return VFS_NEXT_CONNECT(handle, conn, service, user);
+}
- 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;
+static void recycle_disconnect(vfs_handle_struct *handle, connection_struct *conn)
+{
+ DEBUG(10,("recycle_disconnect() connect to service[%s].\n",
+ lp_servicename(SNUM(conn))));
- return recycle_ops;
+ VFS_NEXT_DISCONNECT(handle, conn);
}
-static int recycle_connect(struct connection_struct *conn, const char *service, const char *user)
+static const char *recycle_repository(vfs_handle_struct *handle)
{
- TALLOC_CTX *ctx = NULL;
- recycle_bin_struct *recbin;
- recycle_bin_connections *recconn;
- recycle_bin_connections *recconnbase;
- recycle_bin_private_data *recdata;
- const char *tmp_str;
+ const char *tmp_str = NULL;
+
- DEBUG(10, ("Called for service %s (%d) as user %s\n", service, SNUM(conn), user));
+ tmp_str = lp_parm_const_string(SNUM(handle->conn), "recycle", "repository",".recycle");
- 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;
- }
+ DEBUG(10, ("recycle: repository = %s\n", tmp_str));
+
+ return tmp_str;
+}
- if (!(ctx = talloc_init("recycle bin connection"))) {
- DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n"));
- return -1;
- }
+static BOOL recycle_keep_dir_tree(vfs_handle_struct *handle)
+{
+ BOOL ret;
+
+ ret = lp_parm_bool(SNUM(handle->conn), "recycle", "keeptree", False);
- recbin = talloc_zero(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;
-
- /* parse configuration options */
- if ((tmp_str = lp_parm_const_string(SNUM(conn), "vfs_recycle_bin", "repository", ".recycle")) != NULL) {
- 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));
- } else {
- DEBUG(0,("recycle.bin: no repository found (fail) !\n"));
- goto error;
- }
+ DEBUG(10, ("recycle_bin: keeptree = %s\n", ret?"True":"False"));
- recbin->keep_dir_tree = lp_parm_bool(SNUM(conn), "vfs_recycle_bin", "keeptree", False);
- DEBUG(5, ("recycle.bin: keeptree = %d\n", recbin->keep_dir_tree));
+ return ret;
+}
+
+static BOOL recycle_versions(vfs_handle_struct *handle)
+{
+ BOOL ret;
+
+ ret = lp_parm_bool(SNUM(handle->conn), "recycle", "versions", False);
+
+ DEBUG(10, ("recycle: versions = %s\n", ret?"True":"False"));
- recbin->versions = lp_parm_bool(SNUM(conn), "vfs_recycle_bin", "versions", False);
- DEBUG(5, ("recycle.bin: versions = %d\n", recbin->versions));
+ return ret;
+}
+
+static BOOL recycle_touch(vfs_handle_struct *handle)
+{
+ BOOL ret;
+
+ ret = lp_parm_bool(SNUM(handle->conn), "recycle", "touch", False);
+
+ DEBUG(10, ("recycle: touch = %s\n", ret?"True":"False"));
- recbin->touch = lp_parm_bool(SNUM(conn), "vfs_recycle_bin", "touch", False);
- DEBUG(5, ("recycle.bin: touch = %d\n", recbin->touch));
+ return ret;
+}
- recbin->maxsize = lp_parm_ulong(SNUM(conn), "vfs_recycle_bin", "maxsize" , 0);
- if (recbin->maxsize == 0) {
- recbin->maxsize = -1;
- DEBUG(5, ("recycle.bin: maxsize = -infinite-\n"));
- } else {
- DEBUG(5, ("recycle.bin: maxsize = %ld\n", (long int)recbin->maxsize));
- }
+static const char **recycle_exclude(vfs_handle_struct *handle)
+{
+ const char **tmp_lp;
+
+ tmp_lp = lp_parm_string_list(SNUM(handle->conn), "recycle", "exclude", NULL);
- if ((tmp_str = lp_parm_const_string(SNUM(conn), "vfs_recycle_bin", "exclude", "")) != NULL) {
- 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_const_string(SNUM(conn), "vfs_recycle_bin", "exclude_dir", "")) != NULL) {
- 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_const_string(SNUM(conn), "vfs_recycle_bin", "noversions", "")) != NULL) {
- recbin->noversions = talloc_strdup(recbin->mem_ctx, tmp_str);
- ALLOC_CHECK(recbin->noversions, error);
- DEBUG(5, ("recycle.bin: noversions = %s\n", recbin->noversions));
- }
+ DEBUG(10, ("recycle: exclude = %s ...\n", tmp_lp?*tmp_lp:""));
+
+ return tmp_lp;
+}
- 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);
+static const char **recycle_exclude_dir(vfs_handle_struct *handle)
+{
+ const char **tmp_lp;
+
+ tmp_lp = lp_parm_string_list(SNUM(handle->conn), "recycle", "exclude_dir", NULL);
-error:
- talloc_destroy(ctx);
- return -1;
+ DEBUG(10, ("recycle: exclude_dir = %s ...\n", tmp_lp?*tmp_lp:""));
+
+ return tmp_lp;
}
-static void recycle_disconnect(struct connection_struct *conn)
+static const char **recycle_noversions(vfs_handle_struct *handle)
{
- recycle_bin_private_data *recdata;
- recycle_bin_connections *recconn;
+ const char **tmp_lp;
+
+ tmp_lp = lp_parm_string_list(SNUM(handle->conn), "recycle", "noversions", NULL);
- DEBUG(10, ("Disconnecting VFS module recycle bin\n"));
+ DEBUG(10, ("recycle: noversions = %s\n", tmp_lp?*tmp_lp:""));
+
+ return tmp_lp;
+}
- if (recycle_bin_private_handle)
- recdata = (recycle_bin_private_data *)(recycle_bin_private_handle->data);
- else {
- DEBUG(0, ("Recycle bin not initialized!\n"));
- return;
- }
+static int recycle_maxsize(vfs_handle_struct *handle)
+{
+ int maxsize;
+
+ maxsize = lp_parm_int(SNUM(handle->conn), "recycle", "maxsize", -1);
- 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);
+ DEBUG(10, ("recycle: maxsize = %d\n", maxsize));
+
+ return maxsize;
}
-static BOOL recycle_directory_exist(connection_struct *conn, const char *dname)
+static BOOL recycle_directory_exist(vfs_handle_struct *handle, const char *dname)
{
SMB_STRUCT_STAT st;
- if (default_vfs_ops.stat(conn, dname, &st) == 0) {
+ if (VFS_NEXT_STAT(handle, handle->conn, dname, &st) == 0) {
if (S_ISDIR(st.st_mode)) {
return True;
}
@@ -263,11 +166,11 @@ static BOOL recycle_directory_exist(connection_struct *conn, const char *dname)
return False;
}
-static BOOL recycle_file_exist(connection_struct *conn, const char *fname)
+static BOOL recycle_file_exist(vfs_handle_struct *handle, const char *fname)
{
SMB_STRUCT_STAT st;
- if (default_vfs_ops.stat(conn, fname, &st) == 0) {
+ if (VFS_NEXT_STAT(handle, handle->conn, fname, &st) == 0) {
if (S_ISREG(st.st_mode)) {
return True;
}
@@ -282,13 +185,15 @@ static BOOL recycle_file_exist(connection_struct *conn, const char *fname)
* @param fname file name
* @return size in bytes
**/
-static SMB_OFF_T recycle_get_file_size(connection_struct *conn, const char *fname)
+static SMB_OFF_T recycle_get_file_size(vfs_handle_struct *handle, const char *fname)
{
SMB_STRUCT_STAT st;
- if (default_vfs_ops.stat(conn, fname, &st) != 0) {
- DEBUG(0,("recycle.bin: stat for %s returned %s\n", fname, strerror(errno)));
+
+ if (VFS_NEXT_STAT(handle, handle->conn, fname, &st) != 0) {
+ DEBUG(0,("recycle: stat for %s returned %s\n", fname, strerror(errno)));
return (SMB_OFF_T)0;
}
+
return(st.st_size);
}
@@ -298,7 +203,7 @@ static SMB_OFF_T recycle_get_file_size(connection_struct *conn, const char *fnam
* @param dname Directory tree to be created
* @return Returns True for success
**/
-static BOOL recycle_create_dir(connection_struct *conn, const char *dname)
+static BOOL recycle_create_dir(vfs_handle_struct *handle, const char *dname)
{
int len;
mode_t mode;
@@ -322,18 +227,18 @@ static BOOL recycle_create_dir(connection_struct *conn, const char *dname)
/* Create directory tree if neccessary */
for(token = strtok(tok_str, "/"); token; token = strtok(NULL, "/")) {
safe_strcat(new_dir, token, len);
- if (recycle_directory_exist(conn, new_dir))
- DEBUG(10, ("recycle.bin: dir %s already exists\n", new_dir));
+ if (recycle_directory_exist(handle, new_dir))
+ DEBUG(10, ("recycle: dir %s already exists\n", new_dir));
else {
- DEBUG(5, ("recycle.bin: creating new dir %s\n", new_dir));
- if (default_vfs_ops.mkdir(conn, new_dir, mode) != 0) {
- DEBUG(1,("recycle.bin: mkdir failed for %s with error: %s\n", new_dir, strerror(errno)));
+ DEBUG(5, ("recycle: creating new dir %s\n", new_dir));
+ if (VFS_NEXT_MKDIR(handle, handle->conn, new_dir, mode) != 0) {
+ DEBUG(1,("recycle: mkdir failed for %s with error: %s\n", new_dir, strerror(errno)));
ret = False;
goto done;
}
}
safe_strcat(new_dir, "/", len);
- }
+ }
ret = True;
done:
@@ -348,30 +253,22 @@ done:
* @param needle string to be matched exactly to haystack
* @return True if found
**/
-static BOOL checkparam(const char *haystack, const char *needle)
+static BOOL checkparam(const char **haystack_list, const char *needle)
{
- char *token;
- char *tok_str;
- char *tmp_str;
- BOOL ret = False;
+ int i;
- if (haystack == NULL || strlen(haystack) == 0 || needle == NULL || strlen(needle) == 0) {
+ if (haystack_list == NULL || haystack_list[0] == NULL ||
+ *haystack_list[0] == '\0' || needle == NULL || *needle == '\0') {
return False;
}
- tmp_str = strdup(haystack);
- ALLOC_CHECK(tmp_str, done);
- token = tok_str = tmp_str;
-
- for(token = strtok(tok_str, delimiter); token; token = strtok(NULL, delimiter)) {
- if(strcmp(token, needle) == 0) {
- ret = True;
- goto done;
+ for(i=0; haystack_list[i] ; i++) {
+ if(strequal(haystack_list[i], needle)) {
+ return True;
}
}
-done:
- SAFE_FREE(tmp_str);
- return ret;
+
+ return False;
}
/**
@@ -380,110 +277,87 @@ done:
* @param needle string to be matched exectly to haystack including pattern matching
* @return True if found
**/
-static BOOL matchparam(const char *haystack, const char *needle)
+static BOOL matchparam(const char **haystack_list, const char *needle)
{
- char *token;
- char *tok_str;
- char *tmp_str;
- BOOL ret = False;
+ int i;
- if (haystack == NULL || strlen(haystack) == 0 || needle == NULL || strlen(needle) == 0) {
+ if (haystack_list == NULL || haystack_list[0] == NULL ||
+ *haystack_list[0] == '\0' || needle == NULL || *needle == '\0') {
return False;
}
- tmp_str = strdup(haystack);
- ALLOC_CHECK(tmp_str, done);
- token = tok_str = tmp_str;
-
- for(token = strtok(tok_str, delimiter); token; token = strtok(NULL, delimiter)) {
- if (!unix_wild_match(token, needle)) {
- ret = True;
- goto done;
+ for(i=0; haystack_list[i] ; i++) {
+ if(!unix_wild_match((char *)haystack_list[i], (char *)needle)) {
+ return True;
}
}
-done:
- SAFE_FREE(tmp_str);
- return ret;
+
+ return False;
}
/**
* Touch access date
**/
-static void recycle_touch(connection_struct *conn, const char *fname)
+static void recycle_do_touch(vfs_handle_struct *handle, const char *fname)
{
SMB_STRUCT_STAT st;
struct utimbuf tb;
time_t currtime;
-
- if (default_vfs_ops.stat(conn, fname, &st) != 0) {
- DEBUG(0,("recycle.bin: stat for %s returned %s\n", fname, strerror(errno)));
+
+ if (VFS_NEXT_STAT(handle, handle->conn, fname, &st) != 0) {
+ DEBUG(0,("recycle: stat for %s returned %s\n", fname, strerror(errno)));
return;
}
currtime = time(&currtime);
tb.actime = currtime;
tb.modtime = st.st_mtime;
- if (default_vfs_ops.utime(conn, fname, &tb) == -1 )
- DEBUG(0, ("recycle.bin: touching %s failed, reason = %s\n", fname, strerror(errno)));
+ if (VFS_NEXT_UTIME(handle, handle->conn, fname, &tb) == -1 ) {
+ DEBUG(0, ("recycle: touching %s failed, reason = %s\n", fname, strerror(errno)));
}
+}
/**
* Check if file should be recycled
**/
-static int recycle_unlink(connection_struct *conn, const char *file_name)
+static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *file_name)
{
- recycle_bin_private_data *recdata;
- recycle_bin_connections *recconn;
- recycle_bin_struct *recbin;
char *path_name = NULL;
char *temp_name = NULL;
char *final_name = NULL;
const char *base;
- int i;
-/* SMB_BIG_UINT dfree, dsize, bsize; */
+ char *repository = NULL;
+ int i = 1;
+ int maxsize;
SMB_OFF_T file_size; /* space_avail; */
BOOL exist;
int rc = -1;
- 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;
- }
-
- if(!recbin->repository || *(recbin->repository) == '\0') {
- DEBUG(3, ("Recycle path not set, purging %s...\n", file_name));
- rc = default_vfs_ops.unlink(conn, file_name);
+ repository = alloc_sub_conn(conn, (char *)recycle_repository(handle));
+ ALLOC_CHECK(repository, done);
+ /* shouldn't we allow absolute path names here? --metze */
+ trim_string(repository, "/", "/");
+
+ if(!repository || *(repository) == '\0') {
+ DEBUG(3, ("recycle: repository path not set, purging %s...\n", file_name));
+ rc = VFS_NEXT_UNLINK(handle, conn, file_name);
goto done;
}
/* we don't recycle the recycle bin... */
- if (strncmp(file_name, recbin->repository, strlen(recbin->repository)) == 0) {
- DEBUG(3, ("File is within recycling bin, unlinking ...\n"));
- rc = default_vfs_ops.unlink(conn, file_name);
+ if (strncmp(file_name, repository, strlen(repository)) == 0) {
+ DEBUG(3, ("recycle: File is within recycling bin, unlinking ...\n"));
+ rc = VFS_NEXT_UNLINK(handle, conn, file_name);
goto done;
}
- file_size = recycle_get_file_size(conn, file_name);
+ file_size = recycle_get_file_size(handle, file_name);
/* it is wrong to purge filenames only because they are empty imho
* --- simo
*
if(fsize == 0) {
- DEBUG(3, ("File %s is empty, purging...\n", file_name));
- rc = default_vfs_ops.unlink(conn,file_name);
+ DEBUG(3, ("recycle: File %s is empty, purging...\n", file_name));
+ rc = VFS_NEXT_UNLINK(handle,conn,file_name);
goto done;
}
*/
@@ -492,20 +366,21 @@ static int recycle_unlink(connection_struct *conn, const char *file_name)
* not greater then maxsize, not the size of the single file, also it is better
* to remove older files
*/
- if(recbin->maxsize > 0 && file_size > recbin->maxsize) {
- DEBUG(3, ("File %s exceeds maximum recycle size, purging... \n", file_name));
- rc = default_vfs_ops.unlink(conn, file_name);
+ maxsize = recycle_maxsize(handle);
+ if(maxsize > 0 && file_size > maxsize) {
+ DEBUG(3, ("recycle: File %s exceeds maximum recycle size, purging... \n", file_name));
+ rc = VFS_NEXT_UNLINK(handle, conn, file_name);
goto done;
}
/* FIXME: this is wrong: moving files with rename does not change the disk space
* allocation
*
- space_avail = default_vfs_ops.disk_free(conn, ".", True, &bsize, &dfree, &dsize) * 1024L;
+ space_avail = VFS_NEXT_DISK_FREE(handle, conn, ".", True, &bsize, &dfree, &dsize) * 1024L;
DEBUG(5, ("space_avail = %Lu, file_size = %Lu\n", space_avail, file_size));
if(space_avail < file_size) {
- DEBUG(3, ("Not enough diskspace, purging file %s\n", file_name));
- rc = default_vfs_ops.unlink(conn, file_name);
+ DEBUG(3, ("recycle: Not enough diskspace, purging file %s\n", file_name));
+ rc = VFS_NEXT_UNLINK(handle, conn, file_name);
goto done;
}
*/
@@ -524,13 +399,13 @@ static int recycle_unlink(connection_struct *conn, const char *file_name)
base++;
}
- DEBUG(10, ("recycle.bin: fname = %s\n", file_name)); /* original filename with path */
- DEBUG(10, ("recycle.bin: fpath = %s\n", path_name)); /* original path */
- DEBUG(10, ("recycle.bin: base = %s\n", base)); /* filename without path */
+ DEBUG(10, ("recycle: fname = %s\n", file_name)); /* original filename with path */
+ DEBUG(10, ("recycle: fpath = %s\n", path_name)); /* original path */
+ DEBUG(10, ("recycle: base = %s\n", base)); /* filename without path */
- if (matchparam(recbin->exclude, base)) {
- DEBUG(3, ("recycle.bin: file %s is excluded \n", base));
- rc = default_vfs_ops.unlink(conn, file_name);
+ if (matchparam(recycle_exclude(handle), base)) {
+ DEBUG(3, ("recycle: file %s is excluded \n", base));
+ rc = VFS_NEXT_UNLINK(handle, conn, file_name);
goto done;
}
@@ -538,72 +413,85 @@ static int recycle_unlink(connection_struct *conn, const char *file_name)
* we shoud check for every level 1, 1/2, 1/2/3, 1/2/3/4 ....
* ---simo
*/
- if (checkparam(recbin->exclude_dir, path_name)) {
- DEBUG(3, ("recycle.bin: directory %s is excluded \n", path_name));
- rc = default_vfs_ops.unlink(conn, file_name);
+ if (checkparam(recycle_exclude_dir(handle), path_name)) {
+ DEBUG(3, ("recycle: directory %s is excluded \n", path_name));
+ rc = VFS_NEXT_UNLINK(handle, conn, file_name);
goto done;
}
- /* see if we need to recreate the original directory structure in the recycle bin */
- if (recbin->keep_dir_tree == True) {
- asprintf(&temp_name, "%s/%s", recbin->repository, path_name);
+ if (recycle_keep_dir_tree(handle) == True) {
+ asprintf(&temp_name, "%s/%s", repository, path_name);
} else {
- temp_name = strdup(recbin->repository);
+ temp_name = strdup(repository);
}
ALLOC_CHECK(temp_name, done);
- exist = recycle_directory_exist(conn, temp_name);
+ exist = recycle_directory_exist(handle, temp_name);
if (exist) {
- DEBUG(10, ("recycle.bin: Directory already exists\n"));
+ DEBUG(10, ("recycle: Directory already exists\n"));
} else {
- DEBUG(10, ("recycle.bin: Creating directory %s\n", temp_name));
- if (recycle_create_dir(conn, temp_name) == False) {
- DEBUG(3, ("Could not create directory, purging %s...\n", file_name));
- rc = default_vfs_ops.unlink(conn, file_name);
+ DEBUG(10, ("recycle: Creating directory %s\n", temp_name));
+ if (recycle_create_dir(handle, temp_name) == False) {
+ DEBUG(3, ("recycle: Could not create directory, purging %s...\n", file_name));
+ rc = VFS_NEXT_UNLINK(handle, conn, file_name);
goto done;
}
}
asprintf(&final_name, "%s/%s", temp_name, base);
ALLOC_CHECK(final_name, done);
- DEBUG(10, ("recycle.bin: recycled file name: %s\n", temp_name)); /* new filename with path */
+ DEBUG(10, ("recycle: recycled file name: %s\n", final_name)); /* new filename with path */
/* check if we should delete file from recycle bin */
- if (recycle_file_exist(conn, final_name)) {
- if (recbin->versions == False || matchparam(recbin->noversions, base) == True) {
- DEBUG(3, ("recycle.bin: Removing old file %s from recycle bin\n", final_name));
- if (default_vfs_ops.unlink(conn, final_name) != 0) {
- DEBUG(1, ("recycle.bin: Error deleting old file: %s\n", strerror(errno)));
+ if (recycle_file_exist(handle, final_name)) {
+ if (recycle_versions(handle) == False || matchparam(recycle_noversions(handle), base) == True) {
+ DEBUG(3, ("recycle: Removing old file %s from recycle bin\n", final_name));
+ if (VFS_NEXT_UNLINK(handle, conn, final_name) != 0) {
+ DEBUG(1, ("recycle: Error deleting old file: %s\n", strerror(errno)));
}
}
}
/* rename file we move to recycle bin */
i = 1;
- while (recycle_file_exist(conn, final_name)) {
- snprintf(final_name, PATH_MAX, "%s/Copy #%d of %s", temp_name, i++, base);
+ while (recycle_file_exist(handle, final_name)) {
+ snprintf(final_name, PATH_MAX -1, "%s/Copy #%d of %s", temp_name, i++, base);
}
- DEBUG(10, ("recycle.bin: Moving %s to %s\n", file_name, final_name));
- rc = default_vfs_ops.rename(conn, file_name, final_name);
+ DEBUG(10, ("recycle: Moving %s to %s\n", file_name, final_name));
+ rc = VFS_NEXT_RENAME(handle, conn, file_name, final_name);
if (rc != 0) {
- DEBUG(3, ("recycle.bin: Move error %d (%s), purging file %s (%s)\n", errno, strerror(errno), file_name, final_name));
- rc = default_vfs_ops.unlink(conn, file_name);
+ DEBUG(3, ("recycle: Move error %d (%s), purging file %s (%s)\n", errno, strerror(errno), file_name, final_name));
+ rc = VFS_NEXT_UNLINK(handle, conn, file_name);
goto done;
}
/* touch access date of moved file */
- if (recbin->touch == True )
- recycle_touch(conn, final_name);
+ if (recycle_touch(handle) == True )
+ recycle_do_touch(handle, final_name);
done:
SAFE_FREE(path_name);
SAFE_FREE(temp_name);
SAFE_FREE(final_name);
+ SAFE_FREE(repository);
return rc;
}
NTSTATUS vfs_recycle_init(void)
-{
- return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "recycle", recycle_init);
+{
+ NTSTATUS ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "recycle", recycle_ops);
+
+ if (NT_STATUS_IS_ERR(ret))
+ return ret;
+
+ vfs_recycle_debug_level = debug_add_class("recycle");
+ if (vfs_recycle_debug_level == -1) {
+ vfs_recycle_debug_level = DBGC_VFS;
+ DEBUG(0, ("vfs_recycle: Couldn't register custom debugging class!\n"));
+ } else {
+ DEBUG(10, ("vfs_recycle: Debug class number of 'recycle': %d\n", vfs_recycle_debug_level));
+ }
+
+ return ret;
}