Added support for a WINELOADER environment variable which allows the
[wine] / server / file.c
1 /*
2  * Server-side file management
3  *
4  * Copyright (C) 1998 Alexandre Julliard
5  */
6
7 #include "config.h"
8
9 #include <assert.h>
10 #include <fcntl.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <errno.h>
15 #ifdef HAVE_SYS_ERRNO_H
16 #include <sys/errno.h>
17 #endif
18 #include <sys/stat.h>
19 #include <sys/time.h>
20 #include <sys/types.h>
21 #include <time.h>
22 #include <unistd.h>
23 #include <utime.h>
24
25 #include "winerror.h"
26 #include "winbase.h"
27
28 #include "handle.h"
29 #include "thread.h"
30 #include "request.h"
31
32 struct file
33 {
34     struct object       obj;        /* object header */
35     struct file        *next;       /* next file in hashing list */
36     char               *name;       /* file name */
37     unsigned int        access;     /* file access (GENERIC_READ/WRITE) */
38     unsigned int        flags;      /* flags (FILE_FLAG_*) */
39     unsigned int        sharing;    /* file sharing mode */
40 };
41
42 #define NAME_HASH_SIZE 37
43
44 static struct file *file_hash[NAME_HASH_SIZE];
45
46 static void file_dump( struct object *obj, int verbose );
47 static int file_get_poll_events( struct object *obj );
48 static int file_get_read_fd( struct object *obj );
49 static int file_get_write_fd( struct object *obj );
50 static int file_flush( struct object *obj );
51 static int file_get_info( struct object *obj, struct get_file_info_request *req );
52 static void file_destroy( struct object *obj );
53
54 static const struct object_ops file_ops =
55 {
56     sizeof(struct file),          /* size */
57     file_dump,                    /* dump */
58     default_poll_add_queue,       /* add_queue */
59     default_poll_remove_queue,    /* remove_queue */
60     default_poll_signaled,        /* signaled */
61     no_satisfied,                 /* satisfied */
62     file_get_poll_events,         /* get_poll_events */
63     default_poll_event,           /* poll_event */
64     file_get_read_fd,             /* get_read_fd */
65     file_get_write_fd,            /* get_write_fd */
66     file_flush,                   /* flush */
67     file_get_info,                /* get_file_info */
68     file_destroy                  /* destroy */
69 };
70
71
72 static int get_name_hash( const char *name )
73 {
74     int hash = 0;
75     while (*name) hash ^= (unsigned char)*name++;
76     return hash % NAME_HASH_SIZE;
77 }
78
79 /* check if the desired access is possible without violating */
80 /* the sharing mode of other opens of the same file */
81 static int check_sharing( const char *name, int hash, unsigned int access,
82                           unsigned int sharing )
83 {
84     struct file *file;
85     unsigned int existing_sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
86     unsigned int existing_access = 0;
87
88     for (file = file_hash[hash]; file; file = file->next)
89     {
90         if (strcmp( file->name, name )) continue;
91         existing_sharing &= file->sharing;
92         existing_access |= file->access;
93     }
94     if ((access & GENERIC_READ) && !(existing_sharing & FILE_SHARE_READ)) goto error;
95     if ((access & GENERIC_WRITE) && !(existing_sharing & FILE_SHARE_WRITE)) goto error;
96     if ((existing_access & GENERIC_READ) && !(sharing & FILE_SHARE_READ)) goto error;
97     if ((existing_access & GENERIC_WRITE) && !(sharing & FILE_SHARE_WRITE)) goto error;
98     return 1;
99  error:
100     set_error( STATUS_SHARING_VIOLATION );
101     return 0;
102 }
103
104 /* create a file from a file descriptor */
105 /* if the function fails the fd is closed */
106 static struct file *create_file_for_fd( int fd, unsigned int access, unsigned int sharing,
107                                         unsigned int attrs )
108 {
109     struct file *file;
110     if ((file = alloc_object( &file_ops, fd )))
111     {
112         file->name    = NULL;
113         file->next    = NULL;
114         file->access  = access;
115         file->flags   = attrs;
116         file->sharing = sharing;
117     }
118     return file;
119 }
120
121
122 static struct file *create_file( const char *nameptr, size_t len, unsigned int access,
123                                  unsigned int sharing, int create, unsigned int attrs )
124 {
125     struct file *file;
126     int hash, flags;
127     struct stat st;
128     char *name;
129     int fd = -1;
130
131     if (!(name = mem_alloc( len + 1 ))) return NULL;
132     memcpy( name, nameptr, len );
133     name[len] = 0;
134
135     /* check sharing mode */
136     hash = get_name_hash( name );
137     if (!check_sharing( name, hash, access, sharing )) goto error;
138
139     switch(create)
140     {
141     case CREATE_NEW:        flags = O_CREAT | O_EXCL; break;
142     case CREATE_ALWAYS:     flags = O_CREAT | O_TRUNC; break;
143     case OPEN_ALWAYS:       flags = O_CREAT; break;
144     case TRUNCATE_EXISTING: flags = O_TRUNC; break;
145     case OPEN_EXISTING:     flags = 0; break;
146     default:                set_error( STATUS_INVALID_PARAMETER ); goto error;
147     }
148     switch(access & (GENERIC_READ | GENERIC_WRITE))
149     {
150     case 0: break;
151     case GENERIC_READ:  flags |= O_RDONLY; break;
152     case GENERIC_WRITE: flags |= O_WRONLY; break;
153     case GENERIC_READ|GENERIC_WRITE: flags |= O_RDWR; break;
154     }
155
156     /* FIXME: should set error to STATUS_OBJECT_NAME_COLLISION if file existed before */
157     if ((fd = open( name, flags | O_NONBLOCK,
158                     (attrs & FILE_ATTRIBUTE_READONLY) ? 0444 : 0666 )) == -1)
159         goto file_error;
160     /* refuse to open a directory */
161     if (fstat( fd, &st ) == -1) goto file_error;
162     if (S_ISDIR(st.st_mode))
163     {
164         set_error( STATUS_ACCESS_DENIED );
165         goto error;
166     }            
167
168     if (!(file = create_file_for_fd( fd, access, sharing, attrs )))
169     {
170         free( name );
171         return NULL;
172     }
173     file->name = name;
174     file->next = file_hash[hash];
175     file_hash[hash] = file;
176     return file;
177
178  file_error:
179     file_set_error();
180  error:
181     if (fd != -1) close( fd );
182     free( name );
183     return NULL;
184 }
185
186 /* Create an anonymous Unix file */
187 int create_anonymous_file(void)
188 {
189     char *name;
190     int fd;
191
192     do
193     {
194         if (!(name = tmpnam(NULL)))
195         {
196             set_error( STATUS_TOO_MANY_OPENED_FILES );
197             return -1;
198         }
199         fd = open( name, O_CREAT | O_EXCL | O_RDWR, 0600 );
200     } while ((fd == -1) && (errno == EEXIST));
201     if (fd == -1)
202     {
203         file_set_error();
204         return -1;
205     }
206     unlink( name );
207     return fd;
208 }
209
210 /* Create a temp file for anonymous mappings */
211 struct file *create_temp_file( int access )
212 {
213     int fd;
214
215     if ((fd = create_anonymous_file()) == -1) return NULL;
216     return create_file_for_fd( fd, access, 0, 0 );
217 }
218
219 static void file_dump( struct object *obj, int verbose )
220 {
221     struct file *file = (struct file *)obj;
222     assert( obj->ops == &file_ops );
223     fprintf( stderr, "File fd=%d flags=%08x name='%s'\n", file->obj.fd, file->flags, file->name );
224 }
225
226 static int file_get_poll_events( struct object *obj )
227 {
228     struct file *file = (struct file *)obj;
229     int events = 0;
230     assert( obj->ops == &file_ops );
231     if (file->access & GENERIC_READ) events |= POLLIN;
232     if (file->access & GENERIC_WRITE) events |= POLLOUT;
233     return events;
234 }
235
236 static int file_get_read_fd( struct object *obj )
237 {
238     struct file *file = (struct file *)obj;
239     assert( obj->ops == &file_ops );
240     return dup( file->obj.fd );
241 }
242
243 static int file_get_write_fd( struct object *obj )
244 {
245     struct file *file = (struct file *)obj;
246     assert( obj->ops == &file_ops );
247     return dup( file->obj.fd );
248 }
249
250 static int file_flush( struct object *obj )
251 {
252     int ret;
253     struct file *file = (struct file *)grab_object(obj);
254     assert( obj->ops == &file_ops );
255
256     ret = (fsync( file->obj.fd ) != -1);
257     if (!ret) file_set_error();
258     release_object( file );
259     return ret;
260 }
261
262 static int file_get_info( struct object *obj, struct get_file_info_request *req )
263 {
264     struct stat st;
265     struct file *file = (struct file *)obj;
266     assert( obj->ops == &file_ops );
267
268     if (fstat( file->obj.fd, &st ) == -1)
269     {
270         file_set_error();
271         return 0;
272     }
273     if (S_ISCHR(st.st_mode) || S_ISFIFO(st.st_mode) ||
274         S_ISSOCK(st.st_mode) || isatty(file->obj.fd)) req->type = FILE_TYPE_CHAR;
275     else req->type = FILE_TYPE_DISK;
276     if (S_ISDIR(st.st_mode)) req->attr = FILE_ATTRIBUTE_DIRECTORY;
277     else req->attr = FILE_ATTRIBUTE_ARCHIVE;
278     if (!(st.st_mode & S_IWUSR)) req->attr |= FILE_ATTRIBUTE_READONLY;
279     req->access_time = st.st_atime;
280     req->write_time  = st.st_mtime;
281     req->size_high   = 0;
282     req->size_low    = S_ISDIR(st.st_mode) ? 0 : st.st_size;
283     req->links       = st.st_nlink;
284     req->index_high  = st.st_dev;
285     req->index_low   = st.st_ino;
286     req->serial      = 0; /* FIXME */
287     return 1;
288 }
289
290 static void file_destroy( struct object *obj )
291 {
292     struct file *file = (struct file *)obj;
293     assert( obj->ops == &file_ops );
294
295     if (file->name)
296     {
297         /* remove it from the hashing list */
298         struct file **pptr = &file_hash[get_name_hash( file->name )];
299         while (*pptr && *pptr != file) pptr = &(*pptr)->next;
300         assert( *pptr );
301         *pptr = (*pptr)->next;
302         if (file->flags & FILE_FLAG_DELETE_ON_CLOSE) unlink( file->name );
303         free( file->name );
304     }
305 }
306
307 /* set the last error depending on errno */
308 void file_set_error(void)
309 {
310     switch (errno)
311     {
312     case EAGAIN:    set_error( STATUS_SHARING_VIOLATION ); break;
313     case EBADF:     set_error( STATUS_INVALID_HANDLE ); break;
314     case ENOSPC:    set_error( STATUS_DISK_FULL ); break;
315     case EACCES:
316     case EPERM:     set_error( STATUS_ACCESS_DENIED ); break;
317     case EROFS:     set_error( STATUS_MEDIA_WRITE_PROTECTED ); break;
318     case EBUSY:     set_error( STATUS_FILE_LOCK_CONFLICT ); break;
319     case ENOENT:    set_error( STATUS_NO_SUCH_FILE ); break;
320     case EISDIR:    set_error( 0xc0010000 | ERROR_CANNOT_MAKE /* FIXME */ ); break;
321     case ENFILE:
322     case EMFILE:    set_error( STATUS_NO_MORE_FILES ); break;
323     case EEXIST:    set_error( STATUS_OBJECT_NAME_COLLISION ); break;
324     case EINVAL:    set_error( STATUS_INVALID_PARAMETER ); break;
325     case ESPIPE:    set_error( 0xc0010000 | ERROR_SEEK /* FIXME */ ); break;
326     case ENOTEMPTY: set_error( STATUS_DIRECTORY_NOT_EMPTY ); break;
327     case EIO:       set_error( STATUS_ACCESS_VIOLATION ); break;
328     default:        perror("file_set_error"); set_error( ERROR_UNKNOWN /* FIXME */ ); break;
329     }
330 }
331
332 struct file *get_file_obj( struct process *process, int handle, unsigned int access )
333 {
334     return (struct file *)get_handle_obj( process, handle, access, &file_ops );
335 }
336
337 int file_get_mmap_fd( struct file *file )
338 {
339     return dup( file->obj.fd );
340 }
341
342 static int set_file_pointer( int handle, int *low, int *high, int whence )
343 {
344     struct file *file;
345     int result;
346
347     if ((*low >= 0 && *high != 0) || (*low < 0 && *high != -1))
348     {
349         fprintf( stderr, "set_file_pointer: offset > 2Gb not supported yet\n" );
350         set_error( STATUS_INVALID_PARAMETER );
351         return 0;
352     }
353
354     if (!(file = get_file_obj( current->process, handle, 0 )))
355         return 0;
356     if ((result = lseek( file->obj.fd, *low, whence )) == -1)
357     {
358         /* Check for seek before start of file */
359         if ((errno == EINVAL) && (whence != SEEK_SET) && (*low < 0))
360             set_error( 0xc0010000 | ERROR_NEGATIVE_SEEK /* FIXME */ );
361         else
362             file_set_error();
363         release_object( file );
364         return 0;
365     }
366     *low = result;
367     release_object( file );
368     return 1;
369 }
370
371 static int truncate_file( int handle )
372 {
373     struct file *file;
374     int result;
375
376     if (!(file = get_file_obj( current->process, handle, GENERIC_WRITE )))
377         return 0;
378     if (((result = lseek( file->obj.fd, 0, SEEK_CUR )) == -1) ||
379         (ftruncate( file->obj.fd, result ) == -1))
380     {
381         file_set_error();
382         release_object( file );
383         return 0;
384     }
385     release_object( file );
386     return 1;
387     
388 }
389
390 /* try to grow the file to the specified size */
391 int grow_file( struct file *file, int size_high, int size_low )
392 {
393     struct stat st;
394
395     if (size_high)
396     {
397         set_error( STATUS_INVALID_PARAMETER );
398         return 0;
399     }
400     if (fstat( file->obj.fd, &st ) == -1)
401     {
402         file_set_error();
403         return 0;
404     }
405     if (st.st_size >= size_low) return 1;  /* already large enough */
406     if (ftruncate( file->obj.fd, size_low ) != -1) return 1;
407     file_set_error();
408     return 0;
409 }
410
411 static int set_file_time( int handle, time_t access_time, time_t write_time )
412 {
413     struct file *file;
414     struct utimbuf utimbuf;
415
416     if (!(file = get_file_obj( current->process, handle, GENERIC_WRITE )))
417         return 0;
418     if (!access_time || !write_time)
419     {
420         struct stat st;
421         if (stat( file->name, &st ) == -1) goto error;
422         if (!access_time) access_time = st.st_atime;
423         if (!write_time) write_time = st.st_mtime;
424     }
425     utimbuf.actime  = access_time;
426     utimbuf.modtime = write_time;
427     if (utime( file->name, &utimbuf ) == -1) goto error;
428     release_object( file );
429     return 1;
430  error:
431     file_set_error();
432     release_object( file );
433     return 0;
434 }
435
436 static int file_lock( struct file *file, int offset_high, int offset_low,
437                       int count_high, int count_low )
438 {
439     /* FIXME: implement this */
440     return 1;
441 }
442
443 static int file_unlock( struct file *file, int offset_high, int offset_low,
444                         int count_high, int count_low )
445 {
446     /* FIXME: implement this */
447     return 1;
448 }
449
450 /* create a file */
451 DECL_HANDLER(create_file)
452 {
453     struct file *file;
454
455     req->handle = -1;
456     if ((file = create_file( get_req_data(req), get_req_data_size(req), req->access,
457                              req->sharing, req->create, req->attrs )))
458     {
459         req->handle = alloc_handle( current->process, file, req->access, req->inherit );
460         release_object( file );
461     }
462 }
463
464 /* allocate a file handle for a Unix fd */
465 DECL_HANDLER(alloc_file_handle)
466 {
467     struct file *file;
468
469     req->handle = -1;
470     if (current->pass_fd != -1)
471     {
472         if ((file = create_file_for_fd( current->pass_fd, req->access,
473                                         FILE_SHARE_READ | FILE_SHARE_WRITE, 0 )))
474         {
475             req->handle = alloc_handle( current->process, file, req->access, 0 );
476             release_object( file );
477         }
478         current->pass_fd = -1;
479     }
480     else set_error( STATUS_INVALID_PARAMETER );
481 }
482
483 /* get a Unix fd to read from a file */
484 DECL_HANDLER(get_read_fd)
485 {
486     struct object *obj;
487
488     if ((obj = get_handle_obj( current->process, req->handle, GENERIC_READ, NULL )))
489     {
490         set_reply_fd( current, obj->ops->get_read_fd( obj ) );
491         release_object( obj );
492     }
493 }
494
495 /* get a Unix fd to write to a file */
496 DECL_HANDLER(get_write_fd)
497 {
498     struct object *obj;
499
500     if ((obj = get_handle_obj( current->process, req->handle, GENERIC_WRITE, NULL )))
501     {
502         set_reply_fd( current, obj->ops->get_write_fd( obj ) );
503         release_object( obj );
504     }
505 }
506
507 /* set a file current position */
508 DECL_HANDLER(set_file_pointer)
509 {
510     int high = req->high;
511     int low  = req->low;
512     set_file_pointer( req->handle, &low, &high, req->whence );
513     req->new_low  = low;
514     req->new_high = high;
515 }
516
517 /* truncate (or extend) a file */
518 DECL_HANDLER(truncate_file)
519 {
520     truncate_file( req->handle );
521 }
522
523 /* flush a file buffers */
524 DECL_HANDLER(flush_file)
525 {
526     struct object *obj;
527
528     if ((obj = get_handle_obj( current->process, req->handle, 0, NULL )))
529     {
530         obj->ops->flush( obj );
531         release_object( obj );
532     }
533 }
534
535 /* set a file access and modification times */
536 DECL_HANDLER(set_file_time)
537 {
538     set_file_time( req->handle, req->access_time, req->write_time );
539 }
540
541 /* get a file information */
542 DECL_HANDLER(get_file_info)
543 {
544     struct object *obj;
545
546     if ((obj = get_handle_obj( current->process, req->handle, 0, NULL )))
547     {
548         obj->ops->get_file_info( obj, req );
549         release_object( obj );
550     }
551 }
552
553 /* lock a region of a file */
554 DECL_HANDLER(lock_file)
555 {
556     struct file *file;
557
558     if ((file = get_file_obj( current->process, req->handle, 0 )))
559     {
560         file_lock( file, req->offset_high, req->offset_low,
561                    req->count_high, req->count_low );
562         release_object( file );
563     }
564 }
565
566 /* unlock a region of a file */
567 DECL_HANDLER(unlock_file)
568 {
569     struct file *file;
570
571     if ((file = get_file_obj( current->process, req->handle, 0 )))
572     {
573         file_unlock( file, req->offset_high, req->offset_low,
574                      req->count_high, req->count_low );
575         release_object( file );
576     }
577 }