1 /**
2 * @namespace biewlib
3 * @file biewlib/sysdep/generic/linux/mmfio.c
4 * @brief This file contains implementation of memory mapped file i/o routines for POSIX compatible OS.
5 * @version -
6 * @remark this source file is part of Binary vIEW project (BIEW).
7 * The Binary vIEW (BIEW) is copyright (C) 1995 Nickols_K.
8 * All rights reserved. This software is redistributable under the
9 * licence given in the file "Licence.en" ("Licence.ru" in russian
10 * translation) distributed in the BIEW archive.
11 * @note Requires POSIX compatible development system
12 *
13 * @author Nickols_K
14 * @since 2000
15 * @note Development, fixes and improvements
16 **/
17 #ifdef __DISABLE_MMF
18 #include "biewlib/sysdep/ia16/dos/mmfio.c"
19 #else
20 #include <sys/mman.h>
21 #include "biewlib/pmalloc.h"
22 #include "biewlib/biewlib.h"
23
24 #ifndef MREMAP_MAYMOVE
25 #define MREMAP_MAYMOVE 1
26 #endif
27
28 /* The lack of this function declaration on some systems and may cause segfault */
29 extern void *mremap (void *__addr, size_t __old_len, size_t __new_len,
30 int __flags, ...);
31
32 struct mmfRecord
33 {
34 void * addr;
35 long length;
36 bhandle_t fhandle;
37 int mode;
38 };
39
mk_prot(int mode)40 static int __FASTCALL__ mk_prot(int mode)
41 {
42 int pflg;
43 pflg = PROT_READ;
44 if(mode & FO_WRITEONLY) pflg = PROT_WRITE;
45 else
46 if(mode & FO_READWRITE) pflg |= PROT_WRITE;
47 return pflg;
48 }
49
mk_flags(int mode)50 static int __FASTCALL__ mk_flags(int mode)
51 {
52 int pflg;
53 pflg = 0;
54 #ifdef MAP_SHARED
55 if((mode & SO_DENYREAD) ||
56 (mode & SO_DENYWRITE) ||
57 (mode & SO_DENYNONE)) pflg |= MAP_SHARED;
58 #endif
59 #ifdef MAP_PRIVATE
60 if(mode & SO_PRIVATE) pflg |= MAP_PRIVATE;
61 #endif
62 return pflg;
63 }
64
__mmfOpen(const char * fname,int mode)65 mmfHandle __FASTCALL__ __mmfOpen(const char *fname,int mode)
66 {
67 struct mmfRecord *mret;
68 bhandle_t fhandle;
69 fhandle = __OsOpen(fname,mode);
70 if(((int)fhandle) != -1)
71 {
72 mret = PMalloc(sizeof(struct mmfRecord));
73 if(mret)
74 {
75 __fileoff_t length;
76 void *addr;
77 length = __FileLength(fhandle);
78 if(length <= PTRDIFF_MAX)
79 {
80 addr = mmap(NULL,length,mk_prot(mode),
81 mk_flags(mode),(int)fhandle,0L);
82 if(addr != (void *)-1)
83 {
84 mret->fhandle = fhandle;
85 mret->addr = addr;
86 mret->length = length;
87 mret->mode = mode;
88 return mret;
89 }
90 }
91 PFree(mret);
92 }
93 __OsClose(fhandle);
94 }
95 return NULL;
96 }
97
__mmfFlush(mmfHandle mh)98 tBool __FASTCALL__ __mmfFlush(mmfHandle mh)
99 {
100 struct mmfRecord *mrec = (struct mmfRecord *)mh;
101 return msync(mrec->addr,mrec->length,MS_SYNC) ? False : True;
102 }
103
__mmfSync(mmfHandle mh)104 mmfHandle __FASTCALL__ __mmfSync(mmfHandle mh)
105 {
106 struct mmfRecord *mrec = (struct mmfRecord *)mh;
107 long length;
108 void * new_addr;
109 length = __FileLength(mrec->fhandle);
110 msync(mrec->addr,min(length,mrec->length),MS_SYNC);
111 if(length!=mrec->length) {
112 if((new_addr = mremap(mrec->addr,mrec->length,length,0)) != (void *)-1)
113 {
114 mrec->length = length;
115 mrec->addr = new_addr;
116 }
117 else
118 {
119 __OsClose(mrec->fhandle);
120 PFree(mrec);
121 return NULL;
122 }
123 }
124 return mrec;
125 }
126
__mmfProtect(mmfHandle mh,int flags)127 tBool __FASTCALL__ __mmfProtect(mmfHandle mh,int flags)
128 {
129 struct mmfRecord *mrec = (struct mmfRecord *)mh;
130 mrec->mode = flags;
131 return mprotect(mrec->addr,mrec->length,mk_prot(flags)) ? False : True;
132 }
133
__mmfResize(mmfHandle mh,long size)134 tBool __FASTCALL__ __mmfResize(mmfHandle mh,long size)
135 {
136 struct mmfRecord *mrec = (struct mmfRecord *)mh;
137 void *new_addr;
138 tBool can_continue = False;
139 if(mrec->length > size) /* truncate */
140 {
141 if((new_addr = mremap(mrec->addr,mrec->length,size,MREMAP_MAYMOVE)) != (void *)-1) can_continue = True;
142 if(can_continue)
143 can_continue = __OsChSize(mrec->fhandle,size) != -1 ? True : False;
144 }
145 else /* expand */
146 {
147 if(__OsChSize(mrec->fhandle,size) != -1) can_continue = True;
148 if(can_continue)
149 can_continue = (new_addr = mremap(mrec->addr,mrec->length,size,MREMAP_MAYMOVE)) != (void *)-1 ? True : False;
150 }
151 if(can_continue)
152 {
153 mrec->addr = new_addr;
154 mrec->length = size;
155 return True;
156 }
157 else /* Attempt to unroll transaction back */
158 __OsChSize(mrec->fhandle,mrec->length);
159 return False;
160 }
161
__mmfClose(mmfHandle mh)162 void __FASTCALL__ __mmfClose(mmfHandle mh)
163 {
164 struct mmfRecord *mrec = (struct mmfRecord *)mh;
165 munmap(mrec->addr,mrec->length);
166 __OsClose(mrec->fhandle);
167 PFree(mrec);
168 }
169
__mmfAddress(mmfHandle mh)170 void * __FASTCALL__ __mmfAddress(mmfHandle mh)
171 {
172 return ((struct mmfRecord *)mh)->addr;
173 }
174
__mmfSize(mmfHandle mh)175 long __FASTCALL__ __mmfSize(mmfHandle mh)
176 {
177 return ((struct mmfRecord *)mh)->length;
178 }
179
__mmfIsWorkable(void)180 tBool __FASTCALL__ __mmfIsWorkable( void ) { return True; }
181
182 #endif
183