Alexandre Julliard : server: Check sharing options when duplicating an fd object.

Alexandre Julliard julliard at winehq.org
Mon Apr 18 11:10:59 CDT 2011


Module: wine
Branch: master
Commit: 35431ed0e7dece8676f5b4c01cbedbf7dee3df6b
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=35431ed0e7dece8676f5b4c01cbedbf7dee3df6b

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Apr 18 13:41:32 2011 +0200

server: Check sharing options when duplicating an fd object.

---

 server/fd.c |   92 ++++++++++++++++++++++++++++++----------------------------
 1 files changed, 48 insertions(+), 44 deletions(-)

diff --git a/server/fd.c b/server/fd.c
index e0ec708..1743952 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -1471,6 +1471,48 @@ static void fd_destroy( struct object *obj )
     }
 }
 
+/* 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,
+                                   unsigned int open_flags, unsigned int options )
+{
+    unsigned int existing_sharing = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+    unsigned int existing_access = 0;
+    struct list *ptr;
+
+    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)
+        {
+            /* if access mode is 0, sharing mode is ignored */
+            if (fd_ptr->access) existing_sharing &= fd_ptr->sharing;
+            existing_access  |= fd_ptr->access;
+        }
+    }
+
+    if (((access & FILE_UNIX_READ_ACCESS) && !(existing_sharing & FILE_SHARE_READ)) ||
+        ((access & FILE_UNIX_WRITE_ACCESS) && !(existing_sharing & FILE_SHARE_WRITE)) ||
+        ((access & DELETE) && !(existing_sharing & FILE_SHARE_DELETE)))
+        return STATUS_SHARING_VIOLATION;
+    if (((existing_access & FILE_MAPPING_WRITE) && !(sharing & FILE_SHARE_WRITE)) ||
+        ((existing_access & FILE_MAPPING_IMAGE) && (access & FILE_UNIX_WRITE_ACCESS)))
+        return STATUS_SHARING_VIOLATION;
+    if ((existing_access & FILE_MAPPING_IMAGE) && (options & FILE_DELETE_ON_CLOSE))
+        return STATUS_CANNOT_DELETE;
+    if ((existing_access & FILE_MAPPING_ACCESS) && (open_flags & O_TRUNC))
+        return STATUS_USER_MAPPED_FILE;
+    if (!access) return 0;  /* if access mode is 0, sharing mode is ignored (except for mappings) */
+    if (((existing_access & FILE_UNIX_READ_ACCESS) && !(sharing & FILE_SHARE_READ)) ||
+        ((existing_access & FILE_UNIX_WRITE_ACCESS) && !(sharing & FILE_SHARE_WRITE)) ||
+        ((existing_access & DELETE) && !(sharing & FILE_SHARE_DELETE)))
+        return STATUS_SHARING_VIOLATION;
+    return 0;
+}
+
 /* set the events that select waits for on this fd */
 void set_fd_events( struct fd *fd, int events )
 {
@@ -1581,13 +1623,12 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use
 /* duplicate an fd object for a different user */
 struct fd *dup_fd_object( struct fd *orig, unsigned int access, unsigned int sharing, unsigned int options )
 {
+    unsigned int err;
     struct fd *fd = alloc_fd_object();
 
     if (!fd) return NULL;
 
-    fd->access     = access;
     fd->options    = options;
-    fd->sharing    = sharing;
     fd->cacheable  = orig->cacheable;
 
     if (orig->unix_name)
@@ -1611,6 +1652,11 @@ struct fd *dup_fd_object( struct fd *orig, unsigned int access, unsigned int sha
         fd->closed = closed;
         fd->inode = (struct inode *)grab_object( orig->inode );
         list_add_head( &fd->inode->open, &fd->inode_entry );
+        if ((err = check_sharing( fd, access, sharing, 0, options )))
+        {
+            set_error( err );
+            goto failed;
+        }
     }
     else if ((fd->unix_fd = dup( orig->unix_fd )) == -1)
     {
@@ -1630,48 +1676,6 @@ void set_no_fd_status( struct fd *fd, unsigned int status )
     fd->no_fd_status = status;
 }
 
-/* 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,
-                                   unsigned int open_flags, unsigned int options )
-{
-    unsigned int existing_sharing = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
-    unsigned int existing_access = 0;
-    struct list *ptr;
-
-    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)
-        {
-            /* if access mode is 0, sharing mode is ignored */
-            if (fd_ptr->access) existing_sharing &= fd_ptr->sharing;
-            existing_access  |= fd_ptr->access;
-        }
-    }
-
-    if (((access & FILE_UNIX_READ_ACCESS) && !(existing_sharing & FILE_SHARE_READ)) ||
-        ((access & FILE_UNIX_WRITE_ACCESS) && !(existing_sharing & FILE_SHARE_WRITE)) ||
-        ((access & DELETE) && !(existing_sharing & FILE_SHARE_DELETE)))
-        return STATUS_SHARING_VIOLATION;
-    if (((existing_access & FILE_MAPPING_WRITE) && !(sharing & FILE_SHARE_WRITE)) ||
-        ((existing_access & FILE_MAPPING_IMAGE) && (access & FILE_SHARE_WRITE)))
-        return STATUS_SHARING_VIOLATION;
-    if ((existing_access & FILE_MAPPING_IMAGE) && (options & FILE_DELETE_ON_CLOSE))
-        return STATUS_CANNOT_DELETE;
-    if ((existing_access & FILE_MAPPING_ACCESS) && (open_flags & O_TRUNC))
-        return STATUS_USER_MAPPED_FILE;
-    if (!access) return 0;  /* if access mode is 0, sharing mode is ignored (except for mappings) */
-    if (((existing_access & FILE_UNIX_READ_ACCESS) && !(sharing & FILE_SHARE_READ)) ||
-        ((existing_access & FILE_UNIX_WRITE_ACCESS) && !(sharing & FILE_SHARE_WRITE)) ||
-        ((existing_access & DELETE) && !(sharing & FILE_SHARE_DELETE)))
-        return STATUS_SHARING_VIOLATION;
-    return 0;
-}
-
 /* sets the user of an fd that previously had no user */
 void set_fd_user( struct fd *fd, const struct fd_ops *user_ops, struct object *user )
 {




More information about the wine-cvs mailing list