| 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 |