Changed fd operations to take a struct fd instead of a struct object.
[wine] / server / file.c
1 /*
2  * Server-side file management
3  *
4  * Copyright (C) 1998 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <assert.h>
25 #include <fcntl.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <errno.h>
30 #ifdef HAVE_SYS_ERRNO_H
31 #include <sys/errno.h>
32 #endif
33 #include <sys/stat.h>
34 #include <sys/time.h>
35 #include <sys/types.h>
36 #include <time.h>
37 #include <unistd.h>
38 #ifdef HAVE_UTIME_H
39 #include <utime.h>
40 #endif
41
42 #include "winerror.h"
43 #include "winbase.h"
44
45 #include "file.h"
46 #include "handle.h"
47 #include "thread.h"
48 #include "request.h"
49 #include "async.h"
50
51 struct file
52 {
53     struct object       obj;        /* object header */
54     struct file        *next;       /* next file in hashing list */
55     char               *name;       /* file name */
56     unsigned int        access;     /* file access (GENERIC_READ/WRITE) */
57     unsigned int        flags;      /* flags (FILE_FLAG_*) */
58     unsigned int        sharing;    /* file sharing mode */
59     int                 drive_type; /* type of drive the file is on */
60     struct async_queue  read_q;
61     struct async_queue  write_q;
62 };
63
64 #define NAME_HASH_SIZE 37
65
66 static struct file *file_hash[NAME_HASH_SIZE];
67
68 static void file_dump( struct object *obj, int verbose );
69 static void file_destroy( struct object *obj );
70
71 static int file_get_poll_events( struct fd *fd );
72 static void file_poll_event( struct fd *fd, int event );
73 static int file_flush( struct fd *fd );
74 static int file_get_info( struct fd *fd, struct get_file_info_reply *reply, int *flags );
75 static void file_queue_async( struct fd *fd, void *ptr, unsigned int status, int type, int count );
76
77 static const struct object_ops file_ops =
78 {
79     sizeof(struct file),          /* size */
80     file_dump,                    /* dump */
81     default_fd_add_queue,         /* add_queue */
82     default_fd_remove_queue,      /* remove_queue */
83     default_fd_signaled,          /* signaled */
84     no_satisfied,                 /* satisfied */
85     default_get_fd,               /* get_fd */
86     file_destroy                  /* destroy */
87 };
88
89 static const struct fd_ops file_fd_ops =
90 {
91     file_get_poll_events,         /* get_poll_events */
92     file_poll_event,              /* poll_event */
93     file_flush,                   /* flush */
94     file_get_info,                /* get_file_info */
95     file_queue_async              /* queue_async */
96 };
97
98 static int get_name_hash( const char *name )
99 {
100     int hash = 0;
101     while (*name) hash ^= (unsigned char)*name++;
102     return hash % NAME_HASH_SIZE;
103 }
104
105 /* check if the desired access is possible without violating */
106 /* the sharing mode of other opens of the same file */
107 static int check_sharing( const char *name, int hash, unsigned int access,
108                           unsigned int sharing )
109 {
110     struct file *file;
111     unsigned int existing_sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
112     unsigned int existing_access = 0;
113
114     for (file = file_hash[hash]; file; file = file->next)
115     {
116         if (strcmp( file->name, name )) continue;
117         existing_sharing &= file->sharing;
118         existing_access |= file->access;
119     }
120     if ((access & GENERIC_READ) && !(existing_sharing & FILE_SHARE_READ)) goto error;
121     if ((access & GENERIC_WRITE) && !(existing_sharing & FILE_SHARE_WRITE)) goto error;
122     if ((existing_access & GENERIC_READ) && !(sharing & FILE_SHARE_READ)) goto error;
123     if ((existing_access & GENERIC_WRITE) && !(sharing & FILE_SHARE_WRITE)) goto error;
124     return 1;
125  error:
126     set_error( STATUS_SHARING_VIOLATION );
127     return 0;
128 }
129
130 /* create a file from a file descriptor */
131 /* if the function fails the fd is closed */
132 static struct file *create_file_for_fd( int fd, unsigned int access, unsigned int sharing,
133                                         unsigned int attrs, int drive_type )
134 {
135     struct file *file;
136
137     if ((file = alloc_fd_object( &file_ops, &file_fd_ops, fd )))
138     {
139         file->name       = NULL;
140         file->next       = NULL;
141         file->access     = access;
142         file->flags      = attrs;
143         file->sharing    = sharing;
144         file->drive_type = drive_type;
145         if (file->flags & FILE_FLAG_OVERLAPPED)
146         {
147             init_async_queue (&file->read_q);
148             init_async_queue (&file->write_q);
149         }
150     }
151     return file;
152 }
153
154
155 static struct file *create_file( const char *nameptr, size_t len, unsigned int access,
156                                  unsigned int sharing, int create, unsigned int attrs,
157                                  int drive_type )
158 {
159     struct file *file;
160     int hash, flags;
161     struct stat st;
162     char *name;
163     int fd = -1;
164     mode_t mode;
165
166     if (!(name = mem_alloc( len + 1 ))) return NULL;
167     memcpy( name, nameptr, len );
168     name[len] = 0;
169
170     /* check sharing mode */
171     hash = get_name_hash( name );
172     if (!check_sharing( name, hash, access, sharing )) goto error;
173
174     switch(create)
175     {
176     case CREATE_NEW:        flags = O_CREAT | O_EXCL; break;
177     case CREATE_ALWAYS:     flags = O_CREAT | O_TRUNC; break;
178     case OPEN_ALWAYS:       flags = O_CREAT; break;
179     case TRUNCATE_EXISTING: flags = O_TRUNC; break;
180     case OPEN_EXISTING:     flags = 0; break;
181     default:                set_error( STATUS_INVALID_PARAMETER ); goto error;
182     }
183     switch(access & (GENERIC_READ | GENERIC_WRITE))
184     {
185     case 0: break;
186     case GENERIC_READ:  flags |= O_RDONLY; break;
187     case GENERIC_WRITE: flags |= O_WRONLY; break;
188     case GENERIC_READ|GENERIC_WRITE: flags |= O_RDWR; break;
189     }
190     mode = (attrs & FILE_ATTRIBUTE_READONLY) ? 0444 : 0666;
191
192     if (len >= 4 &&
193         (!strcasecmp( name + len - 4, ".exe" ) || !strcasecmp( name + len - 4, ".com" )))
194         mode |= 0111;
195
196     /* FIXME: should set error to STATUS_OBJECT_NAME_COLLISION if file existed before */
197     if ((fd = open( name, flags | O_NONBLOCK | O_LARGEFILE, mode )) == -1 )
198         goto file_error;
199     /* refuse to open a directory */
200     if (fstat( fd, &st ) == -1) goto file_error;
201     if (S_ISDIR(st.st_mode))
202     {
203         set_error( STATUS_ACCESS_DENIED );
204         goto error;
205     }
206
207     if (!(file = create_file_for_fd( fd, access, sharing, attrs, drive_type )))
208     {
209         free( name );
210         return NULL;
211     }
212     file->name = name;
213     file->next = file_hash[hash];
214     file_hash[hash] = file;
215     return file;
216
217  file_error:
218     file_set_error();
219  error:
220     if (fd != -1) close( fd );
221     free( name );
222     return NULL;
223 }
224
225 /* check if two file objects point to the same file */
226 int is_same_file( struct file *file1, struct file *file2 )
227 {
228     return !strcmp( file1->name, file2->name );
229 }
230
231 /* get the type of drive the file is on */
232 int get_file_drive_type( struct file *file )
233 {
234     return file->drive_type;
235 }
236
237 /* Create an anonymous Unix file */
238 int create_anonymous_file(void)
239 {
240     char tmpfn[21];
241     int fd;
242
243     sprintf(tmpfn,"/tmp/anonmap.XXXXXX");
244     fd = mkstemp(tmpfn);
245     if (fd == -1)
246     {
247         file_set_error();
248         return -1;
249     }
250     unlink( tmpfn );
251     return fd;
252 }
253
254 /* Create a temp file for anonymous mappings */
255 struct file *create_temp_file( int access )
256 {
257     int fd;
258
259     if ((fd = create_anonymous_file()) == -1) return NULL;
260     return create_file_for_fd( fd, access, 0, 0, DRIVE_FIXED );
261 }
262
263 static void file_dump( struct object *obj, int verbose )
264 {
265     struct file *file = (struct file *)obj;
266     assert( obj->ops == &file_ops );
267     fprintf( stderr, "File fd=%p flags=%08x name='%s'\n", file->obj.fd_obj, file->flags, file->name );
268 }
269
270 static int file_get_poll_events( struct fd *fd )
271 {
272     struct file *file = get_fd_user( fd );
273     int events = 0;
274     assert( file->obj.ops == &file_ops );
275     if (file->access & GENERIC_READ) events |= POLLIN;
276     if (file->access & GENERIC_WRITE) events |= POLLOUT;
277     return events;
278 }
279
280 static void file_poll_event( struct fd *fd, int event )
281 {
282     struct file *file = get_fd_user( fd );
283     assert( file->obj.ops == &file_ops );
284     if ( file->flags & FILE_FLAG_OVERLAPPED )
285     {
286         if( IS_READY(file->read_q) && (POLLIN & event) )
287         {
288             async_notify(file->read_q.head, STATUS_ALERTED);
289             return;
290         }
291         if( IS_READY(file->write_q) && (POLLOUT & event) )
292         {
293             async_notify(file->write_q.head, STATUS_ALERTED);
294             return;
295         }
296     }
297     default_poll_event( fd, event );
298 }
299
300
301 static int file_flush( struct fd *fd )
302 {
303     int ret = (fsync( get_unix_fd(fd) ) != -1);
304     if (!ret) file_set_error();
305     return ret;
306 }
307
308 static int file_get_info( struct fd *fd, struct get_file_info_reply *reply, int *flags )
309 {
310     struct stat st;
311     struct file *file = get_fd_user( fd );
312     int unix_fd = get_unix_fd( fd );
313
314     if (reply)
315     {
316         if (fstat( unix_fd, &st ) == -1)
317         {
318             file_set_error();
319             return FD_TYPE_INVALID;
320         }
321         if (S_ISCHR(st.st_mode) || S_ISFIFO(st.st_mode) ||
322             S_ISSOCK(st.st_mode) || isatty(unix_fd)) reply->type = FILE_TYPE_CHAR;
323         else reply->type = FILE_TYPE_DISK;
324         if (S_ISDIR(st.st_mode)) reply->attr = FILE_ATTRIBUTE_DIRECTORY;
325         else reply->attr = FILE_ATTRIBUTE_ARCHIVE;
326         if (!(st.st_mode & S_IWUSR)) reply->attr |= FILE_ATTRIBUTE_READONLY;
327         reply->access_time = st.st_atime;
328         reply->write_time  = st.st_mtime;
329         if (S_ISDIR(st.st_mode))
330         {
331             reply->size_high = 0;
332             reply->size_low  = 0;
333         }
334         else
335         {
336             reply->size_high = st.st_size >> 32;
337             reply->size_low  = st.st_size & 0xffffffff;
338         }
339         reply->links       = st.st_nlink;
340         reply->index_high  = st.st_dev;
341         reply->index_low   = st.st_ino;
342         reply->serial      = 0; /* FIXME */
343     }
344     *flags = 0;
345     if (file->flags & FILE_FLAG_OVERLAPPED) *flags |= FD_FLAG_OVERLAPPED;
346     return FD_TYPE_DEFAULT;
347 }
348
349 static void file_queue_async(struct fd *fd, void *ptr, unsigned int status, int type, int count)
350 {
351     struct file *file = get_fd_user( fd );
352     struct async *async;
353     struct async_queue *q;
354
355     assert( file->obj.ops == &file_ops );
356
357     if ( !(file->flags & FILE_FLAG_OVERLAPPED) )
358     {
359         set_error ( STATUS_INVALID_HANDLE );
360         return;
361     }
362
363     switch(type)
364     {
365     case ASYNC_TYPE_READ:
366         q = &file->read_q;
367         break;
368     case ASYNC_TYPE_WRITE:
369         q = &file->write_q;
370         break;
371     default:
372         set_error( STATUS_INVALID_PARAMETER );
373         return;
374     }
375
376     async = find_async ( q, current, ptr );
377
378     if ( status == STATUS_PENDING )
379     {
380         int events;
381
382         if ( !async )
383             async = create_async ( &file->obj, current, ptr );
384         if ( !async )
385             return;
386
387         async->status = STATUS_PENDING;
388         if ( !async->q )
389             async_insert( q, async );
390
391         /* Check if the new pending request can be served immediately */
392         events = check_fd_events( fd, file_get_poll_events( fd ) );
393         if (events) file_poll_event ( fd, events );
394     }
395     else if ( async ) destroy_async ( async );
396     else set_error ( STATUS_INVALID_PARAMETER );
397
398     set_select_events( &file->obj, file_get_poll_events( fd ));
399 }
400
401 static void file_destroy( struct object *obj )
402 {
403     struct file *file = (struct file *)obj;
404     assert( obj->ops == &file_ops );
405
406     if (file->name)
407     {
408         /* remove it from the hashing list */
409         struct file **pptr = &file_hash[get_name_hash( file->name )];
410         while (*pptr && *pptr != file) pptr = &(*pptr)->next;
411         assert( *pptr );
412         *pptr = (*pptr)->next;
413         if (file->flags & FILE_FLAG_DELETE_ON_CLOSE) unlink( file->name );
414         free( file->name );
415     }
416     if (file->flags & FILE_FLAG_OVERLAPPED)
417     {
418         destroy_async_queue (&file->read_q);
419         destroy_async_queue (&file->write_q);
420     }
421 }
422
423 /* set the last error depending on errno */
424 void file_set_error(void)
425 {
426     switch (errno)
427     {
428     case EAGAIN:    set_error( STATUS_SHARING_VIOLATION ); break;
429     case EBADF:     set_error( STATUS_INVALID_HANDLE ); break;
430     case ENOSPC:    set_error( STATUS_DISK_FULL ); break;
431     case EACCES:
432     case ESRCH:
433     case EPERM:     set_error( STATUS_ACCESS_DENIED ); break;
434     case EROFS:     set_error( STATUS_MEDIA_WRITE_PROTECTED ); break;
435     case EBUSY:     set_error( STATUS_FILE_LOCK_CONFLICT ); break;
436     case ENOENT:    set_error( STATUS_NO_SUCH_FILE ); break;
437     case EISDIR:    set_error( 0xc0010000 | ERROR_CANNOT_MAKE /* FIXME */ ); break;
438     case ENFILE:
439     case EMFILE:    set_error( STATUS_NO_MORE_FILES ); break;
440     case EEXIST:    set_error( STATUS_OBJECT_NAME_COLLISION ); break;
441     case EINVAL:    set_error( STATUS_INVALID_PARAMETER ); break;
442     case ESPIPE:    set_error( 0xc0010000 | ERROR_SEEK /* FIXME */ ); break;
443     case ENOTEMPTY: set_error( STATUS_DIRECTORY_NOT_EMPTY ); break;
444     case EIO:       set_error( STATUS_ACCESS_VIOLATION ); break;
445     default:        perror("file_set_error"); set_error( ERROR_UNKNOWN /* FIXME */ ); break;
446     }
447 }
448
449 struct file *get_file_obj( struct process *process, obj_handle_t handle, unsigned int access )
450 {
451     return (struct file *)get_handle_obj( process, handle, access, &file_ops );
452 }
453
454 int get_file_unix_fd( struct file *file )
455 {
456     return get_unix_fd( file->obj.fd_obj );
457 }
458
459 static int set_file_pointer( obj_handle_t handle, unsigned int *low, int *high, int whence )
460 {
461     struct file *file;
462     off_t result,xto;
463
464     xto = *low+((off_t)*high<<32);
465     if (!(file = get_file_obj( current->process, handle, 0 )))
466         return 0;
467     if ((result = lseek( get_file_unix_fd(file), xto, whence))==-1)
468     {
469         /* Check for seek before start of file */
470
471         /* also check EPERM due to SuSE7 2.2.16 lseek() EPERM kernel bug */
472         if (((errno == EINVAL) || (errno == EPERM))
473             && (whence != SEEK_SET) && (*high < 0))
474             set_error( 0xc0010000 | ERROR_NEGATIVE_SEEK /* FIXME */ );
475         else
476             file_set_error();
477         release_object( file );
478         return 0;
479     }
480     *low  = result & 0xffffffff;
481     *high = result >> 32;
482     release_object( file );
483     return 1;
484 }
485
486 /* extend a file beyond the current end of file */
487 static int extend_file( struct file *file, off_t size )
488 {
489     static const char zero;
490     int unix_fd = get_file_unix_fd( file );
491
492     /* extend the file one byte beyond the requested size and then truncate it */
493     /* this should work around ftruncate implementations that can't extend files */
494     if ((lseek( unix_fd, size, SEEK_SET ) != -1) &&
495         (write( unix_fd, &zero, 1 ) != -1))
496     {
497         ftruncate( unix_fd, size );
498         return 1;
499     }
500     file_set_error();
501     return 0;
502 }
503
504 /* truncate file at current position */
505 static int truncate_file( struct file *file )
506 {
507     int ret = 0;
508     int unix_fd = get_file_unix_fd( file );
509     off_t pos = lseek( unix_fd, 0, SEEK_CUR );
510     off_t eof = lseek( unix_fd, 0, SEEK_END );
511
512     if (eof < pos) ret = extend_file( file, pos );
513     else
514     {
515         if (ftruncate( unix_fd, pos ) != -1) ret = 1;
516         else file_set_error();
517     }
518     lseek( unix_fd, pos, SEEK_SET );  /* restore file pos */
519     return ret;
520 }
521
522 /* try to grow the file to the specified size */
523 int grow_file( struct file *file, int size_high, int size_low )
524 {
525     int ret = 0;
526     struct stat st;
527     int unix_fd = get_file_unix_fd( file );
528     off_t old_pos, size = size_low + (((off_t)size_high)<<32);
529
530     if (fstat( unix_fd, &st ) == -1)
531     {
532         file_set_error();
533         return 0;
534     }
535     if (st.st_size >= size) return 1;  /* already large enough */
536     old_pos = lseek( unix_fd, 0, SEEK_CUR );  /* save old pos */
537     ret = extend_file( file, size );
538     lseek( unix_fd, old_pos, SEEK_SET );  /* restore file pos */
539     return ret;
540 }
541
542 static int set_file_time( obj_handle_t handle, time_t access_time, time_t write_time )
543 {
544     struct file *file;
545     struct utimbuf utimbuf;
546
547     if (!(file = get_file_obj( current->process, handle, GENERIC_WRITE )))
548         return 0;
549     if (!file->name)
550     {
551         set_error( STATUS_INVALID_HANDLE );
552         release_object( file );
553         return 0;
554     }
555     if (!access_time || !write_time)
556     {
557         struct stat st;
558         if (stat( file->name, &st ) == -1) goto error;
559         if (!access_time) access_time = st.st_atime;
560         if (!write_time) write_time = st.st_mtime;
561     }
562     utimbuf.actime  = access_time;
563     utimbuf.modtime = write_time;
564     if (utime( file->name, &utimbuf ) == -1) goto error;
565     release_object( file );
566     return 1;
567  error:
568     file_set_error();
569     release_object( file );
570     return 0;
571 }
572
573 static int file_lock( struct file *file, int offset_high, int offset_low,
574                       int count_high, int count_low )
575 {
576     /* FIXME: implement this */
577     return 1;
578 }
579
580 static int file_unlock( struct file *file, int offset_high, int offset_low,
581                         int count_high, int count_low )
582 {
583     /* FIXME: implement this */
584     return 1;
585 }
586
587 /* create a file */
588 DECL_HANDLER(create_file)
589 {
590     struct file *file;
591
592     reply->handle = 0;
593     if ((file = create_file( get_req_data(), get_req_data_size(), req->access,
594                              req->sharing, req->create, req->attrs, req->drive_type )))
595     {
596         reply->handle = alloc_handle( current->process, file, req->access, req->inherit );
597         release_object( file );
598     }
599 }
600
601 /* allocate a file handle for a Unix fd */
602 DECL_HANDLER(alloc_file_handle)
603 {
604     struct file *file;
605     int fd;
606
607     reply->handle = 0;
608     if ((fd = thread_get_inflight_fd( current, req->fd )) == -1)
609     {
610         set_error( STATUS_INVALID_HANDLE );
611         return;
612     }
613     if ((file = create_file_for_fd( fd, req->access, FILE_SHARE_READ | FILE_SHARE_WRITE,
614                                     0, DRIVE_UNKNOWN )))
615     {
616         reply->handle = alloc_handle( current->process, file, req->access, req->inherit );
617         release_object( file );
618     }
619 }
620
621 /* set a file current position */
622 DECL_HANDLER(set_file_pointer)
623 {
624     int high = req->high;
625     int low  = req->low;
626     set_file_pointer( req->handle, &low, &high, req->whence );
627     reply->new_low  = low;
628     reply->new_high = high;
629 }
630
631 /* truncate (or extend) a file */
632 DECL_HANDLER(truncate_file)
633 {
634     struct file *file;
635
636     if ((file = get_file_obj( current->process, req->handle, GENERIC_WRITE )))
637     {
638         truncate_file( file );
639         release_object( file );
640     }
641 }
642
643 /* set a file access and modification times */
644 DECL_HANDLER(set_file_time)
645 {
646     set_file_time( req->handle, req->access_time, req->write_time );
647 }
648
649 /* lock a region of a file */
650 DECL_HANDLER(lock_file)
651 {
652     struct file *file;
653
654     if ((file = get_file_obj( current->process, req->handle, 0 )))
655     {
656         file_lock( file, req->offset_high, req->offset_low,
657                    req->count_high, req->count_low );
658         release_object( file );
659     }
660 }
661
662 /* unlock a region of a file */
663 DECL_HANDLER(unlock_file)
664 {
665     struct file *file;
666
667     if ((file = get_file_obj( current->process, req->handle, 0 )))
668     {
669         file_unlock( file, req->offset_high, req->offset_low,
670                      req->count_high, req->count_low );
671         release_object( file );
672     }
673 }