2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 2000
6 Copyright (C) Jeremy Allison 1994-1998
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 extern int DEBUGLEVEL
;
27 static struct cnotify_fns
*cnotify
;
29 /****************************************************************************
30 This is the structure to queue to implement NT change
31 notify. It consists of smb_size bytes stored from the
32 transact command (to keep the mid, tid etc around).
33 Plus the fid to examine and notify private data
34 *****************************************************************************/
36 struct change_notify
{
37 struct change_notify
*next
, *prev
;
39 connection_struct
*conn
;
41 char request_buf
[smb_size
];
45 static struct change_notify
*change_notify_list
;
47 /****************************************************************************
48 Setup the common parts of the return packet and send it.
49 *****************************************************************************/
50 static void change_notify_reply_packet(char *inbuf
, NTSTATUS error_code
)
52 char outbuf
[smb_size
+38];
54 memset(outbuf
, '\0', sizeof(outbuf
));
55 construct_reply_common(inbuf
, outbuf
);
60 * Seems NT needs a transact command with an error code
61 * in it. This is a longer packet than a simple error.
63 set_message(outbuf
,18,0,False
);
65 if (!send_smb(smbd_server_fd(),outbuf
))
66 exit_server("change_notify_reply_packet: send_smb failed.\n");
69 /****************************************************************************
70 remove an entry from the list and free it, also closing any
71 directory handle if necessary
72 Notice the horrible stuff we have to do because this is a singly linked list.
73 *****************************************************************************/
74 static void change_notify_remove(struct change_notify
*cnbp
)
76 cnotify
->remove_notify(cnbp
->change_data
);
77 DLIST_REMOVE(change_notify_list
, cnbp
);
83 /****************************************************************************
84 Delete entries by fnum from the change notify pending queue.
85 *****************************************************************************/
86 void remove_pending_change_notify_requests_by_fid(files_struct
*fsp
)
88 struct change_notify
*cnbp
, *next
;
90 for (cnbp
=change_notify_list
; cnbp
; cnbp
=next
) {
92 if (cnbp
->fsp
->fnum
== fsp
->fnum
) {
93 change_notify_remove(cnbp
);
98 /****************************************************************************
99 Delete entries by mid from the change notify pending queue. Always send reply.
100 *****************************************************************************/
101 void remove_pending_change_notify_requests_by_mid(int mid
)
103 struct change_notify
*cnbp
, *next
;
105 for (cnbp
=change_notify_list
; cnbp
; cnbp
=next
) {
107 if(SVAL(cnbp
->request_buf
,smb_mid
) == mid
) {
108 change_notify_reply_packet(cnbp
->request_buf
,NT_STATUS_CANCELLED
);
109 change_notify_remove(cnbp
);
114 /****************************************************************************
115 Delete entries by filename and cnum from the change notify pending queue.
117 *****************************************************************************/
118 void remove_pending_change_notify_requests_by_filename(files_struct
*fsp
)
120 struct change_notify
*cnbp
, *next
;
122 for (cnbp
=change_notify_list
; cnbp
; cnbp
=next
) {
125 * We know it refers to the same directory if the connection number and
126 * the filename are identical.
128 if((cnbp
->fsp
->conn
== fsp
->conn
) && strequal(cnbp
->fsp
->fsp_name
,fsp
->fsp_name
)) {
129 change_notify_reply_packet(cnbp
->request_buf
,NT_STATUS_CANCELLED
);
130 change_notify_remove(cnbp
);
135 /****************************************************************************
136 Return true if there are pending change notifies.
137 ****************************************************************************/
138 int change_notify_timeout(void)
140 return cnotify
->select_time
;
143 /****************************************************************************
144 Process the change notify queue. Note that this is only called as root.
145 Returns True if there are still outstanding change notify requests on the
147 *****************************************************************************/
148 BOOL
process_pending_change_notify_queue(time_t t
)
150 struct change_notify
*cnbp
, *next
;
153 for (cnbp
=change_notify_list
; cnbp
; cnbp
=next
) {
156 vuid
= (lp_security() == SEC_SHARE
) ? UID_FIELD_INVALID
: SVAL(cnbp
->request_buf
,smb_uid
);
158 if (cnotify
->check_notify(cnbp
->conn
, vuid
, cnbp
->fsp
->fsp_name
, cnbp
->flags
, cnbp
->change_data
, t
)) {
159 change_notify_reply_packet(cnbp
->request_buf
,STATUS_NOTIFY_ENUM_DIR
);
160 change_notify_remove(cnbp
);
164 return (change_notify_list
!= NULL
);
167 /****************************************************************************
168 * Now queue an entry on the notify change list.
169 * We only need to save smb_size bytes from this incoming packet
170 * as we will always by returning a 'read the directory yourself'
172 ****************************************************************************/
173 BOOL
change_notify_set(char *inbuf
, files_struct
*fsp
, connection_struct
*conn
, uint32 flags
)
175 struct change_notify
*cnbp
;
177 if((cnbp
= (struct change_notify
*)malloc(sizeof(*cnbp
))) == NULL
) {
178 DEBUG(0,("call_nt_transact_notify_change: malloc fail !\n" ));
184 memcpy(cnbp
->request_buf
, inbuf
, smb_size
);
188 cnbp
->change_data
= cnotify
->register_notify(conn
, fsp
->fsp_name
, flags
);
190 if (!cnbp
->change_data
) {
195 DLIST_ADD(change_notify_list
, cnbp
);
201 /****************************************************************************
202 initialise the change notify subsystem
203 ****************************************************************************/
204 BOOL
init_change_notify(void)
206 #if HAVE_KERNEL_CHANGE_NOTIFY
207 cnotify
= kernel_notify_init();
209 if (!cnotify
) cnotify
= hash_notify_init();
212 DEBUG(0,("Failed to init change notify system\n"));