tmpfile.cpp revision 91875dcd6e17b7f3b251efe9b236b905ef414dde
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 4191875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughesclass ScopedSignalBlocker { 4291875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes public: 4391875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes ScopedSignalBlocker() { 4491875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes sigset_t set; 4591875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes sigfillset(&set); 4691875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes sigprocmask(SIG_BLOCK, &set, &old_set_); 4791875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes } 4891875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes 4991875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes ~ScopedSignalBlocker() { 5091875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes sigprocmask(SIG_SETMASK, &old_set_, NULL); 5191875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes } 521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5391875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes private: 5491875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes sigset_t old_set_; 5591875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes}; 561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5791875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughesstatic FILE* __tmpfile_dir(const char* tmp_dir) { 5891875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes char buf[PATH_MAX]; 5991875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes int path_length = snprintf(buf, sizeof(buf), "%s/tmp.XXXXXXXXXX", tmp_dir); 6091875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes if (path_length >= sizeof(buf)) { 6191875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes return NULL; 6291875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes } 631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6491875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes int fd; 6591875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes { 6691875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes ScopedSignalBlocker ssb; 6791875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes fd = mkstemp(buf); 6891875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes if (fd == -1) { 6991875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes return NULL; 7091875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes } 711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7291875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes // Unlink the file now so that it's removed when closed. 7391875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes unlink(buf); 741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7591875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes // Can we still use the file now it's unlinked? 7691875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes // File systems without hard link support won't have the usual Unix semantics. 7791875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes struct stat sb; 7891875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes int rc = fstat(fd, &sb); 7991875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes if (rc == -1) { 8091875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes int old_errno = errno; 8191875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes close(fd); 8291875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes errno = old_errno; 8391875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes return NULL; 8491875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes } 8591875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes } 8691875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes 8791875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes // Turn the file descriptor into a FILE*. 8891875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes FILE* fp = fdopen(fd, "w+"); 8991875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes if (fp != NULL) { 9091875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes return fp; 9191875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes } 9291875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes 9391875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes // Failure. Clean up. We already unlinked, so we just need to close. 9491875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes int old_errno = errno; 9591875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes close(fd); 9691875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes errno = old_errno; 9791875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes return NULL; 9891875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes} 991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10091875dcd6e17b7f3b251efe9b236b905ef414ddeElliott HughesFILE* tmpfile() { 10191875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes // TODO: get this app's temporary directory from the framework ("/data/data/app/cache"). 1021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10391875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes // $EXTERNAL_STORAGE turns out not to be very useful because it doesn't support hard links. 10491875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes // This means we can't do the usual trick of calling unlink before handing the file back. 1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10691875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes FILE* fp = __tmpfile_dir("/data/local/tmp"); 10791875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes if (fp == NULL) { 10891875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes // P_tmpdir is "/tmp/", but POSIX explicitly says that tmpdir(3) should try P_tmpdir before 10991875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes // giving up. This is potentially useful for bionic on the host anyway. 11091875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes fp = __tmpfile_dir(P_tmpdir); 11191875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes } 11291875dcd6e17b7f3b251efe9b236b905ef414ddeElliott Hughes return fp; 1131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 114