2 * Server-side file management
4 * Copyright (C) 1998 Alexandre Julliard
12 #include <sys/errno.h>
15 #include <sys/types.h>
21 #include "server/thread.h"
25 struct object obj
; /* object header */
26 int fd
; /* Unix file descriptor */
27 int event
; /* possible events on this file */
30 static void file_dump( struct object
*obj
, int verbose
);
31 static int file_add_queue( struct object
*obj
, struct wait_queue_entry
*entry
);
32 static void file_remove_queue( struct object
*obj
, struct wait_queue_entry
*entry
);
33 static int file_signaled( struct object
*obj
, struct thread
*thread
);
34 static int file_get_read_fd( struct object
*obj
);
35 static int file_get_write_fd( struct object
*obj
);
36 static int file_flush( struct object
*obj
);
37 static void file_destroy( struct object
*obj
);
39 static const struct object_ops file_ops
=
52 static const struct select_ops select_ops
=
55 NULL
/* we never set a timeout on a file */
58 struct object
*create_file( int fd
)
63 if ((flags
= fcntl( fd
, F_GETFL
)) == -1)
68 if (!(file
= mem_alloc( sizeof(*file
) ))) return NULL
;
69 init_object( &file
->obj
, &file_ops
, NULL
);
74 file
->event
= READ_EVENT
;
77 file
->event
= WRITE_EVENT
;
80 file
->event
= READ_EVENT
| WRITE_EVENT
;
87 static void file_dump( struct object
*obj
, int verbose
)
89 struct file
*file
= (struct file
*)obj
;
90 assert( obj
->ops
== &file_ops
);
91 printf( "File fd=%d\n", file
->fd
);
94 static int file_add_queue( struct object
*obj
, struct wait_queue_entry
*entry
)
96 struct file
*file
= (struct file
*)obj
;
97 assert( obj
->ops
== &file_ops
);
98 if (!obj
->head
) /* first on the queue */
100 if (!add_select_user( file
->fd
, READ_EVENT
| WRITE_EVENT
, &select_ops
, file
))
102 SET_ERROR( ERROR_OUTOFMEMORY
);
106 add_queue( obj
, entry
);
110 static void file_remove_queue( struct object
*obj
, struct wait_queue_entry
*entry
)
112 struct file
*file
= (struct file
*)grab_object(obj
);
113 assert( obj
->ops
== &file_ops
);
115 remove_queue( obj
, entry
);
116 if (!obj
->head
) /* last on the queue is gone */
117 remove_select_user( file
->fd
);
118 release_object( obj
);
121 static int file_signaled( struct object
*obj
, struct thread
*thread
)
123 fd_set read_fds
, write_fds
;
124 struct timeval tv
= { 0, 0 };
126 struct file
*file
= (struct file
*)obj
;
127 assert( obj
->ops
== &file_ops
);
129 FD_ZERO( &read_fds
);
130 FD_ZERO( &write_fds
);
131 if (file
->event
& READ_EVENT
) FD_SET( file
->fd
, &read_fds
);
132 if (file
->event
& WRITE_EVENT
) FD_SET( file
->fd
, &write_fds
);
133 return select( file
->fd
+ 1, &read_fds
, &write_fds
, NULL
, &tv
) > 0;
136 static int file_get_read_fd( struct object
*obj
)
138 struct file
*file
= (struct file
*)obj
;
139 assert( obj
->ops
== &file_ops
);
141 if (!(file
->event
& READ_EVENT
)) /* FIXME: should not be necessary */
143 SET_ERROR( ERROR_ACCESS_DENIED
);
146 return dup( file
->fd
);
149 static int file_get_write_fd( struct object
*obj
)
151 struct file
*file
= (struct file
*)obj
;
152 assert( obj
->ops
== &file_ops
);
154 if (!(file
->event
& WRITE_EVENT
)) /* FIXME: should not be necessary */
156 SET_ERROR( ERROR_ACCESS_DENIED
);
159 return dup( file
->fd
);
162 static int file_flush( struct object
*obj
)
165 struct file
*file
= (struct file
*)grab_object(obj
);
166 assert( obj
->ops
== &file_ops
);
168 ret
= (fsync( file
->fd
) != -1);
169 if (!ret
) file_set_error();
170 release_object( file
);
174 static void file_destroy( struct object
*obj
)
176 struct file
*file
= (struct file
*)obj
;
177 assert( obj
->ops
== &file_ops
);
182 /* set the last error depending on errno */
183 void file_set_error(void)
187 case EAGAIN
: SET_ERROR( ERROR_SHARING_VIOLATION
); break;
188 case EBADF
: SET_ERROR( ERROR_INVALID_HANDLE
); break;
189 case ENOSPC
: SET_ERROR( ERROR_HANDLE_DISK_FULL
); break;
191 case EPERM
: SET_ERROR( ERROR_ACCESS_DENIED
); break;
192 case EROFS
: SET_ERROR( ERROR_WRITE_PROTECT
); break;
193 case EBUSY
: SET_ERROR( ERROR_LOCK_VIOLATION
); break;
194 case ENOENT
: SET_ERROR( ERROR_FILE_NOT_FOUND
); break;
195 case EISDIR
: SET_ERROR( ERROR_CANNOT_MAKE
); break;
197 case EMFILE
: SET_ERROR( ERROR_NO_MORE_FILES
); break;
198 case EEXIST
: SET_ERROR( ERROR_FILE_EXISTS
); break;
199 case EINVAL
: SET_ERROR( ERROR_INVALID_PARAMETER
); break;
200 case ESPIPE
: SET_ERROR( ERROR_SEEK
); break;
201 case ENOTEMPTY
: SET_ERROR( ERROR_DIR_NOT_EMPTY
); break;
202 default: perror("file_set_error"); SET_ERROR( ERROR_UNKNOWN
); break;
206 struct file
*get_file_obj( struct process
*process
, int handle
,
207 unsigned int access
)
209 return (struct file
*)get_handle_obj( current
->process
, handle
,
213 int file_get_mmap_fd( struct file
*file
)
215 return dup( file
->fd
);
218 int set_file_pointer( int handle
, int *low
, int *high
, int whence
)
225 fprintf( stderr
, "set_file_pointer: offset > 4Gb not supported yet\n" );
226 SET_ERROR( ERROR_INVALID_PARAMETER
);
230 if (!(file
= get_file_obj( current
->process
, handle
, 0 )))
232 if ((result
= lseek( file
->fd
, *low
, whence
)) == -1)
234 /* Check for seek before start of file */
235 if ((errno
== EINVAL
) && (whence
!= SEEK_SET
) && (*low
< 0))
236 SET_ERROR( ERROR_NEGATIVE_SEEK
);
239 release_object( file
);
243 release_object( file
);
247 int truncate_file( int handle
)
252 if (!(file
= get_file_obj( current
->process
, handle
, GENERIC_WRITE
)))
254 if (((result
= lseek( file
->fd
, 0, SEEK_CUR
)) == -1) ||
255 (ftruncate( file
->fd
, result
) == -1))
258 release_object( file
);
261 release_object( file
);
266 int get_file_info( int handle
, struct get_file_info_reply
*reply
)
271 if (!(file
= get_file_obj( current
->process
, handle
, 0 )))
273 if (fstat( file
->fd
, &st
) == -1)
276 release_object( file
);
279 if (S_ISDIR(st
.st_mode
)) reply
->attr
= FILE_ATTRIBUTE_DIRECTORY
;
280 else reply
->attr
= FILE_ATTRIBUTE_ARCHIVE
;
281 if (!(st
.st_mode
& S_IWUSR
)) reply
->attr
|= FILE_ATTRIBUTE_READONLY
;
282 reply
->access_time
= st
.st_atime
;
283 reply
->write_time
= st
.st_mtime
;
284 reply
->size_high
= 0;
285 reply
->size_low
= S_ISDIR(st
.st_mode
) ? 0 : st
.st_size
;
286 reply
->links
= st
.st_nlink
;
287 reply
->index_high
= st
.st_dev
;
288 reply
->index_low
= st
.st_ino
;
289 reply
->serial
= 0; /* FIXME */
291 release_object( file
);