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_get_read_fd( struct object
*obj
);
34 static int file_get_write_fd( struct object
*obj
);
35 static int file_flush( struct object
*obj
);
36 static void file_destroy( struct object
*obj
);
38 static const struct object_ops file_ops
=
51 static const struct select_ops select_ops
=
54 NULL
/* we never set a timeout on a file */
57 struct object
*create_file( int fd
)
62 if ((flags
= fcntl( fd
, F_GETFL
)) == -1)
67 if (!(file
= mem_alloc( sizeof(*file
) ))) return NULL
;
68 init_object( &file
->obj
, &file_ops
, NULL
);
73 file
->event
= READ_EVENT
;
76 file
->event
= WRITE_EVENT
;
79 file
->event
= READ_EVENT
| WRITE_EVENT
;
86 static void file_dump( struct object
*obj
, int verbose
)
88 struct file
*file
= (struct file
*)obj
;
89 assert( obj
->ops
== &file_ops
);
90 printf( "File fd=%d\n", file
->fd
);
93 static void file_add_queue( struct object
*obj
, struct wait_queue_entry
*entry
)
95 struct file
*file
= (struct file
*)obj
;
96 assert( obj
->ops
== &file_ops
);
97 if (!obj
->head
) /* first on the queue */
98 add_select_user( file
->fd
, READ_EVENT
| WRITE_EVENT
, &select_ops
, file
);
99 add_queue( obj
, entry
);
102 static void file_remove_queue( struct object
*obj
, struct wait_queue_entry
*entry
)
104 struct file
*file
= (struct file
*)grab_object(obj
);
105 assert( obj
->ops
== &file_ops
);
107 remove_queue( obj
, entry
);
108 if (!obj
->head
) /* last on the queue is gone */
109 remove_select_user( file
->fd
);
110 release_object( obj
);
113 static int file_signaled( struct object
*obj
, struct thread
*thread
)
115 fd_set read_fds
, write_fds
;
116 struct timeval tv
= { 0, 0 };
118 struct file
*file
= (struct file
*)obj
;
119 assert( obj
->ops
== &file_ops
);
121 FD_ZERO( &read_fds
);
122 FD_ZERO( &write_fds
);
123 if (file
->event
& READ_EVENT
) FD_SET( file
->fd
, &read_fds
);
124 if (file
->event
& WRITE_EVENT
) FD_SET( file
->fd
, &write_fds
);
125 return select( file
->fd
+ 1, &read_fds
, &write_fds
, NULL
, &tv
) > 0;
128 static int file_get_read_fd( struct object
*obj
)
130 struct file
*file
= (struct file
*)obj
;
131 assert( obj
->ops
== &file_ops
);
133 if (!(file
->event
& READ_EVENT
)) /* FIXME: should not be necessary */
135 SET_ERROR( ERROR_ACCESS_DENIED
);
138 return dup( file
->fd
);
141 static int file_get_write_fd( struct object
*obj
)
143 struct file
*file
= (struct file
*)obj
;
144 assert( obj
->ops
== &file_ops
);
146 if (!(file
->event
& WRITE_EVENT
)) /* FIXME: should not be necessary */
148 SET_ERROR( ERROR_ACCESS_DENIED
);
151 return dup( file
->fd
);
154 static int file_flush( struct object
*obj
)
157 struct file
*file
= (struct file
*)grab_object(obj
);
158 assert( obj
->ops
== &file_ops
);
160 ret
= (fsync( file
->fd
) != -1);
161 if (!ret
) file_set_error();
162 release_object( file
);
166 static void file_destroy( struct object
*obj
)
168 struct file
*file
= (struct file
*)obj
;
169 assert( obj
->ops
== &file_ops
);
174 /* set the last error depending on errno */
175 void file_set_error(void)
179 case EAGAIN
: SET_ERROR( ERROR_SHARING_VIOLATION
); break;
180 case EBADF
: SET_ERROR( ERROR_INVALID_HANDLE
); break;
181 case ENOSPC
: SET_ERROR( ERROR_HANDLE_DISK_FULL
); break;
183 case EPERM
: SET_ERROR( ERROR_ACCESS_DENIED
); break;
184 case EROFS
: SET_ERROR( ERROR_WRITE_PROTECT
); break;
185 case EBUSY
: SET_ERROR( ERROR_LOCK_VIOLATION
); break;
186 case ENOENT
: SET_ERROR( ERROR_FILE_NOT_FOUND
); break;
187 case EISDIR
: SET_ERROR( ERROR_CANNOT_MAKE
); break;
189 case EMFILE
: SET_ERROR( ERROR_NO_MORE_FILES
); break;
190 case EEXIST
: SET_ERROR( ERROR_FILE_EXISTS
); break;
191 case EINVAL
: SET_ERROR( ERROR_INVALID_PARAMETER
); break;
192 case ESPIPE
: SET_ERROR( ERROR_SEEK
); break;
193 case ENOTEMPTY
: SET_ERROR( ERROR_DIR_NOT_EMPTY
); break;
194 default: perror("file_set_error"); SET_ERROR( ERROR_UNKNOWN
); break;
198 int file_get_unix_handle( int handle
, unsigned int access
)
203 if (!(file
= (struct file
*)get_handle_obj( current
->process
, handle
,
204 access
, &file_ops
)))
206 unix_handle
= dup( file
->fd
);
207 release_object( file
);
211 int set_file_pointer( int handle
, int *low
, int *high
, int whence
)
218 fprintf( stderr
, "set_file_pointer: offset > 4Gb not supported yet\n" );
219 SET_ERROR( ERROR_INVALID_PARAMETER
);
223 if (!(file
= (struct file
*)get_handle_obj( current
->process
, handle
,
226 if ((result
= lseek( file
->fd
, *low
, whence
)) == -1)
228 /* Check for seek before start of file */
229 if ((errno
== EINVAL
) && (whence
!= SEEK_SET
) && (*low
< 0))
230 SET_ERROR( ERROR_NEGATIVE_SEEK
);
233 release_object( file
);
237 release_object( file
);
241 int truncate_file( int handle
)
246 if (!(file
= (struct file
*)get_handle_obj( current
->process
, handle
,
247 GENERIC_WRITE
, &file_ops
)))
249 if (((result
= lseek( file
->fd
, 0, SEEK_CUR
)) == -1) ||
250 (ftruncate( file
->fd
, result
) == -1))
253 release_object( file
);
256 release_object( file
);
261 int get_file_info( int handle
, struct get_file_info_reply
*reply
)
266 if (!(file
= (struct file
*)get_handle_obj( current
->process
, handle
,
269 if (fstat( file
->fd
, &st
) == -1)
272 release_object( file
);
275 if (S_ISDIR(st
.st_mode
)) reply
->attr
= FILE_ATTRIBUTE_DIRECTORY
;
276 else reply
->attr
= FILE_ATTRIBUTE_ARCHIVE
;
277 if (!(st
.st_mode
& S_IWUSR
)) reply
->attr
|= FILE_ATTRIBUTE_READONLY
;
278 reply
->access_time
= st
.st_atime
;
279 reply
->write_time
= st
.st_mtime
;
280 reply
->size_high
= 0;
281 reply
->size_low
= S_ISDIR(st
.st_mode
) ? 0 : st
.st_size
;
282 reply
->links
= st
.st_nlink
;
283 reply
->index_high
= st
.st_dev
;
284 reply
->index_low
= st
.st_ino
;
285 reply
->serial
= 0; /* FIXME */
287 release_object( file
);