Corrected location of FAQ.
[wine] / server / file.c
1 /*
2  * Server-side file management
3  *
4  * Copyright (C) 1998 Alexandre Julliard
5  */
6
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>
20
21 #include "winerror.h"
22 #include "winbase.h"
23 #include "server/process.h"
24 #include "server/thread.h"
25
26 struct file
27 {
28     struct object  obj;             /* object header */
29     struct file   *next;            /* next file in hashing list */
30     char          *name;            /* file name */
31     int            fd;              /* Unix file descriptor */
32     unsigned int   access;          /* file access (GENERIC_READ/WRITE) */
33     unsigned int   flags;           /* flags (FILE_FLAG_*) */
34     unsigned int   sharing;         /* file sharing mode */
35 };
36
37 #define NAME_HASH_SIZE 37
38
39 static struct file *file_hash[NAME_HASH_SIZE];
40
41 static void file_dump( struct object *obj, int verbose );
42 static int file_add_queue( struct object *obj, struct wait_queue_entry *entry );
43 static void file_remove_queue( struct object *obj, struct wait_queue_entry *entry );
44 static int file_signaled( struct object *obj, struct thread *thread );
45 static int file_get_read_fd( struct object *obj );
46 static int file_get_write_fd( struct object *obj );
47 static int file_flush( struct object *obj );
48 static int file_get_info( struct object *obj, struct get_file_info_reply *reply );
49 static void file_destroy( struct object *obj );
50
51 static const struct object_ops file_ops =
52 {
53     file_dump,
54     file_add_queue,
55     file_remove_queue,
56     file_signaled,
57     no_satisfied,
58     file_get_read_fd,
59     file_get_write_fd,
60     file_flush,
61     file_get_info,
62     file_destroy
63 };
64
65 static const struct select_ops select_ops =
66 {
67     default_select_event,
68     NULL   /* we never set a timeout on a file */
69 };
70
71
72 static int get_name_hash( const char *name )
73 {
74     int hash = 0;
75     while (*name) hash ^= *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)) return 0;
95     if ((access & GENERIC_WRITE) && !(existing_sharing & FILE_SHARE_WRITE)) return 0;
96     if ((existing_access & GENERIC_READ) && !(sharing & FILE_SHARE_READ)) return 0;
97     if ((existing_access & GENERIC_WRITE) && !(sharing & FILE_SHARE_WRITE)) return 0;
98     return 1;
99 }
100
101 struct object *create_file( int fd, const char *name, unsigned int access,
102                             unsigned int sharing, int create, unsigned int attrs )
103 {
104     struct file *file;
105     int hash = 0;
106
107     if (fd == -1)
108     {
109         int flags;
110         struct stat st;
111
112         if (!name)
113         {
114             SET_ERROR( ERROR_INVALID_PARAMETER );
115             return NULL;
116         }
117
118         /* check sharing mode */
119         hash = get_name_hash( name );
120         if (!check_sharing( name, hash, access, sharing ))
121         {
122             SET_ERROR( ERROR_SHARING_VIOLATION );
123             return NULL;
124         }
125
126         switch(create)
127         {
128         case CREATE_NEW:        flags = O_CREAT | O_EXCL; break;
129         case CREATE_ALWAYS:     flags = O_CREAT | O_TRUNC; break;
130         case OPEN_ALWAYS:       flags = O_CREAT; break;
131         case TRUNCATE_EXISTING: flags = O_TRUNC; break;
132         case OPEN_EXISTING:     flags = 0; break;
133         default:                SET_ERROR( ERROR_INVALID_PARAMETER ); return NULL;
134         }
135         switch(access & (GENERIC_READ | GENERIC_WRITE))
136         {
137         case 0: break;
138         case GENERIC_READ:  flags |= O_RDONLY; break;
139         case GENERIC_WRITE: flags |= O_WRONLY; break;
140         case GENERIC_READ|GENERIC_WRITE: flags |= O_RDWR; break;
141         }
142
143         /* FIXME: should set error to ERROR_ALREADY_EXISTS if file existed before */
144         if ((fd = open( name, flags | O_NONBLOCK,
145                         (attrs & FILE_ATTRIBUTE_READONLY) ? 0444 : 0666 )) == -1)
146         {
147             file_set_error();
148             return NULL;
149         }
150         /* Refuse to open a directory */
151         if (fstat( fd, &st ) == -1)
152         {
153             file_set_error();
154             close( fd );
155             return NULL;
156         }
157         if (S_ISDIR(st.st_mode))
158         {
159             SET_ERROR( ERROR_ACCESS_DENIED );
160             close( fd );
161             return NULL;
162         }            
163     }
164     else
165     {
166         if ((fd = dup(fd)) == -1)
167         {
168             file_set_error();
169             return NULL;
170         }
171     }
172
173     if (!(file = mem_alloc( sizeof(*file) )))
174     {
175         close( fd );
176         return NULL;
177     }
178     if (name)
179     {
180         if (!(file->name = mem_alloc( strlen(name) + 1 )))
181         {
182             close( fd );
183             free( file );
184             return NULL;
185         }
186         strcpy( file->name, name );
187         file->next = file_hash[hash];
188         file_hash[hash] = file;
189     }
190     else
191     {
192         file->name = NULL;
193         file->next = NULL;
194     }
195     init_object( &file->obj, &file_ops, NULL );
196     file->fd      = fd;
197     file->access  = access;
198     file->flags   = attrs;
199     file->sharing = sharing;
200     CLEAR_ERROR();
201     return &file->obj;
202 }
203
204 /* Create a temp file for anonymous mappings */
205 struct file *create_temp_file( int access )
206 {
207     struct file *file;
208     char *name;
209     int fd;
210
211     do
212     {
213         if (!(name = tmpnam(NULL)))
214         {
215             SET_ERROR( ERROR_TOO_MANY_OPEN_FILES );
216             return NULL;
217         }
218         fd = open( name, O_CREAT | O_EXCL | O_RDWR, 0600 );
219     } while ((fd == -1) && (errno == EEXIST));
220     if (fd == -1)
221     {
222         file_set_error();
223         return NULL;
224     }
225     unlink( name );
226
227     if (!(file = mem_alloc( sizeof(*file) )))
228     {
229         close( fd );
230         return NULL;
231     }
232     init_object( &file->obj, &file_ops, NULL );
233     file->name    = NULL;
234     file->next    = NULL;
235     file->fd      = fd;
236     file->access  = access;
237     file->flags   = 0;
238     file->sharing = 0;
239     CLEAR_ERROR();
240     return file;
241 }
242
243 static void file_dump( struct object *obj, int verbose )
244 {
245     struct file *file = (struct file *)obj;
246     assert( obj->ops == &file_ops );
247     printf( "File fd=%d flags=%08x name='%s'\n",
248             file->fd, file->flags, file->name );
249 }
250
251 static int file_add_queue( struct object *obj, struct wait_queue_entry *entry )
252 {
253     struct file *file = (struct file *)obj;
254     assert( obj->ops == &file_ops );
255     if (!obj->head)  /* first on the queue */
256     {
257         if (!add_select_user( file->fd, READ_EVENT | WRITE_EVENT, &select_ops, file ))
258         {
259             SET_ERROR( ERROR_OUTOFMEMORY );
260             return 0;
261         }
262     }
263     add_queue( obj, entry );
264     return 1;
265 }
266
267 static void file_remove_queue( struct object *obj, struct wait_queue_entry *entry )
268 {
269     struct file *file = (struct file *)grab_object(obj);
270     assert( obj->ops == &file_ops );
271
272     remove_queue( obj, entry );
273     if (!obj->head)  /* last on the queue is gone */
274         remove_select_user( file->fd );
275     release_object( obj );
276 }
277
278 static int file_signaled( struct object *obj, struct thread *thread )
279 {
280     fd_set read_fds, write_fds;
281     struct timeval tv = { 0, 0 };
282
283     struct file *file = (struct file *)obj;
284     assert( obj->ops == &file_ops );
285
286     FD_ZERO( &read_fds );
287     FD_ZERO( &write_fds );
288     if (file->access & GENERIC_READ) FD_SET( file->fd, &read_fds );
289     if (file->access & GENERIC_WRITE) FD_SET( file->fd, &write_fds );
290     return select( file->fd + 1, &read_fds, &write_fds, NULL, &tv ) > 0;
291 }
292
293 static int file_get_read_fd( struct object *obj )
294 {
295     struct file *file = (struct file *)obj;
296     assert( obj->ops == &file_ops );
297     return dup( file->fd );
298 }
299
300 static int file_get_write_fd( struct object *obj )
301 {
302     struct file *file = (struct file *)obj;
303     assert( obj->ops == &file_ops );
304     return dup( file->fd );
305 }
306
307 static int file_flush( struct object *obj )
308 {
309     int ret;
310     struct file *file = (struct file *)grab_object(obj);
311     assert( obj->ops == &file_ops );
312
313     ret = (fsync( file->fd ) != -1);
314     if (!ret) file_set_error();
315     release_object( file );
316     return ret;
317 }
318
319 static int file_get_info( struct object *obj, struct get_file_info_reply *reply )
320 {
321     struct stat st;
322     struct file *file = (struct file *)obj;
323     assert( obj->ops == &file_ops );
324
325     if (fstat( file->fd, &st ) == -1)
326     {
327         file_set_error();
328         return 0;
329     }
330     if (S_ISCHR(st.st_mode) || S_ISFIFO(st.st_mode) ||
331         S_ISSOCK(st.st_mode) || isatty(file->fd)) reply->type = FILE_TYPE_CHAR;
332     else reply->type = FILE_TYPE_DISK;
333     if (S_ISDIR(st.st_mode)) reply->attr = FILE_ATTRIBUTE_DIRECTORY;
334     else reply->attr = FILE_ATTRIBUTE_ARCHIVE;
335     if (!(st.st_mode & S_IWUSR)) reply->attr |= FILE_ATTRIBUTE_READONLY;
336     reply->access_time = st.st_atime;
337     reply->write_time  = st.st_mtime;
338     reply->size_high   = 0;
339     reply->size_low    = S_ISDIR(st.st_mode) ? 0 : st.st_size;
340     reply->links       = st.st_nlink;
341     reply->index_high  = st.st_dev;
342     reply->index_low   = st.st_ino;
343     reply->serial      = 0; /* FIXME */
344     return 1;
345 }
346
347 static void file_destroy( struct object *obj )
348 {
349     struct file *file = (struct file *)obj;
350     assert( obj->ops == &file_ops );
351
352     if (file->name)
353     {
354         /* remove it from the hashing list */
355         struct file **pptr = &file_hash[get_name_hash( file->name )];
356         while (*pptr && *pptr != file) pptr = &(*pptr)->next;
357         assert( *pptr );
358         *pptr = (*pptr)->next;
359         if (file->flags & FILE_FLAG_DELETE_ON_CLOSE) unlink( file->name );
360         free( file->name );
361     }
362     close( file->fd );
363     free( file );
364 }
365
366 /* set the last error depending on errno */
367 void file_set_error(void)
368 {
369     switch (errno)
370     {
371     case EAGAIN:    SET_ERROR( ERROR_SHARING_VIOLATION ); break;
372     case EBADF:     SET_ERROR( ERROR_INVALID_HANDLE ); break;
373     case ENOSPC:    SET_ERROR( ERROR_HANDLE_DISK_FULL ); break;
374     case EACCES:
375     case EPERM:     SET_ERROR( ERROR_ACCESS_DENIED ); break;
376     case EROFS:     SET_ERROR( ERROR_WRITE_PROTECT ); break;
377     case EBUSY:     SET_ERROR( ERROR_LOCK_VIOLATION ); break;
378     case ENOENT:    SET_ERROR( ERROR_FILE_NOT_FOUND ); break;
379     case EISDIR:    SET_ERROR( ERROR_CANNOT_MAKE ); break;
380     case ENFILE:
381     case EMFILE:    SET_ERROR( ERROR_NO_MORE_FILES ); break;
382     case EEXIST:    SET_ERROR( ERROR_FILE_EXISTS ); break;
383     case EINVAL:    SET_ERROR( ERROR_INVALID_PARAMETER ); break;
384     case ESPIPE:    SET_ERROR( ERROR_SEEK ); break;
385     case ENOTEMPTY: SET_ERROR( ERROR_DIR_NOT_EMPTY ); break;
386     default:        perror("file_set_error"); SET_ERROR( ERROR_UNKNOWN ); break;
387     }
388 }
389
390 struct file *get_file_obj( struct process *process, int handle,
391                            unsigned int access )
392 {
393     return (struct file *)get_handle_obj( current->process, handle,
394                                           access, &file_ops );
395 }
396
397 int file_get_mmap_fd( struct file *file )
398 {
399     return dup( file->fd );
400 }
401
402 int set_file_pointer( int handle, int *low, int *high, int whence )
403 {
404     struct file *file;
405     int result;
406
407     if (*high)
408     {
409         fprintf( stderr, "set_file_pointer: offset > 4Gb not supported yet\n" );
410         SET_ERROR( ERROR_INVALID_PARAMETER );
411         return 0;
412     }
413
414     if (!(file = get_file_obj( current->process, handle, 0 )))
415         return 0;
416     if ((result = lseek( file->fd, *low, whence )) == -1)
417     {
418         /* Check for seek before start of file */
419         if ((errno == EINVAL) && (whence != SEEK_SET) && (*low < 0))
420             SET_ERROR( ERROR_NEGATIVE_SEEK );
421         else
422             file_set_error();
423         release_object( file );
424         return 0;
425     }
426     *low = result;
427     release_object( file );
428     return 1;
429 }
430
431 int truncate_file( int handle )
432 {
433     struct file *file;
434     int result;
435
436     if (!(file = get_file_obj( current->process, handle, GENERIC_WRITE )))
437         return 0;
438     if (((result = lseek( file->fd, 0, SEEK_CUR )) == -1) ||
439         (ftruncate( file->fd, result ) == -1))
440     {
441         file_set_error();
442         release_object( file );
443         return 0;
444     }
445     release_object( file );
446     return 1;
447     
448 }
449
450 /* try to grow the file to the specified size */
451 int grow_file( struct file *file, int size_high, int size_low )
452 {
453     struct stat st;
454
455     if (size_high)
456     {
457         SET_ERROR( ERROR_INVALID_PARAMETER );
458         return 0;
459     }
460     if (fstat( file->fd, &st ) == -1)
461     {
462         file_set_error();
463         return 0;
464     }
465     if (st.st_size >= size_low) return 1;  /* already large enough */
466     if (ftruncate( file->fd, size_low ) != -1) return 1;
467     file_set_error();
468     return 0;
469 }
470
471 int set_file_time( int handle, time_t access_time, time_t write_time )
472 {
473     struct file *file;
474     struct utimbuf utimbuf;
475
476     if (!(file = get_file_obj( current->process, handle, GENERIC_WRITE )))
477         return 0;
478     if (!access_time || !write_time)
479     {
480         struct stat st;
481         if (stat( file->name, &st ) == -1) goto error;
482         if (!access_time) access_time = st.st_atime;
483         if (!write_time) write_time = st.st_mtime;
484     }
485     utimbuf.actime  = access_time;
486     utimbuf.modtime = write_time;
487     if (utime( file->name, &utimbuf ) == -1) goto error;
488     release_object( file );
489     return 1;
490  error:
491     file_set_error();
492     release_object( file );
493     return 0;
494 }
495
496 int file_lock( struct file *file, int offset_high, int offset_low,
497                int count_high, int count_low )
498 {
499     /* FIXME: implement this */
500     return 1;
501 }
502
503 int file_unlock( struct file *file, int offset_high, int offset_low,
504                  int count_high, int count_low )
505 {
506     /* FIXME: implement this */
507     return 1;
508 }