Change Library Names Not To Conflict With Others When Installed
[oota-llvm.git] / lib / System / Unix / MappedFile.inc
1 //===- Unix/MappedFile.cpp - Unix MappedFile Implementation -----*- C++ -*-===//
2 // 
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by Reid Spencer and is distributed under the 
6 // University of Illinois Open Source License. See LICENSE.TXT for details.
7 // 
8 //===----------------------------------------------------------------------===//
9 //
10 // This file provides the generic Unix implementation of the MappedFile concept.
11 //
12 //===----------------------------------------------------------------------===//
13
14 //===----------------------------------------------------------------------===//
15 //=== WARNING: Implementation here must contain only generic UNIX code that
16 //===          is guaranteed to work on *all* UNIX variants.
17 //===----------------------------------------------------------------------===//
18
19 #include "llvm/System/Process.h"
20 #include "Unix.h"
21 #include <fcntl.h>
22 #include <sys/mman.h>
23
24 namespace llvm {
25 using namespace sys;
26
27 struct sys::MappedFileInfo {
28   int fd_;
29   struct stat sbuf_;
30 };
31
32 void MappedFile::initialize() {
33   if (path_.exists()) {
34     info_ = new MappedFileInfo;
35     int mode = 0;
36     if (options_&READ_ACCESS) 
37       if (options_&WRITE_ACCESS)
38         mode = O_RDWR;
39       else
40         mode = O_RDONLY;
41     else if (options_&WRITE_ACCESS)
42       mode = O_WRONLY;
43     info_->fd_ = ::open(path_.c_str(),mode);
44     if (info_->fd_ < 0) {
45       delete info_;
46       info_ = 0;
47       ThrowErrno(std::string("Can't open file: ") + path_.get());
48     }
49     struct stat sbuf;
50     if(::fstat(info_->fd_, &info_->sbuf_) < 0) {
51       ::close(info_->fd_);
52       delete info_;
53       info_ = 0;
54       ThrowErrno(std::string("Can't stat file: ") + path_.get());
55     }
56   }
57 }
58
59 void MappedFile::terminate() {
60   assert(info_ && "MappedFile not initialized");
61   if (info_->fd_ >= 0)
62     ::close(info_->fd_);
63   delete info_;
64   info_ = 0;
65 }
66
67 void MappedFile::unmap() {
68   assert(info_ && "MappedFile not initialized");
69   if (isMapped()) {
70     if (options_ & WRITE_ACCESS)
71       ::msync(base_, info_->sbuf_.st_size, MS_SYNC);
72     ::munmap(base_, info_->sbuf_.st_size);
73   }
74 }
75
76 void* MappedFile::map() {
77   if (!isMapped()) {
78     int prot = PROT_NONE;
79     int flags = 0;
80 #ifdef MAP_FILE
81     flags |= MAP_FILE;
82 #endif
83     if (options_ == 0) {
84       prot = PROT_READ;
85       flags = MAP_PRIVATE;
86     } else {
87       if (options_ & READ_ACCESS)
88         prot |= PROT_READ;
89       if (options_ & WRITE_ACCESS)
90         prot |= PROT_WRITE;
91       if (options_ & EXEC_ACCESS)
92         prot |= PROT_EXEC;
93       if (options_ & SHARED_MAPPING)
94         flags |= MAP_SHARED;
95       else
96         flags |= MAP_PRIVATE;
97     }
98     size_t map_size = ((info_->sbuf_.st_size / Process::GetPageSize())+1) *
99       Process::GetPageSize();
100
101     base_ = ::mmap(0, map_size, prot, flags, info_->fd_, 0);
102     if (base_ == MAP_FAILED)
103       ThrowErrno(std::string("Can't map file:") + path_.get());
104   }
105   return base_;
106 }
107
108 size_t MappedFile::size() {
109   assert(info_ && "MappedFile not initialized");
110   return info_->sbuf_.st_size;
111 }
112
113 void MappedFile::size(size_t new_size) {
114   assert(info_ && "MappedFile not initialized");
115
116   // Take the mapping out of memory
117   this->unmap();
118
119   // Adjust the current size to a page boundary
120   size_t cur_size = ((info_->sbuf_.st_size / Process::GetPageSize())+1) *
121     Process::GetPageSize();
122
123   // Adjust the new_size to a page boundary
124   new_size = ((new_size / Process::GetPageSize())+1) *
125     Process::GetPageSize();
126
127   // If the file needs to be extended
128   if (new_size > cur_size) {
129     // Ensure we can allocate at least the idodes necessary to handle the
130     // file size requested. 
131     ::lseek(info_->fd_, new_size, SEEK_SET);
132     ::write(info_->fd_, "\0", 1);
133   }
134
135   // Seek to current end of file. 
136   this->map();
137 }
138
139 }
140
141 // vim: sw=2 smartindent smarttab tw=80 autoindent expandtab