Attached is a patch that adds support for reporting
individual files during file change notification. The patch
keeps a table of the stats of all files in a watched
directory and then compares the current stats of the files
with the stored stats whenever there is a notification
event. Note that all of the code is in the generic notify.c
file, so it works regardless of whether the server is using
hash_notify.c or kernel_notify.c.
The costs are 1) the memory cost of storing the tdb info in
memory and 2) the performance cost of having to check each
file to figure out which one changed everytime there is a
file notification event. The memory use could be reduced by
storing the table on disk instead of in memory, but that
would incur a cost in performance and could result in a lot
of *tdb files sitting around (one per directory watched).
The only way to reduce the performance cost is to make the
kernel stuff return a file name with its notification. This
change wouldn't be too hard to add to the kernel, but I'd
rather not require a hacked kernel to make samba work as it
should.
The only thing that doesn't work quite as it should is that
the code does not report a file name change event as such,
but instead just treats a name change as a file remove and
then a file add. Supporting this would make the code a lot
more complex (I'd have to keep a separate, inode indexed
table of file stats in addition to the file name indexed
one), and I can't imagine when a remove/add instead of a
move would break a client, though it might cause performance
issues.
Also, though this is a separate issue, the file change stuff
still doesn't support deep notifications as it should as far
as I can tell (which is to say not at all).
-hal
diff -u -r samba-2.2.7a.dist/source/include/smb.h samba-2.2.7a/source/include/smb.h
--- samba-2.2.7a.dist/source/include/smb.h Wed Dec 4 12:16:36 2002
+++ samba-2.2.7a/source/include/smb.h Wed Jan 22 16:26:56 2003
@@ -1202,6 +1202,16 @@
#define FILE_NOTIFY_CHANGE_SECURITY0x100
#define FILE_NOTIFY_CHANGE_FILE_NAME 0x200
+/* file notification actions */
+#define FILE_ACTION_ADDED 0x0001
+#define FILE_ACTION_REMOVED0x0002
+#define FILE_ACTION_MODIFIED 0x0003
+#define FILE_ACTION_RENAMED_OLD_NAME 0x0004
+#define FILE_ACTION_RENAMED_NEW_NAME 0x0005
+#define FILE_ACTION_ADDED_STREAM 0x0006
+#define FILE_ACTION_REMOVED_STREAM 0x0007
+#define FILE_ACTION_MODIFIED_STREAM0x0008
+
/* where to find the base of the SMB packet proper */
#define smb_base(buf) (((char *)(buf))+4)
diff -u -r samba-2.2.7a.dist/source/smbd/notify.c samba-2.2.7a/source/smbd/notify.c
--- samba-2.2.7a.dist/source/smbd/notify.c Fri Feb 1 17:14:47 2002
+++ samba-2.2.7a/source/smbd/notify.c Thu Feb 6 16:08:07 2003
@@ -25,6 +25,16 @@
static struct cnotify_fns *cnotify;
/
+This structure holds a list of files and associated notification actions.
+*/
+struct file_action {
+ struct file_action *next, *prev;
+ int action;
+ char *filename;
+ int filename_length;
+};
+
+/
This is the structure to queue to implement NT change
notify. It consists of smb_size bytes stored from the
transact command (to keep the mid, tid etc around).
@@ -38,14 +48,250 @@
uint32 flags;
char request_buf[smb_size];
void *change_data;
+ TDB_CONTEXT *file_data;
+ struct file_action *file_actions;
};
static struct change_notify *change_notify_list;
/
+ Return a file action struct with the given filename and fileaction
+*/
+struct file_action *change_notify_get_file_action(char *filename,
+ int fileaction) {
+
+ struct file_action *fa;
+
+ if (!(fa = (struct file_action *)malloc(sizeof(struct file_action {
+ DEBUG(0, (malloc failed!));
+ }
+
+ fa-action = fileaction;
+ fa-filename = strdup(filename);
+ fa-filename_length = strlen(filename);
+
+ return fa;
+}
+
+/
+ Check to make sure that the file in the given cnbp.file_data record
+ still exists.
+*/
+int change_notify_file_data_exists(TDB_CONTEXT *tdb, TDB_DATA key,
+ TDB_DATA data, void *status) {
+
+ struct file_action *fa;
+ struct change_notify *cnbp = (struct change_notify *)status;
+ char *filename;
+ char