Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
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-cw
Commits
74bd1e47
Commit
74bd1e47
authored
Mar 27, 2004
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Check file sharing permissions based on the file inode instead of the
file name. Added regression test for sharing permissions.
parent
ae722227
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
116 additions
and
57 deletions
+116
-57
file.c
dlls/kernel/tests/file.c
+61
-0
fd.c
server/fd.c
+48
-1
file.c
server/file.c
+4
-55
file.h
server/file.h
+3
-1
No files found.
dlls/kernel/tests/file.c
View file @
74bd1e47
...
...
@@ -914,6 +914,66 @@ static void test_LockFile(void)
DeleteFileA
(
filename
);
}
static
inline
int
is_sharing_compatible
(
DWORD
access1
,
DWORD
sharing1
,
DWORD
access2
,
DWORD
sharing2
)
{
if
(
!
access1
||
!
access2
)
return
1
;
if
((
access1
&
GENERIC_READ
)
&&
!
(
sharing2
&
FILE_SHARE_READ
))
return
0
;
if
((
access1
&
GENERIC_WRITE
)
&&
!
(
sharing2
&
FILE_SHARE_WRITE
))
return
0
;
if
((
access2
&
GENERIC_READ
)
&&
!
(
sharing1
&
FILE_SHARE_READ
))
return
0
;
if
((
access2
&
GENERIC_WRITE
)
&&
!
(
sharing1
&
FILE_SHARE_WRITE
))
return
0
;
return
1
;
}
static
void
test_file_sharing
(
void
)
{
static
const
DWORD
access_modes
[
4
]
=
{
0
,
GENERIC_READ
,
GENERIC_WRITE
,
GENERIC_READ
|
GENERIC_WRITE
};
static
const
DWORD
sharing_modes
[
4
]
=
{
0
,
FILE_SHARE_READ
,
FILE_SHARE_WRITE
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
};
int
a1
,
s1
,
a2
,
s2
;
for
(
a1
=
0
;
a1
<
4
;
a1
++
)
{
for
(
s1
=
0
;
s1
<
4
;
s1
++
)
{
HANDLE
h
=
CreateFileA
(
filename
,
access_modes
[
a1
],
sharing_modes
[
s1
],
NULL
,
CREATE_ALWAYS
,
0
,
0
);
if
(
h
==
INVALID_HANDLE_VALUE
)
{
ok
(
0
,
"couldn't create file
\"
%s
\"
(err=%ld)
\n
"
,
filename
,
GetLastError
());
return
;
}
for
(
a2
=
0
;
a2
<
4
;
a2
++
)
{
for
(
s2
=
0
;
s2
<
4
;
s2
++
)
{
HANDLE
h2
=
CreateFileA
(
filename
,
access_modes
[
a2
],
sharing_modes
[
s2
],
NULL
,
CREATE_ALWAYS
,
0
,
0
);
if
(
is_sharing_compatible
(
access_modes
[
a1
],
sharing_modes
[
s1
],
access_modes
[
a2
],
sharing_modes
[
s2
]
))
{
ok
(
h2
!=
INVALID_HANDLE_VALUE
,
"open failed for modes %lx/%lx/%lx/%lx err %ld
\n
"
,
access_modes
[
a1
],
sharing_modes
[
s1
],
access_modes
[
a2
],
sharing_modes
[
s2
],
GetLastError
()
);
}
else
{
ok
(
h2
==
INVALID_HANDLE_VALUE
,
"open succeeded for modes %lx/%lx/%lx/%lx
\n
"
,
access_modes
[
a1
],
sharing_modes
[
s1
],
access_modes
[
a2
],
sharing_modes
[
s2
]
);
if
(
h2
==
INVALID_HANDLE_VALUE
)
ok
(
GetLastError
()
==
ERROR_SHARING_VIOLATION
,
"wrong error code %ld
\n
"
,
GetLastError
()
);
}
if
(
h2
!=
INVALID_HANDLE_VALUE
)
CloseHandle
(
h2
);
}
}
CloseHandle
(
h
);
}
}
DeleteFileA
(
filename
);
}
static
void
test_FindFirstFileA
()
{
HANDLE
handle
;
...
...
@@ -1000,6 +1060,7 @@ START_TEST(file)
test_FindFirstFileA
();
test_FindNextFileA
();
test_LockFile
();
test_file_sharing
();
test_offset_in_overlapped_structure
();
test_MapFile
();
}
server/fd.c
View file @
74bd1e47
...
...
@@ -66,6 +66,8 @@ struct fd
struct
closed_fd
*
closed
;
/* structure to store the unix fd at destroy time */
struct
object
*
user
;
/* object using this file descriptor */
struct
list
locks
;
/* list of locks on this fd */
unsigned
int
access
;
/* file access (GENERIC_READ/WRITE) */
unsigned
int
sharing
;
/* file sharing mode */
int
unix_fd
;
/* unix file descriptor */
int
fs_locks
;
/* can we use filesystem locks for this fd? */
int
poll_index
;
/* index of fd in poll array */
...
...
@@ -817,6 +819,8 @@ struct fd *alloc_fd( const struct fd_ops *fd_user_ops, struct object *user )
fd
->
user
=
user
;
fd
->
inode
=
NULL
;
fd
->
closed
=
NULL
;
fd
->
access
=
0
;
fd
->
sharing
=
0
;
fd
->
unix_fd
=
-
1
;
fd
->
fs_locks
=
1
;
fd
->
poll_index
=
-
1
;
...
...
@@ -831,10 +835,41 @@ struct fd *alloc_fd( const struct fd_ops *fd_user_ops, struct object *user )
return
fd
;
}
/* check if the desired access is possible without violating */
/* the sharing mode of other opens of the same file */
static
int
check_sharing
(
struct
fd
*
fd
,
unsigned
int
access
,
unsigned
int
sharing
)
{
unsigned
int
existing_sharing
=
FILE_SHARE_READ
|
FILE_SHARE_WRITE
;
unsigned
int
existing_access
=
0
;
struct
list
*
ptr
;
/* if access mode is 0, sharing mode is ignored */
if
(
!
access
)
sharing
=
FILE_SHARE_READ
|
FILE_SHARE_WRITE
;
fd
->
access
=
access
;
fd
->
sharing
=
sharing
;
LIST_FOR_EACH
(
ptr
,
&
fd
->
inode
->
open
)
{
struct
fd
*
fd_ptr
=
LIST_ENTRY
(
ptr
,
struct
fd
,
inode_entry
);
if
(
fd_ptr
!=
fd
)
{
existing_sharing
&=
fd_ptr
->
sharing
;
existing_access
|=
fd_ptr
->
access
;
}
}
if
((
access
&
GENERIC_READ
)
&&
!
(
existing_sharing
&
FILE_SHARE_READ
))
return
0
;
if
((
access
&
GENERIC_WRITE
)
&&
!
(
existing_sharing
&
FILE_SHARE_WRITE
))
return
0
;
if
((
existing_access
&
GENERIC_READ
)
&&
!
(
sharing
&
FILE_SHARE_READ
))
return
0
;
if
((
existing_access
&
GENERIC_WRITE
)
&&
!
(
sharing
&
FILE_SHARE_WRITE
))
return
0
;
return
1
;
}
/* open() wrapper using a struct fd */
/* the fd must have been created with alloc_fd */
/* on error the fd object is released */
struct
fd
*
open_fd
(
struct
fd
*
fd
,
const
char
*
name
,
int
flags
,
mode_t
*
mode
)
struct
fd
*
open_fd
(
struct
fd
*
fd
,
const
char
*
name
,
int
flags
,
mode_t
*
mode
,
unsigned
int
access
,
unsigned
int
sharing
)
{
struct
stat
st
;
struct
closed_fd
*
closed_fd
;
...
...
@@ -873,6 +908,12 @@ struct fd *open_fd( struct fd *fd, const char *name, int flags, mode_t *mode )
fd
->
inode
=
inode
;
fd
->
closed
=
closed_fd
;
list_add_head
(
&
inode
->
open
,
&
fd
->
inode_entry
);
if
(
!
check_sharing
(
fd
,
access
,
sharing
))
{
release_object
(
fd
);
set_error
(
STATUS_SHARING_VIOLATION
);
return
NULL
;
}
}
else
{
...
...
@@ -908,6 +949,12 @@ int get_unix_fd( struct fd *fd )
return
fd
->
unix_fd
;
}
/* check if two file descriptors point to the same file */
int
is_same_file_fd
(
struct
fd
*
fd1
,
struct
fd
*
fd2
)
{
return
fd1
->
inode
==
fd2
->
inode
;
}
/* callback for event happening in the main poll() loop */
void
fd_poll_event
(
struct
fd
*
fd
,
int
event
)
{
...
...
server/file.c
View file @
74bd1e47
...
...
@@ -56,20 +56,14 @@ struct file
{
struct
object
obj
;
/* object header */
struct
fd
*
fd
;
/* file descriptor for this file */
struct
file
*
next
;
/* next file in hashing list */
char
*
name
;
/* file name */
unsigned
int
access
;
/* file access (GENERIC_READ/WRITE) */
unsigned
int
options
;
/* file options (FILE_DELETE_ON_CLOSE, FILE_SYNCHRONOUS...) */
unsigned
int
sharing
;
/* file sharing mode */
int
removable
;
/* is file on removable media? */
struct
async_queue
read_q
;
struct
async_queue
write_q
;
};
#define NAME_HASH_SIZE 37
static
struct
file
*
file_hash
[
NAME_HASH_SIZE
];
static
void
file_dump
(
struct
object
*
obj
,
int
verbose
);
static
struct
fd
*
file_get_fd
(
struct
object
*
obj
);
static
void
file_destroy
(
struct
object
*
obj
);
...
...
@@ -106,38 +100,6 @@ static inline int is_overlapped( const struct file *file )
return
!
(
file
->
options
&
(
FILE_SYNCHRONOUS_IO_ALERT
|
FILE_SYNCHRONOUS_IO_NONALERT
));
}
static
int
get_name_hash
(
const
char
*
name
)
{
int
hash
=
0
;
while
(
*
name
)
hash
^=
(
unsigned
char
)
*
name
++
;
return
hash
%
NAME_HASH_SIZE
;
}
/* check if the desired access is possible without violating */
/* the sharing mode of other opens of the same file */
static
int
check_sharing
(
const
char
*
name
,
int
hash
,
unsigned
int
access
,
unsigned
int
sharing
)
{
struct
file
*
file
;
unsigned
int
existing_sharing
=
FILE_SHARE_READ
|
FILE_SHARE_WRITE
;
unsigned
int
existing_access
=
0
;
for
(
file
=
file_hash
[
hash
];
file
;
file
=
file
->
next
)
{
if
(
strcmp
(
file
->
name
,
name
))
continue
;
existing_sharing
&=
file
->
sharing
;
existing_access
|=
file
->
access
;
}
if
((
access
&
GENERIC_READ
)
&&
!
(
existing_sharing
&
FILE_SHARE_READ
))
goto
error
;
if
((
access
&
GENERIC_WRITE
)
&&
!
(
existing_sharing
&
FILE_SHARE_WRITE
))
goto
error
;
if
((
existing_access
&
GENERIC_READ
)
&&
!
(
sharing
&
FILE_SHARE_READ
))
goto
error
;
if
((
existing_access
&
GENERIC_WRITE
)
&&
!
(
sharing
&
FILE_SHARE_WRITE
))
goto
error
;
return
1
;
error:
set_error
(
STATUS_SHARING_VIOLATION
);
return
0
;
}
/* create a file from a file descriptor */
/* if the function fails the fd is closed */
static
struct
file
*
create_file_for_fd
(
int
fd
,
unsigned
int
access
,
unsigned
int
sharing
)
...
...
@@ -147,10 +109,8 @@ static struct file *create_file_for_fd( int fd, unsigned int access, unsigned in
if
((
file
=
alloc_object
(
&
file_ops
)))
{
file
->
name
=
NULL
;
file
->
next
=
NULL
;
file
->
access
=
access
;
file
->
options
=
FILE_SYNCHRONOUS_IO_NONALERT
;
file
->
sharing
=
sharing
;
file
->
removable
=
0
;
if
(
!
(
file
->
fd
=
create_anonymous_fd
(
&
file_fd_ops
,
fd
,
&
file
->
obj
)))
{
...
...
@@ -167,7 +127,7 @@ static struct object *create_file( const char *nameptr, size_t len, unsigned int
unsigned
int
attrs
,
int
removable
)
{
struct
file
*
file
;
int
hash
,
flags
;
int
flags
;
char
*
name
;
mode_t
mode
;
...
...
@@ -175,10 +135,6 @@ static struct object *create_file( const char *nameptr, size_t len, unsigned int
memcpy
(
name
,
nameptr
,
len
);
name
[
len
]
=
0
;
/* check sharing mode */
hash
=
get_name_hash
(
name
);
if
(
!
check_sharing
(
name
,
hash
,
access
,
sharing
))
goto
error
;
switch
(
create
)
{
case
FILE_CREATE
:
flags
=
O_CREAT
|
O_EXCL
;
break
;
...
...
@@ -206,11 +162,8 @@ static struct object *create_file( const char *nameptr, size_t len, unsigned int
file
->
access
=
access
;
file
->
options
=
options
;
file
->
sharing
=
sharing
;
file
->
removable
=
removable
;
file
->
name
=
name
;
file
->
next
=
file_hash
[
hash
];
file_hash
[
hash
]
=
file
;
if
(
is_overlapped
(
file
))
{
init_async_queue
(
&
file
->
read_q
);
...
...
@@ -219,7 +172,8 @@ static struct object *create_file( const char *nameptr, size_t len, unsigned int
/* FIXME: should set error to STATUS_OBJECT_NAME_COLLISION if file existed before */
if
(
!
(
file
->
fd
=
alloc_fd
(
&
file_fd_ops
,
&
file
->
obj
))
||
!
(
file
->
fd
=
open_fd
(
file
->
fd
,
name
,
flags
|
O_NONBLOCK
|
O_LARGEFILE
,
&
mode
)))
!
(
file
->
fd
=
open_fd
(
file
->
fd
,
name
,
flags
|
O_NONBLOCK
|
O_LARGEFILE
,
&
mode
,
access
,
sharing
)))
{
release_object
(
file
);
return
NULL
;
...
...
@@ -249,7 +203,7 @@ static struct object *create_file( const char *nameptr, size_t len, unsigned int
/* check if two file objects point to the same file */
int
is_same_file
(
struct
file
*
file1
,
struct
file
*
file2
)
{
return
!
strcmp
(
file1
->
name
,
file2
->
name
);
return
is_same_file_fd
(
file1
->
fd
,
file2
->
fd
);
}
/* check if the file is on removable media */
...
...
@@ -434,11 +388,6 @@ static void file_destroy( struct object *obj )
if
(
file
->
name
)
{
/* remove it from the hashing list */
struct
file
**
pptr
=
&
file_hash
[
get_name_hash
(
file
->
name
)];
while
(
*
pptr
&&
*
pptr
!=
file
)
pptr
=
&
(
*
pptr
)
->
next
;
assert
(
*
pptr
);
*
pptr
=
(
*
pptr
)
->
next
;
if
(
file
->
options
&
FILE_DELETE_ON_CLOSE
)
unlink
(
file
->
name
);
free
(
file
->
name
);
}
...
...
server/file.h
View file @
74bd1e47
...
...
@@ -45,11 +45,13 @@ struct fd_ops
/* file descriptor functions */
extern
struct
fd
*
alloc_fd
(
const
struct
fd_ops
*
fd_user_ops
,
struct
object
*
user
);
extern
struct
fd
*
open_fd
(
struct
fd
*
fd
,
const
char
*
name
,
int
flags
,
mode_t
*
mode
);
extern
struct
fd
*
open_fd
(
struct
fd
*
fd
,
const
char
*
name
,
int
flags
,
mode_t
*
mode
,
unsigned
int
access
,
unsigned
int
sharing
);
extern
struct
fd
*
create_anonymous_fd
(
const
struct
fd_ops
*
fd_user_ops
,
int
unix_fd
,
struct
object
*
user
);
extern
void
*
get_fd_user
(
struct
fd
*
fd
);
extern
int
get_unix_fd
(
struct
fd
*
fd
);
extern
int
is_same_file_fd
(
struct
fd
*
fd1
,
struct
fd
*
fd2
);
extern
void
fd_poll_event
(
struct
fd
*
fd
,
int
event
);
extern
int
check_fd_events
(
struct
fd
*
fd
,
int
events
);
extern
void
set_fd_events
(
struct
fd
*
fd
,
int
events
);
...
...
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