2.2.5pre1: unlink design flaw
jd at epcnet.de
jd at epcnet.de
Wed Jun 12 14:55:01 GMT 2002
Hi,
I recovered a design flaw in the unlink part of samba. If you try to re-export a smbfs-share with
samba and if you create a file with the delete-on-close flag set the file remains on disk.
Unlink over smbfs fails if the file is open.
The samba way of closing a open delete-on-close flagged file is:
1. unlink file
2. close file
But with a underlying smbfs unlink returns ETXTBUSY, so i changed it into:
1. unlink file
2. close file
3. if unlink returned ETXTBUSY -> try second time
The same for an open directory which is set delete on close with kernel directory notifiys. First
the standard samba way:
1. open dirA for notify
2. rmdir dirA
3. catch notify signal and close dirA
But with a underlying smbfs rmdir fails, so i changed it into:
1. open dirA for notify
2. rmdir dirA
3. If rmdir fails force close of dirA notify handler und try rmdir dirA second time.
I don't know if this also apply to NTFS/FAT filesystems or any other filesystem with a non-posix
unlink and rmdir behaviour.
Diff against close.c and notify_kernel.c attached.
Greetings
Jochen Dolze
--- close.c.orig Mon Jun 10 13:07:45 2002
+++ close.c Wed Jun 12 18:19:08 2002
@@ -1,4 +1,4 @@
-/*
+/*
Unix SMB/Netbios implementation.
Version 1.9.
file closing
@@ -120,6 +120,7 @@
share_mode_entry *share_entry = NULL;
size_t share_entry_count = 0;
BOOL delete_on_close = False;
+ BOOL delete_after_close = False;
connection_struct *conn = fsp->conn;
int err = 0;
int err1 = 0;
@@ -172,6 +173,8 @@
DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n",
fsp->fsp_name));
if(fsp->conn->vfs_ops.unlink(conn,dos_to_unix_static(fsp->fsp_name)) != 0) {
+ if (errno == ETXTBSY) delete_after_close = True;
+
/*
* This call can potentially fail as another smbd may have
* had the file open with delete on close set and deleted
@@ -193,6 +196,23 @@
err = fd_close(conn, fsp);
+ if (normal_close && delete_on_close && delete_after_close) {
+ DEBUG(5,("close_file: file %s. Delete after close was set - deleting file.\n",
+ fsp->fsp_name));
+ if(fsp->conn->vfs_ops.unlink(conn,dos_to_unix_static(fsp->fsp_name)) != 0) {
+
+ /*
+ * This call can potentially fail as another smbd may have
+ * had the file open with delete on close set and deleted
+ * it when its last reference to this file went away. Hence
+ * we log this but not at debug level zero.
+ */
+
+ DEBUG(5,("close_file: file %s. Delete after close was set and unlink failed \
+with error %s\n", fsp->fsp_name, strerror(errno) ));
+ }
+ }
+
/* check for magic scripts */
if (normal_close) {
check_magic(fsp,conn);
@@ -229,6 +249,9 @@
static int close_directory(files_struct *fsp, BOOL normal_close)
{
+ int delete_after_close = False;
+ BOOL ok;
+
remove_pending_change_notify_requests_by_fid(fsp);
/*
@@ -237,10 +260,15 @@
*/
if (normal_close && fsp->directory_delete_on_close) {
- BOOL ok = rmdir_internals(fsp->conn, fsp->fsp_name);
+ ok = rmdir_internals(fsp->conn, fsp->fsp_name);
DEBUG(5,("close_directory: %s. Delete on close was set - deleting directory %s.\n",
fsp->fsp_name, ok ? "succeeded" : "failed" ));
+ if (!ok) {
+ delete_after_close = True;
+ errno = 0; /* reset error */
+ }
+
/*
* Ensure we remove any change notify requests that would
* now fail as the directory has been deleted.
@@ -250,10 +278,20 @@
remove_pending_change_notify_requests_by_filename(fsp);
}
+ if (normal_close && fsp->directory_delete_on_close && delete_after_close) {
+ remove_pending_change_notify_requests_by_filename(fsp);
+ }
+
/*
* Do the code common to files and directories.
*/
close_filestruct(fsp);
+
+ if (normal_close && fsp->directory_delete_on_close && delete_after_close) {
+ ok = rmdir_internals(fsp->conn, fsp->fsp_name);
+ DEBUG(5,("close_directory: %s. Delete after close was set - deleting directory %s.\n",
+ fsp->fsp_name, ok ? "succeeded" : "failed" ));
+ }
if (fsp->fsp_name)
string_free(&fsp->fsp_name);
--- notify_kernel.c.orig Sat Jun 8 14:55:58 2002
+++ notify_kernel.c Wed Jun 12 21:25:30 2002
@@ -128,6 +128,7 @@
for (i = 0; i < signals_received; i++) {
if (fd == (int)fd_pending_array[i]) {
close(fd);
+ fd = -1;
fd_pending_array[i] = (sig_atomic_t)-1;
if (signals_received - i - 1) {
memmove((void *)&fd_pending_array[i], (void *)&fd_pending_array[i+1],
@@ -141,6 +142,8 @@
BlockSignals(False, RT_SIGNAL_NOTIFY);
}
SAFE_FREE(data);
+ if (fd != -1)
+ close(fd);
DEBUG(3,("kernel_remove_notify: fd=%d\n", fd));
}
---
EPCNet GmbH
ISP & Web Design
Bleichstrasse 24
89077 Ulm
Tel. +49 731 1416 0
Fax +49 731 1416 120
More information about the samba-technical
mailing list