blob: 0758404ba5d46a4f46bcfbee348789a01d91ec2e [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_desktop.hxx"
#include <stdlib.h>
#include <time.h>
#ifdef WNT
#include <tools/prewin.h>
#include <windows.h>
#include <tools/postwin.h>
#endif
#include <sal/types.h>
#include <osl/file.hxx>
#include <osl/socket.hxx>
#include <osl/security.hxx>
#include <unotools/bootstrap.hxx>
#include <tools/string.hxx>
#include <tools/config.hxx>
#include "lockfile.hxx"
using namespace ::osl;
using namespace ::rtl;
using namespace ::utl;
namespace desktop {
// initialize static members...
// lock suffix
const OUString Lockfile::Suffix()
{ return OUString::createFromAscii( "/.lock" ); }
// values for datafile
const ByteString Lockfile::Group()
{ return ByteString( "Lockdata" ); }
const ByteString Lockfile::Userkey()
{ return ByteString( "User" ); }
const ByteString Lockfile::Hostkey()
{ return ByteString( "Host" ); }
const ByteString Lockfile::Stampkey()
{ return ByteString( "Stamp" ); }
const ByteString Lockfile::Timekey()
{ return ByteString( "Time" ); }
const ByteString Lockfile::IPCkey()
{ return ByteString( "IPCServer" ); }
Lockfile::Lockfile( bool bIPCserver )
:m_bIPCserver(bIPCserver)
,m_bRemove(sal_False)
,m_bIsLocked(sal_False)
{
// build the file-url to use for the lock
OUString aUserPath;
utl::Bootstrap::locateUserInstallation( aUserPath );
m_aLockname = aUserPath + Suffix();
// generate ID
const int nIdBytes = 16;
char tmpId[nIdBytes*2+1];
time_t t;
srand( (unsigned)(t = time( NULL )) );
int tmpByte = 0;
for (int i = 0; i<nIdBytes; i++) {
tmpByte = rand( ) % 0xFF;
sprintf( tmpId+i*2, "%02X", tmpByte ); // #100211# - checked
}
tmpId[nIdBytes*2]=0x00;
m_aId = OUString::createFromAscii( tmpId );
// generate date string
char *tmpTime = ctime( &t );
if (tmpTime != NULL) {
m_aDate = OUString::createFromAscii( tmpTime );
sal_Int32 i = m_aDate.indexOf('\n');
if (i > 0)
m_aDate = m_aDate.copy(0, i);
}
// try to create file
File aFile(m_aLockname);
if (aFile.open( OpenFlag_Create ) == File::E_EXIST) {
m_bIsLocked = sal_True;
} else {
// new lock created
aFile.close( );
syncToFile( );
m_bRemove = sal_True;
}
}
sal_Bool Lockfile::check( fpExecWarning execWarning )
{
if (m_bIsLocked) {
// lock existed, ask user what to do
if (isStale() ||
(execWarning != 0 && (*execWarning)( this ))) {
// remove file and create new
File::remove( m_aLockname );
File aFile(m_aLockname);
aFile.open( OpenFlag_Create );
aFile.close( );
syncToFile( );
m_bRemove = sal_True;
return sal_True;
} else {
//leave alone and return false
m_bRemove = sal_False;
return sal_False;
}
} else {
// lock was created by us
return sal_True;
}
}
sal_Bool Lockfile::isStale( void ) const
{
// this checks whether the lockfile was created on the same
// host by the same user. Should this be the case it is safe
// to assume that it is a stale lockfile which can be overwritten
String aLockname = m_aLockname;
Config aConfig(aLockname);
aConfig.SetGroup(Group());
ByteString aIPCserver = aConfig.ReadKey( IPCkey() );
if (! aIPCserver.EqualsIgnoreCaseAscii( "true" ))
return false;
ByteString aHost = aConfig.ReadKey( Hostkey() );
ByteString aUser = aConfig.ReadKey( Userkey() );
// lockfile from same host?
ByteString myHost;
#ifdef WNT
/*
prevent windows from connecting to the net to get it's own
hostname by using the netbios name
*/
sal_Int32 sz = MAX_COMPUTERNAME_LENGTH + 1;
char* szHost = new char[sz];
if (GetComputerName(szHost, (LPDWORD)&sz))
myHost = OString(szHost);
else
myHost = OString("UNKNOWN");
delete[] szHost;
#else
oslSocketResult sRes;
myHost = OUStringToOString(
SocketAddr::getLocalHostname( &sRes ), RTL_TEXTENCODING_ASCII_US );
#endif
if (aHost == myHost) {
// lockfile by same UID
OUString myUserName;
Security aSecurity;
aSecurity.getUserName( myUserName );
ByteString myUser = OUStringToOString( myUserName, RTL_TEXTENCODING_ASCII_US );
if (aUser == myUser)
return sal_True;
}
return sal_False;
}
void Lockfile::syncToFile( void ) const
{
String aLockname = m_aLockname;
Config aConfig(aLockname);
aConfig.SetGroup(Group());
// get information
ByteString aHost;
#ifdef WNT
/*
prevent windows from connecting to the net to get it's own
hostname by using the netbios name
*/
sal_Int32 sz = MAX_COMPUTERNAME_LENGTH + 1;
char* szHost = new char[sz];
if (GetComputerName(szHost, (LPDWORD)&sz))
aHost = OString(szHost);
else
aHost = OString("UNKNOWN");
delete[] szHost;
#else
oslSocketResult sRes;
aHost = OUStringToOString(
SocketAddr::getLocalHostname( &sRes ), RTL_TEXTENCODING_ASCII_US );
#endif
OUString aUserName;
Security aSecurity;
aSecurity.getUserName( aUserName );
ByteString aUser = OUStringToOString( aUserName, RTL_TEXTENCODING_ASCII_US );
ByteString aTime = OUStringToOString( m_aDate, RTL_TEXTENCODING_ASCII_US );
ByteString aStamp = OUStringToOString( m_aId, RTL_TEXTENCODING_ASCII_US );
// write information
aConfig.WriteKey( Userkey(), aUser );
aConfig.WriteKey( Hostkey(), aHost );
aConfig.WriteKey( Stampkey(), aStamp );
aConfig.WriteKey( Timekey(), aTime );
aConfig.WriteKey(
IPCkey(),
m_bIPCserver ? ByteString("true") : ByteString("false") );
aConfig.Flush( );
}
void Lockfile::clean( void )
{
if ( m_bRemove )
{
File::remove( m_aLockname );
m_bRemove = sal_False;
}
}
Lockfile::~Lockfile( void )
{
// unlock userdata by removing file
if ( m_bRemove )
File::remove( m_aLockname );
}
}