From: Joel Holdsworth <joel@airwebreathe.org.uk> Signed-off-by: Joel Holdsworth <joel@airwebreathe.org.uk> --- server/fd.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/server/fd.c b/server/fd.c index efb6e8e76b9..ac72ace49d2 100644 --- a/server/fd.c +++ b/server/fd.c @@ -1625,6 +1625,31 @@ static void fd_destroy( struct object *obj ) if (fd->sync) release_object( fd->sync ); } +static void get_inode_open_sharing(struct fd *fd, struct inode *inode, + unsigned int *sharing, unsigned int *access ) +{ + static const unsigned int all_access = FILE_READ_DATA | FILE_EXECUTE | FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE; + + struct list *ptr; + + *sharing = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; + *access = 0; + + if (!inode) + inode = fd->inode; + + LIST_FOR_EACH( ptr, &inode->open ) + { + struct fd *fd_ptr = LIST_ENTRY( ptr, struct fd, inode_entry ); + if (fd_ptr != fd) + { + /* if access mode is 0, sharing mode is ignored */ + if (fd_ptr->access & all_access) *sharing &= fd_ptr->sharing; + *access |= fd_ptr->access; + } + } +} + /* check if the desired access is possible without violating */ /* the sharing mode of other opens of the same file */ static unsigned int check_sharing( struct fd *fd, unsigned int access, unsigned int sharing, @@ -1635,20 +1660,12 @@ static unsigned int check_sharing( struct fd *fd, unsigned int access, unsigned const unsigned int write_access = FILE_WRITE_DATA | FILE_APPEND_DATA; const unsigned int all_access = read_access | write_access | DELETE; - unsigned int existing_sharing = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; - unsigned int existing_access = 0; - struct fd *fd_ptr; + unsigned int existing_sharing, existing_access; fd->access = access; fd->sharing = sharing; - LIST_FOR_EACH_ENTRY( fd_ptr, &fd->inode->open, struct fd, inode_entry ) - { - if (fd_ptr == fd) continue; - /* if access mode is 0, sharing mode is ignored */ - if (fd_ptr->access & all_access) existing_sharing &= fd_ptr->sharing; - existing_access |= fd_ptr->access; - } + get_inode_open_sharing(fd, NULL, &existing_sharing, &existing_access); if (((access & read_access) && !(existing_sharing & FILE_SHARE_READ)) || ((access & write_access) && !(existing_sharing & FILE_SHARE_WRITE)) || -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/4457