18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Copyright (C) 2007-2008 The Android Open Source Project
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project**
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This software is licensed under the terms of the GNU General Public
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** License version 2, as published by the Free Software Foundation, and
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** may be copied, distributed, and modified under those terms.
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project**
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This program is distributed in the hope that it will be useful,
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** but WITHOUT ANY WARRANTY; without even the implied warranty of
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** GNU General Public License for more details.
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/utils/tempfile.h"
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/utils/bufprint.h"
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/utils/debug.h"
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdlib.h>
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <string.h>
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <fcntl.h>
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define WIN32_LEAN_AND_MEAN
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  include <windows.h>
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  include <unistd.h>
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  D(...)  ((void)0)
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/** TEMP FILE SUPPORT
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ** simple interface to create an empty temporary file on the system.
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ** create the file with tempfile_create(), which returns a reference to a TempFile
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ** object, or NULL if your system is so weird it doesn't have a temporary directory.
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ** you can then call tempfile_path() to retrieve the TempFile's real path to open
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ** it. the returned path is owned by the TempFile object and should not be freed.
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ** all temporary files are destroyed when the program quits, unless you explicitely
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ** close them before that with tempfile_close()
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **/
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct TempFile
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*  name;
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TempFile*    next;
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void       tempfile_atexit();
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic TempFile*  _all_tempfiles;
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectTempFile*
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttempfile_create( void )
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TempFile*    tempfile;
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*  tempname = NULL;
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char  temp_namebuff[MAX_PATH];
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char  temp_dir[MAX_PATH];
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char  *p = temp_dir, *end = p + sizeof(temp_dir);
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    UINT  retval;
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p = bufprint_temp_dir( p, end );
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (p >= end) {
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D( "TEMP directory path is too long" );
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    retval = GetTempFileName(temp_dir, "TMP", 0, temp_namebuff);
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (retval == 0) {
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D( "can't create temporary file in '%s'", temp_dir );
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tempname = temp_namebuff;
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  TEMPLATE  "/tmp/.android-emulator-XXXXXX"
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   tempfd = -1;
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char  template[512];
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char  *p = template, *end = p + sizeof(template);
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p = bufprint_temp_file( p, end, "emulator-XXXXXX" );
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (p >= end) {
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D( "Xcannot create temporary file in /tmp/android !!" );
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    D( "template: %s", template );
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tempfd = mkstemp( template );
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (tempfd < 0) {
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D("cannot create temporary file in /tmp/android !!");
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    close(tempfd);
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tempname = template;
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tempfile = malloc( sizeof(*tempfile) + strlen(tempname) + 1 );
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tempfile->name = (char*)(tempfile + 1);
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    strcpy( (char*)tempfile->name, tempname );
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tempfile->next = _all_tempfiles;
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    _all_tempfiles = tempfile;
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !tempfile->next ) {
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        atexit( tempfile_atexit );
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tempfile;
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectconst char*
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttempfile_path(TempFile*  temp)
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return temp ? temp->name : NULL;
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttempfile_close(TempFile*  tempfile)
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DeleteFile(tempfile->name);
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unlink(tempfile->name);
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/** TEMP FILE CLEANUP
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **/
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* we don't expect to use many temporary files */
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define MAX_ATEXIT_FDS  16
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct {
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   count;
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   fds[ MAX_ATEXIT_FDS ];
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} AtExitFds;
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectatexit_fds_add( AtExitFds*  t, int  fd )
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (t->count < MAX_ATEXIT_FDS)
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        t->fds[t->count++] = fd;
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else {
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dwarning("%s: over %d calls. Program exit may not cleanup all temporary files",
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            __FUNCTION__, MAX_ATEXIT_FDS);
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectatexit_fds_del( AtExitFds*  t, int  fd )
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < t->count; nn++)
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (t->fds[nn] == fd) {
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* move the last element to the current position */
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            t->count  -= 1;
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            t->fds[nn] = t->fds[t->count];
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectatexit_fds_close_all( AtExitFds*  t )
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < t->count; nn++)
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        close(t->fds[nn]);
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic AtExitFds   _atexit_fds[1];
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectatexit_close_fd(int  fd)
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (fd >= 0)
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        atexit_fds_add(_atexit_fds, fd);
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectatexit_close_fd_remove(int  fd)
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (fd >= 0)
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        atexit_fds_del(_atexit_fds, fd);
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttempfile_atexit( void )
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TempFile*  tempfile;
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    atexit_fds_close_all( _atexit_fds );
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (tempfile = _all_tempfiles; tempfile; tempfile = tempfile->next)
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tempfile_close(tempfile);
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
199