Hello Hal,

thanks for coding this patch, unfortunately it doesn't work for me.
Checking the generated network packets with ethereal shows that the NT_NOTIFY packet I receive on the Windwows side
is invalid. The packet (frame size as shown in ethereal) is much too short, it's size is 93 bytes, it should be 162.
Below is the hex dump of a defect packet:
0000 00 04 e2 1c 6f c0 00 04 e2 1c 6f 55 08 00 45 10 ..â.oÀ.. â.oU..E.
0010 00 4f 18 e6 40 00 40 06 a0 56 c0 a8 00 04 c0 a8 .O.æ@.@. VÀ¨..À¨
0020 00 08 00 8b 04 c8 0e 6a 4a aa d4 2d f3 f9 50 18 .....È.j JªÔ-óùP.
0030 16 d0 01 12 00 00 00 00 00 23 ff 53 4d 42 a0 00 .Ð...... .#ÿSMB .
0040 00 00 00 88 01 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0050 00 00 01 00 9c 05 64 00 c0 6f 40 20 00 ......d. Ào@ .
This is what a W2K generated packet looks like:
0000 00 04 e2 1c 6f c0 00 50 56 4b 85 6f 08 00 45 10 ..â.oÀ.P VK.o..E.
0010 00 94 da 29 40 00 40 06 de bf c0 a8 00 12 c0 a8 ..Ú)@.@. Þ¿À¨..À¨
0020 00 08 00 8b 04 ba 92 f9 13 50 b8 db b8 fd 50 18 .....º.ù .P¸Û¸ýP.
0030 2e 10 9a 20 00 00 00 00 00 68 ff 53 4d 42 a0 00 ... .... .hÿSMB .
0040 00 00 00 88 01 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0050 00 00 01 00 c0 03 64 00 c1 ac 12 00 00 00 1e 00 ....À.d. Á¬......
0060 00 00 00 00 00 00 1e 00 00 00 48 00 00 00 00 00 ........ ..H.....
0070 00 00 00 00 00 00 68 00 00 00 00 00 00 00 00 21 ......h. .......!
0080 00 00 00 00 00 00 03 00 00 00 12 00 00 00 66 00 ........ ......f.
0090 69 00 6c 00 65 00 32 00 2e 00 74 00 78 00 74 00 i.l.e.2. ..t.x.t.
00a0 00 00 ..
I attached my own hack which creates a reply packet identical to Windows (see the change_notify_reply_packet function).
It only replies one single file name per reply packet, because you don't get more than one file change per signal using dnotify.

Another thing I noticed is that you don't return an unicode filename, you simply return the filename with the unix charset
and pad it with zeroes. Please convert the filename to Unicode when you assemble the packet.

...Juergen

--- smbd/notify_kernel.orig     2003-01-14 21:57:16.000000000 +0100
+++ smbd/notify_kernel.c        2003-02-02 00:01:24.000000000 +0100
@@ -37,7 +37,6 @@
 #define DN_MULTISHOT    0x80000000      /* Don't remove notifier */
 #endif
 
-
 #ifndef RT_SIGNAL_NOTIFY
 #define RT_SIGNAL_NOTIFY 34
 #endif
@@ -50,6 +49,14 @@
 #define F_NOTIFY 1026
 #endif
 
+#define F_NOTIFY_FN    1027
+
+/* this gets returned from the kernel */
+struct dnotify_info_struct {
+       unsigned long           event;
+       char filename[NAME_MAX+1];
+};
+
 /****************************************************************************
  This is the structure to keep the information needed to
  determine if a directory has changed.
@@ -57,6 +64,8 @@
 
 struct change_data {
        int directory_handle;
+//     uint32 Action;
+       struct dnotify_info_struct fi;
 };
 
 /****************************************************************************
@@ -95,9 +104,10 @@
        BlockSignals(True, RT_SIGNAL_NOTIFY);
        for (i = 0; i < signals_received; i++) {
                if (data->directory_handle == (int)fd_pending_array[i]) {
-                       DEBUG(3,("kernel_check_notify: kernel change notify on %s 
fd[%d]=%d (signals_received=%d)\n",
-                                               path, i, (int)fd_pending_array[i], 
(int)signals_received ));
-
+               data->fi.event=0;
+               fcntl((int)fd_pending_array[i],F_NOTIFY_FN,&(data->fi.event));
+                       DEBUG(0,("kernel_check_notify: kernel change notify on %s in 
+file %s, event %d, fd[%d]=%d (signals_received=%d)\n",
+                                               path, 
+data->fi.filename,data->fi.event, i, (int)fd_pending_array[i], (int)signals_received 
+));
                        close((int)fd_pending_array[i]);
                        fd_pending_array[i] = (SIG_ATOMIC_T)-1;
                        if (signals_received - i - 1) {
@@ -166,7 +176,7 @@
                return NULL;
        }
 
-       kernel_flags = DN_CREATE|DN_DELETE|DN_RENAME; /* creation/deletion changes 
everything! */
+       kernel_flags = DN_CREATE|DN_DELETE|DN_RENAME|DN_MULTISHOT; /* 
+creation/deletion changes everything! */
        if (flags & FILE_NOTIFY_CHANGE_FILE)        kernel_flags |= DN_MODIFY;
        if (flags & FILE_NOTIFY_CHANGE_DIR_NAME)    kernel_flags |= 
DN_RENAME|DN_DELETE;
        if (flags & FILE_NOTIFY_CHANGE_ATTRIBUTES)  kernel_flags |= DN_ATTRIB;
--- smbd/notify.orig    2003-01-14 21:57:29.000000000 +0100
+++ smbd/notify.c       2003-02-02 00:40:54.000000000 +0100
@@ -45,20 +45,54 @@
 /****************************************************************************
  Setup the common parts of the return packet and send it.
 *****************************************************************************/
-static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code)
+
+static void change_notify_reply_error_packet(char *inbuf, NTSTATUS error_code)
 {
        char outbuf[smb_size+38];
 
        memset(outbuf, '\0', sizeof(outbuf));
        construct_reply_common(inbuf, outbuf);
 
-       ERROR_NT(error_code);
-
        /*
         * Seems NT needs a transact command with an error code
         * in it. This is a longer packet than a simple error.
         */
+               ERROR_NT(error_code);
        set_message(outbuf,18,0,False);
+               if (!send_smb(smbd_server_fd(),outbuf))
+                       exit_server("change_notify_reply_packet: send_smb failed.");
+}
+
+static void change_notify_reply_packet(char *inbuf,char *filename, unsigned long 
+event)
+{
+
+       char outbuf[smb_size+200];
+       char *p = outbuf+76;
+       FILE_NOTIFY_INFORMATION *fi;
+
+       memset(outbuf, '\0', sizeof(outbuf));
+       construct_reply_common(inbuf, outbuf);
+
+       set_message(outbuf,18,33,False);
+
+DEBUG(0,("send_reply_packet: %s, %u\n",filename,event));
+       fi = (FILE_NOTIFY_INFORMATION *) p;
+       fi->NextEntryOffset=0;
+       /* convert event type */
+       if (event & DN_MODIFY) fi->Action |= FILE_ACTION_MODIFIED;
+       if (event & DN_CREATE) fi->Action |= FILE_ACTION_ADDED;
+       if (event & DN_DELETE) fi->Action |= FILE_ACTION_REMOVED;
+       if (event & DN_RENAME) fi->Action |= FILE_ACTION_RENAMED_NEW_NAME;
+
+       
+fi->FileNameLength=dos_PutUniCode(fi->FileName,unix_to_dos_static(filename),sizeof(fstring),
+ False);
+       /* fallback if no filename is given */
+       if (fi->FileNameLength == 0)
+               change_notify_reply_error_packet(inbuf,STATUS_NOTIFY_ENUM_DIR);
+
+       SIVAL(outbuf,smb_ntr_TotalParameterCount,12+fi->FileNameLength);
+       SIVAL(outbuf,smb_ntr_ParameterCount,12+fi->FileNameLength);
+       SIVAL(outbuf,smb_ntr_ParameterOffset,72);       // vom SMB header bis zum 
+NT_NOTIFY_INFORMATION
+       SIVAL(outbuf,smb_ntr_DataOffset,104);           // Ende des Pakets
 
        if (!send_smb(smbd_server_fd(),outbuf))
                exit_server("change_notify_reply_packet: send_smb failed.");
@@ -104,7 +138,7 @@
        for (cnbp=change_notify_list; cnbp; cnbp=next) {
                next=cnbp->next;
                if(SVAL(cnbp->request_buf,smb_mid) == mid) {
-                       
change_notify_reply_packet(cnbp->request_buf,NT_STATUS_CANCELLED);
+                       
+change_notify_reply_error_packet(cnbp->request_buf,NT_STATUS_CANCELLED);
                        change_notify_remove(cnbp);
                }
        }
@@ -126,7 +160,7 @@
                 * the filename are identical.
                 */
                if((cnbp->fsp->conn == fsp->conn) && 
strequal(cnbp->fsp->fsp_name,fsp->fsp_name)) {
-                       
change_notify_reply_packet(cnbp->request_buf,NT_STATUS_CANCELLED);
+                       
+change_notify_reply_error_packet(cnbp->request_buf,NT_STATUS_CANCELLED);
                        change_notify_remove(cnbp);
                }
        }
@@ -146,6 +180,15 @@
  Returns True if there are still outstanding change notify requests on the
  queue.
 *****************************************************************************/
+struct dnotify_info_struct {
+       unsigned long           event;
+       char filename[NAME_MAX+1];
+};
+
+struct change_data {
+       int directory_handle;
+       struct dnotify_info_struct fi;
+};
 
 BOOL process_pending_change_notify_queue(time_t t)
 {
@@ -159,7 +202,11 @@
 
                if (cnotify->check_notify(cnbp->conn, vuid, cnbp->fsp->fsp_name, 
cnbp->flags, cnbp->change_data, t)) {
                        DEBUG(10,("process_pending_change_notify_queue: dir %s changed 
!\n", cnbp->fsp->fsp_name ));
-                       
change_notify_reply_packet(cnbp->request_buf,STATUS_NOTIFY_ENUM_DIR);
+                       struct change_data *data = (struct change_data *) 
+cnbp->change_data;
+                       if (data->fi.event > 0)
+                               change_notify_reply_packet(cnbp->request_buf, 
+data->fi.filename, data->fi.event);
+                       else
+                               
+change_notify_reply_error_packet(cnbp->request_buf,STATUS_NOTIFY_ENUM_DIR);
                        change_notify_remove(cnbp);
                }
        }
--- include/smb.orig    2003-02-02 00:44:14.000000000 +0100
+++ include/smb.h       2003-02-01 18:46:26.000000000 +0100
@@ -1203,6 +1203,23 @@
 #define FILE_NOTIFY_CHANGE_SECURITY    0x100
 #define FILE_NOTIFY_CHANGE_FILE_NAME   0x200
 
+/* FILE_NOTIFY_INFORMATION */
+#define FILE_ACTION_ADDED            0x00000001
+#define FILE_ACTION_REMOVED          0x00000002
+#define FILE_ACTION_MODIFIED         0x00000003
+#define FILE_ACTION_RENAMED_OLD_NAME 0x00000004
+#define FILE_ACTION_RENAMED_NEW_NAME 0x00000005
+#define FILE_ACTION_ADDED_STREAM     0x00000006
+#define FILE_ACTION_REMOVED_STREAM   0x00000007
+#define FILE_ACTION_MODIFIED_STREAM  0x00000008
+
+typedef struct {
+       uint32 NextEntryOffset;
+       uint32 Action;
+       uint32 FileNameLength;
+       char FileName[1];
+} FILE_NOTIFY_INFORMATION;
+
 /* where to find the base of the SMB packet proper */
 #define smb_base(buf) (((char *)(buf))+4)
 



Reply via email to