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