[Qt] QtWebKit will not compile with QT_ASCII_CAST_WARNINGS enabled
[WebKit-https.git] / Source / WebKit2 / Platform / qt / SharedMemoryQt.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 #include "SharedMemory.h"
30
31 #include "ArgumentDecoder.h"
32 #include "ArgumentEncoder.h"
33 #include "WebCoreArgumentCoders.h"
34 #include <QDir>
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 namespace WebKit {
46
47 SharedMemory::Handle::Handle()
48     : m_fileDescriptor(-1)
49     , m_size(0)
50 {
51 }
52
53 SharedMemory::Handle::~Handle()
54 {
55     if (!isNull())
56         while (close(m_fileDescriptor) == -1 && errno == EINTR) { }
57 }
58
59 bool SharedMemory::Handle::isNull() const
60 {
61     return m_fileDescriptor == -1;
62 }
63
64 void SharedMemory::Handle::encode(CoreIPC::ArgumentEncoder* encoder) const
65 {
66     ASSERT(!isNull());
67
68     encoder->encode(releaseToAttachment());
69 }
70
71 bool SharedMemory::Handle::decode(CoreIPC::ArgumentDecoder* decoder, Handle& handle)
72 {
73     ASSERT_ARG(handle, !handle.m_size);
74     ASSERT_ARG(handle, handle.isNull());
75
76     CoreIPC::Attachment attachment;
77     if (!decoder->decode(attachment))
78         return false;
79
80     handle.adoptFromAttachment(attachment.releaseFileDescriptor(), attachment.size());
81     return true;
82 }
83
84 CoreIPC::Attachment SharedMemory::Handle::releaseToAttachment() const
85 {
86     ASSERT(!isNull());
87
88     int temp = m_fileDescriptor;
89     m_fileDescriptor = -1;
90     return CoreIPC::Attachment(temp, m_size);
91 }
92
93 void SharedMemory::Handle::adoptFromAttachment(int fileDescriptor, size_t size)
94 {
95     ASSERT(!m_size);
96     ASSERT(isNull());
97
98     m_fileDescriptor = fileDescriptor;
99     m_size = size;
100 }
101
102 PassRefPtr<SharedMemory> SharedMemory::create(size_t size)
103 {
104     QString tempName = QDir::temp().filePath(QLatin1String("qwkshm.XXXXXX"));
105     QByteArray tempNameCSTR = tempName.toLocal8Bit();
106     char* tempNameC = tempNameCSTR.data();
107
108     int fileDescriptor;
109     while ((fileDescriptor = mkstemp(tempNameC)) == -1) {
110         if (errno != EINTR)
111             return 0;
112     }
113     while (fcntl(fileDescriptor, F_SETFD, FD_CLOEXEC) == -1) {
114         if (errno != EINTR) {
115             while (close(fileDescriptor) == -1 && errno == EINTR) { }
116             unlink(tempNameC);
117             return 0;
118         }
119     }
120
121     while (ftruncate(fileDescriptor, size) == -1) {
122         if (errno != EINTR) {
123             while (close(fileDescriptor) == -1 && errno == EINTR) { }
124             unlink(tempNameC);
125             return 0;
126         }
127     }
128
129     void* data = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileDescriptor, 0);
130     if (data == MAP_FAILED) {
131         while (close(fileDescriptor) == -1 && errno == EINTR) { }
132         unlink(tempNameC);
133         return 0;
134     }
135
136     unlink(tempNameC);
137
138     RefPtr<SharedMemory> instance = adoptRef(new SharedMemory());
139     instance->m_data = data;
140     instance->m_fileDescriptor = fileDescriptor;
141     instance->m_size = size;
142     return instance.release();
143 }
144
145 static inline int accessModeMMap(SharedMemory::Protection protection)
146 {
147     switch (protection) {
148     case SharedMemory::ReadOnly:
149         return PROT_READ;
150     case SharedMemory::ReadWrite:
151         return PROT_READ | PROT_WRITE;
152     }
153
154     ASSERT_NOT_REACHED();
155     return PROT_READ | PROT_WRITE;
156 }
157
158 PassRefPtr<SharedMemory> SharedMemory::create(const Handle& handle, Protection protection)
159 {
160     ASSERT(!handle.isNull());
161
162     void* data = mmap(0, handle.m_size, accessModeMMap(protection), MAP_SHARED, handle.m_fileDescriptor, 0);
163     if (data == MAP_FAILED)
164         return 0;
165
166     RefPtr<SharedMemory> instance = adoptRef(new SharedMemory());
167     instance->m_data = data;
168     instance->m_fileDescriptor = handle.m_fileDescriptor;
169     instance->m_size = handle.m_size;
170     handle.m_fileDescriptor = -1;
171     return instance;
172 }
173
174 SharedMemory::~SharedMemory()
175 {
176     munmap(m_data, m_size);
177     while (close(m_fileDescriptor) == -1 && errno == EINTR) { }
178 }
179
180 static inline int accessModeFile(SharedMemory::Protection protection)
181 {
182     switch (protection) {
183     case SharedMemory::ReadOnly:
184         return O_RDONLY;
185     case SharedMemory::ReadWrite:
186         return O_RDWR;
187     }
188
189     ASSERT_NOT_REACHED();
190     return O_RDWR;
191 }
192
193 bool SharedMemory::createHandle(Handle& handle, Protection protection)
194 {
195     ASSERT_ARG(handle, !handle.m_size);
196     ASSERT_ARG(handle, handle.isNull());
197
198     int duplicatedHandle;
199     while ((duplicatedHandle = dup(m_fileDescriptor)) == -1) {
200         if (errno != EINTR) {
201             ASSERT_NOT_REACHED();
202             return false;
203         }
204     }
205
206     while ((fcntl(duplicatedHandle, F_SETFD, FD_CLOEXEC | accessModeFile(protection)) == -1)) {
207         if (errno != EINTR) {
208             ASSERT_NOT_REACHED();
209             while (close(duplicatedHandle) == -1 && errno == EINTR) { }
210             return false;
211         }
212     }
213     handle.m_fileDescriptor = duplicatedHandle;
214     handle.m_size = m_size;
215     return true;
216 }
217
218 unsigned SharedMemory::systemPageSize()
219 {
220     static unsigned pageSize = 0;
221
222     if (!pageSize)
223         pageSize = getpagesize();
224
225     return pageSize;
226 }
227
228 } // namespace WebKit