cf37a31cac
2008/04/01 12:34:09 thb 1.10.288.2: #i85898# Stripping all external header guards 2008/03/31 13:23:45 rt 1.10.288.1: #i87441# Change license header to LPGL v3.
373 lines
11 KiB
C
373 lines
11 KiB
C
/*************************************************************************
|
|
*
|
|
* 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.11 $
|
|
*
|
|
* 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 )
|
|
{
|
|
#ifdef MACOSX
|
|
const char *pValue = getenv( "TMPDIR" );
|
|
|
|
/* If TMPDIR environment variable is not set, use "/tmp" instead
|
|
of P_tmpdir because its value is "/var/tmp" and it is not
|
|
deleted on system start up */
|
|
if ( !pValue )
|
|
pValue = "/tmp";
|
|
#else
|
|
|
|
const char *pValue = getenv( "TEMP" );
|
|
|
|
if ( !pValue )
|
|
{
|
|
pValue = getenv( "TMP" );
|
|
#if defined(SOLARIS) || defined (LINUX) || defined (FREEBSD)
|
|
if ( !pValue )
|
|
pValue = P_tmpdir;
|
|
#endif
|
|
}
|
|
#endif /* MACOSX */
|
|
|
|
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;
|
|
}
|