new vfs_recycle option?
Eddy PELAIC
eddy.pelaic at univ-paris5.fr
Wed Dec 12 18:20:12 GMT 2007
Hi,
Since my last mail [VFS recycle hack (Home folder's suite...)], I found
the way to cut the user home dir path in the
recycle bin. This is a usefull option for Home directory shares (only?).
The end user will not have to think why there are a folder with is name
in the recycle bin (when keeptree = yes)... (not user friendly I think).
Ex:
file in /home/t/o/toto/file.txt
for a Trash in %x/%U/Trash, will give :
/home/t/o/toto/Trash/t/o/toto/file.txt
%x is a custom add, for %U = toto, %x = t/o (subdir's before homedir
in the share)
I had few options to cut 't/o/toto' dir in Trash
[share]
...
vfs object = recycle recycle:repository recycle:keeptree
recycle:cutpath recycle:cutrepopath ...
recycle:keeptree
recycle:repository=%x/%U/Trash
recycle:cutpath=%x/%U/
recycle:cutrepopath=Yes
...
Now if I recycle the same file, It give /home/t/o/Trash/file.txt
and for /home/t/o/toto/dir1/dir2/file.txt =>
/home/t/o/toto/Trash/dir1/dir2/file.txt
Here the patch for samba-3.04 Debian Etch.
Next step will be for a directory or file path like
/home/t/o/toto/dir1/dir2/dir3/dir4, if I put in the recycle bin the dir3
directory, to have => /home/t/o/toto/Trash/dir3/(and subdir's of dir3).
Like a Desktop recycle bin.
Is, the unlink call from the client recursive dir by dir and file by
file...?
@+
Edo...
PS: You should wonder while reading the code, but I did my best with my
little knowledge of C and I tried to respect samba team's style coding.
*** samba-3.0.24/source/lib/substitute.c 2007-02-04
19:59:17.000000000 +0100
--- samba-3.0.24/source/lib/substitute.c 2007-12-12
14:43:10.000000000 +0100
***************
*** 24,29 ****
--- 24,31 ----
extern struct current_user current_user;
+ void sub_set_smb_name_dir(const char *name);
+
fstring local_machine="";
fstring remote_arch="UNKNOWN";
userdom_struct current_user_info;
***************
*** 31,36 ****
--- 33,39 ----
static fstring remote_machine;
static fstring smb_user_name;
+ static fstring smb_user_name_dir;
/**
* Set the 'local' machine name
***************
*** 135,146 ****
--- 138,178 ----
alpha_strcpy( smb_user_name, tmp, SAFE_NETBIOS_CHARS,
sizeof(smb_user_name)-1 );
+ sub_set_smb_name_dir( smb_user_name );
+
if ( is_machine_account ) {
len = strlen( smb_user_name );
smb_user_name[len-1] = '$';
}
}
+ void sub_set_smb_name_dir(const char *name)
+ {
+
+ smb_user_name_dir[0] = smb_user_name[0];
+ smb_user_name_dir[1] = '/';
+ smb_user_name_dir[2] = smb_user_name[1];
+ smb_user_name_dir[3] = '\0';
+
+ }
+
+ char * sub_parse_smb_name_dir(const char *name)
+ {
+ char * tmp = NULL;
+ tmp = malloc( sizeof( char ) * 4 );
+ if ( tmp == NULL){
+ return NULL;
+ }
+ else{
+ tmp[0] = name[0];
+ tmp[1] = '/';
+ tmp[2] = name[1];
+ tmp[3] = '\0';
+
+ return tmp;
+ }
+ }
+
char* sub_get_smb_name( void )
{
return smb_user_name;
***************
*** 549,554 ****
--- 581,593 ----
case '(':
a_string = realloc_expand_longvar( a_string, p );
break;
+ case 'x' :
+ r = strdup_lower( sub_parse_smb_name_dir( smb_name ) );
+ if (r == NULL) {
+ goto error;
+ }
+ a_string = realloc_string_sub(a_string, "%x", r);
+ break;
default:
break;
}
*** samba-3.0.24/source/modules/vfs_recycle.c 2007-02-04
19:59:19.000000000 +0100
--- samba-3.0.24/source/modules/vfs_recycle.c 2007-12-12
18:35:57.000000000 +0100
***************
*** 75,80 ****
--- 75,204 ----
return tmp_str;
}
+ /*
+ * Check if full_string start with sub_string, if sub_string finish
with '/'
+ * it won't be checked.
+ * edo
+ */
+ static BOOL recycle_startwith( const char *full_string, const char
*sub_string )
+ {
+ BOOL ret;
+ int i = 0;
+ int full_string_len = 0;
+ int sub_string_len = 0;
+
+ ret = True;
+
+ if ( ( full_string != NULL ) &&
+ ( sub_string != NULL ) ){
+
+ full_string_len = strlen( full_string );
+ sub_string_len = strlen( sub_string );
+
+ if ( sub_string_len > 1 ){
+ if ( sub_string[sub_string_len-1] == '/' ){
+ sub_string_len--;
+ DEBUG( 10, ( "recycle: startwith : cut last '/' in
sub_string\n" ) );
+ }
+ }
+
+ if ( sub_string_len <= full_string_len ){
+
+ for( i = 0; i < sub_string_len; i++ ){
+
+ if ( sub_string[i] != full_string[i] ){
+
+ ret = False;
+ break;
+ DEBUG( 10, ( "recycle: startwith : cut last
leaving loop\n" ) );
+ }
+ }
+ }
+ else{
+ ret = False;
+ DEBUG( 10, ( "recycle: startwith : sub_string_len >
full_string_len \n" ) );
+ }
+ }
+ else{
+ ret = False;
+ DEBUG( 10, ( "recycle: startwith : parameter(s) NULL ?\n" ) );
+ }
+
+ DEBUG(10, ("recycle: startwith = %s\n", ret?"True":"False"));
+
+ return ret;
+ }
+ /*
+ * cut sub_string in full_string if it start with, use
recycle_startwith( full_string, sub_string )
+ * to check if it start with.
+ * edo
+ */
+ static char *recycle_cut_substr( const char *full_string, const char
*sub_string )
+ {
+ char *tmp_str = NULL;
+
+ int sub_string_len = 0;
+ int full_string_len = 0;
+
+ tmp_str = malloc( sizeof( pstring ) );
+
+ if ( ( tmp_str != NULL) &&
+ ( full_string != NULL) &&
+ ( sub_string != NULL) ){
+
+ DEBUG( 10, ( "recycle: cut_substr : full_string : %s\n",
full_string ) );
+ DEBUG( 10, ( "recycle: cut_substr : sub_string : %s\n",
sub_string ) );
+
+ sub_string_len = strlen( sub_string );
+ full_string_len = strlen( full_string );
+
+ int i = 0;
+ int j = 0;
+
+ for( i = i + sub_string_len; i < full_string_len; i++, j++ ){
+ tmp_str[j] = (char)full_string[i];
+ }
+
+ tmp_str[j] = '\0';
+
+ DEBUG( 10, ( "recycle: cut_substr : tmp_str : %s\n", tmp_str ) );
+ }
+ else{
+
+ }
+
+ return tmp_str;
+ }
+ /*
+ * get the pattern to cut stored in recycle:cutpath option (string
option, wildcard's allowed).
+ * ex: recycle:cutpath = %U/
+ * edo
+ */
+ static const char *recycle_cut_path(vfs_handle_struct *handle)
+ {
+ const char *tmp_str = NULL;
+
+
+ tmp_str = lp_parm_const_string(SNUM(handle->conn), "recycle",
"cutpath", NULL);
+
+ DEBUG(10, ("recycle: cut path pattern = %s\n", tmp_str));
+
+ return tmp_str;
+ }
+ /*
+ * check if recycle_unlink(...) must cut the string pattern
+ * stored in recycle:cutrepath option (Boolean value)
+ */
+ static BOOL recycle_cut_repository_path(vfs_handle_struct *handle)
+ {
+ BOOL ret;
+
+ ret = lp_parm_bool(SNUM(handle->conn), "recycle", "cutrepopath",
False);
+
+ DEBUG(10, ("recycle_bin: cutrepopath = %s\n", ret?"True":"False"));
+
+ return ret;
+ }
static BOOL recycle_keep_dir_tree(vfs_handle_struct *handle)
{
***************
*** 373,379 ****
static int recycle_unlink(vfs_handle_struct *handle, connection_struct
*conn, const char *file_name)
{
char *path_name = NULL;
! char *temp_name = NULL;
char *final_name = NULL;
const char *base;
char *repository = NULL;
--- 497,503 ----
static int recycle_unlink(vfs_handle_struct *handle, connection_struct
*conn, const char *file_name)
{
char *path_name = NULL;
! char *temp_name = NULL;
char *final_name = NULL;
const char *base;
char *repository = NULL;
***************
*** 383,388 ****
--- 507,520 ----
BOOL exist;
int rc = -1;
+
+ /* custom adds */
+ char *cut_path_tmp = NULL;
+ char *cut_path_name = NULL;
+ char *cut_start = NULL;
+
+
+
repository = alloc_sub_conn(conn, recycle_repository(handle));
ALLOC_CHECK(repository, done);
/* shouldn't we allow absolute path names here? --metze */
***************
*** 394,400 ****
rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name);
goto done;
}
!
/* we don't recycle the recycle bin... */
if (strncmp(file_name, repository, strlen(repository)) == 0) {
DEBUG(3, ("recycle: File is within recycling bin, unlinking
...\n"));
--- 526,532 ----
rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name);
goto done;
}
!
/* we don't recycle the recycle bin... */
if (strncmp(file_name, repository, strlen(repository)) == 0) {
DEBUG(3, ("recycle: File is within recycling bin, unlinking
...\n"));
***************
*** 453,465 ****
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(recycle_exclude(handle), base)) {
DEBUG(3, ("recycle: file %s is excluded \n", base));
rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name);
goto done;
}
/* FIXME: this check will fail if we have more than one level of
directories,
* we shoud check for every level 1, 1/2, 1/2/3, 1/2/3/4 ....
* ---simo
--- 585,602 ----
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(recycle_exclude(handle), base)) {
DEBUG(3, ("recycle: file %s is excluded \n", base));
rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name);
goto done;
}
+
+
/* FIXME: this check will fail if we have more than one level of
directories,
* we shoud check for every level 1, 1/2, 1/2/3, 1/2/3/4 ....
* ---simo
***************
*** 471,482 ****
}
if (recycle_keep_dir_tree(handle) == True) {
! asprintf(&temp_name, "%s/%s", repository, path_name);
} else {
temp_name = SMB_STRDUP(repository);
}
ALLOC_CHECK(temp_name, done);
exist = recycle_directory_exist(handle, temp_name);
if (exist) {
DEBUG(10, ("recycle: Directory already exists\n"));
--- 608,658 ----
}
if (recycle_keep_dir_tree(handle) == True) {
!
! if ( recycle_cut_repository_path(handle) == True ){
!
! DEBUG( 10, ("recycle: cut_repository_path Yes\n" ) );
!
! cut_path_tmp = alloc_sub_conn(conn,
recycle_cut_path(handle));
!
! ALLOC_CHECK( cut_path_tmp, done);
!
! DEBUG( 10, ( "recycle: cut_path_tmp : %s\n",
cut_path_tmp) );
!
! if ( recycle_startwith( path_name, cut_path_tmp ) ==
True ){
! /* cut start with path pattern in path_name */
! cut_path_name = recycle_cut_substr( path_name ,
cut_path_tmp );
!
! ALLOC_CHECK( cut_path_name, done );
!
! DEBUG( 10, ( "recycle: cut_path_name : %s\n",
cut_path_name ) );
!
! if ( strlen( cut_path_name) != 0 ){
! asprintf(&temp_name, "%s/%s", repository,
cut_path_name );
! DEBUG( 10, ( "recycle: temp_name : %s\n",
temp_name ) );
! }
! else{
! temp_name = SMB_STRDUP(repository);
! DEBUG( 10, ( "recycle: temp_name : %s\n",
temp_name ) );
! }
! }
! else{
! DEBUG( 10, ("recycle: won't change original path,
check recycle:cutpath in smb.conf\n" ) );
! asprintf(&temp_name, "%s/%s", repository, path_name );
! }
!
! }
! else{
! DEBUG( 10, ("recycle: cut_repository_path No\n" ) );
! asprintf(&temp_name, "%s/%s", repository, path_name );
! }
} else {
temp_name = SMB_STRDUP(repository);
+ DEBUG( 10, (" temp_name: %s \n", temp_name));
}
ALLOC_CHECK(temp_name, done);
+
exist = recycle_directory_exist(handle, temp_name);
if (exist) {
DEBUG(10, ("recycle: Directory already exists\n"));
***************
*** 527,532 ****
--- 703,711 ----
SAFE_FREE(temp_name);
SAFE_FREE(final_name);
SAFE_FREE(repository);
+ SAFE_FREE(cut_path_tmp);
+ SAFE_FREE(cut_path_name);
+ SAFE_FREE(cut_start);
return rc;
}
--
Eddy PELAIC
Service informatique
Faculté de chirurgie dentaire
Université Paris Descartes
1, rue Maurice Arnoux
92120
Montrouge
Tel: 01 58 07 67 13
mail: eddy.pelaic at univ-paris5.fr
More information about the samba-technical
mailing list