diff options
Diffstat (limited to 'sal/osl/os2/tempfile.c')
-rw-r--r-- | sal/osl/os2/tempfile.c | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/sal/osl/os2/tempfile.c b/sal/osl/os2/tempfile.c new file mode 100644 index 000000000000..f6f80f79e69a --- /dev/null +++ b/sal/osl/os2/tempfile.c @@ -0,0 +1,362 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tempfile.c,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +/*****************************************************************/ +/* Includes */ +/*****************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/time.h> +#include "system.h" +#include <osl/file.h> +#include <osl/thread.h> +#include <rtl/ustrbuf.h> +#include <osl/diagnose.h> + +#ifndef _FILE_URL_H_ +#include "file_url.h" +#endif + +/*****************************************************************/ +/* osl_getTempFirURL */ +/*****************************************************************/ + +oslFileError SAL_CALL osl_getTempDirURL( rtl_uString** pustrTempDir ) +{ + const char *pValue = getenv( "TEMP" ); + + if ( !pValue ) + { + pValue = getenv( "TMP" ); +#if defined(SOLARIS) || defined (LINUX) || defined (FREEBSD) || defined (MACOSX) + if ( !pValue ) + pValue = P_tmpdir; +#endif + } + + if ( pValue ) + { + oslFileError error; + rtl_uString *ustrTempPath = NULL; + + rtl_string2UString( &ustrTempPath, pValue, strlen( pValue ), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS ); + OSL_ASSERT(ustrTempPath != NULL); + error = osl_getFileURLFromSystemPath( ustrTempPath, pustrTempDir ); + rtl_uString_release( ustrTempPath ); + + return error; + } + else + return osl_File_E_NOENT; +} + +/****************************************************************** + * Generates a random unique file name. We're using the scheme + * from the standard c-lib function mkstemp to generate a more + * or less random unique file name + * + * @param rand_name + * receives the random name + ******************************************************************/ + +static const char LETTERS[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; +static const int COUNT_OF_LETTERS = sizeof(LETTERS)/sizeof(LETTERS[0]) - 1; + +#define RAND_NAME_LENGTH 6 + +static void osl_gen_random_name_impl_(rtl_uString** rand_name) +{ + static uint64_t value; + + char buffer[RAND_NAME_LENGTH]; + struct timeval tv; + uint64_t v; + int i; + + gettimeofday(&tv, NULL); + + value += ((uint64_t)tv.tv_usec << 16) ^ tv.tv_sec ^ getpid(); + + v = value; + + for (i = 0; i < RAND_NAME_LENGTH; i++) + { + buffer[i] = LETTERS[v % COUNT_OF_LETTERS]; + v /= COUNT_OF_LETTERS; + } + + rtl_string2UString( + rand_name, + buffer, + RAND_NAME_LENGTH, + RTL_TEXTENCODING_ASCII_US, + OSTRING_TO_OUSTRING_CVTFLAGS); + OSL_ASSERT(*rand_name != NULL); +} + +/***************************************************************** + * Helper function + * Either use the directory provided or the result of + * osl_getTempDirUrl and return it as system path and file url + ****************************************************************/ + +static oslFileError osl_setup_base_directory_impl_( + rtl_uString* pustrDirectoryURL, + rtl_uString** ppustr_base_dir) +{ + rtl_uString* dir_url = 0; + rtl_uString* dir = 0; + oslFileError error = osl_File_E_None; + + if (pustrDirectoryURL) + rtl_uString_assign(&dir_url, pustrDirectoryURL); + else + error = osl_getTempDirURL(&dir_url); + + if (osl_File_E_None == error) + { + error = osl_getSystemPathFromFileURL_Ex(dir_url, &dir, FURL_DENY_RELATIVE); + rtl_uString_release(dir_url); + } + + if (osl_File_E_None == error) + { + rtl_uString_assign(ppustr_base_dir, dir); + rtl_uString_release(dir); + } + + return error; +} + +/***************************************************************** + * osl_setup_createTempFile_impl + * validate input parameter, setup variables + ****************************************************************/ + + static oslFileError osl_setup_createTempFile_impl_( + rtl_uString* pustrDirectoryURL, + oslFileHandle* pHandle, + rtl_uString** ppustrTempFileURL, + rtl_uString** ppustr_base_dir, + sal_Bool* b_delete_on_close) + { + oslFileError osl_error; + + OSL_PRECOND(((0 != pHandle) || (0 != ppustrTempFileURL)), "Invalid parameter!"); + + if ((0 == pHandle) && (0 == ppustrTempFileURL)) + { + osl_error = osl_File_E_INVAL; + } + else + { + osl_error = osl_setup_base_directory_impl_( + pustrDirectoryURL, ppustr_base_dir); + + *b_delete_on_close = (0 == ppustrTempFileURL); + } + + return osl_error; + } + +/***************************************************************** + * Create a unique file in the specified directory and return + * it's name + ****************************************************************/ + +static oslFileError osl_create_temp_file_impl_( + const rtl_uString* pustr_base_directory, + oslFileHandle* file_handle, + rtl_uString** ppustr_temp_file_name) +{ + rtl_uString* rand_name = 0; + sal_uInt32 len_base_dir = 0; + rtl_uString* tmp_file_path = 0; + rtl_uString* tmp_file_url = 0; + sal_Int32 capacity = 0; + oslFileError osl_error = osl_File_E_None; + sal_Int32 offset_file_name; + const sal_Unicode* puchr; + + OSL_PRECOND(pustr_base_directory, "Invalid Parameter"); + OSL_PRECOND(file_handle, "Invalid Parameter"); + OSL_PRECOND(ppustr_temp_file_name, "Invalid Parameter"); + + len_base_dir = rtl_uString_getLength(pustr_base_directory); + + rtl_uStringbuffer_newFromStr_WithLength( + &tmp_file_path, + rtl_uString_getStr((rtl_uString*)pustr_base_directory), + len_base_dir); + + rtl_uStringbuffer_ensureCapacity( + &tmp_file_path, + &capacity, + (len_base_dir + 1 + RAND_NAME_LENGTH)); + + offset_file_name = len_base_dir; + + puchr = rtl_uString_getStr(tmp_file_path); + + /* ensure that the last character is a '\' */ + + if ((sal_Unicode)'\\' != puchr[len_base_dir - 1]) + { + rtl_uStringbuffer_insert_ascii( + &tmp_file_path, + &capacity, + len_base_dir, + "\\", + 1); + + offset_file_name++; + } + + while(1) /* try until success */ + { + osl_gen_random_name_impl_(&rand_name); + + rtl_uStringbuffer_insert( + &tmp_file_path, + &capacity, + offset_file_name, + rtl_uString_getStr(rand_name), + rtl_uString_getLength(rand_name)); + + osl_error = osl_getFileURLFromSystemPath( + tmp_file_path, &tmp_file_url); + + if (osl_File_E_None == osl_error) + { + /* RW permission for the user only! */ + mode_t old_mode = umask(077); + + osl_error = osl_openFile( + tmp_file_url, + file_handle, + osl_File_OpenFlag_Read | + osl_File_OpenFlag_Write | + osl_File_OpenFlag_Create); + + umask(old_mode); + } + + /* in case of error osl_File_E_EXIST we simply try again else we give up */ + + if ((osl_File_E_None == osl_error) || (osl_error != osl_File_E_EXIST)) + { + if (rand_name) + rtl_uString_release(rand_name); + + if (tmp_file_url) + rtl_uString_release(tmp_file_url); + + break; + } + } /* while(1) */ + + if (osl_File_E_None == osl_error) + rtl_uString_assign(ppustr_temp_file_name, tmp_file_path); + + if (tmp_file_path) + rtl_uString_release(tmp_file_path); + + return osl_error; +} + +/***************************************************************** + * osl_createTempFile + *****************************************************************/ + +oslFileError SAL_CALL osl_createTempFile( + rtl_uString* pustrDirectoryURL, + oslFileHandle* pHandle, + rtl_uString** ppustrTempFileURL) +{ + rtl_uString* base_directory = 0; + rtl_uString* temp_file_name = 0; + oslFileHandle temp_file_handle; + sal_Bool b_delete_on_close; + oslFileError osl_error; + + osl_error = osl_setup_createTempFile_impl_( + pustrDirectoryURL, + pHandle, + ppustrTempFileURL, + &base_directory, + &b_delete_on_close); + + if (osl_File_E_None != osl_error) + return osl_error; + + osl_error = osl_create_temp_file_impl_( + base_directory, &temp_file_handle, &temp_file_name); + + if (osl_File_E_None == osl_error) + { + rtl_uString* temp_file_url = 0; + + /* assuming this works */ + osl_getFileURLFromSystemPath(temp_file_name, &temp_file_url); + + if (b_delete_on_close) + { + osl_error = osl_removeFile(temp_file_url); + + if (osl_File_E_None == osl_error) + *pHandle = temp_file_handle; + else + osl_closeFile(temp_file_handle); + } + else + { + if (pHandle) + *pHandle = temp_file_handle; + else + osl_closeFile(temp_file_handle); + + rtl_uString_assign(ppustrTempFileURL, temp_file_url); + } + + if (temp_file_url) + rtl_uString_release(temp_file_url); + + if (temp_file_name) + rtl_uString_release(temp_file_name); + } + + if (base_directory) + rtl_uString_release(base_directory); + + return osl_error; +} |