OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 #include <assert.h> | |
6 #include <errno.h> | |
7 #include <stdlib.h> | |
8 #include <string.h> | |
9 | |
10 #include "dart_archive.h" | |
11 #include "entry.h" | |
12 #include "messaging.h" | |
13 #include "reader.h" | |
14 | |
15 /** The enumeration of request types for communicating with Dart. */ | |
16 enum RequestType { | |
17 kArchiveReadNew = 0, | |
18 kArchiveReadSupportFilterAll, | |
19 kArchiveReadSupportFilterBzip2, | |
20 kArchiveReadSupportFilterCompress, | |
21 kArchiveReadSupportFilterGzip, | |
22 kArchiveReadSupportFilterLzma, | |
23 kArchiveReadSupportFilterXz, | |
24 kArchiveReadSupportFilterProgram, | |
25 kArchiveReadSupportFilterProgramSignature, | |
26 kArchiveReadSupportFormatAll, | |
27 kArchiveReadSupportFormatAr, | |
28 kArchiveReadSupportFormatCpio, | |
29 kArchiveReadSupportFormatEmpty, | |
30 kArchiveReadSupportFormatIso9660, | |
31 kArchiveReadSupportFormatMtree, | |
32 kArchiveReadSupportFormatRaw, | |
33 kArchiveReadSupportFormatTar, | |
34 kArchiveReadSupportFormatZip, | |
35 kArchiveReadSetFilterOption, | |
36 kArchiveReadSetFormatOption, | |
37 kArchiveReadSetOption, | |
38 kArchiveReadOpenFilename, | |
39 kArchiveReadOpenMemory, | |
40 kArchiveReadNextHeader, | |
41 kArchiveReadDataBlock, | |
42 kArchiveReadDataSkip, | |
43 kArchiveReadClose, | |
44 kArchiveReadFree, | |
45 kArchiveEntryClone, | |
46 kArchiveEntryFree, | |
47 kArchiveEntryNew, | |
48 kArchiveEntrySetHardlink, | |
49 kArchiveEntrySetPathname, | |
50 kArchiveEntrySetSymlink, | |
51 kArchiveEntrySetGid, | |
52 kArchiveEntrySetUid, | |
53 kArchiveEntrySetPerm, | |
54 kArchiveEntrySetGname, | |
55 kArchiveEntrySetUname, | |
56 kArchiveEntrySetFflagsSet, | |
57 kArchiveEntrySetFflagsClear, | |
58 kArchiveEntrySetFflagsText, | |
59 kArchiveEntrySetFiletype, | |
60 kArchiveEntrySetMode, | |
61 kArchiveEntrySetSize, | |
62 kArchiveEntrySetDev, | |
63 kArchiveEntrySetDevmajor, | |
64 kArchiveEntrySetDevminor, | |
65 kArchiveEntrySetIno, | |
66 kArchiveEntrySetNlink, | |
67 kArchiveEntrySetRdev, | |
68 kArchiveEntrySetRdevmajor, | |
69 kArchiveEntrySetRdevminor, | |
70 kArchiveEntrySetAtime, | |
71 kArchiveEntrySetBirthtime, | |
72 kArchiveEntrySetCtime, | |
73 kArchiveEntrySetMtime, | |
74 kNumberOfRequestTypes | |
75 }; | |
76 | |
77 /** | |
78 * Dispatches a message from Dart to its native function equivalent. | |
79 * | |
80 * In addition to matching up a message with its respective function, this | |
81 * parses out the standard archive struct argument from the message and resolves | |
82 * it to an actual pointer to an archive struct. | |
83 */ | |
84 static void archiveDispatch(Dart_Port dest_port_id, | |
85 Dart_Port reply_port_id, | |
86 Dart_CObject* message) { | |
87 if (message->type != kArray) { | |
88 postInvalidArgument(reply_port_id, "Message was not an array."); | |
89 return; | |
90 } else if (message->value.as_array.length < 2) { | |
91 postInvalidArgument(reply_port_id, "Message array had %d elements, " \ | |
92 "expected at least 2.", message->value.as_array.length); | |
93 return; | |
94 } | |
95 | |
96 Dart_CObject* wrapped_request_type = message->value.as_array.values[0]; | |
97 if (wrapped_request_type->type != kInt32) { | |
98 postInvalidArgument(reply_port_id, "Invalid request type %d.", | |
99 wrapped_request_type->type); | |
100 return; | |
101 } | |
102 enum RequestType request_type = wrapped_request_type->value.as_int32; | |
103 | |
104 Dart_CObject* id = message->value.as_array.values[1]; | |
105 void* ptr; | |
106 if (id->type == kNull) { | |
107 ptr = NULL; | |
108 } else if (id->type == kInt64 || id->type == kInt32) { | |
109 ptr = (void*) (intptr_t) getInteger(id); | |
110 } else { | |
111 postInvalidArgument(reply_port_id, "Invalid id type %d.", id->type); | |
112 return; | |
113 } | |
114 | |
115 switch (request_type) { | |
116 case kArchiveReadNew: | |
117 archiveReadNew(reply_port_id); | |
118 break; | |
119 case kArchiveReadSupportFilterAll: | |
120 archiveReadSupportFilterAll(reply_port_id, (struct archive*) ptr); | |
121 break; | |
122 case kArchiveReadSupportFilterBzip2: | |
123 archiveReadSupportFilterBzip2(reply_port_id, (struct archive*) ptr); | |
124 break; | |
125 case kArchiveReadSupportFilterCompress: | |
126 archiveReadSupportFilterCompress(reply_port_id, (struct archive*) ptr); | |
127 break; | |
128 case kArchiveReadSupportFilterGzip: | |
129 archiveReadSupportFilterGzip(reply_port_id, (struct archive*) ptr); | |
130 break; | |
131 case kArchiveReadSupportFilterLzma: | |
132 archiveReadSupportFilterLzma(reply_port_id, (struct archive*) ptr); | |
133 break; | |
134 case kArchiveReadSupportFilterXz: | |
135 archiveReadSupportFilterXz(reply_port_id, (struct archive*) ptr); | |
136 break; | |
137 case kArchiveReadSupportFilterProgram: | |
138 archiveReadSupportFilterProgram( | |
139 reply_port_id, (struct archive*) ptr, message); | |
140 break; | |
141 case kArchiveReadSupportFilterProgramSignature: | |
142 archiveReadSupportFilterProgramSignature( | |
143 reply_port_id, (struct archive*) ptr, message); | |
144 break; | |
145 case kArchiveReadSupportFormatAll: | |
146 archiveReadSupportFormatAll(reply_port_id, (struct archive*) ptr); | |
147 break; | |
148 case kArchiveReadSupportFormatAr: | |
149 archiveReadSupportFormatAr(reply_port_id, (struct archive*) ptr); | |
150 break; | |
151 case kArchiveReadSupportFormatCpio: | |
152 archiveReadSupportFormatCpio(reply_port_id, (struct archive*) ptr); | |
153 break; | |
154 case kArchiveReadSupportFormatEmpty: | |
155 archiveReadSupportFormatEmpty(reply_port_id, (struct archive*) ptr); | |
156 break; | |
157 case kArchiveReadSupportFormatIso9660: | |
158 archiveReadSupportFormatIso9660(reply_port_id, (struct archive*) ptr); | |
159 break; | |
160 case kArchiveReadSupportFormatMtree: | |
161 archiveReadSupportFormatMtree(reply_port_id, (struct archive*) ptr); | |
162 break; | |
163 case kArchiveReadSupportFormatRaw: | |
164 archiveReadSupportFormatRaw(reply_port_id, (struct archive*) ptr); | |
165 break; | |
166 case kArchiveReadSupportFormatTar: | |
167 archiveReadSupportFormatTar(reply_port_id, (struct archive*) ptr); | |
168 break; | |
169 case kArchiveReadSupportFormatZip: | |
170 archiveReadSupportFormatZip(reply_port_id, (struct archive*) ptr); | |
171 break; | |
172 case kArchiveReadSetFilterOption: | |
173 archiveReadSetFilterOption(reply_port_id, (struct archive*) ptr, message); | |
174 break; | |
175 case kArchiveReadSetFormatOption: | |
176 archiveReadSetFormatOption(reply_port_id, (struct archive*) ptr, message); | |
177 break; | |
178 case kArchiveReadSetOption: | |
179 archiveReadSetOption(reply_port_id, (struct archive*) ptr, message); | |
180 break; | |
181 case kArchiveReadOpenFilename: | |
182 archiveReadOpenFilename(reply_port_id, (struct archive*) ptr, message); | |
183 break; | |
184 case kArchiveReadOpenMemory: | |
185 archiveReadOpenMemory(reply_port_id, (struct archive*) ptr, message); | |
186 break; | |
187 case kArchiveReadNextHeader: | |
188 archiveReadNextHeader(reply_port_id, (struct archive*) ptr); | |
189 break; | |
190 case kArchiveReadDataBlock: | |
191 archiveReadDataBlock(reply_port_id, (struct archive*) ptr); | |
192 break; | |
193 case kArchiveReadDataSkip: | |
194 archiveReadDataSkip(reply_port_id, (struct archive*) ptr); | |
195 break; | |
196 case kArchiveReadClose: | |
197 archiveReadClose(reply_port_id, (struct archive*) ptr); | |
198 break; | |
199 case kArchiveReadFree: | |
200 archiveReadFree(reply_port_id, (struct archive*) ptr); | |
201 break; | |
202 case kArchiveEntryClone: | |
203 archiveEntryClone(reply_port_id, (struct archive_entry*) ptr); | |
204 break; | |
205 case kArchiveEntryFree: | |
206 archiveEntryFree(reply_port_id, (struct archive_entry*) ptr); | |
207 break; | |
208 case kArchiveEntryNew: | |
209 archiveEntryNew(reply_port_id); | |
210 break; | |
211 case kArchiveEntrySetHardlink: | |
212 archiveEntrySetHardlink( | |
213 reply_port_id, (struct archive_entry*) ptr, message); | |
214 break; | |
215 case kArchiveEntrySetPathname: | |
216 archiveEntrySetPathname( | |
217 reply_port_id, (struct archive_entry*) ptr, message); | |
218 break; | |
219 case kArchiveEntrySetSymlink: | |
220 archiveEntrySetSymlink(reply_port_id, (struct archive_entry*) ptr, message); | |
221 break; | |
222 case kArchiveEntrySetGid: | |
223 archiveEntrySetGid(reply_port_id, (struct archive_entry*) ptr, message); | |
224 break; | |
225 case kArchiveEntrySetUid: | |
226 archiveEntrySetUid(reply_port_id, (struct archive_entry*) ptr, message); | |
227 break; | |
228 case kArchiveEntrySetPerm: | |
229 archiveEntrySetPerm(reply_port_id, (struct archive_entry*) ptr, message); | |
230 break; | |
231 case kArchiveEntrySetGname: | |
232 archiveEntrySetGname(reply_port_id, (struct archive_entry*) ptr, message); | |
233 break; | |
234 case kArchiveEntrySetUname: | |
235 archiveEntrySetUname(reply_port_id, (struct archive_entry*) ptr, message); | |
236 break; | |
237 case kArchiveEntrySetFflagsSet: | |
238 archiveEntrySetFflagsSet( | |
239 reply_port_id, (struct archive_entry*) ptr, message); | |
240 break; | |
241 case kArchiveEntrySetFflagsClear: | |
242 archiveEntrySetFflagsClear( | |
243 reply_port_id, (struct archive_entry*) ptr, message); | |
244 break; | |
245 case kArchiveEntrySetFiletype: | |
246 archiveEntrySetFiletype( | |
247 reply_port_id, (struct archive_entry*) ptr, message); | |
248 break; | |
249 case kArchiveEntrySetMode: | |
250 archiveEntrySetMode(reply_port_id, (struct archive_entry*) ptr, message); | |
251 break; | |
252 case kArchiveEntrySetSize: | |
253 archiveEntrySetSize(reply_port_id, (struct archive_entry*) ptr, message); | |
254 break; | |
255 case kArchiveEntrySetDev: | |
256 archiveEntrySetDev(reply_port_id, (struct archive_entry*) ptr, message); | |
257 break; | |
258 case kArchiveEntrySetDevmajor: | |
259 archiveEntrySetDevmajor( | |
260 reply_port_id, (struct archive_entry*) ptr, message); | |
261 break; | |
262 case kArchiveEntrySetDevminor: | |
263 archiveEntrySetDevminor( | |
264 reply_port_id, (struct archive_entry*) ptr, message); | |
265 break; | |
266 case kArchiveEntrySetIno: | |
267 archiveEntrySetIno(reply_port_id, (struct archive_entry*) ptr, message); | |
268 break; | |
269 case kArchiveEntrySetNlink: | |
270 archiveEntrySetNlink(reply_port_id, (struct archive_entry*) ptr, message); | |
271 break; | |
272 case kArchiveEntrySetRdev: | |
273 archiveEntrySetRdev(reply_port_id, (struct archive_entry*) ptr, message); | |
274 break; | |
275 case kArchiveEntrySetRdevmajor: | |
276 archiveEntrySetRdevmajor( | |
277 reply_port_id, (struct archive_entry*) ptr, message); | |
278 break; | |
279 case kArchiveEntrySetRdevminor: | |
280 archiveEntrySetRdevminor( | |
281 reply_port_id, (struct archive_entry*) ptr, message); | |
282 break; | |
283 case kArchiveEntrySetAtime: | |
284 archiveEntrySetAtime(reply_port_id, (struct archive_entry*) ptr, message); | |
285 break; | |
286 case kArchiveEntrySetBirthtime: | |
287 archiveEntrySetBirthtime( | |
288 reply_port_id, (struct archive_entry*) ptr, message); | |
289 break; | |
290 case kArchiveEntrySetCtime: | |
291 archiveEntrySetCtime(reply_port_id, (struct archive_entry*) ptr, message); | |
292 break; | |
293 case kArchiveEntrySetMtime: | |
294 archiveEntrySetMtime(reply_port_id, (struct archive_entry*) ptr, message); | |
295 break; | |
296 default: | |
297 postInvalidArgument(reply_port_id, "Invalid request id %d.", request_type); | |
298 break; | |
299 } | |
300 } | |
301 | |
302 /** | |
303 * Checks if [handle] represents an error and, if so, propagates it to Dart. | |
304 * Otherwise, returns [handle]. | |
305 */ | |
306 static Dart_Handle handleError(Dart_Handle handle) { | |
307 if (Dart_IsError(handle)) Dart_PropagateError(handle); | |
308 return handle; | |
309 } | |
310 | |
311 /** | |
312 * A function exposed to Dart that creates a [ServicePort] for two-way | |
313 * communication between Dart and C. | |
314 * | |
315 * Takes no arguments and returns a [ServicePort]. | |
316 */ | |
317 static void archiveServicePort(Dart_NativeArguments arguments) { | |
318 Dart_EnterScope(); | |
319 Dart_SetReturnValue(arguments, Dart_Null()); | |
320 Dart_Port service_port = | |
321 Dart_NewNativePort("ArchiveService", archiveDispatch, false); | |
322 if (service_port != ILLEGAL_PORT) { | |
323 Dart_Handle send_port = handleError(Dart_NewSendPort(service_port)); | |
324 Dart_SetReturnValue(arguments, send_port); | |
325 } | |
326 Dart_ExitScope(); | |
327 } | |
328 | |
329 /** | |
330 * The C callback that runs the Dart finalizer for an object. Set up by | |
331 * [attachDartFinalizer]. [handle] is the object that's been collected, and | |
332 * [peerPtr] is a Dart list containing the callback and its argument. | |
333 */ | |
334 static void runDartFinalizer(Dart_Handle handle, void* peerPtr) { | |
335 Dart_EnterScope(); | |
336 Dart_Handle wrappedPeer = (Dart_Handle) peerPtr; | |
337 Dart_Handle callback = handleError(Dart_ListGetAt(wrappedPeer, 0)); | |
338 Dart_Handle peer = handleError(Dart_ListGetAt(wrappedPeer, 1)); | |
339 | |
340 handleError(Dart_InvokeClosure(callback, 1, &peer)); | |
341 Dart_DeletePersistentHandle(wrappedPeer); | |
342 Dart_ExitScope(); | |
343 } | |
344 | |
345 /** | |
346 * Attaches a finalizer callback to a Dart object. | |
347 * | |
348 * This takes a Dart object, a callback function, and an argument to pass to the | |
349 * callback function. The callback will be called with the given argument some | |
350 * time after the object has been garbage collected. | |
351 */ | |
352 static void attachDartFinalizer(Dart_NativeArguments arguments) { | |
353 Dart_EnterScope(); | |
354 Dart_SetReturnValue(arguments, Dart_Null()); | |
355 Dart_Handle object = handleError(Dart_GetNativeArgument(arguments, 0)); | |
356 Dart_Handle callback = handleError(Dart_GetNativeArgument(arguments, 1)); | |
357 Dart_Handle peer = handleError(Dart_GetNativeArgument(arguments, 2)); | |
358 | |
359 Dart_Handle wrappedPeer = handleError(Dart_NewList(2)); | |
360 handleError(Dart_ListSetAt(wrappedPeer, 0, callback)); | |
361 handleError(Dart_ListSetAt(wrappedPeer, 1, peer)); | |
362 wrappedPeer = handleError(Dart_NewPersistentHandle(wrappedPeer)); | |
363 | |
364 handleError(Dart_NewWeakPersistentHandle( | |
365 object, wrappedPeer, runDartFinalizer)); | |
366 Dart_ExitScope(); | |
367 } | |
368 | |
369 /** | |
370 * A struct representing a function exposed to Dart and the name under which it | |
371 * can be looked up. | |
372 */ | |
373 struct FunctionLookup { | |
374 const char* name; | |
375 Dart_NativeFunction function; | |
376 }; | |
377 | |
378 /** The list of functions exposed to Dart. */ | |
379 struct FunctionLookup function_list[] = { | |
380 {"Archive_ServicePort", archiveServicePort}, | |
381 {"Archive_AttachFinalizer", attachDartFinalizer}, | |
382 {NULL, NULL} | |
383 }; | |
384 | |
385 /** | |
386 * Resolves a Dart name as provided in a `native` declaration and returns the | |
387 * C function that should be invoked for that name. | |
388 */ | |
389 static Dart_NativeFunction resolveName(Dart_Handle name, int argc) { | |
390 if (!Dart_IsString8(name)) return NULL; | |
391 Dart_EnterScope(); | |
392 const char* cname; | |
393 handleError(Dart_StringToCString(name, &cname)); | |
394 | |
395 Dart_NativeFunction result = NULL; | |
396 int i; | |
397 for (i = 0; function_list[i].name != NULL; ++i) { | |
398 if (strcmp(function_list[i].name, cname) == 0) { | |
399 result = function_list[i].function; | |
400 break; | |
401 } | |
402 } | |
403 Dart_ExitScope(); | |
404 return result; | |
405 } | |
406 | |
407 /** Initializes the C extension. */ | |
408 DART_EXPORT Dart_Handle dart_archive_Init(Dart_Handle parent_library) { | |
409 if (Dart_IsError(parent_library)) return parent_library; | |
410 | |
411 Dart_Handle result_code = Dart_SetNativeResolver(parent_library, resolveName); | |
412 if (Dart_IsError(result_code)) return result_code; | |
413 | |
414 return Dart_Null(); | |
415 } | |
OLD | NEW |