mirror of
https://github.com/samba-team/samba.git
synced 2024-12-24 21:34:56 +03:00
r20433: Work in progress: Survive more of RAW-NOTIFY.
call_nt_transact_notify_change() is now sync if there are changes around.
A notify_message does a direct reply from within the message, so
process_pending_change_notify_queue is not needed anymore for samba-generated
events. Next step is to restructure the kernel-mechanisms to generate
messages.
Volker
(This used to be commit c813f71d00
)
This commit is contained in:
parent
ab7fc62edf
commit
165f5f3f40
@ -33,7 +33,6 @@ static struct cnotify_fns *cnotify;
|
|||||||
struct change_notify {
|
struct change_notify {
|
||||||
struct change_notify *next, *prev;
|
struct change_notify *next, *prev;
|
||||||
files_struct *fsp;
|
files_struct *fsp;
|
||||||
connection_struct *conn;
|
|
||||||
uint32 flags;
|
uint32 flags;
|
||||||
uint32 max_param_count;
|
uint32 max_param_count;
|
||||||
char request_buf[smb_size];
|
char request_buf[smb_size];
|
||||||
@ -97,13 +96,13 @@ static BOOL notify_marshall_changes(struct notify_changes *changes,
|
|||||||
Setup the common parts of the return packet and send it.
|
Setup the common parts of the return packet and send it.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
static void change_notify_reply_packet(struct change_notify *notify,
|
static void change_notify_reply_packet(const char *request_buf,
|
||||||
NTSTATUS error_code)
|
NTSTATUS error_code)
|
||||||
{
|
{
|
||||||
char outbuf[smb_size+38];
|
char outbuf[smb_size+38];
|
||||||
|
|
||||||
memset(outbuf, '\0', sizeof(outbuf));
|
memset(outbuf, '\0', sizeof(outbuf));
|
||||||
construct_reply_common(notify->request_buf, outbuf);
|
construct_reply_common(request_buf, outbuf);
|
||||||
|
|
||||||
ERROR_NT(error_code);
|
ERROR_NT(error_code);
|
||||||
|
|
||||||
@ -118,34 +117,34 @@ static void change_notify_reply_packet(struct change_notify *notify,
|
|||||||
exit_server_cleanly("change_notify_reply_packet: send_smb failed.");
|
exit_server_cleanly("change_notify_reply_packet: send_smb failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void change_notify_reply(struct change_notify *notify)
|
void change_notify_reply(const char *request_buf, uint32 max_param_count,
|
||||||
|
files_struct *fsp)
|
||||||
{
|
{
|
||||||
char *outbuf = NULL;
|
char *outbuf = NULL;
|
||||||
prs_struct ps;
|
prs_struct ps;
|
||||||
size_t buflen = smb_size+38+notify->max_param_count;
|
size_t buflen = smb_size+38+max_param_count;
|
||||||
|
|
||||||
if (!prs_init(&ps, 0, NULL, False)
|
if (!prs_init(&ps, 0, NULL, False)
|
||||||
|| !notify_marshall_changes(notify->fsp->notify, &ps)) {
|
|| !notify_marshall_changes(fsp->notify, &ps)) {
|
||||||
change_notify_reply_packet(notify, NT_STATUS_NO_MEMORY);
|
change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prs_offset(&ps) > notify->max_param_count) {
|
if (prs_offset(&ps) > max_param_count) {
|
||||||
/*
|
/*
|
||||||
* We exceed what the client is willing to accept. Send
|
* We exceed what the client is willing to accept. Send
|
||||||
* nothing.
|
* nothing.
|
||||||
*/
|
*/
|
||||||
change_notify_reply_packet(notify, NT_STATUS_OK);
|
change_notify_reply_packet(request_buf, NT_STATUS_OK);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(outbuf = SMB_MALLOC_ARRAY(char, buflen))) {
|
if (!(outbuf = SMB_MALLOC_ARRAY(char, buflen))) {
|
||||||
change_notify_reply_packet(notify, NT_STATUS_NO_MEMORY);
|
change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(outbuf, '\0', sizeof(outbuf));
|
construct_reply_common(request_buf, outbuf);
|
||||||
construct_reply_common(notify->request_buf, outbuf);
|
|
||||||
|
|
||||||
if (send_nt_replies(outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps),
|
if (send_nt_replies(outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps),
|
||||||
prs_offset(&ps), NULL, 0) == -1) {
|
prs_offset(&ps), NULL, 0) == -1) {
|
||||||
@ -155,8 +154,8 @@ static void change_notify_reply(struct change_notify *notify)
|
|||||||
done:
|
done:
|
||||||
SAFE_FREE(outbuf);
|
SAFE_FREE(outbuf);
|
||||||
prs_mem_free(&ps);
|
prs_mem_free(&ps);
|
||||||
notify->fsp->notify->num_changes = 0;
|
fsp->notify->num_changes = 0;
|
||||||
TALLOC_FREE(notify->fsp->notify->changes);
|
TALLOC_FREE(fsp->notify->changes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -183,7 +182,7 @@ void remove_pending_change_notify_requests_by_fid(files_struct *fsp, NTSTATUS st
|
|||||||
for (cnbp=change_notify_list; cnbp; cnbp=next) {
|
for (cnbp=change_notify_list; cnbp; cnbp=next) {
|
||||||
next=cnbp->next;
|
next=cnbp->next;
|
||||||
if (cnbp->fsp->fnum == fsp->fnum) {
|
if (cnbp->fsp->fnum == fsp->fnum) {
|
||||||
change_notify_reply_packet(cnbp, status);
|
change_notify_reply_packet(cnbp->request_buf, status);
|
||||||
change_notify_remove(cnbp);
|
change_notify_remove(cnbp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -200,7 +199,8 @@ void remove_pending_change_notify_requests_by_mid(int mid)
|
|||||||
for (cnbp=change_notify_list; cnbp; cnbp=next) {
|
for (cnbp=change_notify_list; cnbp; cnbp=next) {
|
||||||
next=cnbp->next;
|
next=cnbp->next;
|
||||||
if(SVAL(cnbp->request_buf,smb_mid) == mid) {
|
if(SVAL(cnbp->request_buf,smb_mid) == mid) {
|
||||||
change_notify_reply_packet(cnbp, NT_STATUS_CANCELLED);
|
change_notify_reply_packet(cnbp->request_buf,
|
||||||
|
NT_STATUS_CANCELLED);
|
||||||
change_notify_remove(cnbp);
|
change_notify_remove(cnbp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -222,7 +222,7 @@ void remove_pending_change_notify_requests_by_filename(files_struct *fsp, NTSTAT
|
|||||||
* the filename are identical.
|
* the filename are identical.
|
||||||
*/
|
*/
|
||||||
if((cnbp->fsp->conn == fsp->conn) && strequal(cnbp->fsp->fsp_name,fsp->fsp_name)) {
|
if((cnbp->fsp->conn == fsp->conn) && strequal(cnbp->fsp->fsp_name,fsp->fsp_name)) {
|
||||||
change_notify_reply_packet(cnbp, status);
|
change_notify_reply_packet(cnbp->request_buf, status);
|
||||||
change_notify_remove(cnbp);
|
change_notify_remove(cnbp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -265,13 +265,25 @@ BOOL process_pending_change_notify_queue(time_t t)
|
|||||||
|
|
||||||
vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(cnbp->request_buf,smb_uid);
|
vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(cnbp->request_buf,smb_uid);
|
||||||
|
|
||||||
if ((cnbp->fsp->notify->num_changes != 0)
|
if (cnbp->fsp->notify->num_changes != 0) {
|
||||||
|| cnotify->check_notify(cnbp->conn, vuid,
|
DEBUG(10,("process_pending_change_notify_queue: %s "
|
||||||
cnbp->fsp->fsp_name, cnbp->flags,
|
"has %d changes!\n", cnbp->fsp->fsp_name,
|
||||||
cnbp->change_data, t)) {
|
cnbp->fsp->notify->num_changes));
|
||||||
|
change_notify_reply(cnbp->request_buf,
|
||||||
|
cnbp->max_param_count,
|
||||||
|
cnbp->fsp);
|
||||||
|
change_notify_remove(cnbp);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cnotify->check_notify(cnbp->fsp->conn, vuid,
|
||||||
|
cnbp->fsp->fsp_name, cnbp->flags,
|
||||||
|
cnbp->change_data, t)) {
|
||||||
DEBUG(10,("process_pending_change_notify_queue: dir "
|
DEBUG(10,("process_pending_change_notify_queue: dir "
|
||||||
"%s changed !\n", cnbp->fsp->fsp_name ));
|
"%s changed !\n", cnbp->fsp->fsp_name ));
|
||||||
change_notify_reply(cnbp);
|
change_notify_reply(cnbp->request_buf,
|
||||||
|
cnbp->max_param_count,
|
||||||
|
cnbp->fsp);
|
||||||
change_notify_remove(cnbp);
|
change_notify_remove(cnbp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -300,7 +312,6 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn,
|
|||||||
|
|
||||||
memcpy(cnbp->request_buf, inbuf, smb_size);
|
memcpy(cnbp->request_buf, inbuf, smb_size);
|
||||||
cnbp->fsp = fsp;
|
cnbp->fsp = fsp;
|
||||||
cnbp->conn = conn;
|
|
||||||
cnbp->flags = flags;
|
cnbp->flags = flags;
|
||||||
cnbp->max_param_count = max_param_count;
|
cnbp->max_param_count = max_param_count;
|
||||||
cnbp->change_data = cnotify->register_notify(conn, fsp->fsp_name,
|
cnbp->change_data = cnotify->register_notify(conn, fsp->fsp_name,
|
||||||
@ -393,6 +404,9 @@ void notify_action(connection_struct *conn, const char *parent,
|
|||||||
struct process_id *pids;
|
struct process_id *pids;
|
||||||
int num_pids;
|
int num_pids;
|
||||||
|
|
||||||
|
DEBUG(10, ("notify_action: parent=%s, name=%s, action=%u\n",
|
||||||
|
parent, name, (unsigned)action));
|
||||||
|
|
||||||
if (SMB_VFS_STAT(conn, parent, &sbuf) != 0) {
|
if (SMB_VFS_STAT(conn, parent, &sbuf) != 0) {
|
||||||
/*
|
/*
|
||||||
* Not 100% critical, ignore failure
|
* Not 100% critical, ignore failure
|
||||||
@ -458,12 +472,13 @@ void notify_action(connection_struct *conn, const char *parent,
|
|||||||
TALLOC_FREE(lck);
|
TALLOC_FREE(lck);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void notify_message(int msgtype, struct process_id pid,
|
static void notify_message_callback(int msgtype, struct process_id pid,
|
||||||
void *buf, size_t len)
|
void *buf, size_t len)
|
||||||
{
|
{
|
||||||
struct notify_message msg;
|
struct notify_message msg;
|
||||||
files_struct *fsp;
|
files_struct *fsp;
|
||||||
struct notify_change *changes, *change;
|
struct notify_change *changes, *change;
|
||||||
|
struct change_notify *cnbp;
|
||||||
|
|
||||||
if (!buf_to_notify_message(buf, len, &msg)) {
|
if (!buf_to_notify_message(buf, len, &msg)) {
|
||||||
return;
|
return;
|
||||||
@ -472,7 +487,24 @@ static void notify_message(int msgtype, struct process_id pid,
|
|||||||
DEBUG(10, ("Received notify_message for 0x%x/%.0f: %d\n",
|
DEBUG(10, ("Received notify_message for 0x%x/%.0f: %d\n",
|
||||||
(unsigned)msg.dev, (double)msg.inode, msg.action));
|
(unsigned)msg.dev, (double)msg.inode, msg.action));
|
||||||
|
|
||||||
if (!(fsp = file_find_dir_lowest_id(msg.dev, msg.inode))) {
|
fsp = NULL;
|
||||||
|
|
||||||
|
for (cnbp = change_notify_list; cnbp != NULL; cnbp = cnbp->next) {
|
||||||
|
if ((cnbp->fsp->dev == msg.dev)
|
||||||
|
&& (cnbp->fsp->inode == msg.inode)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cnbp != NULL) {
|
||||||
|
DEBUG(10, ("Found pending change notify for %s\n",
|
||||||
|
cnbp->fsp->fsp_name));
|
||||||
|
fsp = cnbp->fsp;
|
||||||
|
SMB_ASSERT(fsp->notify->num_changes == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fsp == NULL)
|
||||||
|
&& !(fsp = file_find_dir_lowest_id(msg.dev, msg.inode))) {
|
||||||
DEBUG(10, ("notify_message: did not find fsp\n"));
|
DEBUG(10, ("notify_message: did not find fsp\n"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -494,6 +526,18 @@ static void notify_message(int msgtype, struct process_id pid,
|
|||||||
}
|
}
|
||||||
change->action = msg.action;
|
change->action = msg.action;
|
||||||
fsp->notify->num_changes += 1;
|
fsp->notify->num_changes += 1;
|
||||||
|
|
||||||
|
if (cnbp != NULL) {
|
||||||
|
/*
|
||||||
|
* Respond directly, we have a someone waiting for this change
|
||||||
|
*/
|
||||||
|
DEBUG(10, ("Found pending cn for %s, responding directly\n",
|
||||||
|
cnbp->fsp->fsp_name));
|
||||||
|
change_notify_reply(cnbp->request_buf, cnbp->max_param_count,
|
||||||
|
cnbp->fsp);
|
||||||
|
change_notify_remove(cnbp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -519,7 +563,7 @@ BOOL init_change_notify(void)
|
|||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
message_register(MSG_SMB_NOTIFY, notify_message);
|
message_register(MSG_SMB_NOTIFY, notify_message_callback);
|
||||||
|
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
@ -186,6 +186,9 @@ static BOOL hash_check_notify(connection_struct *conn, uint16 vuid, char *path,
|
|||||||
struct change_data data2;
|
struct change_data data2;
|
||||||
int cnto = lp_change_notify_timeout(SNUM(conn));
|
int cnto = lp_change_notify_timeout(SNUM(conn));
|
||||||
|
|
||||||
|
DEBUG(10, ("hash_change_notify called for path %s\n", path));
|
||||||
|
return False;
|
||||||
|
|
||||||
if (t && cnto <= 0) {
|
if (t && cnto <= 0) {
|
||||||
/* Change notify turned off on this share.
|
/* Change notify turned off on this share.
|
||||||
* Only scan when (t==0) - we think something changed. */
|
* Only scan when (t==0) - we think something changed. */
|
||||||
|
@ -1847,6 +1847,17 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf,
|
|||||||
return ERROR_DOS(ERRDOS,ERRbadfid);
|
return ERROR_DOS(ERRDOS,ERRbadfid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fsp->notify->num_changes > 0) {
|
||||||
|
|
||||||
|
change_notify_reply(inbuf, max_param_count, fsp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* change_notify_reply() above has independently sent its
|
||||||
|
* results
|
||||||
|
*/
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (!change_notify_set(inbuf, fsp, conn, flags, max_param_count)) {
|
if (!change_notify_set(inbuf, fsp, conn, flags, max_param_count)) {
|
||||||
return(UNIXERROR(ERRDOS,ERRbadfid));
|
return(UNIXERROR(ERRDOS,ERRbadfid));
|
||||||
}
|
}
|
||||||
|
@ -198,7 +198,8 @@ static void change_dir_owner_to_parent(connection_struct *conn,
|
|||||||
static NTSTATUS open_file(files_struct *fsp,
|
static NTSTATUS open_file(files_struct *fsp,
|
||||||
connection_struct *conn,
|
connection_struct *conn,
|
||||||
const char *parent_dir,
|
const char *parent_dir,
|
||||||
const char *fname,
|
const char *name,
|
||||||
|
const char *path,
|
||||||
SMB_STRUCT_STAT *psbuf,
|
SMB_STRUCT_STAT *psbuf,
|
||||||
int flags,
|
int flags,
|
||||||
mode_t unx_mode,
|
mode_t unx_mode,
|
||||||
@ -227,7 +228,7 @@ static NTSTATUS open_file(files_struct *fsp,
|
|||||||
if (!CAN_WRITE(conn)) {
|
if (!CAN_WRITE(conn)) {
|
||||||
/* It's a read-only share - fail if we wanted to write. */
|
/* It's a read-only share - fail if we wanted to write. */
|
||||||
if(accmode != O_RDONLY) {
|
if(accmode != O_RDONLY) {
|
||||||
DEBUG(3,("Permission denied opening %s\n",fname));
|
DEBUG(3,("Permission denied opening %s\n", path));
|
||||||
return NT_STATUS_ACCESS_DENIED;
|
return NT_STATUS_ACCESS_DENIED;
|
||||||
} else if(flags & O_CREAT) {
|
} else if(flags & O_CREAT) {
|
||||||
/* We don't want to write - but we must make sure that
|
/* We don't want to write - but we must make sure that
|
||||||
@ -253,7 +254,7 @@ static NTSTATUS open_file(files_struct *fsp,
|
|||||||
|
|
||||||
if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC)) {
|
if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC)) {
|
||||||
DEBUG(10,("open_file: truncate requested on read-only open "
|
DEBUG(10,("open_file: truncate requested on read-only open "
|
||||||
"for file %s\n",fname ));
|
"for file %s\n", path));
|
||||||
local_flags = (flags & ~O_ACCMODE)|O_RDWR;
|
local_flags = (flags & ~O_ACCMODE)|O_RDWR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,15 +283,15 @@ static NTSTATUS open_file(files_struct *fsp,
|
|||||||
|
|
||||||
/* Don't create files with Microsoft wildcard characters. */
|
/* Don't create files with Microsoft wildcard characters. */
|
||||||
if ((local_flags & O_CREAT) && !file_existed &&
|
if ((local_flags & O_CREAT) && !file_existed &&
|
||||||
ms_has_wild(fname)) {
|
ms_has_wild(path)) {
|
||||||
return NT_STATUS_OBJECT_NAME_INVALID;
|
return NT_STATUS_OBJECT_NAME_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Actually do the open */
|
/* Actually do the open */
|
||||||
if (!fd_open(conn, fname, fsp, local_flags, unx_mode)) {
|
if (!fd_open(conn, path, fsp, local_flags, unx_mode)) {
|
||||||
DEBUG(3,("Error opening file %s (%s) (local_flags=%d) "
|
DEBUG(3,("Error opening file %s (%s) (local_flags=%d) "
|
||||||
"(flags=%d)\n",
|
"(flags=%d)\n",
|
||||||
fname,strerror(errno),local_flags,flags));
|
path,strerror(errno),local_flags,flags));
|
||||||
return map_nt_error_from_unix(errno);
|
return map_nt_error_from_unix(errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,7 +299,7 @@ static NTSTATUS open_file(files_struct *fsp,
|
|||||||
|
|
||||||
/* Inherit the ACL if required */
|
/* Inherit the ACL if required */
|
||||||
if (lp_inherit_perms(SNUM(conn))) {
|
if (lp_inherit_perms(SNUM(conn))) {
|
||||||
inherit_access_acl(conn, parent_dir, fname,
|
inherit_access_acl(conn, parent_dir, path,
|
||||||
unx_mode);
|
unx_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,6 +308,9 @@ static NTSTATUS open_file(files_struct *fsp,
|
|||||||
change_file_owner_to_parent(conn, parent_dir,
|
change_file_owner_to_parent(conn, parent_dir,
|
||||||
fsp);
|
fsp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notify_action(conn, parent_dir, name,
|
||||||
|
NOTIFY_ACTION_ADDED);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -317,13 +321,13 @@ static NTSTATUS open_file(files_struct *fsp,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (fsp->fh->fd == -1) {
|
if (fsp->fh->fd == -1) {
|
||||||
ret = SMB_VFS_STAT(conn, fname, psbuf);
|
ret = SMB_VFS_STAT(conn, path, psbuf);
|
||||||
} else {
|
} else {
|
||||||
ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf);
|
ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf);
|
||||||
/* If we have an fd, this stat should succeed. */
|
/* If we have an fd, this stat should succeed. */
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
DEBUG(0,("Error doing fstat on open file %s "
|
DEBUG(0,("Error doing fstat on open file %s "
|
||||||
"(%s)\n", fname,strerror(errno) ));
|
"(%s)\n", path,strerror(errno) ));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,12 +369,13 @@ static NTSTATUS open_file(files_struct *fsp,
|
|||||||
fsp->sent_oplock_break = NO_BREAK_SENT;
|
fsp->sent_oplock_break = NO_BREAK_SENT;
|
||||||
fsp->is_directory = False;
|
fsp->is_directory = False;
|
||||||
fsp->is_stat = False;
|
fsp->is_stat = False;
|
||||||
if (conn->aio_write_behind_list &&
|
if (conn->aio_write_behind_list
|
||||||
is_in_path(fname, conn->aio_write_behind_list, conn->case_sensitive)) {
|
&& is_in_path(path, conn->aio_write_behind_list,
|
||||||
|
conn->case_sensitive)) {
|
||||||
fsp->aio_write_behind = True;
|
fsp->aio_write_behind = True;
|
||||||
}
|
}
|
||||||
|
|
||||||
string_set(&fsp->fsp_name,fname);
|
string_set(&fsp->fsp_name, path);
|
||||||
fsp->wcp = NULL; /* Write cache pointer. */
|
fsp->wcp = NULL; /* Write cache pointer. */
|
||||||
|
|
||||||
DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n",
|
DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n",
|
||||||
@ -1579,8 +1584,9 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
|
|||||||
* open_file strips any O_TRUNC flags itself.
|
* open_file strips any O_TRUNC flags itself.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
fsp_open = open_file(fsp, conn, parent_dir, fname, psbuf, flags|flags2,
|
fsp_open = open_file(fsp, conn, parent_dir, newname, fname, psbuf,
|
||||||
unx_mode, access_mask, open_access_mask);
|
flags|flags2, unx_mode, access_mask,
|
||||||
|
open_access_mask);
|
||||||
|
|
||||||
if (!NT_STATUS_IS_OK(fsp_open)) {
|
if (!NT_STATUS_IS_OK(fsp_open)) {
|
||||||
if (lck != NULL) {
|
if (lck != NULL) {
|
||||||
@ -1845,7 +1851,7 @@ NTSTATUS open_file_fchmod(connection_struct *conn, const char *fname,
|
|||||||
|
|
||||||
/* note! we must use a non-zero desired access or we don't get
|
/* note! we must use a non-zero desired access or we don't get
|
||||||
a real file descriptor. Oh what a twisted web we weave. */
|
a real file descriptor. Oh what a twisted web we weave. */
|
||||||
status = open_file(fsp, conn, NULL, fname, psbuf, O_WRONLY, 0,
|
status = open_file(fsp, conn, NULL, NULL, fname, psbuf, O_WRONLY, 0,
|
||||||
FILE_WRITE_DATA, FILE_WRITE_DATA);
|
FILE_WRITE_DATA, FILE_WRITE_DATA);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1975,10 +1975,12 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL b
|
|||||||
code.
|
code.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, BOOL has_wild)
|
NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
|
||||||
|
char *name, BOOL has_wild)
|
||||||
{
|
{
|
||||||
pstring directory;
|
pstring directory;
|
||||||
pstring mask;
|
pstring mask;
|
||||||
|
pstring orig_name;
|
||||||
char *p;
|
char *p;
|
||||||
int count=0;
|
int count=0;
|
||||||
NTSTATUS error = NT_STATUS_OK;
|
NTSTATUS error = NT_STATUS_OK;
|
||||||
@ -1989,6 +1991,11 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, B
|
|||||||
*directory = *mask = 0;
|
*directory = *mask = 0;
|
||||||
|
|
||||||
rc = unix_convert(name,conn,0,&bad_path,&sbuf);
|
rc = unix_convert(name,conn,0,&bad_path,&sbuf);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Feel my pain, this code needs rewriting *very* badly! -- vl
|
||||||
|
*/
|
||||||
|
pstrcpy(orig_name, name);
|
||||||
|
|
||||||
p = strrchr_m(name,'/');
|
p = strrchr_m(name,'/');
|
||||||
if (!p) {
|
if (!p) {
|
||||||
@ -2089,6 +2096,18 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, B
|
|||||||
error = map_nt_error_from_unix(errno);
|
error = map_nt_error_from_unix(errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char *dir;
|
||||||
|
const char *fname;
|
||||||
|
|
||||||
|
if (parent_dirname_talloc(tmp_talloc_ctx(), orig_name,
|
||||||
|
&dir, &fname)) {
|
||||||
|
notify_action(conn, dir, fname,
|
||||||
|
NOTIFY_ACTION_REMOVED);
|
||||||
|
TALLOC_FREE(dir); /* not strictly necessary */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user