11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*- 21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (c) 1990, 1993 31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * The Regents of the University of California. All rights reserved. 41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * This code is derived from software contributed to Berkeley by 61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Chris Torek. 71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Redistribution and use in source and binary forms, with or without 91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * modification, are permitted provided that the following conditions 101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * are met: 111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice, this list of conditions and the following disclaimer. 131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * documentation and/or other materials provided with the distribution. 161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 3. Neither the name of the University nor the names of its contributors 171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * may be used to endorse or promote products derived from this software 181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * without specific prior written permission. 191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * SUCH DAMAGE. 311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <errno.h> 3491875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes#include <signal.h> 351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdio.h> 361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdlib.h> 3791875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes#include <sys/stat.h> 3891875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes#include <sys/types.h> 3991875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes#include <unistd.h> 4091875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes 413e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes#include "private/ErrnoRestorer.h" 423e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes 4391875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughesclass ScopedSignalBlocker { 4491875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes public: 4591875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes ScopedSignalBlocker() { 4691875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes sigset_t set; 4791875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes sigfillset(&set); 4891875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes sigprocmask(SIG_BLOCK, &set, &old_set_); 4991875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes } 5091875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes 5191875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes ~ScopedSignalBlocker() { 5291875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes sigprocmask(SIG_SETMASK, &old_set_, NULL); 5391875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes } 541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5591875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes private: 5691875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes sigset_t old_set_; 5791875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes}; 581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5991875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughesstatic FILE* __tmpfile_dir(const char* tmp_dir) { 60b6943186ce78105155ba67ab261a970859b190dfElliott Hughes char* path = NULL; 61b6943186ce78105155ba67ab261a970859b190dfElliott Hughes if (asprintf(&path, "%s/tmp.XXXXXXXXXX", tmp_dir) == -1) { 6291875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes return NULL; 6391875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes } 641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6591875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes int fd; 6691875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes { 6791875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes ScopedSignalBlocker ssb; 68b6943186ce78105155ba67ab261a970859b190dfElliott Hughes fd = mkstemp(path); 6991875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes if (fd == -1) { 70b6943186ce78105155ba67ab261a970859b190dfElliott Hughes free(path); 7191875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes return NULL; 7291875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes } 731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7491875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes // Unlink the file now so that it's removed when closed. 75b6943186ce78105155ba67ab261a970859b190dfElliott Hughes unlink(path); 76b6943186ce78105155ba67ab261a970859b190dfElliott Hughes free(path); 771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7891875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes // Can we still use the file now it's unlinked? 7991875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes // File systems without hard link support won't have the usual Unix semantics. 8091875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes struct stat sb; 8191875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes int rc = fstat(fd, &sb); 8291875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes if (rc == -1) { 833e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes ErrnoRestorer errno_restorer; 8491875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes close(fd); 8591875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes return NULL; 8691875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes } 8791875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes } 8891875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes 8991875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes // Turn the file descriptor into a FILE*. 9091875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes FILE* fp = fdopen(fd, "w+"); 9191875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes if (fp != NULL) { 9291875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes return fp; 9391875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes } 9491875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes 9591875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes // Failure. Clean up. We already unlinked, so we just need to close. 963e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes ErrnoRestorer errno_restorer; 9791875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes close(fd); 9891875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes return NULL; 9991875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes} 1001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10191875dcd6e17b7f3b251efe9b236b905ef414ddeElliott HughesFILE* tmpfile() { 10291875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes // TODO: get this app's temporary directory from the framework ("/data/data/app/cache"). 1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10491875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes // $EXTERNAL_STORAGE turns out not to be very useful because it doesn't support hard links. 10591875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes // This means we can't do the usual trick of calling unlink before handing the file back. 1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10791875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes FILE* fp = __tmpfile_dir("/data/local/tmp"); 10891875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes if (fp == NULL) { 10991875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes // P_tmpdir is "/tmp/", but POSIX explicitly says that tmpdir(3) should try P_tmpdir before 11091875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes // giving up. This is potentially useful for bionic on the host anyway. 11191875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes fp = __tmpfile_dir(P_tmpdir); 11291875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes } 11391875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes return fp; 1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 115f226ee59e0effedeabed09e2d65be7fa7499cc25Elliott Hughes__strong_alias(tmpfile64, tmpfile); 116