Started moving functions that deal with Unix file descriptors to a
separate fd object. This will be needed for file locking.

diff --git a/server/file.c b/server/file.c
index b302fe6..b4560a8 100644
--- a/server/file.c
+++ b/server/file.c
@@ -40,6 +40,7 @@
 #include "winerror.h"
 #include "winbase.h"
 
+#include "file.h"
 #include "handle.h"
 #include "thread.h"
 #include "request.h"
@@ -65,7 +66,6 @@
 static void file_dump( struct object *obj, int verbose );
 static int file_get_poll_events( struct object *obj );
 static void file_poll_event( struct object *obj, int event );
-static int file_get_fd( struct object *obj );
 static int file_flush( struct object *obj );
 static int file_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags );
 static void file_destroy( struct object *obj );
@@ -75,19 +75,23 @@
 {
     sizeof(struct file),          /* size */
     file_dump,                    /* dump */
-    default_poll_add_queue,       /* add_queue */
-    default_poll_remove_queue,    /* remove_queue */
-    default_poll_signaled,        /* signaled */
+    default_fd_add_queue,         /* add_queue */
+    default_fd_remove_queue,      /* remove_queue */
+    default_fd_signaled,          /* signaled */
     no_satisfied,                 /* satisfied */
-    file_get_poll_events,         /* get_poll_events */
-    file_poll_event,              /* poll_event */
-    file_get_fd,                  /* get_fd */
-    file_flush,                   /* flush */
+    default_get_fd,               /* get_fd */
     file_get_info,                /* get_file_info */
-    file_queue_async,             /* queue_async */
     file_destroy                  /* destroy */
 };
 
+static const struct fd_ops file_fd_ops =
+{
+    file_get_poll_events,         /* get_poll_events */
+    file_poll_event,              /* poll_event */
+    file_flush,                   /* flush */
+    file_get_info,                /* get_file_info */
+    file_queue_async              /* queue_async */
+};
 
 static int get_name_hash( const char *name )
 {
@@ -127,7 +131,8 @@
                                         unsigned int attrs, int drive_type )
 {
     struct file *file;
-    if ((file = alloc_object( &file_ops, fd )))
+
+    if ((file = alloc_fd_object( &file_ops, &file_fd_ops, fd )))
     {
         file->name       = NULL;
         file->next       = NULL;
@@ -291,22 +296,10 @@
 }
 
 
-static int file_get_fd( struct object *obj )
-{
-    struct file *file = (struct file *)obj;
-    assert( obj->ops == &file_ops );
-    return file->obj.fd;
-}
-
 static int file_flush( struct object *obj )
 {
-    int ret;
-    struct file *file = (struct file *)grab_object(obj);
-    assert( obj->ops == &file_ops );
-
-    ret = (fsync( file->obj.fd ) != -1);
+    int ret = (fsync( get_unix_fd(obj) ) != -1);
     if (!ret) file_set_error();
-    release_object( file );
     return ret;
 }
 
@@ -314,17 +307,17 @@
 {
     struct stat st;
     struct file *file = (struct file *)obj;
-    assert( obj->ops == &file_ops );
+    int unix_fd = get_unix_fd( obj );
 
     if (reply)
     {
-        if (fstat( file->obj.fd, &st ) == -1)
+        if (fstat( unix_fd, &st ) == -1)
         {
             file_set_error();
             return FD_TYPE_INVALID;
         }
         if (S_ISCHR(st.st_mode) || S_ISFIFO(st.st_mode) ||
-            S_ISSOCK(st.st_mode) || isatty(file->obj.fd)) reply->type = FILE_TYPE_CHAR;
+            S_ISSOCK(st.st_mode) || isatty(unix_fd)) reply->type = FILE_TYPE_CHAR;
         else reply->type = FILE_TYPE_DISK;
         if (S_ISDIR(st.st_mode)) reply->attr = FILE_ATTRIBUTE_DIRECTORY;
         else reply->attr = FILE_ATTRIBUTE_ARCHIVE;
@@ -394,7 +387,7 @@
             async_insert( q, async );
 
         /* Check if the new pending request can be served immediately */
-        pfd.fd = obj->fd;
+        pfd.fd = get_unix_fd( obj );
         pfd.events = file_get_poll_events ( obj );
         pfd.revents = 0;
         poll ( &pfd, 1, 0 );
@@ -469,7 +462,7 @@
     xto = *low+((off_t)*high<<32);
     if (!(file = get_file_obj( current->process, handle, 0 )))
         return 0;
-    if ((result = lseek(file->obj.fd,xto,whence))==-1)
+    if ((result = lseek( get_unix_fd(&file->obj), xto, whence))==-1)
     {
         /* Check for seek before start of file */
 
@@ -492,13 +485,14 @@
 static int extend_file( struct file *file, off_t size )
 {
     static const char zero;
+    int unix_fd = get_unix_fd( &file->obj );
 
     /* extend the file one byte beyond the requested size and then truncate it */
     /* this should work around ftruncate implementations that can't extend files */
-    if ((lseek( file->obj.fd, size, SEEK_SET ) != -1) &&
-        (write( file->obj.fd, &zero, 1 ) != -1))
+    if ((lseek( unix_fd, size, SEEK_SET ) != -1) &&
+        (write( unix_fd, &zero, 1 ) != -1))
     {
-        ftruncate( file->obj.fd, size );
+        ftruncate( unix_fd, size );
         return 1;
     }
     file_set_error();
@@ -509,16 +503,17 @@
 static int truncate_file( struct file *file )
 {
     int ret = 0;
-    off_t pos = lseek( file->obj.fd, 0, SEEK_CUR );
-    off_t eof = lseek( file->obj.fd, 0, SEEK_END );
+    int unix_fd = get_unix_fd( &file->obj );
+    off_t pos = lseek( unix_fd, 0, SEEK_CUR );
+    off_t eof = lseek( unix_fd, 0, SEEK_END );
 
     if (eof < pos) ret = extend_file( file, pos );
     else
     {
-        if (ftruncate( file->obj.fd, pos ) != -1) ret = 1;
+        if (ftruncate( unix_fd, pos ) != -1) ret = 1;
         else file_set_error();
     }
-    lseek( file->obj.fd, pos, SEEK_SET );  /* restore file pos */
+    lseek( unix_fd, pos, SEEK_SET );  /* restore file pos */
     return ret;
 }
 
@@ -527,17 +522,18 @@
 {
     int ret = 0;
     struct stat st;
+    int unix_fd = get_unix_fd( &file->obj );
     off_t old_pos, size = size_low + (((off_t)size_high)<<32);
 
-    if (fstat( file->obj.fd, &st ) == -1)
+    if (fstat( unix_fd, &st ) == -1)
     {
         file_set_error();
         return 0;
     }
     if (st.st_size >= size) return 1;  /* already large enough */
-    old_pos = lseek( file->obj.fd, 0, SEEK_CUR );  /* save old pos */
+    old_pos = lseek( unix_fd, 0, SEEK_CUR );  /* save old pos */
     ret = extend_file( file, size );
-    lseek( file->obj.fd, old_pos, SEEK_SET );  /* restore file pos */
+    lseek( unix_fd, old_pos, SEEK_SET );  /* restore file pos */
     return ret;
 }
 
@@ -633,8 +629,8 @@
         if (fd != -1) reply->fd = fd;
         else if (!get_error())
         {
-            if ((fd = obj->ops->get_fd( obj )) != -1)
-                send_client_fd( current->process, fd, req->handle );
+            int unix_fd = get_unix_fd( obj );
+            if (unix_fd != -1) send_client_fd( current->process, unix_fd, req->handle );
         }
         reply->type = obj->ops->get_file_info( obj, NULL, &reply->flags );
         release_object( obj );
@@ -663,18 +659,6 @@
     }
 }
 
-/* flush a file buffers */
-DECL_HANDLER(flush_file)
-{
-    struct object *obj;
-
-    if ((obj = get_handle_obj( current->process, req->handle, 0, NULL )))
-    {
-        obj->ops->flush( obj );
-        release_object( obj );
-    }
-}
-
 /* set a file access and modification times */
 DECL_HANDLER(set_file_time)
 {