Server reorganization:
[wine/multimedia.git] / server / file.c
blob00f1c60897b5f14b9832946c462472f037e85145
1 /*
2 * Server-side file management
4 * Copyright (C) 1998 Alexandre Julliard
5 */
7 #include <assert.h>
8 #include <fcntl.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <errno.h>
13 #include <sys/errno.h>
14 #include <sys/stat.h>
15 #include <sys/time.h>
16 #include <sys/types.h>
17 #include <time.h>
18 #include <unistd.h>
19 #include <utime.h>
21 #include "winerror.h"
22 #include "winbase.h"
24 #include "handle.h"
25 #include "thread.h"
27 struct file
29 struct object obj; /* object header */
30 struct file *next; /* next file in hashing list */
31 char *name; /* file name */
32 int fd; /* Unix file descriptor */
33 unsigned int access; /* file access (GENERIC_READ/WRITE) */
34 unsigned int flags; /* flags (FILE_FLAG_*) */
35 unsigned int sharing; /* file sharing mode */
38 #define NAME_HASH_SIZE 37
40 static struct file *file_hash[NAME_HASH_SIZE];
42 static void file_dump( struct object *obj, int verbose );
43 static int file_add_queue( struct object *obj, struct wait_queue_entry *entry );
44 static void file_remove_queue( struct object *obj, struct wait_queue_entry *entry );
45 static int file_signaled( struct object *obj, struct thread *thread );
46 static int file_get_read_fd( struct object *obj );
47 static int file_get_write_fd( struct object *obj );
48 static int file_flush( struct object *obj );
49 static int file_get_info( struct object *obj, struct get_file_info_reply *reply );
50 static void file_destroy( struct object *obj );
52 static const struct object_ops file_ops =
54 file_dump,
55 file_add_queue,
56 file_remove_queue,
57 file_signaled,
58 no_satisfied,
59 file_get_read_fd,
60 file_get_write_fd,
61 file_flush,
62 file_get_info,
63 file_destroy
66 static const struct select_ops select_ops =
68 default_select_event,
69 NULL /* we never set a timeout on a file */
73 static int get_name_hash( const char *name )
75 int hash = 0;
76 while (*name) hash ^= *name++;
77 return hash % NAME_HASH_SIZE;
80 /* check if the desired access is possible without violating */
81 /* the sharing mode of other opens of the same file */
82 static int check_sharing( const char *name, int hash, unsigned int access,
83 unsigned int sharing )
85 struct file *file;
86 unsigned int existing_sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
87 unsigned int existing_access = 0;
89 for (file = file_hash[hash]; file; file = file->next)
91 if (strcmp( file->name, name )) continue;
92 existing_sharing &= file->sharing;
93 existing_access |= file->access;
95 if ((access & GENERIC_READ) && !(existing_sharing & FILE_SHARE_READ)) return 0;
96 if ((access & GENERIC_WRITE) && !(existing_sharing & FILE_SHARE_WRITE)) return 0;
97 if ((existing_access & GENERIC_READ) && !(sharing & FILE_SHARE_READ)) return 0;
98 if ((existing_access & GENERIC_WRITE) && !(sharing & FILE_SHARE_WRITE)) return 0;
99 return 1;
102 static struct object *create_file( int fd, const char *name, unsigned int access,
103 unsigned int sharing, int create, unsigned int attrs )
105 struct file *file;
106 int hash = 0;
108 if (fd == -1)
110 int flags;
111 struct stat st;
113 if (!name)
115 SET_ERROR( ERROR_INVALID_PARAMETER );
116 return NULL;
119 /* check sharing mode */
120 hash = get_name_hash( name );
121 if (!check_sharing( name, hash, access, sharing ))
123 SET_ERROR( ERROR_SHARING_VIOLATION );
124 return NULL;
127 switch(create)
129 case CREATE_NEW: flags = O_CREAT | O_EXCL; break;
130 case CREATE_ALWAYS: flags = O_CREAT | O_TRUNC; break;
131 case OPEN_ALWAYS: flags = O_CREAT; break;
132 case TRUNCATE_EXISTING: flags = O_TRUNC; break;
133 case OPEN_EXISTING: flags = 0; break;
134 default: SET_ERROR( ERROR_INVALID_PARAMETER ); return NULL;
136 switch(access & (GENERIC_READ | GENERIC_WRITE))
138 case 0: break;
139 case GENERIC_READ: flags |= O_RDONLY; break;
140 case GENERIC_WRITE: flags |= O_WRONLY; break;
141 case GENERIC_READ|GENERIC_WRITE: flags |= O_RDWR; break;
144 /* FIXME: should set error to ERROR_ALREADY_EXISTS if file existed before */
145 if ((fd = open( name, flags | O_NONBLOCK,
146 (attrs & FILE_ATTRIBUTE_READONLY) ? 0444 : 0666 )) == -1)
148 file_set_error();
149 return NULL;
151 /* Refuse to open a directory */
152 if (fstat( fd, &st ) == -1)
154 file_set_error();
155 close( fd );
156 return NULL;
158 if (S_ISDIR(st.st_mode))
160 SET_ERROR( ERROR_ACCESS_DENIED );
161 close( fd );
162 return NULL;
165 else
167 if ((fd = dup(fd)) == -1)
169 file_set_error();
170 return NULL;
174 if (!(file = mem_alloc( sizeof(*file) )))
176 close( fd );
177 return NULL;
179 if (name)
181 if (!(file->name = mem_alloc( strlen(name) + 1 )))
183 close( fd );
184 free( file );
185 return NULL;
187 strcpy( file->name, name );
188 file->next = file_hash[hash];
189 file_hash[hash] = file;
191 else
193 file->name = NULL;
194 file->next = NULL;
196 init_object( &file->obj, &file_ops, NULL );
197 file->fd = fd;
198 file->access = access;
199 file->flags = attrs;
200 file->sharing = sharing;
201 CLEAR_ERROR();
202 return &file->obj;
205 /* Create a temp file for anonymous mappings */
206 struct file *create_temp_file( int access )
208 struct file *file;
209 char *name;
210 int fd;
214 if (!(name = tmpnam(NULL)))
216 SET_ERROR( ERROR_TOO_MANY_OPEN_FILES );
217 return NULL;
219 fd = open( name, O_CREAT | O_EXCL | O_RDWR, 0600 );
220 } while ((fd == -1) && (errno == EEXIST));
221 if (fd == -1)
223 file_set_error();
224 return NULL;
226 unlink( name );
228 if (!(file = mem_alloc( sizeof(*file) )))
230 close( fd );
231 return NULL;
233 init_object( &file->obj, &file_ops, NULL );
234 file->name = NULL;
235 file->next = NULL;
236 file->fd = fd;
237 file->access = access;
238 file->flags = 0;
239 file->sharing = 0;
240 CLEAR_ERROR();
241 return file;
244 static void file_dump( struct object *obj, int verbose )
246 struct file *file = (struct file *)obj;
247 assert( obj->ops == &file_ops );
248 printf( "File fd=%d flags=%08x name='%s'\n",
249 file->fd, file->flags, file->name );
252 static int file_add_queue( struct object *obj, struct wait_queue_entry *entry )
254 struct file *file = (struct file *)obj;
255 assert( obj->ops == &file_ops );
256 if (!obj->head) /* first on the queue */
258 if (!add_select_user( file->fd, READ_EVENT | WRITE_EVENT, &select_ops, file ))
260 SET_ERROR( ERROR_OUTOFMEMORY );
261 return 0;
264 add_queue( obj, entry );
265 return 1;
268 static void file_remove_queue( struct object *obj, struct wait_queue_entry *entry )
270 struct file *file = (struct file *)grab_object(obj);
271 assert( obj->ops == &file_ops );
273 remove_queue( obj, entry );
274 if (!obj->head) /* last on the queue is gone */
275 remove_select_user( file->fd );
276 release_object( obj );
279 static int file_signaled( struct object *obj, struct thread *thread )
281 fd_set read_fds, write_fds;
282 struct timeval tv = { 0, 0 };
284 struct file *file = (struct file *)obj;
285 assert( obj->ops == &file_ops );
287 FD_ZERO( &read_fds );
288 FD_ZERO( &write_fds );
289 if (file->access & GENERIC_READ) FD_SET( file->fd, &read_fds );
290 if (file->access & GENERIC_WRITE) FD_SET( file->fd, &write_fds );
291 return select( file->fd + 1, &read_fds, &write_fds, NULL, &tv ) > 0;
294 static int file_get_read_fd( struct object *obj )
296 struct file *file = (struct file *)obj;
297 assert( obj->ops == &file_ops );
298 return dup( file->fd );
301 static int file_get_write_fd( struct object *obj )
303 struct file *file = (struct file *)obj;
304 assert( obj->ops == &file_ops );
305 return dup( file->fd );
308 static int file_flush( struct object *obj )
310 int ret;
311 struct file *file = (struct file *)grab_object(obj);
312 assert( obj->ops == &file_ops );
314 ret = (fsync( file->fd ) != -1);
315 if (!ret) file_set_error();
316 release_object( file );
317 return ret;
320 static int file_get_info( struct object *obj, struct get_file_info_reply *reply )
322 struct stat st;
323 struct file *file = (struct file *)obj;
324 assert( obj->ops == &file_ops );
326 if (fstat( file->fd, &st ) == -1)
328 file_set_error();
329 return 0;
331 if (S_ISCHR(st.st_mode) || S_ISFIFO(st.st_mode) ||
332 S_ISSOCK(st.st_mode) || isatty(file->fd)) reply->type = FILE_TYPE_CHAR;
333 else reply->type = FILE_TYPE_DISK;
334 if (S_ISDIR(st.st_mode)) reply->attr = FILE_ATTRIBUTE_DIRECTORY;
335 else reply->attr = FILE_ATTRIBUTE_ARCHIVE;
336 if (!(st.st_mode & S_IWUSR)) reply->attr |= FILE_ATTRIBUTE_READONLY;
337 reply->access_time = st.st_atime;
338 reply->write_time = st.st_mtime;
339 reply->size_high = 0;
340 reply->size_low = S_ISDIR(st.st_mode) ? 0 : st.st_size;
341 reply->links = st.st_nlink;
342 reply->index_high = st.st_dev;
343 reply->index_low = st.st_ino;
344 reply->serial = 0; /* FIXME */
345 return 1;
348 static void file_destroy( struct object *obj )
350 struct file *file = (struct file *)obj;
351 assert( obj->ops == &file_ops );
353 if (file->name)
355 /* remove it from the hashing list */
356 struct file **pptr = &file_hash[get_name_hash( file->name )];
357 while (*pptr && *pptr != file) pptr = &(*pptr)->next;
358 assert( *pptr );
359 *pptr = (*pptr)->next;
360 if (file->flags & FILE_FLAG_DELETE_ON_CLOSE) unlink( file->name );
361 free( file->name );
363 close( file->fd );
364 free( file );
367 /* set the last error depending on errno */
368 void file_set_error(void)
370 switch (errno)
372 case EAGAIN: SET_ERROR( ERROR_SHARING_VIOLATION ); break;
373 case EBADF: SET_ERROR( ERROR_INVALID_HANDLE ); break;
374 case ENOSPC: SET_ERROR( ERROR_HANDLE_DISK_FULL ); break;
375 case EACCES:
376 case EPERM: SET_ERROR( ERROR_ACCESS_DENIED ); break;
377 case EROFS: SET_ERROR( ERROR_WRITE_PROTECT ); break;
378 case EBUSY: SET_ERROR( ERROR_LOCK_VIOLATION ); break;
379 case ENOENT: SET_ERROR( ERROR_FILE_NOT_FOUND ); break;
380 case EISDIR: SET_ERROR( ERROR_CANNOT_MAKE ); break;
381 case ENFILE:
382 case EMFILE: SET_ERROR( ERROR_NO_MORE_FILES ); break;
383 case EEXIST: SET_ERROR( ERROR_FILE_EXISTS ); break;
384 case EINVAL: SET_ERROR( ERROR_INVALID_PARAMETER ); break;
385 case ESPIPE: SET_ERROR( ERROR_SEEK ); break;
386 case ENOTEMPTY: SET_ERROR( ERROR_DIR_NOT_EMPTY ); break;
387 default: perror("file_set_error"); SET_ERROR( ERROR_UNKNOWN ); break;
391 struct file *get_file_obj( struct process *process, int handle,
392 unsigned int access )
394 return (struct file *)get_handle_obj( current->process, handle,
395 access, &file_ops );
398 int file_get_mmap_fd( struct file *file )
400 return dup( file->fd );
403 static int set_file_pointer( int handle, int *low, int *high, int whence )
405 struct file *file;
406 int result;
408 if (*high)
410 fprintf( stderr, "set_file_pointer: offset > 4Gb not supported yet\n" );
411 SET_ERROR( ERROR_INVALID_PARAMETER );
412 return 0;
415 if (!(file = get_file_obj( current->process, handle, 0 )))
416 return 0;
417 if ((result = lseek( file->fd, *low, whence )) == -1)
419 /* Check for seek before start of file */
420 if ((errno == EINVAL) && (whence != SEEK_SET) && (*low < 0))
421 SET_ERROR( ERROR_NEGATIVE_SEEK );
422 else
423 file_set_error();
424 release_object( file );
425 return 0;
427 *low = result;
428 release_object( file );
429 return 1;
432 static int truncate_file( int handle )
434 struct file *file;
435 int result;
437 if (!(file = get_file_obj( current->process, handle, GENERIC_WRITE )))
438 return 0;
439 if (((result = lseek( file->fd, 0, SEEK_CUR )) == -1) ||
440 (ftruncate( file->fd, result ) == -1))
442 file_set_error();
443 release_object( file );
444 return 0;
446 release_object( file );
447 return 1;
451 /* try to grow the file to the specified size */
452 int grow_file( struct file *file, int size_high, int size_low )
454 struct stat st;
456 if (size_high)
458 SET_ERROR( ERROR_INVALID_PARAMETER );
459 return 0;
461 if (fstat( file->fd, &st ) == -1)
463 file_set_error();
464 return 0;
466 if (st.st_size >= size_low) return 1; /* already large enough */
467 if (ftruncate( file->fd, size_low ) != -1) return 1;
468 file_set_error();
469 return 0;
472 static int set_file_time( int handle, time_t access_time, time_t write_time )
474 struct file *file;
475 struct utimbuf utimbuf;
477 if (!(file = get_file_obj( current->process, handle, GENERIC_WRITE )))
478 return 0;
479 if (!access_time || !write_time)
481 struct stat st;
482 if (stat( file->name, &st ) == -1) goto error;
483 if (!access_time) access_time = st.st_atime;
484 if (!write_time) write_time = st.st_mtime;
486 utimbuf.actime = access_time;
487 utimbuf.modtime = write_time;
488 if (utime( file->name, &utimbuf ) == -1) goto error;
489 release_object( file );
490 return 1;
491 error:
492 file_set_error();
493 release_object( file );
494 return 0;
497 static int file_lock( struct file *file, int offset_high, int offset_low,
498 int count_high, int count_low )
500 /* FIXME: implement this */
501 return 1;
504 static int file_unlock( struct file *file, int offset_high, int offset_low,
505 int count_high, int count_low )
507 /* FIXME: implement this */
508 return 1;
510 /* create a file */
511 DECL_HANDLER(create_file)
513 struct create_file_reply reply = { -1 };
514 struct object *obj;
515 char *name = (char *)data;
516 if (!len) name = NULL;
517 else CHECK_STRING( "create_file", name, len );
519 if ((obj = create_file( fd, name, req->access,
520 req->sharing, req->create, req->attrs )) != NULL)
522 reply.handle = alloc_handle( current->process, obj, req->access, req->inherit );
523 release_object( obj );
525 send_reply( current, -1, 1, &reply, sizeof(reply) );
528 /* get a Unix fd to read from a file */
529 DECL_HANDLER(get_read_fd)
531 struct object *obj;
532 int read_fd;
534 if ((obj = get_handle_obj( current->process, req->handle, GENERIC_READ, NULL )))
536 read_fd = obj->ops->get_read_fd( obj );
537 release_object( obj );
539 else read_fd = -1;
540 send_reply( current, read_fd, 0 );
543 /* get a Unix fd to write to a file */
544 DECL_HANDLER(get_write_fd)
546 struct object *obj;
547 int write_fd;
549 if ((obj = get_handle_obj( current->process, req->handle, GENERIC_WRITE, NULL )))
551 write_fd = obj->ops->get_write_fd( obj );
552 release_object( obj );
554 else write_fd = -1;
555 send_reply( current, write_fd, 0 );
558 /* set a file current position */
559 DECL_HANDLER(set_file_pointer)
561 struct set_file_pointer_reply reply;
562 reply.low = req->low;
563 reply.high = req->high;
564 set_file_pointer( req->handle, &reply.low, &reply.high, req->whence );
565 send_reply( current, -1, 1, &reply, sizeof(reply) );
568 /* truncate (or extend) a file */
569 DECL_HANDLER(truncate_file)
571 truncate_file( req->handle );
572 send_reply( current, -1, 0 );
575 /* flush a file buffers */
576 DECL_HANDLER(flush_file)
578 struct object *obj;
580 if ((obj = get_handle_obj( current->process, req->handle, GENERIC_WRITE, NULL )))
582 obj->ops->flush( obj );
583 release_object( obj );
585 send_reply( current, -1, 0 );
588 /* set a file access and modification times */
589 DECL_HANDLER(set_file_time)
591 set_file_time( req->handle, req->access_time, req->write_time );
592 send_reply( current, -1, 0 );
595 /* get a file information */
596 DECL_HANDLER(get_file_info)
598 struct object *obj;
599 struct get_file_info_reply reply;
601 if ((obj = get_handle_obj( current->process, req->handle, 0, NULL )))
603 obj->ops->get_file_info( obj, &reply );
604 release_object( obj );
606 send_reply( current, -1, 1, &reply, sizeof(reply) );
609 /* lock a region of a file */
610 DECL_HANDLER(lock_file)
612 struct file *file;
614 if ((file = get_file_obj( current->process, req->handle, 0 )))
616 file_lock( file, req->offset_high, req->offset_low,
617 req->count_high, req->count_low );
618 release_object( file );
620 send_reply( current, -1, 0 );
623 /* unlock a region of a file */
624 DECL_HANDLER(unlock_file)
626 struct file *file;
628 if ((file = get_file_obj( current->process, req->handle, 0 )))
630 file_unlock( file, req->offset_high, req->offset_low,
631 req->count_high, req->count_low );
632 release_object( file );
634 send_reply( current, -1, 0 );