From a2ca2ebd505bb628f0870fb246b0aa77dd34a5d4 Mon Sep 17 00:00:00 2001
From: Alexandre Julliard <julliard@winehq.org>
Date: Mon, 23 Aug 2010 17:09:45 +0200
Subject: [PATCH] server: Change the removable fd flag to a cacheable flag to
 make it possible for fd users to set it dynamically.

---
 dlls/ntdll/server.c            |  2 +-
 include/wine/server_protocol.h |  4 ++--
 server/fd.c                    | 14 +++++++++++++-
 server/file.c                  |  1 +
 server/file.h                  |  1 +
 server/mailslot.c              | 10 +++++++---
 server/mapping.c               |  1 +
 server/named_pipe.c            |  2 ++
 server/protocol.def            |  2 +-
 server/request.h               |  2 +-
 server/sock.c                  |  2 ++
 server/trace.c                 |  2 +-
 12 files changed, 33 insertions(+), 10 deletions(-)

diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c
index ce27d5d5243..5e67bd6414e 100644
--- a/dlls/ntdll/server.c
+++ b/dlls/ntdll/server.c
@@ -564,7 +564,7 @@ int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd,
             if ((fd = receive_fd( &fd_handle )) != -1)
             {
                 assert( wine_server_ptr_handle(fd_handle) == handle );
-                *needs_close = (reply->removable ||
+                *needs_close = (!reply->cacheable ||
                                 !add_fd_to_cache( handle, fd, reply->type,
                                                   reply->access, reply->options ));
             }
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 1a78bc2e77a..0c43ecf6d03 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -1242,7 +1242,7 @@ struct get_handle_fd_reply
 {
     struct reply_header __header;
     int          type;
-    int          removable;
+    int          cacheable;
     unsigned int access;
     unsigned int options;
 };
@@ -5487,6 +5487,6 @@ union generic_reply
     struct set_cursor_reply set_cursor_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 402
+#define SERVER_PROTOCOL_VERSION 403
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/fd.c b/server/fd.c
index ca317c4a1a9..9111a657e91 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -197,6 +197,7 @@ struct fd
     char                *unix_name;   /* unix file name */
     int                  unix_fd;     /* unix file descriptor */
     unsigned int         no_fd_status;/* status to return when unix_fd is -1 */
+    unsigned int         cacheable :1;/* can the fd be cached on the client side? */
     unsigned int         signaled :1; /* is the fd signaled? */
     unsigned int         fs_locks :1; /* can we use filesystem locks for this fd? */
     int                  poll_index;  /* index of fd in poll array */
@@ -1546,6 +1547,7 @@ static struct fd *alloc_fd_object(void)
     fd->sharing    = 0;
     fd->unix_fd    = -1;
     fd->unix_name  = NULL;
+    fd->cacheable  = 0;
     fd->signaled   = 1;
     fd->fs_locks   = 1;
     fd->poll_index = -1;
@@ -1580,6 +1582,7 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use
     fd->sharing    = 0;
     fd->unix_name  = NULL;
     fd->unix_fd    = -1;
+    fd->cacheable  = 0;
     fd->signaled   = 0;
     fd->fs_locks   = 0;
     fd->poll_index = -1;
@@ -1608,6 +1611,7 @@ struct fd *dup_fd_object( struct fd *orig, unsigned int access, unsigned int sha
     fd->options    = options;
     fd->sharing    = sharing;
     fd->unix_fd    = -1;
+    fd->cacheable  = orig->cacheable;
     fd->signaled   = 0;
     fd->fs_locks   = 0;
     fd->poll_index = -1;
@@ -1823,6 +1827,7 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
         }
         fd->inode = inode;
         fd->closed = closed_fd;
+        fd->cacheable = !inode->device->removable;
         list_add_head( &inode->open, &fd->inode_entry );
 
         /* check directory options */
@@ -1869,6 +1874,7 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
             goto error;
         }
         free( closed_fd );
+        fd->cacheable = 1;
     }
     return fd;
 
@@ -1922,6 +1928,12 @@ int is_same_file_fd( struct fd *fd1, struct fd *fd2 )
     return fd1->inode == fd2->inode;
 }
 
+/* allow the fd to be cached (can't be reset once set) */
+void allow_fd_caching( struct fd *fd )
+{
+    fd->cacheable = 1;
+}
+
 /* check if fd is on a removable device */
 int is_fd_removable( struct fd *fd )
 {
@@ -2269,7 +2281,7 @@ DECL_HANDLER(get_handle_fd)
         if (unix_fd != -1)
         {
             reply->type = fd->fd_ops->get_fd_type( fd );
-            reply->removable = is_fd_removable(fd);
+            reply->cacheable = fd->cacheable;
             reply->options = fd->options;
             reply->access = get_handle_access( current->process, req->handle );
             send_client_fd( current->process, unix_fd, req->handle );
diff --git a/server/file.c b/server/file.c
index 105c3396728..d17b25b8ca0 100644
--- a/server/file.c
+++ b/server/file.c
@@ -136,6 +136,7 @@ struct file *create_file_for_fd( int fd, unsigned int access, unsigned int shari
             release_object( file );
             return NULL;
         }
+        allow_fd_caching( file->fd );
     }
     return file;
 }
diff --git a/server/file.h b/server/file.h
index 9a348bfd572..26290a38969 100644
--- a/server/file.h
+++ b/server/file.h
@@ -71,6 +71,7 @@ extern int check_fd_events( struct fd *fd, int events );
 extern void set_fd_events( struct fd *fd, int events );
 extern obj_handle_t lock_fd( struct fd *fd, file_pos_t offset, file_pos_t count, int shared, int wait );
 extern void unlock_fd( struct fd *fd, file_pos_t offset, file_pos_t count );
+extern void allow_fd_caching( struct fd *fd );
 extern void set_fd_signaled( struct fd *fd, int signaled );
 extern int is_fd_signaled( struct fd *fd );
 
diff --git a/server/mailslot.c b/server/mailslot.c
index 97da8d2df83..051f0adb48f 100644
--- a/server/mailslot.c
+++ b/server/mailslot.c
@@ -297,6 +297,7 @@ static struct object *mailslot_open_file( struct object *obj, unsigned int acces
         release_object( writer );
         return NULL;
     }
+    allow_fd_caching( writer->fd );
     return &writer->obj;
 }
 
@@ -442,9 +443,12 @@ static struct mailslot *create_mailslot( struct directory *root,
         fcntl( fds[1], F_SETFL, O_NONBLOCK );
         shutdown( fds[0], SHUT_RD );
         mailslot->write_fd = fds[0];
-        mailslot->fd = create_anonymous_fd( &mailslot_fd_ops, fds[1], &mailslot->obj,
-                                            FILE_SYNCHRONOUS_IO_NONALERT );
-        if (mailslot->fd) return mailslot;
+        if ((mailslot->fd = create_anonymous_fd( &mailslot_fd_ops, fds[1], &mailslot->obj,
+                                                 FILE_SYNCHRONOUS_IO_NONALERT )))
+        {
+            allow_fd_caching( mailslot->fd );
+            return mailslot;
+        }
     }
     else file_set_error();
 
diff --git a/server/mapping.c b/server/mapping.c
index 1cf53b9fe99..c8b8edfa2e6 100644
--- a/server/mapping.c
+++ b/server/mapping.c
@@ -515,6 +515,7 @@ static struct object *create_mapping( struct directory *root, const struct unico
         if ((unix_fd = create_temp_file( size )) == -1) goto error;
         if (!(mapping->fd = create_anonymous_fd( &mapping_fd_ops, unix_fd, &mapping->obj,
                                                  FILE_SYNCHRONOUS_IO_NONALERT ))) goto error;
+        allow_fd_caching( mapping->fd );
     }
     mapping->size    = (size + page_mask) & ~((mem_size_t)page_mask);
     mapping->protect = protect;
diff --git a/server/named_pipe.c b/server/named_pipe.c
index 95f06b9aab0..29d5c5efdf8 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -838,6 +838,8 @@ static struct object *named_pipe_open_file( struct object *obj, unsigned int acc
             server->fd = create_anonymous_fd( &pipe_server_fd_ops, fds[0], &server->obj, server->options );
             if (client->fd && server->fd)
             {
+                allow_fd_caching( client->fd );
+                allow_fd_caching( server->fd );
                 fd_copy_completion( server->ioctl_fd, server->fd );
                 if (server->state == ps_wait_open)
                     fd_async_wake_up( server->ioctl_fd, ASYNC_TYPE_WAIT, STATUS_SUCCESS );
diff --git a/server/protocol.def b/server/protocol.def
index e41cd183ab8..5f1a8f99950 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1018,7 +1018,7 @@ enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT };
     obj_handle_t handle;        /* handle to the file */
 @REPLY
     int          type;          /* file type (see below) */
-    int          removable;     /* is file removable? */
+    int          cacheable;     /* can fd be cached in the client? */
     unsigned int access;        /* file access rights */
     unsigned int options;       /* file open options */
 @END
diff --git a/server/request.h b/server/request.h
index 722fc25c679..7897673bb27 100644
--- a/server/request.h
+++ b/server/request.h
@@ -888,7 +888,7 @@ C_ASSERT( sizeof(struct get_handle_unix_name_reply) == 16 );
 C_ASSERT( FIELD_OFFSET(struct get_handle_fd_request, handle) == 12 );
 C_ASSERT( sizeof(struct get_handle_fd_request) == 16 );
 C_ASSERT( FIELD_OFFSET(struct get_handle_fd_reply, type) == 8 );
-C_ASSERT( FIELD_OFFSET(struct get_handle_fd_reply, removable) == 12 );
+C_ASSERT( FIELD_OFFSET(struct get_handle_fd_reply, cacheable) == 12 );
 C_ASSERT( FIELD_OFFSET(struct get_handle_fd_reply, access) == 16 );
 C_ASSERT( FIELD_OFFSET(struct get_handle_fd_reply, options) == 20 );
 C_ASSERT( sizeof(struct get_handle_fd_reply) == 24 );
diff --git a/server/sock.c b/server/sock.c
index 24ad50c18d3..639421d3157 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -646,6 +646,7 @@ static struct object *create_socket( int family, int type, int protocol, unsigne
         release_object( sock );
         return NULL;
     }
+    allow_fd_caching( sock->fd );
     sock_reselect( sock );
     clear_error();
     return &sock->obj;
@@ -718,6 +719,7 @@ static struct sock *accept_socket( obj_handle_t handle )
             release_object( sock );
             return NULL;
         }
+        allow_fd_caching( acceptsock->fd );
     }
     clear_error();
     sock->pmask &= ~FD_ACCEPT;
diff --git a/server/trace.c b/server/trace.c
index fd2318e102c..944d939cb84 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1475,7 +1475,7 @@ static void dump_get_handle_fd_request( const struct get_handle_fd_request *req
 static void dump_get_handle_fd_reply( const struct get_handle_fd_reply *req )
 {
     fprintf( stderr, " type=%d", req->type );
-    fprintf( stderr, ", removable=%d", req->removable );
+    fprintf( stderr, ", cacheable=%d", req->cacheable );
     fprintf( stderr, ", access=%08x", req->access );
     fprintf( stderr, ", options=%08x", req->options );
 }
-- 
GitLab