initial import
[vuplus_webkit] / Source / WebKit2 / Platform / unix / SharedMemoryUnix.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  * Copyright (c) 2010 University of Szeged
4  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
19  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25  * THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include "config.h"
29 #if USE(UNIX_DOMAIN_SOCKETS)
30 #include "SharedMemory.h"
31
32 #include "ArgumentDecoder.h"
33 #include "ArgumentEncoder.h"
34 #include "WebCoreArgumentCoders.h"
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <stdlib.h>
38 #include <sys/mman.h>
39 #include <sys/stat.h>
40 #include <sys/types.h>
41 #include <unistd.h>
42 #include <wtf/Assertions.h>
43 #include <wtf/CurrentTime.h>
44
45 #if PLATFORM(QT)
46 #include <QDir>
47 #elif PLATFORM(GTK)
48 #include <glib.h>
49 #include <wtf/gobject/GOwnPtr.h>
50 #endif
51
52 namespace WebKit {
53
54 SharedMemory::Handle::Handle()
55     : m_fileDescriptor(-1)
56     , m_size(0)
57 {
58 }
59
60 SharedMemory::Handle::~Handle()
61 {
62     if (!isNull())
63         while (close(m_fileDescriptor) == -1 && errno == EINTR) { }
64 }
65
66 bool SharedMemory::Handle::isNull() const
67 {
68     return m_fileDescriptor == -1;
69 }
70
71 void SharedMemory::Handle::encode(CoreIPC::ArgumentEncoder* encoder) const
72 {
73     encoder->encode(releaseToAttachment());
74 }
75
76 bool SharedMemory::Handle::decode(CoreIPC::ArgumentDecoder* decoder, Handle& handle)
77 {
78     ASSERT_ARG(handle, !handle.m_size);
79     ASSERT_ARG(handle, handle.isNull());
80
81     CoreIPC::Attachment attachment;
82     if (!decoder->decode(attachment))
83         return false;
84
85     handle.adoptFromAttachment(attachment.releaseFileDescriptor(), attachment.size());
86     return true;
87 }
88
89 CoreIPC::Attachment SharedMemory::Handle::releaseToAttachment() const
90 {
91     int temp = m_fileDescriptor;
92     m_fileDescriptor = -1;
93     return CoreIPC::Attachment(temp, m_size);
94 }
95
96 void SharedMemory::Handle::adoptFromAttachment(int fileDescriptor, size_t size)
97 {
98     ASSERT(!m_size);
99     ASSERT(isNull());
100
101     m_fileDescriptor = fileDescriptor;
102     m_size = size;
103 }
104
105 PassRefPtr<SharedMemory> SharedMemory::create(size_t size)
106 {
107 #if PLATFORM(QT)
108     QString tempName = QDir::temp().filePath(QLatin1String("qwkshm.XXXXXX"));
109     QByteArray tempNameCSTR = tempName.toLocal8Bit();
110     char* tempNameC = tempNameCSTR.data();
111 #elif PLATFORM(GTK)
112     GOwnPtr<gchar> tempName(g_build_filename(g_get_tmp_dir(), "WK2SharedMemoryXXXXXX", NULL));
113     gchar* tempNameC = tempName.get();
114 #endif
115
116     int fileDescriptor;
117     while ((fileDescriptor = mkstemp(tempNameC)) == -1) {
118         if (errno != EINTR)
119             return 0;
120     }
121     while (fcntl(fileDescriptor, F_SETFD, FD_CLOEXEC) == -1) {
122         if (errno != EINTR) {
123             while (close(fileDescriptor) == -1 && errno == EINTR) { }
124             unlink(tempNameC);
125             return 0;
126         }
127     }
128
129     while (ftruncate(fileDescriptor, size) == -1) {
130         if (errno != EINTR) {
131             while (close(fileDescriptor) == -1 && errno == EINTR) { }
132             unlink(tempNameC);
133             return 0;
134         }
135     }
136
137     void* data = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileDescriptor, 0);
138     if (data == MAP_FAILED) {
139         while (close(fileDescriptor) == -1 && errno == EINTR) { }
140         unlink(tempNameC);
141         return 0;
142     }
143
144     unlink(tempNameC);
145
146     RefPtr<SharedMemory> instance = adoptRef(new SharedMemory());
147     instance->m_data = data;
148     instance->m_fileDescriptor = fileDescriptor;
149     instance->m_size = size;
150     return instance.release();
151 }
152
153 static inline int accessModeMMap(SharedMemory::Protection protection)
154 {
155     switch (protection) {
156     case SharedMemory::ReadOnly:
157         return PROT_READ;
158     case SharedMemory::ReadWrite:
159         return PROT_READ | PROT_WRITE;
160     }
161
162     ASSERT_NOT_REACHED();
163     return PROT_READ | PROT_WRITE;
164 }
165
166 PassRefPtr<SharedMemory> SharedMemory::create(const Handle& handle, Protection protection)
167 {
168     ASSERT(!handle.isNull());
169
170     void* data = mmap(0, handle.m_size, accessModeMMap(protection), MAP_SHARED, handle.m_fileDescriptor, 0);
171     if (data == MAP_FAILED)
172         return 0;
173
174     RefPtr<SharedMemory> instance = adoptRef(new SharedMemory());
175     instance->m_data = data;
176     instance->m_fileDescriptor = handle.m_fileDescriptor;
177     instance->m_size = handle.m_size;
178     handle.m_fileDescriptor = -1;
179     return instance;
180 }
181
182 SharedMemory::~SharedMemory()
183 {
184     munmap(m_data, m_size);
185     while (close(m_fileDescriptor) == -1 && errno == EINTR) { }
186 }
187
188 static inline int accessModeFile(SharedMemory::Protection protection)
189 {
190     switch (protection) {
191     case SharedMemory::ReadOnly:
192         return O_RDONLY;
193     case SharedMemory::ReadWrite:
194         return O_RDWR;
195     }
196
197     ASSERT_NOT_REACHED();
198     return O_RDWR;
199 }
200
201 bool SharedMemory::createHandle(Handle& handle, Protection protection)
202 {
203     ASSERT_ARG(handle, !handle.m_size);
204     ASSERT_ARG(handle, handle.isNull());
205
206     int duplicatedHandle;
207     while ((duplicatedHandle = dup(m_fileDescriptor)) == -1) {
208         if (errno != EINTR) {
209             ASSERT_NOT_REACHED();
210             return false;
211         }
212     }
213
214     while ((fcntl(duplicatedHandle, F_SETFD, FD_CLOEXEC | accessModeFile(protection)) == -1)) {
215         if (errno != EINTR) {
216             ASSERT_NOT_REACHED();
217             while (close(duplicatedHandle) == -1 && errno == EINTR) { }
218             return false;
219         }
220     }
221     handle.m_fileDescriptor = duplicatedHandle;
222     handle.m_size = m_size;
223     return true;
224 }
225
226 unsigned SharedMemory::systemPageSize()
227 {
228     static unsigned pageSize = 0;
229
230     if (!pageSize)
231         pageSize = getpagesize();
232
233     return pageSize;
234 }
235
236 } // namespace WebKit
237
238 #endif
239