2 * Server-side file management
4 * Copyright (C) 1998 Alexandre Julliard
11 #include <sys/errno.h>
14 #include <sys/types.h>
20 #include "server/thread.h"
24 struct object obj
; /* object header */
25 int fd
; /* Unix file descriptor */
26 int event
; /* possible events on this file */
29 static void file_dump( struct object
*obj
, int verbose
);
30 static void file_add_queue( struct object
*obj
, struct wait_queue_entry
*entry
);
31 static void file_remove_queue( struct object
*obj
, struct wait_queue_entry
*entry
);
32 static int file_signaled( struct object
*obj
, struct thread
*thread
);
33 static int file_satisfied( struct object
*obj
, struct thread
*thread
);
34 static void file_destroy( struct object
*obj
);
36 static const struct object_ops file_ops
=
46 static void file_event( int fd
, int event
, void *private );
47 static void file_timeout( int fd
, void *private );
49 static const struct select_ops select_ops
=
55 struct object
*create_file( int fd
)
60 if ((flags
= fcntl( fd
, F_GETFL
)) == -1)
65 if (!(file
= mem_alloc( sizeof(*file
) ))) return NULL
;
66 init_object( &file
->obj
, &file_ops
, NULL
);
71 file
->event
= READ_EVENT
;
74 file
->event
= WRITE_EVENT
;
77 file
->event
= READ_EVENT
| WRITE_EVENT
;
84 static void file_dump( struct object
*obj
, int verbose
)
86 struct file
*file
= (struct file
*)obj
;
87 assert( obj
->ops
== &file_ops
);
88 printf( "File fd=%d\n", file
->fd
);
91 static void file_add_queue( struct object
*obj
, struct wait_queue_entry
*entry
)
93 struct file
*file
= (struct file
*)obj
;
94 assert( obj
->ops
== &file_ops
);
95 if (!obj
->head
) /* first on the queue */
96 add_select_user( file
->fd
, READ_EVENT
| WRITE_EVENT
, &select_ops
, file
);
97 add_queue( obj
, entry
);
100 static void file_remove_queue( struct object
*obj
, struct wait_queue_entry
*entry
)
102 struct file
*file
= (struct file
*)grab_object(obj
);
103 assert( obj
->ops
== &file_ops
);
105 remove_queue( obj
, entry
);
106 if (!obj
->head
) /* last on the queue is gone */
107 remove_select_user( file
->fd
);
108 release_object( obj
);
111 static int file_signaled( struct object
*obj
, struct thread
*thread
)
113 fd_set read_fds
, write_fds
;
114 struct timeval tv
= { 0, 0 };
116 struct file
*file
= (struct file
*)obj
;
117 assert( obj
->ops
== &file_ops
);
119 FD_ZERO( &read_fds
);
120 FD_ZERO( &write_fds
);
121 if (file
->event
& READ_EVENT
) FD_SET( file
->fd
, &read_fds
);
122 if (file
->event
& WRITE_EVENT
) FD_SET( file
->fd
, &write_fds
);
123 return select( file
->fd
+ 1, &read_fds
, &write_fds
, NULL
, &tv
) > 0;
126 static int file_satisfied( struct object
*obj
, struct thread
*thread
)
129 return 0; /* Not abandoned */
132 static void file_destroy( struct object
*obj
)
134 struct file
*file
= (struct file
*)obj
;
135 assert( obj
->ops
== &file_ops
);
140 static void file_event( int fd
, int event
, void *private )
142 struct file
*file
= (struct file
*)private;
145 wake_up( &file
->obj
, 0 );
148 static void file_timeout( int fd
, void *private )
150 /* we never set a timeout on a file */
154 int file_get_unix_handle( int handle
, unsigned int access
)
159 if (!(file
= (struct file
*)get_handle_obj( current
->process
, handle
,
160 access
, &file_ops
)))
162 unix_handle
= dup( file
->fd
);
163 release_object( file
);
167 int get_file_info( int handle
, struct get_file_info_reply
*reply
)
172 if (!(file
= (struct file
*)get_handle_obj( current
->process
, handle
,
175 if (fstat( file
->fd
, &st
) == -1)
177 /* file_set_error(); */
178 release_object( file
);
181 if (S_ISDIR(st
.st_mode
)) reply
->attr
= FILE_ATTRIBUTE_DIRECTORY
;
182 else reply
->attr
= FILE_ATTRIBUTE_ARCHIVE
;
183 if (!(st
.st_mode
& S_IWUSR
)) reply
->attr
|= FILE_ATTRIBUTE_READONLY
;
184 reply
->access_time
= st
.st_atime
;
185 reply
->write_time
= st
.st_mtime
;
186 reply
->size_high
= 0;
187 reply
->size_low
= S_ISDIR(st
.st_mode
) ? 0 : st
.st_size
;
188 reply
->links
= st
.st_nlink
;
189 reply
->index_high
= st
.st_dev
;
190 reply
->index_low
= st
.st_ino
;
191 reply
->serial
= 0; /* FIXME */
193 release_object( file
);