Home | History | Annotate | Download | only in io
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package libcore.io;
     18 
     19 import java.io.FileDescriptor;
     20 import java.io.IOException;
     21 import java.io.RandomAccessFile;
     22 import java.nio.ByteOrder;
     23 import java.nio.NioUtils;
     24 import java.nio.channels.FileChannel;
     25 import libcore.io.ErrnoException;
     26 import libcore.io.Libcore;
     27 import libcore.io.Memory;
     28 import static libcore.io.OsConstants.*;
     29 
     30 /**
     31  * A memory-mapped file. Use {@link #mmap} to map a file, {@link #close} to unmap a file,
     32  * and either {@link #bigEndianIterator} or {@link #littleEndianIterator} to get a seekable
     33  * {@link BufferIterator} over the mapped data.
     34  */
     35 public final class MemoryMappedFile implements AutoCloseable {
     36     private long address;
     37     private final long size;
     38 
     39     /**
     40      * Use this if you've called {@code mmap} yourself.
     41      */
     42     public MemoryMappedFile(long address, long size) {
     43         this.address = address;
     44         this.size = size;
     45     }
     46 
     47     /**
     48      * Use this to mmap the whole file read-only.
     49      */
     50     public static MemoryMappedFile mmapRO(String path) throws ErrnoException {
     51         FileDescriptor fd = Libcore.os.open(path, O_RDONLY, 0);
     52         long size = Libcore.os.fstat(fd).st_size;
     53         long address = Libcore.os.mmap(0L, size, PROT_READ, MAP_SHARED, fd, 0);
     54         Libcore.os.close(fd);
     55         return new MemoryMappedFile(address, size);
     56     }
     57 
     58     /**
     59      * Unmaps this memory-mapped file using munmap(2). This is a no-op if close has already been
     60      * called. Note that this class does <i>not</i> use finalization; you must call {@code close}
     61      * yourself.
     62      *
     63      * Calling this method invalidates any iterators over this {@code MemoryMappedFile}. It is an
     64      * error to use such an iterator after calling {@code close}.
     65      */
     66     public synchronized void close() throws ErrnoException {
     67         if (address != 0) {
     68             Libcore.os.munmap(address, size);
     69             address = 0;
     70         }
     71     }
     72 
     73     /**
     74      * Returns a new iterator that treats the mapped data as big-endian.
     75      */
     76     public BufferIterator bigEndianIterator() {
     77         return new NioBufferIterator(address, (int) size, ByteOrder.nativeOrder() != ByteOrder.BIG_ENDIAN);
     78     }
     79 
     80     /**
     81      * Returns a new iterator that treats the mapped data as little-endian.
     82      */
     83     public BufferIterator littleEndianIterator() {
     84         return new NioBufferIterator(address, (int) size, ByteOrder.nativeOrder() != ByteOrder.LITTLE_ENDIAN);
     85     }
     86 
     87     /**
     88      * Returns the size in bytes of the memory-mapped region.
     89      */
     90     public long size() {
     91         return size;
     92     }
     93 }
     94