Patch to do "safe" delete.

Rogier Wolff R.E.Wolff at BitWizard.nl
Fri Feb 23 12:50:55 GMT 2001


Hi,

Many people delete files they end up needing later on. 

Attached is a patch that I think allows the sysop to find and retrieve
files that have been accidentally deleted.

This is implemented in the "samba" server, so it only helps the folks
who use the windows clients, not those logging in directly on the unix
server.

Questions for the "samba mailing list": 

- Does this look OK?
- Have I missed calls to "unlink" in the server?
  (Yes: I deliberatly don't save "temporary" files...  Anything else?)

- Have I missed something that makes it less useful? (e.g. in the idx 
  file...)


Samba team, would you be willing to include this? What's missing?


Implementation restriction: The file is copied, not "renamed".

- This allows the trashcan to reside on a different partition from the
  original data. 
- This allows me to use "mkstemp", wich was convenient. 
- Does have the overhead of copying the file on delete. This can take
a while if you delete for instance a CDROM image... 


Sysops are expected to start deleting files if the trashcan directory
becomes too full. Or when the daily backup has run. Or when a certain
time has expired. 

			Roger.


-- 
** R.E.Wolff at BitWizard.nl ** http://www.BitWizard.nl/ ** +31-15-2137555 **
*-- BitWizard writes Linux device drivers for any device you may have! --*
* There are old pilots, and there are bold pilots. 
* There are also old, bald pilots. 
-------------- next part --------------
diff -ur samba-2.0.5a/source/include/proto.h samba-2.0.5a.new/source/include/proto.h
--- samba-2.0.5a/source/include/proto.h	Thu Jul 22 04:00:26 1999
+++ samba-2.0.5a.new/source/include/proto.h	Fri Feb 23 12:58:00 2001
@@ -1123,6 +1123,7 @@
 char *lp_hide_files(int );
 char *lp_veto_oplocks(int );
 char *lp_driverlocation(int );
+char *lp_trashcan(int );
 BOOL lp_revalidate(int );
 BOOL lp_casesensitive(int );
 BOOL lp_preservecase(int );
diff -ur samba-2.0.5a/source/lib/doscalls.c samba-2.0.5a.new/source/lib/doscalls.c
--- samba-2.0.5a/source/lib/doscalls.c	Thu Apr  8 23:13:01 1999
+++ samba-2.0.5a.new/source/lib/doscalls.c	Fri Feb 23 12:57:52 2001
@@ -33,6 +33,60 @@
 
 extern int DEBUGLEVEL;
 
+
+
+/*******************************************************************
+ Unlink wrapper that calls dos_to_unix AND does the undelete stuff.
+********************************************************************/
+
+int safe_dos_unlink (struct connection_struct *conn, char *fname)
+{
+  char *ufname;
+  char *bname;
+  char *idxname;
+  char *newname;
+  int idx, old, new, l, n;
+#define BUFSIZE 1024
+  char buf[BUFSIZE];
+
+  DEBUG(0,("trashcan is %s\n",  lp_trashcan(SNUM(conn))));
+  if (! lp_trashcan(SNUM(conn)))
+    return dos_unlink (fname);
+
+  ufname = dos_to_unix(fname,False);
+  bname = strchr (ufname, '/');
+  if (!bname) bname = ufname;
+  else        bname++;
+
+  l = strlen (lp_trashcan(SNUM(conn))) + strlen (bname) + 32;
+  idxname = malloc (l);
+  newname = malloc (l);
+
+  snprintf (idxname, l, "%s/%s.idx.XXXXXX", lp_trashcan(SNUM(conn)), bname);
+  snprintf (newname, l, "%s/%s.del.XXXXXX", lp_trashcan(SNUM(conn)), bname);
+
+  idx = mkstemp (idxname);
+  new = mkstemp (newname); 
+  old = open (ufname, O_RDONLY);
+
+  while ((n = read (old, buf, BUFSIZE)) > 0) {
+    write (new, buf, n);
+  }
+  snprintf (buf, BUFSIZE, "dosname=%s\nunixname=%s\nnewname=%s\n", 
+	   fname, ufname, newname);
+  write (idx, buf, strlen (buf));
+
+  close (old);
+  close (new);
+  close (idx); 
+
+  free (idxname); 
+  free (newname); 
+  
+  return unlink (ufname); 
+}
+
+
 /*******************************************************************
  Unlink wrapper that calls dos_to_unix.
 ********************************************************************/
diff -ur samba-2.0.5a/source/lib/pidfile.c samba-2.0.5a.new/source/lib/pidfile.c
--- samba-2.0.5a/source/lib/pidfile.c	Wed Jul 21 03:25:08 1999
+++ samba-2.0.5a.new/source/lib/pidfile.c	Fri Feb 23 12:57:52 2001
@@ -94,11 +94,13 @@
 		exit(1);
 	}
 
+#if 0
 	if (fcntl_lock(fd,SMB_F_SETLK,0,1,F_WRLCK)==False) {
 		DEBUG(0,("ERROR: %s : fcntl lock of file %s failed. Error was %s\n",  
               name, pidFile, strerror(errno)));
 		exit(1);
 	}
+#endif
 
 	memset(buf, 0, sizeof(buf));
 	slprintf(buf, sizeof(buf) - 1, "%u\n", (unsigned int) getpid());
diff -ur samba-2.0.5a/source/param/loadparm.c samba-2.0.5a.new/source/param/loadparm.c
--- samba-2.0.5a/source/param/loadparm.c	Wed Jul 21 03:25:12 1999
+++ samba-2.0.5a.new/source/param/loadparm.c	Fri Feb 23 12:57:53 2001
@@ -291,6 +291,7 @@
   char *writelist;
   char *volume;
   char *fstype;
+  char *sTrashcan;
   int  iMinPrintSpace;
   int  iCreate_mask;
   int  iCreate_force_mode;
@@ -391,6 +392,7 @@
   NULL,    /* writelist */
   NULL,    /* volume */
   NULL,    /* fstype */
+  NULL,    /* Trashcan */
   0,       /* iMinPrintSpace */
   0744,    /* iCreate_mask */
   0000,    /* iCreate_force_mode */
@@ -713,6 +715,7 @@
   {"mangled names",    P_BOOL,    P_LOCAL,  &sDefault.bMangledNames,    NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
   {"mangled map",      P_STRING,  P_LOCAL,  &sDefault.szMangledMap,     NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
   {"stat cache",       P_BOOL,    P_GLOBAL, &Globals.bStatCache,        NULL,   NULL,  0},
+  {"trashcan",         P_STRING,  P_LOCAL,  &sDefault.sTrashcan,        NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
 
   {"Domain Options", P_SEP, P_SEPARATOR},
   {"domain groups",    P_STRING,  P_GLOBAL, &Globals.szDomainGroups,    NULL,   NULL,  0},
@@ -1314,6 +1317,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_trashcan,sTrashcan)
 
 FN_LOCAL_BOOL(lp_revalidate,bRevalidate)
 FN_LOCAL_BOOL(lp_casesensitive,bCaseSensitive)
diff -ur samba-2.0.5a/source/smbd/reply.c samba-2.0.5a.new/source/smbd/reply.c
--- samba-2.0.5a/source/smbd/reply.c	Wed Jul 21 03:25:21 1999
+++ samba-2.0.5a.new/source/smbd/reply.c	Fri Feb 23 12:57:54 2001
@@ -44,6 +44,8 @@
 uint32 global_client_caps = 0;
 unsigned int smb_echo_count = 0;
 
+
+
 /****************************************************************************
 report a possible attack via the password buffer overflow bug
 ****************************************************************************/
@@ -1898,7 +1900,7 @@
   if (!has_wild) {
     pstrcat(directory,"/");
     pstrcat(directory,mask);
-    if (can_delete(directory,conn,dirtype) && !dos_unlink(directory))
+    if (can_delete(directory,conn,dirtype) && !safe_dos_unlink(conn, directory))
       count++;
     if (!count)
       exists = dos_file_exist(directory,NULL);    
@@ -1931,7 +1933,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 (!safe_dos_unlink(conn, fname)) count++;
 	    DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
 	  }
 	CloseDir(dirptr);
@@ -3163,7 +3165,7 @@
 tree recursively.
 ****************************************************************************/
 
-static BOOL recursive_rmdir(char *directory)
+static BOOL recursive_rmdir(struct connection_struct *conn, char *directory)
 {
   char *dname = NULL;
   BOOL ret = False;
@@ -3199,7 +3201,7 @@
 
     if(st.st_mode & S_IFDIR)
     {
-      if(recursive_rmdir(fullname)!=0)
+      if(recursive_rmdir(conn, fullname)!=0)
       {
         ret = True;
         break;
@@ -3210,7 +3212,7 @@
         break;
       }
     }
-    else if(dos_unlink(fullname) != 0)
+    else if(safe_dos_unlink(conn, fullname) != 0)
     {
       ret = True;
       break;
@@ -3281,13 +3283,13 @@
           {
             if(lp_recursive_veto_delete(SNUM(conn)))
             {
-              if(recursive_rmdir(fullname) != 0)
+              if(recursive_rmdir(conn, fullname) != 0)
                 break;
             }
             if(dos_rmdir(fullname) != 0)
               break;
           }
-          else if(dos_unlink(fullname) != 0)
+          else if(safe_dos_unlink(conn, fullname) != 0)
             break;
         }
         CloseDir(dirptr);


More information about the samba mailing list