Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
3e588e3a
Commit
3e588e3a
authored
Mar 26, 2003
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implemented file change notifications, based on a patch by Mike
McCormack.
parent
473a8866
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
215 additions
and
46 deletions
+215
-46
Makefile.in
dlls/kernel/Makefile.in
+1
-0
change.c
dlls/kernel/change.c
+31
-21
Makefile.in
dlls/ntdll/Makefile.in
+0
-1
server_protocol.h
include/wine/server_protocol.h
+17
-2
change.c
server/change.c
+140
-12
file.c
server/file.c
+1
-1
file.h
server/file.h
+5
-0
protocol.def
server/protocol.def
+7
-1
request.h
server/request.h
+2
-0
signal.c
server/signal.c
+1
-7
trace.c
server/trace.c
+10
-1
No files found.
dlls/kernel/Makefile.in
View file @
3e588e3a
...
...
@@ -21,6 +21,7 @@ SPEC_SRCS16 = \
C_SRCS
=
\
$(TOPOBJDIR)
/ole/ole2nls.c
\
change.c
\
comm.c
\
computername.c
\
console.c
\
...
...
files
/change.c
→
dlls/kernel
/change.c
View file @
3e588e3a
/*
* Win32 file change notification functions
*
* FIXME: this is VERY difficult to implement with proper Unix support
* at the wineserver side.
* (Unix doesn't really support this)
* See http://x57.deja.com/getdoc.xp?AN=575483053 for possible solutions.
*
* Copyright 1998 Ulrich Weigand
*
* This library is free software; you can redistribute it and/or
...
...
@@ -25,13 +20,9 @@
#include "config.h"
#include <assert.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <string.h>
#include <time.h>
#include "winbase.h"
#include "winerror.h"
#include "wine/server.h"
...
...
@@ -45,38 +36,49 @@ WINE_DEFAULT_DEBUG_CHANNEL(file);
HANDLE
WINAPI
FindFirstChangeNotificationA
(
LPCSTR
lpPathName
,
BOOL
bWatchSubtree
,
DWORD
dwNotifyFilter
)
{
HANDLE
ret
=
INVALID_HANDLE_VALUE
;
HANDLE
file
,
ret
=
INVALID_HANDLE_VALUE
;
TRACE
(
"%s %d %lx
\n
"
,
debugstr_a
(
lpPathName
),
bWatchSubtree
,
dwNotifyFilter
);
FIXME
(
"this is not supported yet (non-trivial).
\n
"
);
if
((
file
=
CreateFileA
(
lpPathName
,
0
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
NULL
,
OPEN_EXISTING
,
FILE_FLAG_BACKUP_SEMANTICS
,
0
))
==
INVALID_HANDLE_VALUE
)
return
INVALID_HANDLE_VALUE
;
SERVER_START_REQ
(
create_change_notification
)
{
req
->
handle
=
file
;
req
->
subtree
=
bWatchSubtree
;
req
->
filter
=
dwNotifyFilter
;
if
(
!
wine_server_call_err
(
req
))
ret
=
reply
->
handle
;
}
SERVER_END_REQ
;
CloseHandle
(
file
);
return
ret
;
}
/****************************************************************************
* FindFirstChangeNotificationW (KERNEL32.@)
*/
HANDLE
WINAPI
FindFirstChangeNotificationW
(
LPCWSTR
lpPathName
,
BOOL
bWatchSubtree
,
DWORD
dwNotifyFilter
)
HANDLE
WINAPI
FindFirstChangeNotificationW
(
LPCWSTR
lpPathName
,
BOOL
bWatchSubtree
,
DWORD
dwNotifyFilter
)
{
HANDLE
ret
=
INVALID_HANDLE_VALUE
;
HANDLE
file
,
ret
=
INVALID_HANDLE_VALUE
;
FIXME
(
"this is not supported yet (non-trivial).
\n
"
);
TRACE
(
"%s %d %lx
\n
"
,
debugstr_w
(
lpPathName
),
bWatchSubtree
,
dwNotifyFilter
);
if
((
file
=
CreateFileW
(
lpPathName
,
0
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
NULL
,
OPEN_EXISTING
,
FILE_FLAG_BACKUP_SEMANTICS
,
0
))
==
INVALID_HANDLE_VALUE
)
return
INVALID_HANDLE_VALUE
;
SERVER_START_REQ
(
create_change_notification
)
{
req
->
handle
=
file
;
req
->
subtree
=
bWatchSubtree
;
req
->
filter
=
dwNotifyFilter
;
if
(
!
wine_server_call_err
(
req
))
ret
=
reply
->
handle
;
}
SERVER_END_REQ
;
CloseHandle
(
file
);
return
ret
;
}
...
...
@@ -85,15 +87,23 @@ HANDLE WINAPI FindFirstChangeNotificationW( LPCWSTR lpPathName,
*/
BOOL
WINAPI
FindNextChangeNotification
(
HANDLE
handle
)
{
/* FIXME: do something */
return
TRUE
;
BOOL
ret
;
TRACE
(
"%p
\n
"
,
handle
);
SERVER_START_REQ
(
next_change_notification
)
{
req
->
handle
=
handle
;
ret
=
!
wine_server_call_err
(
req
);
}
SERVER_END_REQ
;
return
ret
;
}
/****************************************************************************
* FindCloseChangeNotification (KERNEL32.@)
*/
BOOL
WINAPI
FindCloseChangeNotification
(
HANDLE
handle
)
BOOL
WINAPI
FindCloseChangeNotification
(
HANDLE
handle
)
{
return
CloseHandle
(
handle
);
}
dlls/ntdll/Makefile.in
View file @
3e588e3a
...
...
@@ -7,7 +7,6 @@ MODULE = ntdll.dll
EXTRALIBS
=
$(LIBUNICODE)
C_SRCS
=
\
$(TOPOBJDIR)
/files/change.c
\
$(TOPOBJDIR)
/files/directory.c
\
$(TOPOBJDIR)
/files/dos_fs.c
\
$(TOPOBJDIR)
/files/drive.c
\
...
...
include/wine/server_protocol.h
View file @
3e588e3a
...
...
@@ -1429,8 +1429,9 @@ struct send_console_signal_reply
struct
create_change_notification_request
{
struct
request_header
__header
;
obj_handle_t
handle
;
int
subtree
;
int
filter
;
unsigned
int
filter
;
};
struct
create_change_notification_reply
{
...
...
@@ -1440,6 +1441,17 @@ struct create_change_notification_reply
struct
next_change_notification_request
{
struct
request_header
__header
;
obj_handle_t
handle
;
};
struct
next_change_notification_reply
{
struct
reply_header
__header
;
};
struct
create_mapping_request
{
struct
request_header
__header
;
...
...
@@ -3095,6 +3107,7 @@ enum request
REQ_move_console_output
,
REQ_send_console_signal
,
REQ_create_change_notification
,
REQ_next_change_notification
,
REQ_create_mapping
,
REQ_open_mapping
,
REQ_get_mapping_info
,
...
...
@@ -3276,6 +3289,7 @@ union generic_request
struct
move_console_output_request
move_console_output_request
;
struct
send_console_signal_request
send_console_signal_request
;
struct
create_change_notification_request
create_change_notification_request
;
struct
next_change_notification_request
next_change_notification_request
;
struct
create_mapping_request
create_mapping_request
;
struct
open_mapping_request
open_mapping_request
;
struct
get_mapping_info_request
get_mapping_info_request
;
...
...
@@ -3455,6 +3469,7 @@ union generic_reply
struct
move_console_output_reply
move_console_output_reply
;
struct
send_console_signal_reply
send_console_signal_reply
;
struct
create_change_notification_reply
create_change_notification_reply
;
struct
next_change_notification_reply
next_change_notification_reply
;
struct
create_mapping_reply
create_mapping_reply
;
struct
open_mapping_reply
open_mapping_reply
;
struct
get_mapping_info_reply
get_mapping_info_reply
;
...
...
@@ -3557,6 +3572,6 @@ union generic_reply
struct
get_next_hook_reply
get_next_hook_reply
;
};
#define SERVER_PROTOCOL_VERSION 10
2
#define SERVER_PROTOCOL_VERSION 10
3
#endif
/* __WINE_WINE_SERVER_PROTOCOL_H */
server/change.c
View file @
3e588e3a
...
...
@@ -18,25 +18,37 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "wine/port.h"
#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include "windef.h"
#include "file.h"
#include "handle.h"
#include "thread.h"
#include "request.h"
#include "list.h"
struct
change
{
struct
object
obj
;
/* object header */
struct
fd
*
fd
;
/* file descriptor to the directory */
struct
list
entry
;
/* entry in global change notifications list */
int
subtree
;
/* watch all the subtree */
int
filter
;
/* notification filter */
unsigned
int
filter
;
/* notification filter */
long
notified
;
/* SIGIO counter */
long
signaled
;
/* the file changed */
};
static
void
change_dump
(
struct
object
*
obj
,
int
verbose
);
static
int
change_signaled
(
struct
object
*
obj
,
struct
thread
*
thread
);
static
void
change_destroy
(
struct
object
*
obj
);
static
const
struct
object_ops
change_ops
=
{
...
...
@@ -47,17 +59,72 @@ static const struct object_ops change_ops =
change_signaled
,
/* signaled */
no_satisfied
,
/* satisfied */
no_get_fd
,
/* get_fd */
no_destroy
/* destroy */
change_destroy
/* destroy */
};
static
struct
list
change_list
=
LIST_INIT
(
change_list
);
static
void
adjust_changes
(
int
fd
,
unsigned
int
filter
)
{
#ifdef F_NOTIFY
unsigned
int
val
;
if
(
0
>
fcntl
(
fd
,
F_SETSIG
,
SIGIO
)
)
return
;
val
=
DN_MULTISHOT
;
if
(
filter
&
FILE_NOTIFY_CHANGE_FILE_NAME
)
val
|=
DN_RENAME
|
DN_DELETE
|
DN_CREATE
;
if
(
filter
&
FILE_NOTIFY_CHANGE_DIR_NAME
)
val
|=
DN_RENAME
|
DN_DELETE
|
DN_CREATE
;
if
(
filter
&
FILE_NOTIFY_CHANGE_ATTRIBUTES
)
val
|=
DN_ATTRIB
;
if
(
filter
&
FILE_NOTIFY_CHANGE_SIZE
)
val
|=
DN_MODIFY
;
if
(
filter
&
FILE_NOTIFY_CHANGE_LAST_WRITE
)
val
|=
DN_MODIFY
;
if
(
filter
&
FILE_NOTIFY_CHANGE_SECURITY
)
val
|=
DN_ATTRIB
;
fcntl
(
fd
,
F_NOTIFY
,
val
);
#endif
}
/* insert change in the global list */
static
inline
void
insert_change
(
struct
change
*
change
)
{
sigset_t
sigset
;
sigemptyset
(
&
sigset
);
sigaddset
(
&
sigset
,
SIGIO
);
sigprocmask
(
SIG_BLOCK
,
&
sigset
,
NULL
);
list_add_head
(
&
change_list
,
&
change
->
entry
);
sigprocmask
(
SIG_UNBLOCK
,
&
sigset
,
NULL
);
}
/* remove change from the global list */
static
inline
void
remove_change
(
struct
change
*
change
)
{
sigset_t
sigset
;
sigemptyset
(
&
sigset
);
sigaddset
(
&
sigset
,
SIGIO
);
sigprocmask
(
SIG_BLOCK
,
&
sigset
,
NULL
);
list_remove
(
&
change
->
entry
);
sigprocmask
(
SIG_UNBLOCK
,
&
sigset
,
NULL
);
}
static
struct
change
*
create_change_notification
(
int
subtree
,
int
filter
)
static
struct
change
*
create_change_notification
(
struct
fd
*
fd
,
int
subtree
,
unsigned
int
filter
)
{
struct
change
*
change
;
if
((
change
=
alloc_object
(
&
change_ops
)))
{
change
->
subtree
=
subtree
;
change
->
filter
=
filter
;
change
->
fd
=
(
struct
fd
*
)
grab_object
(
fd
);
change
->
subtree
=
subtree
;
change
->
filter
=
filter
;
change
->
notified
=
0
;
change
->
signaled
=
0
;
insert_change
(
change
);
adjust_changes
(
get_unix_fd
(
fd
),
filter
);
}
return
change
;
}
...
...
@@ -66,27 +133,88 @@ static void change_dump( struct object *obj, int verbose )
{
struct
change
*
change
=
(
struct
change
*
)
obj
;
assert
(
obj
->
ops
==
&
change_ops
);
fprintf
(
stderr
,
"Change notification sub=%d filter=%08x
\n
"
,
change
->
subtree
,
change
->
filter
);
fprintf
(
stderr
,
"Change notification
fd=%p
sub=%d filter=%08x
\n
"
,
change
->
fd
,
change
->
subtree
,
change
->
filter
);
}
static
int
change_signaled
(
struct
object
*
obj
,
struct
thread
*
thread
)
{
/* struct change *change = (struct change *)obj;*/
assert
(
obj
->
ops
==
&
change_ops
);
return
0
;
/* never signaled for now */
struct
change
*
change
=
(
struct
change
*
)
obj
;
return
change
->
signaled
!=
0
;
}
static
void
change_destroy
(
struct
object
*
obj
)
{
struct
change
*
change
=
(
struct
change
*
)
obj
;
release_object
(
change
->
fd
);
remove_change
(
change
);
}
/* enter here directly from SIGIO signal handler */
void
do_change_notify
(
int
unix_fd
)
{
struct
list
*
ptr
;
/* FIXME: this is O(n) ... probably can be improved */
LIST_FOR_EACH
(
ptr
,
&
change_list
)
{
struct
change
*
change
=
LIST_ENTRY
(
ptr
,
struct
change
,
entry
);
if
(
get_unix_fd
(
change
->
fd
)
!=
unix_fd
)
continue
;
interlocked_xchg_add
(
&
change
->
notified
,
1
);
break
;
}
}
/* SIGIO callback, called synchronously with the poll loop */
void
sigio_callback
(
void
)
{
struct
list
*
ptr
;
LIST_FOR_EACH
(
ptr
,
&
change_list
)
{
struct
change
*
change
=
LIST_ENTRY
(
ptr
,
struct
change
,
entry
);
long
count
=
interlocked_xchg
(
&
change
->
notified
,
0
);
if
(
count
)
{
change
->
signaled
+=
count
;
if
(
change
->
signaled
==
count
)
/* was it 0? */
wake_up
(
&
change
->
obj
,
0
);
}
}
}
/* create a change notification */
DECL_HANDLER
(
create_change_notification
)
{
struct
change
*
change
;
struct
file
*
file
;
struct
fd
*
fd
;
if
(
!
(
file
=
get_file_obj
(
current
->
process
,
req
->
handle
,
0
)))
return
;
fd
=
get_obj_fd
(
(
struct
object
*
)
file
);
release_object
(
file
);
if
(
!
fd
)
return
;
reply
->
handle
=
0
;
if
((
change
=
create_change_notification
(
req
->
subtree
,
req
->
filter
)))
if
((
change
=
create_change_notification
(
fd
,
req
->
subtree
,
req
->
filter
)))
{
reply
->
handle
=
alloc_handle
(
current
->
process
,
change
,
STANDARD_RIGHTS_REQUIRED
|
SYNCHRONIZE
,
0
);
release_object
(
change
);
}
release_object
(
fd
);
}
/* move to the next change notification */
DECL_HANDLER
(
next_change_notification
)
{
struct
change
*
change
;
if
((
change
=
(
struct
change
*
)
get_handle_obj
(
current
->
process
,
req
->
handle
,
0
,
&
change_ops
)))
{
if
(
change
->
signaled
>
0
)
change
->
signaled
--
;
release_object
(
change
);
}
}
server/file.c
View file @
3e588e3a
...
...
@@ -221,7 +221,7 @@ static struct file *create_file( const char *nameptr, size_t len, unsigned int a
return
NULL
;
}
/* refuse to open a directory */
if
(
S_ISDIR
(
mode
))
if
(
S_ISDIR
(
mode
)
&&
!
(
file
->
flags
&
FILE_FLAG_BACKUP_SEMANTICS
)
)
{
set_error
(
STATUS_ACCESS_DENIED
);
release_object
(
file
);
...
...
server/file.h
View file @
3e588e3a
...
...
@@ -95,4 +95,9 @@ extern int grow_file( struct file *file, int size_high, int size_low );
extern
struct
file
*
create_temp_file
(
int
access
);
extern
void
file_set_error
(
void
);
/* change notification functions */
extern
void
do_change_notify
(
int
unix_fd
);
extern
void
sigio_callback
(
void
);
#endif
/* __WINE_SERVER_FILE_H */
server/protocol.def
View file @
3e588e3a
...
...
@@ -1055,13 +1055,19 @@ enum char_info_mode
/* Create a change notification */
@REQ(create_change_notification)
obj_handle_t handle; /* handle to the directory */
int subtree; /* watch all the subtree */
int
filter; /* notification filter */
unsigned int
filter; /* notification filter */
@REPLY
obj_handle_t handle; /* handle to the change notification */
@END
/* Move to the next change notification */
@REQ(next_change_notification)
obj_handle_t handle; /* handle to the change notification */
@END
/* Create a file mapping */
@REQ(create_mapping)
int size_high; /* mapping size */
...
...
server/request.h
View file @
3e588e3a
...
...
@@ -177,6 +177,7 @@ DECL_HANDLER(read_console_output);
DECL_HANDLER
(
move_console_output
);
DECL_HANDLER
(
send_console_signal
);
DECL_HANDLER
(
create_change_notification
);
DECL_HANDLER
(
next_change_notification
);
DECL_HANDLER
(
create_mapping
);
DECL_HANDLER
(
open_mapping
);
DECL_HANDLER
(
get_mapping_info
);
...
...
@@ -357,6 +358,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(
req_handler
)
req_move_console_output
,
(
req_handler
)
req_send_console_signal
,
(
req_handler
)
req_create_change_notification
,
(
req_handler
)
req_next_change_notification
,
(
req_handler
)
req_create_mapping
,
(
req_handler
)
req_open_mapping
,
(
req_handler
)
req_get_mapping_info
,
...
...
server/signal.c
View file @
3e588e3a
...
...
@@ -170,12 +170,6 @@ static void sigint_callback(void)
exit
(
1
);
}
/* SIGIO callback */
static
void
sigio_callback
(
void
)
{
/* nothing here yet */
}
/* SIGHUP handler */
static
void
do_sighup
()
{
...
...
@@ -203,8 +197,8 @@ static void do_sigchld()
/* SIGIO handler */
static
void
do_sigio
(
int
signum
,
siginfo_t
*
si
,
void
*
x
)
{
/* do_change_notify( si->si_fd ); */
do_signal
(
handler_sigio
);
do_change_notify
(
si
->
si_fd
);
}
void
init_signals
(
void
)
...
...
server/trace.c
View file @
3e588e3a
...
...
@@ -1241,8 +1241,9 @@ static void dump_send_console_signal_request( const struct send_console_signal_r
static
void
dump_create_change_notification_request
(
const
struct
create_change_notification_request
*
req
)
{
fprintf
(
stderr
,
" handle=%p,"
,
req
->
handle
);
fprintf
(
stderr
,
" subtree=%d,"
,
req
->
subtree
);
fprintf
(
stderr
,
" filter=%
d
"
,
req
->
filter
);
fprintf
(
stderr
,
" filter=%
08x
"
,
req
->
filter
);
}
static
void
dump_create_change_notification_reply
(
const
struct
create_change_notification_reply
*
req
)
...
...
@@ -1250,6 +1251,11 @@ static void dump_create_change_notification_reply( const struct create_change_no
fprintf
(
stderr
,
" handle=%p"
,
req
->
handle
);
}
static
void
dump_next_change_notification_request
(
const
struct
next_change_notification_request
*
req
)
{
fprintf
(
stderr
,
" handle=%p"
,
req
->
handle
);
}
static
void
dump_create_mapping_request
(
const
struct
create_mapping_request
*
req
)
{
fprintf
(
stderr
,
" size_high=%d,"
,
req
->
size_high
);
...
...
@@ -2495,6 +2501,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(
dump_func
)
dump_move_console_output_request
,
(
dump_func
)
dump_send_console_signal_request
,
(
dump_func
)
dump_create_change_notification_request
,
(
dump_func
)
dump_next_change_notification_request
,
(
dump_func
)
dump_create_mapping_request
,
(
dump_func
)
dump_open_mapping_request
,
(
dump_func
)
dump_get_mapping_info_request
,
...
...
@@ -2672,6 +2679,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(
dump_func
)
0
,
(
dump_func
)
0
,
(
dump_func
)
dump_create_change_notification_reply
,
(
dump_func
)
0
,
(
dump_func
)
dump_create_mapping_reply
,
(
dump_func
)
dump_open_mapping_reply
,
(
dump_func
)
dump_get_mapping_info_reply
,
...
...
@@ -2849,6 +2857,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"move_console_output"
,
"send_console_signal"
,
"create_change_notification"
,
"next_change_notification"
,
"create_mapping"
,
"open_mapping"
,
"get_mapping_info"
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment