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