1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Some utility functions for use with command-line utilities. 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "DexFile.h" 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "ZipArchive.h" 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "CmdUtils.h" 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h> 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <string.h> 251a777d230192f3f8c4d41f58f68b29ef2dbae9ffCarl Shapiro#include <strings.h> 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <fcntl.h> 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <errno.h> 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 29bf0cce6d471ffcd65161eca6e027e1b66f02f054Raphael#ifndef O_BINARY 30bf0cce6d471ffcd65161eca6e027e1b66f02f054Raphael#define O_BINARY 0 31bf0cce6d471ffcd65161eca6e027e1b66f02f054Raphael#endif 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Extract "classes.dex" from archive file. 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "quiet" is set, don't report common errors. 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectUnzipToFileResult dexUnzipToFile(const char* zipFileName, 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const char* outFileName, bool quiet) 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project UnzipToFileResult result = kUTFRSuccess; 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project static const char* kFileToExtract = "classes.dex"; 4339e8b7e287742ea1e1af58d6b25e12897cf66632Narayan Kamath ZipArchiveHandle archive; 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ZipEntry entry; 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool unlinkOnFailure = false; 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int fd = -1; 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dexZipOpenArchive(zipFileName, &archive) != 0) { 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!quiet) { 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fprintf(stderr, "Unable to open '%s' as zip archive\n", 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project zipFileName); 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result = kUTFRNotZip; 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 571506726d9ccd8404b3af6c51173f637cc88aaffeNarayan Kamath fd = open(outFileName, O_RDWR | O_CREAT | O_EXCL, 0600); 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (fd < 0) { 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fprintf(stderr, "Unable to create output file '%s': %s\n", 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project outFileName, strerror(errno)); 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result = kUTFROutputFileProblem; 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project unlinkOnFailure = true; 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 6739e8b7e287742ea1e1af58d6b25e12897cf66632Narayan Kamath if (dexZipFindEntry(archive, kFileToExtract, &entry) != 0) { 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!quiet) { 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fprintf(stderr, "Unable to find '%s' in '%s'\n", 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kFileToExtract, zipFileName); 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result = kUTFRNoClassesDex; 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 7639e8b7e287742ea1e1af58d6b25e12897cf66632Narayan Kamath if (dexZipExtractEntryToFile(archive, &entry, fd) != 0) { 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fprintf(stderr, "Extract of '%s' from '%s' failed\n", 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kFileToExtract, zipFileName); 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result = kUTFRBadZip; 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (fd >= 0) 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project close(fd); 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (unlinkOnFailure && result != kUTFRSuccess) 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project unlink(outFileName); 881506726d9ccd8404b3af6c51173f637cc88aaffeNarayan Kamath dexZipCloseArchive(archive); 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return result; 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Map the specified DEX file read-only (possibly after expanding it into a 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * temp file from a Jar). Pass in a MemMapping struct to hold the info. 954b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein * If the file is an unoptimized DEX file, then byte-swapping and structural 964b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein * verification are performed on it before the memory is made read-only. 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The temp file is deleted after the map succeeds. 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is intended for use by tools (e.g. dexdump) that need to get a 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * read-only copy of a DEX file that could be in a number of different states. 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1034b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein * If "tempFileName" is NULL, a default value is used. The temp file is 1044b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein * deleted after the map succeeds. 1054b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein * 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "quiet" is set, don't report common errors. 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 108bcb095953a1a4a91d86911377e4bc1a72a56e891Andy McFadden * Returns 0 (kUTFRSuccess) on success. 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectUnzipToFileResult dexOpenAndMap(const char* fileName, const char* tempFileName, 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project MemMapping* pMap, bool quiet) 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 113bcb095953a1a4a91d86911377e4bc1a72a56e891Andy McFadden UnzipToFileResult result = kUTFRGenericFailure; 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int len = strlen(fileName); 115a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden char tempNameBuf[32]; 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool removeTemp = false; 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int fd = -1; 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (len < 5) { 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!quiet) { 121de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro fprintf(stderr, 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "ERROR: filename must end in .dex, .zip, .jar, or .apk\n"); 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result = kUTFRBadArgs; 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (strcasecmp(fileName + len -3, "dex") != 0) { 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (tempFileName == NULL) { 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Try .zip/.jar/.apk, all of which are Zip archives with 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "classes.dex" inside. We need to extract the compressed 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * data to a temp file, the location of which varies. 134c49ec998a1d575eb950c529eacb837efbbc3fe17Andy McFadden * 135c49ec998a1d575eb950c529eacb837efbbc3fe17Andy McFadden * On the device we must use /sdcard because most other 136c49ec998a1d575eb950c529eacb837efbbc3fe17Andy McFadden * directories aren't writable (either because of permissions 137c49ec998a1d575eb950c529eacb837efbbc3fe17Andy McFadden * or because the volume is mounted read-only). On desktop 138c49ec998a1d575eb950c529eacb837efbbc3fe17Andy McFadden * it's nice to use the designated temp directory. 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 140c49ec998a1d575eb950c529eacb837efbbc3fe17Andy McFadden if (access("/tmp", W_OK) == 0) { 141a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden sprintf(tempNameBuf, "/tmp/dex-temp-%d", getpid()); 142c49ec998a1d575eb950c529eacb837efbbc3fe17Andy McFadden } else if (access("/sdcard", W_OK) == 0) { 143a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden sprintf(tempNameBuf, "/sdcard/dex-temp-%d", getpid()); 144c49ec998a1d575eb950c529eacb837efbbc3fe17Andy McFadden } else { 145c49ec998a1d575eb950c529eacb837efbbc3fe17Andy McFadden fprintf(stderr, 146c49ec998a1d575eb950c529eacb837efbbc3fe17Andy McFadden "NOTE: /tmp and /sdcard unavailable for temp files\n"); 147c49ec998a1d575eb950c529eacb837efbbc3fe17Andy McFadden sprintf(tempNameBuf, "dex-temp-%d", getpid()); 148c49ec998a1d575eb950c529eacb837efbbc3fe17Andy McFadden } 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 150a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden tempFileName = tempNameBuf; 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 153bcb095953a1a4a91d86911377e4bc1a72a56e891Andy McFadden result = dexUnzipToFile(fileName, tempFileName, quiet); 154de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (result == kUTFRSuccess) { 156a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden //printf("+++ Good unzip to '%s'\n", tempFileName); 157bcb095953a1a4a91d86911377e4bc1a72a56e891Andy McFadden fileName = tempFileName; 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project removeTemp = true; 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (result == kUTFRNotZip) { 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!quiet) { 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fprintf(stderr, "Not Zip, retrying as DEX\n"); 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!quiet && result == kUTFRNoClassesDex) { 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fprintf(stderr, "Zip has no classes.dex\n"); 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1714b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein result = kUTFRGenericFailure; 1724b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pop open the (presumed) DEX file. 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 176b4719eda048c4dc4a4b6e5280c7a2b8299051078Raphael Moll fd = open(fileName, O_RDONLY | O_BINARY); 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (fd < 0) { 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!quiet) { 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fprintf(stderr, "ERROR: unable to open '%s': %s\n", 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fileName, strerror(errno)); 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1854b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein if (sysMapFileInShmemWritableReadOnly(fd, pMap) != 0) { 1864b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein fprintf(stderr, "ERROR: Unable to map '%s'\n", fileName); 1874b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein goto bail; 1884b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein } 1894b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein 1904b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein /* 1914b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein * This call will fail if the file exists on a filesystem that 1924b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein * doesn't support mprotect(). If that's the case, then the file 1934b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein * will have already been mapped private-writable by the previous 1944b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein * call, so we don't need to do anything special if this call 1954b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein * returns non-zero. 1964b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein */ 1974b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein sysChangeMapAccess(pMap->addr, pMap->length, true, pMap); 1984b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein 199a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein if (dexSwapAndVerifyIfNecessary((u1*) pMap->addr, pMap->length)) { 2004b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein fprintf(stderr, "ERROR: Failed structural verification of '%s'\n", 2014b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein fileName); 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 2064b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein * Similar to above, this call will fail if the file wasn't ever 2074b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein * read-only to begin with. This is innocuous, though it is 2084b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein * undesirable from a memory hygiene perspective. 2094b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein */ 2104b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein sysChangeMapAccess(pMap->addr, pMap->length, false, pMap); 2114b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein 2124b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein /* 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Success! Close the file and return with the start/length in pMap. 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 215a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein result = kUTFRSuccess; 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (fd >= 0) 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project close(fd); 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (removeTemp) { 221c49ec998a1d575eb950c529eacb837efbbc3fe17Andy McFadden /* this will fail if the OS doesn't allow removal of a mapped file */ 222a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden if (unlink(tempFileName) != 0) { 2234b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein fprintf(stderr, "WARNING: unable to remove temp '%s'\n", 224a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden tempFileName); 225a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden } 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return result; 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 229