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@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);