/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/*
* File Change Notification (FCN)
* Common parts shared by SMB1 & SMB2
*/
/*
* This command notifies the client when the specified directory
* has changed, and optionally returns the names of files and
* directories that changed, and how they changed. The caller
* specifies a "Completion Filter" to select which kinds of
* changes they want to know about.
*
* When a change that's in the CompletionFilter is made to the directory,
* the command completes. The names of the files that have changed since
* the last time the command was issued are returned to the client.
* If too many files have changed since the last time the command was
* issued, then zero bytes are returned and an alternate status code
* is returned in the Status field of the response.
*
* The CompletionFilter is a mask created as the sum of any of the
* following flags:
*
* FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001
* FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002
* FILE_NOTIFY_CHANGE_NAME 0x00000003
* FILE_NOTIFY_CHANGE_ATTRIBUTES 0x00000004
* FILE_NOTIFY_CHANGE_SIZE 0x00000008
* FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010
* FILE_NOTIFY_CHANGE_LAST_ACCESS 0x00000020
* FILE_NOTIFY_CHANGE_CREATION 0x00000040
* FILE_NOTIFY_CHANGE_EA 0x00000080
* FILE_NOTIFY_CHANGE_SECURITY 0x00000100
* FILE_NOTIFY_CHANGE_STREAM_NAME 0x00000200
* FILE_NOTIFY_CHANGE_STREAM_SIZE 0x00000400
* FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800
*
*
* The response contains FILE_NOTIFY_INFORMATION structures, as defined
* below. The NextEntryOffset field of the structure specifies the offset,
* in bytes, from the start of the current entry to the next entry in the
* list. If this is the last entry in the list, this field is zero. Each
* entry in the list must be longword aligned, so NextEntryOffset must be a
* multiple of four.
*
* typedef struct {
* ULONG NextEntryOffset;
* ULONG Action;
* ULONG FileNameLength;
* WCHAR FileName[1];
* } FILE_NOTIFY_INFORMATION;
*
* Where Action describes what happened to the file named FileName:
*
* FILE_ACTION_ADDED 0x00000001
* FILE_ACTION_REMOVED 0x00000002
* FILE_ACTION_MODIFIED 0x00000003
* FILE_ACTION_RENAMED_OLD_NAME 0x00000004
* FILE_ACTION_RENAMED_NEW_NAME 0x00000005
* FILE_ACTION_ADDED_STREAM 0x00000006
* FILE_ACTION_REMOVED_STREAM 0x00000007
* FILE_ACTION_MODIFIED_STREAM 0x00000008
*/
#include <smbsrv/smb_kproto.h>
mbuf_chain_t *, uint32_t, char *);
{
return (NT_STATUS_INVALID_HANDLE);
/*
* Notify change is only valid on directories.
*/
return (NT_STATUS_INVALID_PARAMETER);
}
/*
* Prepare to receive event data.
*/
/*
* Subscribe to events on this node.
*/
/*
* Wait for subscribed events to arrive.
* Expect SMB_REQ_STATE_EVENT_OCCURRED
* or SMB_REQ_STATE_CANCELED when signaled.
* Note it's possible (though rare) to already
* have SMB_REQ_STATE_CANCELED here.
*/
}
/*
* Unsubscribe from events on this node.
*/
/*
* Why did we wake up?
*/
case SMB_REQ_STATE_ACTIVE:
break;
case SMB_REQ_STATE_CANCELED:
goto out;
default:
goto out;
}
/*
* We have SMB_REQ_STATE_ACTIVE.
*
* If we have event data, marshall it now, else just
* say "many things changed". Note that when we get
* action FILE_ACTION_SUBDIR_CHANGED, we don't have
* any event details and only know that some subdir
* changed, so just report "many things changed".
*/
case FILE_ACTION_ADDED:
case FILE_ACTION_REMOVED:
case FILE_ACTION_MODIFIED:
case FILE_ACTION_ADDED_STREAM:
/*
* Build the reply
*/
break;
break;
break;
default:
ASSERT(0);
break;
}
out:
return (status);
}
/*
* Encode a FILE_NOTIFY_INFORMATION struct.
*
* We only ever put one of these in a response, so this
* does not bother handling appending additional ones.
*/
static uint32_t
{
return (NT_STATUS_INTERNAL_ERROR);
if (namelen == 0)
return (NT_STATUS_INTERNAL_ERROR);
0, /* NextEntryOffset */
return (NT_STATUS_NOTIFY_ENUM_DIR);
return (0);
}
/*
* smb_notify_file_closed
*
* Cancel any change-notify calls on this open file.
*/
void
{
while (sr) {
}
}
}
/*
* smb_notify_event
*
* Post an event to the watchers on a given node.
*
* This makes one exception for RENAME, where we expect a
* pair of events for the {old,new} directory element names.
* This only delivers an event for the "new" name.
*
* The event delivery mechanism does not implement delivery of
* multiple events for one "NT Notify" call. One could do that,
* but modern clients don't actually use the event data. They
* set a max. received data size of zero, which means we discard
* the data and send the special "lots changed" error instead.
* Given that, there's not really any point in implementing the
* delivery of multiple events. In fact, we don't even need to
* implement single event delivery, but do so for completeness,
* for debug convenience, and to be nice to older clients that
* may actually want some event data instead of the error.
*
* Given that we only deliver a single event for an "NT Notify"
* caller, we want to deliver the "new" name event. (The "old"
* name event is less important, even ignored by some clients.)
* Since we know these are delivered in pairs, we can simply
* discard the "old" name event, knowing that the "new" name
* event will be delivered immediately afterwards.
*
* So, why do event sources post the "old name" event at all?
* (1) For debugging, so we see both {old,new} names here.
* (2) If in the future someone decides to implement the
* delivery of both {old,new} events, the changes can be
* mostly isolated to this file.
*/
void
{
if (action == FILE_ACTION_RENAMED_OLD_NAME)
return; /* see above */
while (sr) {
}
}
/*
* What completion filter (masks) apply to each of the
* FILE_ACTION_... events.
*/
static const uint32_t
smb_notify_action_mask[] = {
0, /* not used */
/* FILE_ACTION_ADDED */
/* FILE_ACTION_REMOVED */
/* FILE_ACTION_MODIFIED */
/* FILE_ACTION_RENAMED_OLD_NAME */
/* FILE_ACTION_RENAMED_NEW_NAME */
/* FILE_ACTION_ADDED_STREAM */
/* FILE_ACTION_REMOVED_STREAM */
/* FILE_ACTION_MODIFIED_STREAM */
/* FILE_ACTION_SUBDIR_CHANGED */
/* FILE_ACTION_DELETE_PENDING */
};
static const int smb_notify_action_nelm =
sizeof (smb_notify_action_mask) /
sizeof (smb_notify_action_mask[0]);
/*
* smb_notify_sr
*
* Post an event to an smb request waiting on some node.
*
* Note that node->fcn.mutex is held. This implies a
* lock order: node->fcn.mutex, then sr_mutex
*/
static void
{
/*
* Compute the completion filter mask bits for which
* we will signal waiting notify requests.
*/
/*
* Save event data in the sr_ncr field so the
* reply handler can return it.
*/
}
}