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