Delay initialization of I/O permissions until they are first used.
[wine.git] / server / mapping.c
blobb685317c0998c5cc01f9fcaa82c6405f04bed571
1 /*
2 * Server-side file mapping management
4 * Copyright (C) 1999 Alexandre Julliard
5 */
7 #include <assert.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <unistd.h>
12 #include "config.h"
13 #include "winnt.h"
14 #include "winbase.h"
16 #include "handle.h"
17 #include "thread.h"
18 #include "request.h"
20 struct mapping
22 struct object obj; /* object header */
23 int size_high; /* mapping size */
24 int size_low; /* mapping size */
25 int protect; /* protection flags */
26 struct file *file; /* file mapped */
29 static void mapping_dump( struct object *obj, int verbose );
30 static void mapping_destroy( struct object *obj );
32 static const struct object_ops mapping_ops =
34 sizeof(struct mapping), /* size */
35 mapping_dump, /* dump */
36 no_add_queue, /* add_queue */
37 NULL, /* remove_queue */
38 NULL, /* signaled */
39 NULL, /* satisfied */
40 NULL, /* get_poll_events */
41 NULL, /* poll_event */
42 no_read_fd, /* get_read_fd */
43 no_write_fd, /* get_write_fd */
44 no_flush, /* flush */
45 no_get_file_info, /* get_file_info */
46 mapping_destroy /* destroy */
49 #ifdef __i386__
51 /* These are always the same on an i386, and it will be faster this way */
52 # define page_mask 0xfff
53 # define page_shift 12
54 # define init_page_size() /* nothing */
56 #else /* __i386__ */
58 static int page_shift, page_mask;
60 static void init_page_size(void)
62 int page_size;
63 # ifdef HAVE_GETPAGESIZE
64 page_size = getpagesize();
65 # else
66 # ifdef __svr4__
67 page_size = sysconf(_SC_PAGESIZE);
68 # else
69 # error Cannot get the page size on this platform
70 # endif
71 # endif
72 page_mask = page_size - 1;
73 /* Make sure we have a power of 2 */
74 assert( !(page_size & page_mask) );
75 page_shift = 0;
76 while ((1 << page_shift) != page_size) page_shift++;
78 #endif /* __i386__ */
80 #define ROUND_ADDR(addr) \
81 ((int)(addr) & ~page_mask)
83 #define ROUND_SIZE(addr,size) \
84 (((int)(size) + ((int)(addr) & page_mask) + page_mask) & ~page_mask)
87 static struct object *create_mapping( int size_high, int size_low, int protect,
88 int handle, const WCHAR *name, size_t len )
90 struct mapping *mapping;
91 int access = 0;
93 if (!page_mask) init_page_size();
95 if (!(mapping = create_named_object( &mapping_ops, name, len )))
96 return NULL;
97 if (get_error() == STATUS_OBJECT_NAME_COLLISION)
98 return &mapping->obj; /* Nothing else to do */
100 if (protect & VPROT_READ) access |= GENERIC_READ;
101 if (protect & VPROT_WRITE) access |= GENERIC_WRITE;
103 if (handle != -1)
105 if (!(mapping->file = get_file_obj( current->process, handle, access ))) goto error;
106 if (!size_high && !size_low)
108 struct get_file_info_request req;
109 struct object *obj = (struct object *)mapping->file;
110 obj->ops->get_file_info( obj, &req );
111 size_high = req.size_high;
112 size_low = ROUND_SIZE( 0, req.size_low );
114 else if (!grow_file( mapping->file, size_high, size_low )) goto error;
116 else /* Anonymous mapping (no associated file) */
118 if (!size_high && !size_low)
120 set_error( STATUS_INVALID_PARAMETER );
121 mapping->file = NULL;
122 goto error;
124 if (!(mapping->file = create_temp_file( access ))) goto error;
125 if (!grow_file( mapping->file, size_high, size_low )) goto error;
127 mapping->size_high = size_high;
128 mapping->size_low = ROUND_SIZE( 0, size_low );
129 mapping->protect = protect;
130 return &mapping->obj;
132 error:
133 release_object( mapping );
134 return NULL;
137 static void mapping_dump( struct object *obj, int verbose )
139 struct mapping *mapping = (struct mapping *)obj;
140 assert( obj->ops == &mapping_ops );
141 fprintf( stderr, "Mapping size=%08x%08x prot=%08x file=%p ",
142 mapping->size_high, mapping->size_low, mapping->protect, mapping->file );
143 dump_object_name( &mapping->obj );
144 fputc( '\n', stderr );
147 static void mapping_destroy( struct object *obj )
149 struct mapping *mapping = (struct mapping *)obj;
150 assert( obj->ops == &mapping_ops );
151 if (mapping->file) release_object( mapping->file );
154 int get_page_size(void)
156 if (!page_mask) init_page_size();
157 return page_mask + 1;
160 /* create a file mapping */
161 DECL_HANDLER(create_mapping)
163 size_t len = get_req_strlenW( req, req->name );
164 struct object *obj;
166 req->handle = -1;
167 if ((obj = create_mapping( req->size_high, req->size_low,
168 req->protect, req->file_handle, req->name, len )))
170 int access = FILE_MAP_ALL_ACCESS;
171 if (!(req->protect & VPROT_WRITE)) access &= ~FILE_MAP_WRITE;
172 req->handle = alloc_handle( current->process, obj, access, req->inherit );
173 release_object( obj );
177 /* open a handle to a mapping */
178 DECL_HANDLER(open_mapping)
180 size_t len = get_req_strlenW( req, req->name );
181 req->handle = open_object( req->name, len, &mapping_ops, req->access, req->inherit );
184 /* get a mapping information */
185 DECL_HANDLER(get_mapping_info)
187 struct mapping *mapping;
189 if ((mapping = (struct mapping *)get_handle_obj( current->process, req->handle,
190 0, &mapping_ops )))
192 req->size_high = mapping->size_high;
193 req->size_low = mapping->size_low;
194 req->protect = mapping->protect;
195 if (mapping->file) set_reply_fd( current, file_get_mmap_fd( mapping->file ) );
196 release_object( mapping );