Reland bug 121341.
[wine-gecko.git] / modules / libreg / src / mmapio.c
blobfd9d0ca6fd17b866712fb3988f340c161ae3ba71
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is Mozilla Communicator.
16 * The Initial Developer of the Original Code is
17 * James L. Nance.
18 * Portions created by the Initial Developer are Copyright (C) 1999
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
22 * James L. Nance <jim_nance@yahoo.com>
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
37 #include <string.h>
38 #include "mmapio.h"
39 #include "prmem.h"
40 #include "prlog.h"
42 struct MmioFileStruct
44 PRFileDesc *fd;
45 PRFileMap *fileMap;
46 PRUint32 fsize; /* The size of the file */
47 PRUint32 msize; /* The size of the mmap()ed area */
48 PRInt32 pos; /* Our logical position for doing I/O */
49 char *addr; /* The base address of our mapping */
50 PRBool needSeek; /* Do we need to seek to pos before doing a write() */
53 PRStatus mmio_FileSeek(MmioFile *mmio, PRInt32 offset, PRSeekWhence whence)
55 mmio->needSeek = PR_TRUE;
57 switch(whence) {
58 case PR_SEEK_SET:
59 mmio->pos = offset;
60 break;
61 case PR_SEEK_END:
62 mmio->pos = mmio->fsize + offset;
63 break;
64 case PR_SEEK_CUR:
65 mmio->pos = mmio->pos + offset;
66 break;
67 default:
68 return PR_FAILURE;
71 if(mmio->pos<0) {
72 mmio->pos = 0;
75 return PR_SUCCESS;
78 PRInt32 mmio_FileRead(MmioFile *mmio, char *dest, PRInt32 count)
80 static PRFileMapProtect prot = PR_PROT_READONLY;
81 static PRInt64 fsize_l;
83 /* First see if we are going to try and read past the end of the file
84 * and shorten count if we are.
86 if(mmio->pos+count > mmio->fsize) {
87 count = mmio->fsize - mmio->pos;
90 if(count<1) {
91 return 0;
94 /* Check to see if we need to remap for this read */
95 if(mmio->pos+count > mmio->msize) {
96 if(mmio->addr && mmio->msize) {
97 PR_ASSERT(mmio->fileMap);
98 PR_MemUnmap(mmio->addr, mmio->msize);
99 PR_CloseFileMap(mmio->fileMap);
100 mmio->addr = NULL;
101 mmio->msize = 0;
104 LL_UI2L(fsize_l, mmio->fsize);
105 mmio->fileMap = PR_CreateFileMap(mmio->fd, fsize_l, prot);
107 if(!mmio->fileMap) {
108 return -1;
111 mmio->addr = PR_MemMap(mmio->fileMap, 0, fsize_l);
113 if(!mmio->addr) {
114 return -1;
117 mmio->msize = mmio->fsize;
120 memcpy(dest, mmio->addr+mmio->pos, count);
122 mmio->pos += count;
123 mmio->needSeek = PR_TRUE;
125 return count;
128 PRInt32 mmio_FileWrite(MmioFile *mmio, const char *src, PRInt32 count)
130 PRInt32 wcode;
132 if(mmio->needSeek) {
133 PR_Seek(mmio->fd, mmio->pos, PR_SEEK_SET);
134 mmio->needSeek = PR_FALSE;
137 /* If this system does not keep mmap() and write() synchronized, we can
138 ** force it to by doing an munmap() when we do a write. This will
139 ** obviously slow things down but fortunatly we do not do that many
140 ** writes from within mozilla. Platforms which need this may want to
141 ** use the new USE_BUFFERED_REGISTRY_IO code instead of this code though.
143 #if MMAP_MISSES_WRITES
144 if(mmio->addr && mmio->msize) {
145 PR_ASSERT(mmio->fileMap);
146 PR_MemUnmap(mmio->addr, mmio->msize);
147 PR_CloseFileMap(mmio->fileMap);
148 mmio->addr = NULL;
149 mmio->msize = 0;
151 #endif
153 wcode = PR_Write(mmio->fd, src, count);
155 if(wcode>0) {
156 mmio->pos += wcode;
157 if(mmio->pos>mmio->fsize) {
158 mmio->fsize=mmio->pos;
162 return wcode;
165 PRInt32 mmio_FileTell(MmioFile *mmio)
167 return mmio->pos;
170 PRStatus mmio_FileClose(MmioFile *mmio)
172 if(mmio->addr && mmio->msize) {
173 PR_ASSERT(mmio->fileMap);
174 PR_MemUnmap(mmio->addr, mmio->msize);
175 PR_CloseFileMap(mmio->fileMap);
178 PR_Close(mmio->fd);
180 memset(mmio, 0, sizeof(*mmio)); /* Catch people who try to keep using it */
182 PR_Free(mmio);
184 return PR_SUCCESS;
187 MmioFile *mmio_FileOpen(char *path, PRIntn flags, PRIntn mode)
189 PRFileDesc *fd = PR_Open(path, flags, mode);
190 PRFileInfo info;
191 MmioFile *mmio;
193 if(!fd) {
194 return NULL;
197 mmio = PR_MALLOC(sizeof(MmioFile));
199 if(!mmio || PR_FAILURE==PR_GetOpenFileInfo(fd, &info)) {
200 PR_Close(fd);
201 return NULL;
204 mmio->fd = fd;
205 mmio->fileMap = NULL;
206 mmio->fsize = info.size;
207 mmio->msize = 0;
208 mmio->pos = 0;
209 mmio->addr = NULL;
210 mmio->needSeek = PR_FALSE;
212 return mmio;