Back to index

lightning-sunbird  0.9+nobinonly
mmapio.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is Mozilla Communicator.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * James L. Nance.
00018  * Portions created by the Initial Developer are Copyright (C) 1999
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   James L. Nance <jim_nance@yahoo.com>
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 #include <string.h>
00038 #include "mmapio.h"
00039 #include "prmem.h"
00040 #include "prlog.h"
00041 
00042 struct MmioFileStruct
00043 {
00044     PRFileDesc *fd;
00045     PRFileMap  *fileMap;
00046     PRUint32   fsize; /* The size of the file */
00047     PRUint32   msize; /* The size of the mmap()ed area */
00048     PRInt32    pos;   /* Our logical position for doing I/O */
00049     char       *addr; /* The base address of our mapping */
00050     PRBool     needSeek; /* Do we need to seek to pos before doing a write() */
00051 };
00052 
00053 PRStatus mmio_FileSeek(MmioFile *mmio, PRInt32 offset, PRSeekWhence whence)
00054 {
00055     mmio->needSeek = PR_TRUE;
00056 
00057     switch(whence) {
00058         case PR_SEEK_SET:
00059             mmio->pos = offset;
00060             break;
00061         case PR_SEEK_END:
00062             mmio->pos = mmio->fsize + offset;
00063             break;
00064         case PR_SEEK_CUR:
00065             mmio->pos = mmio->pos + offset;
00066             break;
00067         default:
00068             return PR_FAILURE;
00069     }
00070 
00071     if(mmio->pos<0) {
00072         mmio->pos = 0;
00073     }
00074 
00075     return PR_SUCCESS;
00076 }
00077 
00078 PRInt32  mmio_FileRead(MmioFile *mmio, char *dest, PRInt32 count)
00079 {
00080     static PRFileMapProtect prot = PR_PROT_READONLY;
00081     static PRInt64 fsize_l;
00082 
00083     /* First see if we are going to try and read past the end of the file
00084      * and shorten count if we are.
00085     */
00086     if(mmio->pos+count > mmio->fsize) {
00087         count = mmio->fsize - mmio->pos;
00088     }
00089 
00090     if(count<1) {
00091         return 0;
00092     }
00093 
00094     /* Check to see if we need to remap for this read */
00095     if(mmio->pos+count > mmio->msize) {
00096         if(mmio->addr && mmio->msize) {
00097             PR_ASSERT(mmio->fileMap);
00098             PR_MemUnmap(mmio->addr, mmio->msize);
00099             PR_CloseFileMap(mmio->fileMap);
00100             mmio->addr  = NULL;
00101             mmio->msize = 0;
00102         }
00103 
00104         LL_UI2L(fsize_l, mmio->fsize);
00105         mmio->fileMap = PR_CreateFileMap(mmio->fd, fsize_l, prot);
00106 
00107         if(!mmio->fileMap) {
00108             return -1;
00109         }
00110 
00111         mmio->addr = PR_MemMap(mmio->fileMap, 0, fsize_l);
00112 
00113         if(!mmio->addr) {
00114             return -1;
00115         }
00116 
00117         mmio->msize = mmio->fsize;
00118     }
00119 
00120     memcpy(dest, mmio->addr+mmio->pos, count);
00121 
00122     mmio->pos += count;
00123     mmio->needSeek = PR_TRUE;
00124 
00125     return count;
00126 }
00127 
00128 PRInt32  mmio_FileWrite(MmioFile *mmio, const char *src, PRInt32 count)
00129 {
00130     PRInt32 wcode;
00131 
00132     if(mmio->needSeek) {
00133         PR_Seek(mmio->fd, mmio->pos, PR_SEEK_SET);
00134         mmio->needSeek = PR_FALSE;
00135     }
00136 
00137     /* If this system does not keep mmap() and write() synchronized, we can
00138     ** force it to by doing an munmap() when we do a write.  This will
00139     ** obviously slow things down but fortunatly we do not do that many
00140     ** writes from within mozilla.  Platforms which need this may want to
00141     ** use the new USE_BUFFERED_REGISTRY_IO code instead of this code though.
00142     */
00143 #if MMAP_MISSES_WRITES
00144     if(mmio->addr && mmio->msize) {
00145        PR_ASSERT(mmio->fileMap);
00146        PR_MemUnmap(mmio->addr, mmio->msize);
00147        PR_CloseFileMap(mmio->fileMap);
00148        mmio->addr  = NULL;
00149        mmio->msize = 0;
00150     }
00151 #endif
00152 
00153     wcode = PR_Write(mmio->fd, src, count);
00154 
00155     if(wcode>0) {
00156         mmio->pos += wcode;
00157         if(mmio->pos>mmio->fsize) {
00158             mmio->fsize=mmio->pos;
00159         }
00160     }
00161 
00162     return wcode;
00163 }
00164 
00165 PRInt32  mmio_FileTell(MmioFile *mmio)
00166 {
00167     return mmio->pos;
00168 }
00169 
00170 PRStatus mmio_FileClose(MmioFile *mmio)
00171 {
00172     if(mmio->addr && mmio->msize) {
00173         PR_ASSERT(mmio->fileMap);
00174         PR_MemUnmap(mmio->addr, mmio->msize);
00175         PR_CloseFileMap(mmio->fileMap);
00176     }
00177 
00178     PR_Close(mmio->fd);
00179 
00180     memset(mmio, 0, sizeof(*mmio)); /* Catch people who try to keep using it */
00181 
00182     PR_Free(mmio);
00183 
00184     return PR_SUCCESS;
00185 }
00186 
00187 MmioFile *mmio_FileOpen(char *path, PRIntn flags, PRIntn mode)
00188 {
00189     PRFileDesc *fd = PR_Open(path, flags, mode);
00190     PRFileInfo info;
00191     MmioFile   *mmio;
00192 
00193     if(!fd) {
00194         return NULL;
00195     }
00196 
00197     mmio = PR_MALLOC(sizeof(MmioFile));
00198 
00199     if(!mmio || PR_FAILURE==PR_GetOpenFileInfo(fd, &info)) {
00200         PR_Close(fd);
00201         return NULL;
00202     }
00203 
00204     mmio->fd = fd;
00205     mmio->fileMap = NULL;
00206     mmio->fsize = info.size;
00207     mmio->msize = 0;
00208     mmio->pos   = 0;
00209     mmio->addr  = NULL;
00210     mmio->needSeek = PR_FALSE;
00211 
00212     return mmio;
00213 }