network recycle bin

Peter Samuelson peter at cadcamlab.org
Tue Mar 7 07:56:27 GMT 2000


[Carey Sinclair]
> Yes, surely this would be relatively simply to patch into the Samba
> code.  I too, would be very eager if this facility was available.

I don't feel like I need such a feature, but it sounded like fun.  And
I wanted a break from doing the work I'm supposed to be doing right
now.  Besides, as you reassured us, it's "relatively simple".

Well, "relatively simple" turns out to be in the eye of the beholder.
In my case, as a relative Samba-hacking newbie, the first cut has taken
several hours.  But the patch below is functional (if barely so) at
least at my end.  It is NOT well-tested -- minimally and against NT
only.  Please test!

Features/notes:

* Adds per-share parameter "recycle bin = /some/directory" into which
  deleted files go.
* Files are never overwritten; each file gets a suffix ~N where N is
  the first available nonnegative integer.
* /some/directory must be on the same filesystem as the share, and must 
  be writable by all necessary users.  Sticky bit recommended.

Bugs/TODO:

* Crossing mount points.  Doable but not at all trivial to get right.
* Flat namespace.  Should not be all that hard to fix.  Maybe later.
* Filenames are munged even if original name is not in use.  Should be
  easy to fix.
* Interesting things could happen if you put the recycle bin in the
  share itself.  Loops might be possible if a user tries to delete it,
  I'm not sure.  If you need to do this, use `veto files' to make it
  invisible.  I have no intention of fixing this.

Peter

diff -urNX../xp samba-2.0.6/source/include/proto.h samba-recycle/source/include/proto.h
--- samba-2.0.6/source/include/proto.h	Wed Nov 10 20:36:01 1999
+++ samba-recycle/source/include/proto.h	Mon Mar  6 23:43:20 2000
@@ -1146,6 +1146,7 @@
 char *lp_hide_files(int );
 char *lp_veto_oplocks(int );
 char *lp_driverlocation(int );
+char *lp_recyclebin(int );
 BOOL lp_preexec_close(int );
 BOOL lp_rootpreexec_close(int );
 BOOL lp_revalidate(int );
diff -urNX../xp samba-2.0.6/source/param/loadparm.c samba-recycle/source/param/loadparm.c
--- samba-2.0.6/source/param/loadparm.c	Wed Nov 10 20:36:05 1999
+++ samba-recycle/source/param/loadparm.c	Mon Mar  6 23:44:06 2000
@@ -295,6 +295,7 @@
   char *writelist;
   char *volume;
   char *fstype;
+  char *recycle_bin;
   int  iMinPrintSpace;
   int  iCreate_mask;
   int  iCreate_force_mode;
@@ -396,6 +397,7 @@
   NULL,    /* writelist */
   NULL,    /* volume */
   NULL,    /* fstype */
+  NULL,    /* recycle_bin */
   0,       /* iMinPrintSpace */
   0744,    /* iCreate_mask */
   0000,    /* iCreate_force_mode */
@@ -831,6 +833,7 @@
   
   {"fake directory create times", P_BOOL,P_LOCAL,  &sDefault.bFakeDirCreateTimes, NULL,   NULL, FLAG_SHARE|FLAG_GLOBAL},
   {"panic action",     P_STRING,  P_GLOBAL, &Globals.szPanicAction,     NULL,   NULL,  0},
+  {"recycle bin",      P_STRING,  P_LOCAL,  &sDefault.recycle_bin,      NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
 
   {NULL,               P_BOOL,    P_NONE,   NULL,                       NULL,   NULL, 0}
 };
@@ -1341,6 +1344,7 @@
 FN_LOCAL_STRING(lp_hide_files,szHideFiles)
 FN_LOCAL_STRING(lp_veto_oplocks,szVetoOplockFiles)
 FN_LOCAL_STRING(lp_driverlocation,szPrinterDriverLocation)
+FN_LOCAL_STRING(lp_recyclebin,recycle_bin)
 
 FN_LOCAL_BOOL(lp_preexec_close,bPreexecClose)
 FN_LOCAL_BOOL(lp_rootpreexec_close,bRootpreexecClose)
diff -urNX../xp samba-2.0.6/source/smbd/reply.c samba-recycle/source/smbd/reply.c
--- samba-2.0.6/source/smbd/reply.c	Wed Nov 10 20:36:11 1999
+++ samba-recycle/source/smbd/reply.c	Tue Mar  7 01:27:21 2000
@@ -1916,6 +1916,43 @@
   return(True);
 }
 
+/********************************************************************
+move file to recycle bin, if there is one
+
+The NAME parameter is a DOS filename; RECYCLE_BIN is verbatim.
+Currently, use of a recycle bin across filesystems is b0rken.
+*********************************************************************/
+static int recycle(char *name, char *recycle_bin)
+{
+  char *base;
+  pstring bin;
+  char buf[9];
+  int i=0, len, addlen, rcode;
+
+  if(!recycle_bin || !*recycle_bin)
+    return dos_unlink(name);
+
+  base = strrchr(name, '/') + 1;
+  if(base == (char*)1)
+    base = name;
+
+  /* empty files can just be deleted */
+  if(dos_file_size(name) == 0)
+    return dos_unlink(name);
+
+  pstrcpy(bin, recycle_bin);
+  pstrcat(bin, "/");
+  pstrcat(bin, base);
+  len = strlen(bin);
+  addlen = sizeof(pstring)-len-1;
+  do {
+    slprintf(bin+len, addlen, "~%d", i++);
+  } while(dos_file_exist(bin, NULL));
+
+DEBUG(3, ("recycle bin: source='%s'  dest='%s'\n", name, bin));
+  return rename (name, bin);
+}
+
 /****************************************************************************
  Reply to a unlink
 ****************************************************************************/
@@ -1934,6 +1973,7 @@
   BOOL exists=False;
   BOOL bad_path = False;
   BOOL rc = True;
+  char *recycle_bin = lp_recyclebin(SNUM(conn));
 
   *directory = *mask = 0;
 
@@ -1972,7 +2012,7 @@
   if (!has_wild) {
     pstrcat(directory,"/");
     pstrcat(directory,mask);
-    if (can_delete(directory,conn,dirtype) && !dos_unlink(directory))
+    if (can_delete(directory,conn,dirtype) && !recycle(directory, recycle_bin))
       count++;
     if (!count)
       exists = dos_file_exist(directory,NULL);    
@@ -2005,7 +2045,7 @@
 	    error = ERRnoaccess;
 	    slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
 	    if (!can_delete(fname,conn,dirtype)) continue;
-	    if (!dos_unlink(fname)) count++;
+	    if (!recycle(fname, recycle_bin)) count++;
 	    DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
 	  }
 	CloseDir(dirptr);


More information about the samba-ntdom mailing list