1*b1cdbd2cSJim Jagielski /************************************************************** 2*b1cdbd2cSJim Jagielski * 3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one 4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file 5*b1cdbd2cSJim Jagielski * distributed with this work for additional information 6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file 7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the 8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance 9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at 10*b1cdbd2cSJim Jagielski * 11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0 12*b1cdbd2cSJim Jagielski * 13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing, 14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an 15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the 17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations 18*b1cdbd2cSJim Jagielski * under the License. 19*b1cdbd2cSJim Jagielski * 20*b1cdbd2cSJim Jagielski *************************************************************/ 21*b1cdbd2cSJim Jagielski 22*b1cdbd2cSJim Jagielski 23*b1cdbd2cSJim Jagielski 24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove 25*b1cdbd2cSJim Jagielski #include "precompiled_desktop.hxx" 26*b1cdbd2cSJim Jagielski #include <stdlib.h> 27*b1cdbd2cSJim Jagielski #include <time.h> 28*b1cdbd2cSJim Jagielski #ifdef WNT 29*b1cdbd2cSJim Jagielski #include <tools/prewin.h> 30*b1cdbd2cSJim Jagielski #include <windows.h> 31*b1cdbd2cSJim Jagielski #include <tools/postwin.h> 32*b1cdbd2cSJim Jagielski #endif 33*b1cdbd2cSJim Jagielski #include <sal/types.h> 34*b1cdbd2cSJim Jagielski #include <osl/file.hxx> 35*b1cdbd2cSJim Jagielski #include <osl/socket.hxx> 36*b1cdbd2cSJim Jagielski #include <osl/security.hxx> 37*b1cdbd2cSJim Jagielski #include <unotools/bootstrap.hxx> 38*b1cdbd2cSJim Jagielski #include <tools/string.hxx> 39*b1cdbd2cSJim Jagielski #include <tools/config.hxx> 40*b1cdbd2cSJim Jagielski 41*b1cdbd2cSJim Jagielski #include "lockfile.hxx" 42*b1cdbd2cSJim Jagielski 43*b1cdbd2cSJim Jagielski 44*b1cdbd2cSJim Jagielski using namespace ::osl; 45*b1cdbd2cSJim Jagielski using namespace ::rtl; 46*b1cdbd2cSJim Jagielski using namespace ::utl; 47*b1cdbd2cSJim Jagielski 48*b1cdbd2cSJim Jagielski 49*b1cdbd2cSJim Jagielski namespace desktop { 50*b1cdbd2cSJim Jagielski 51*b1cdbd2cSJim Jagielski // initialize static members... 52*b1cdbd2cSJim Jagielski // lock suffix Suffix()53*b1cdbd2cSJim Jagielski const OUString Lockfile::Suffix() 54*b1cdbd2cSJim Jagielski { return OUString::createFromAscii( "/.lock" ); } 55*b1cdbd2cSJim Jagielski // values for datafile Group()56*b1cdbd2cSJim Jagielski const ByteString Lockfile::Group() 57*b1cdbd2cSJim Jagielski { return ByteString( "Lockdata" ); } Userkey()58*b1cdbd2cSJim Jagielski const ByteString Lockfile::Userkey() 59*b1cdbd2cSJim Jagielski { return ByteString( "User" ); } Hostkey()60*b1cdbd2cSJim Jagielski const ByteString Lockfile::Hostkey() 61*b1cdbd2cSJim Jagielski { return ByteString( "Host" ); } Stampkey()62*b1cdbd2cSJim Jagielski const ByteString Lockfile::Stampkey() 63*b1cdbd2cSJim Jagielski { return ByteString( "Stamp" ); } Timekey()64*b1cdbd2cSJim Jagielski const ByteString Lockfile::Timekey() 65*b1cdbd2cSJim Jagielski { return ByteString( "Time" ); } IPCkey()66*b1cdbd2cSJim Jagielski const ByteString Lockfile::IPCkey() 67*b1cdbd2cSJim Jagielski { return ByteString( "IPCServer" ); } 68*b1cdbd2cSJim Jagielski Lockfile(bool bIPCserver)69*b1cdbd2cSJim Jagielski Lockfile::Lockfile( bool bIPCserver ) 70*b1cdbd2cSJim Jagielski :m_bIPCserver(bIPCserver) 71*b1cdbd2cSJim Jagielski ,m_bRemove(sal_False) 72*b1cdbd2cSJim Jagielski ,m_bIsLocked(sal_False) 73*b1cdbd2cSJim Jagielski { 74*b1cdbd2cSJim Jagielski // build the file-url to use for the lock 75*b1cdbd2cSJim Jagielski OUString aUserPath; 76*b1cdbd2cSJim Jagielski utl::Bootstrap::locateUserInstallation( aUserPath ); 77*b1cdbd2cSJim Jagielski m_aLockname = aUserPath + Suffix(); 78*b1cdbd2cSJim Jagielski 79*b1cdbd2cSJim Jagielski // generate ID 80*b1cdbd2cSJim Jagielski const int nIdBytes = 16; 81*b1cdbd2cSJim Jagielski char tmpId[nIdBytes*2+1]; 82*b1cdbd2cSJim Jagielski time_t t; 83*b1cdbd2cSJim Jagielski srand( (unsigned)(t = time( NULL )) ); 84*b1cdbd2cSJim Jagielski int tmpByte = 0; 85*b1cdbd2cSJim Jagielski for (int i = 0; i<nIdBytes; i++) { 86*b1cdbd2cSJim Jagielski tmpByte = rand( ) % 0xFF; 87*b1cdbd2cSJim Jagielski sprintf( tmpId+i*2, "%02X", tmpByte ); // #100211# - checked 88*b1cdbd2cSJim Jagielski } 89*b1cdbd2cSJim Jagielski tmpId[nIdBytes*2]=0x00; 90*b1cdbd2cSJim Jagielski m_aId = OUString::createFromAscii( tmpId ); 91*b1cdbd2cSJim Jagielski 92*b1cdbd2cSJim Jagielski // generate date string 93*b1cdbd2cSJim Jagielski char *tmpTime = ctime( &t ); 94*b1cdbd2cSJim Jagielski if (tmpTime != NULL) { 95*b1cdbd2cSJim Jagielski m_aDate = OUString::createFromAscii( tmpTime ); 96*b1cdbd2cSJim Jagielski sal_Int32 i = m_aDate.indexOf('\n'); 97*b1cdbd2cSJim Jagielski if (i > 0) 98*b1cdbd2cSJim Jagielski m_aDate = m_aDate.copy(0, i); 99*b1cdbd2cSJim Jagielski } 100*b1cdbd2cSJim Jagielski 101*b1cdbd2cSJim Jagielski 102*b1cdbd2cSJim Jagielski // try to create file 103*b1cdbd2cSJim Jagielski File aFile(m_aLockname); 104*b1cdbd2cSJim Jagielski if (aFile.open( OpenFlag_Create ) == File::E_EXIST) { 105*b1cdbd2cSJim Jagielski m_bIsLocked = sal_True; 106*b1cdbd2cSJim Jagielski } else { 107*b1cdbd2cSJim Jagielski // new lock created 108*b1cdbd2cSJim Jagielski aFile.close( ); 109*b1cdbd2cSJim Jagielski syncToFile( ); 110*b1cdbd2cSJim Jagielski m_bRemove = sal_True; 111*b1cdbd2cSJim Jagielski } 112*b1cdbd2cSJim Jagielski } 113*b1cdbd2cSJim Jagielski check(fpExecWarning execWarning)114*b1cdbd2cSJim Jagielski sal_Bool Lockfile::check( fpExecWarning execWarning ) 115*b1cdbd2cSJim Jagielski { 116*b1cdbd2cSJim Jagielski 117*b1cdbd2cSJim Jagielski if (m_bIsLocked) { 118*b1cdbd2cSJim Jagielski // lock existed, ask user what to do 119*b1cdbd2cSJim Jagielski if (isStale() || 120*b1cdbd2cSJim Jagielski (execWarning != 0 && (*execWarning)( this ))) { 121*b1cdbd2cSJim Jagielski // remove file and create new 122*b1cdbd2cSJim Jagielski File::remove( m_aLockname ); 123*b1cdbd2cSJim Jagielski File aFile(m_aLockname); 124*b1cdbd2cSJim Jagielski aFile.open( OpenFlag_Create ); 125*b1cdbd2cSJim Jagielski aFile.close( ); 126*b1cdbd2cSJim Jagielski syncToFile( ); 127*b1cdbd2cSJim Jagielski m_bRemove = sal_True; 128*b1cdbd2cSJim Jagielski return sal_True; 129*b1cdbd2cSJim Jagielski } else { 130*b1cdbd2cSJim Jagielski //leave alone and return false 131*b1cdbd2cSJim Jagielski m_bRemove = sal_False; 132*b1cdbd2cSJim Jagielski return sal_False; 133*b1cdbd2cSJim Jagielski } 134*b1cdbd2cSJim Jagielski } else { 135*b1cdbd2cSJim Jagielski // lock was created by us 136*b1cdbd2cSJim Jagielski return sal_True; 137*b1cdbd2cSJim Jagielski } 138*b1cdbd2cSJim Jagielski } 139*b1cdbd2cSJim Jagielski isStale(void) const140*b1cdbd2cSJim Jagielski sal_Bool Lockfile::isStale( void ) const 141*b1cdbd2cSJim Jagielski { 142*b1cdbd2cSJim Jagielski // this checks whether the lockfile was created on the same 143*b1cdbd2cSJim Jagielski // host by the same user. Should this be the case it is safe 144*b1cdbd2cSJim Jagielski // to assume that it is a stale lockfile which can be overwritten 145*b1cdbd2cSJim Jagielski String aLockname = m_aLockname; 146*b1cdbd2cSJim Jagielski Config aConfig(aLockname); 147*b1cdbd2cSJim Jagielski aConfig.SetGroup(Group()); 148*b1cdbd2cSJim Jagielski ByteString aIPCserver = aConfig.ReadKey( IPCkey() ); 149*b1cdbd2cSJim Jagielski if (! aIPCserver.EqualsIgnoreCaseAscii( "true" )) 150*b1cdbd2cSJim Jagielski return false; 151*b1cdbd2cSJim Jagielski 152*b1cdbd2cSJim Jagielski ByteString aHost = aConfig.ReadKey( Hostkey() ); 153*b1cdbd2cSJim Jagielski ByteString aUser = aConfig.ReadKey( Userkey() ); 154*b1cdbd2cSJim Jagielski // lockfile from same host? 155*b1cdbd2cSJim Jagielski ByteString myHost; 156*b1cdbd2cSJim Jagielski #ifdef WNT 157*b1cdbd2cSJim Jagielski /* 158*b1cdbd2cSJim Jagielski prevent windows from connecting to the net to get it's own 159*b1cdbd2cSJim Jagielski hostname by using the netbios name 160*b1cdbd2cSJim Jagielski */ 161*b1cdbd2cSJim Jagielski sal_Int32 sz = MAX_COMPUTERNAME_LENGTH + 1; 162*b1cdbd2cSJim Jagielski char* szHost = new char[sz]; 163*b1cdbd2cSJim Jagielski if (GetComputerName(szHost, (LPDWORD)&sz)) 164*b1cdbd2cSJim Jagielski myHost = OString(szHost); 165*b1cdbd2cSJim Jagielski else 166*b1cdbd2cSJim Jagielski myHost = OString("UNKNOWN"); 167*b1cdbd2cSJim Jagielski delete[] szHost; 168*b1cdbd2cSJim Jagielski #else 169*b1cdbd2cSJim Jagielski oslSocketResult sRes; 170*b1cdbd2cSJim Jagielski myHost = OUStringToOString( 171*b1cdbd2cSJim Jagielski SocketAddr::getLocalHostname( &sRes ), RTL_TEXTENCODING_ASCII_US ); 172*b1cdbd2cSJim Jagielski #endif 173*b1cdbd2cSJim Jagielski if (aHost == myHost) { 174*b1cdbd2cSJim Jagielski // lockfile by same UID 175*b1cdbd2cSJim Jagielski OUString myUserName; 176*b1cdbd2cSJim Jagielski Security aSecurity; 177*b1cdbd2cSJim Jagielski aSecurity.getUserName( myUserName ); 178*b1cdbd2cSJim Jagielski ByteString myUser = OUStringToOString( myUserName, RTL_TEXTENCODING_ASCII_US ); 179*b1cdbd2cSJim Jagielski if (aUser == myUser) 180*b1cdbd2cSJim Jagielski return sal_True; 181*b1cdbd2cSJim Jagielski } 182*b1cdbd2cSJim Jagielski return sal_False; 183*b1cdbd2cSJim Jagielski } 184*b1cdbd2cSJim Jagielski syncToFile(void) const185*b1cdbd2cSJim Jagielski void Lockfile::syncToFile( void ) const 186*b1cdbd2cSJim Jagielski { 187*b1cdbd2cSJim Jagielski String aLockname = m_aLockname; 188*b1cdbd2cSJim Jagielski Config aConfig(aLockname); 189*b1cdbd2cSJim Jagielski aConfig.SetGroup(Group()); 190*b1cdbd2cSJim Jagielski 191*b1cdbd2cSJim Jagielski // get information 192*b1cdbd2cSJim Jagielski ByteString aHost; 193*b1cdbd2cSJim Jagielski #ifdef WNT 194*b1cdbd2cSJim Jagielski /* 195*b1cdbd2cSJim Jagielski prevent windows from connecting to the net to get it's own 196*b1cdbd2cSJim Jagielski hostname by using the netbios name 197*b1cdbd2cSJim Jagielski */ 198*b1cdbd2cSJim Jagielski sal_Int32 sz = MAX_COMPUTERNAME_LENGTH + 1; 199*b1cdbd2cSJim Jagielski char* szHost = new char[sz]; 200*b1cdbd2cSJim Jagielski if (GetComputerName(szHost, (LPDWORD)&sz)) 201*b1cdbd2cSJim Jagielski aHost = OString(szHost); 202*b1cdbd2cSJim Jagielski else 203*b1cdbd2cSJim Jagielski aHost = OString("UNKNOWN"); 204*b1cdbd2cSJim Jagielski delete[] szHost; 205*b1cdbd2cSJim Jagielski #else 206*b1cdbd2cSJim Jagielski oslSocketResult sRes; 207*b1cdbd2cSJim Jagielski aHost = OUStringToOString( 208*b1cdbd2cSJim Jagielski SocketAddr::getLocalHostname( &sRes ), RTL_TEXTENCODING_ASCII_US ); 209*b1cdbd2cSJim Jagielski #endif 210*b1cdbd2cSJim Jagielski OUString aUserName; 211*b1cdbd2cSJim Jagielski Security aSecurity; 212*b1cdbd2cSJim Jagielski aSecurity.getUserName( aUserName ); 213*b1cdbd2cSJim Jagielski ByteString aUser = OUStringToOString( aUserName, RTL_TEXTENCODING_ASCII_US ); 214*b1cdbd2cSJim Jagielski ByteString aTime = OUStringToOString( m_aDate, RTL_TEXTENCODING_ASCII_US ); 215*b1cdbd2cSJim Jagielski ByteString aStamp = OUStringToOString( m_aId, RTL_TEXTENCODING_ASCII_US ); 216*b1cdbd2cSJim Jagielski 217*b1cdbd2cSJim Jagielski // write information 218*b1cdbd2cSJim Jagielski aConfig.WriteKey( Userkey(), aUser ); 219*b1cdbd2cSJim Jagielski aConfig.WriteKey( Hostkey(), aHost ); 220*b1cdbd2cSJim Jagielski aConfig.WriteKey( Stampkey(), aStamp ); 221*b1cdbd2cSJim Jagielski aConfig.WriteKey( Timekey(), aTime ); 222*b1cdbd2cSJim Jagielski aConfig.WriteKey( 223*b1cdbd2cSJim Jagielski IPCkey(), 224*b1cdbd2cSJim Jagielski m_bIPCserver ? ByteString("true") : ByteString("false") ); 225*b1cdbd2cSJim Jagielski aConfig.Flush( ); 226*b1cdbd2cSJim Jagielski } 227*b1cdbd2cSJim Jagielski clean(void)228*b1cdbd2cSJim Jagielski void Lockfile::clean( void ) 229*b1cdbd2cSJim Jagielski { 230*b1cdbd2cSJim Jagielski if ( m_bRemove ) 231*b1cdbd2cSJim Jagielski { 232*b1cdbd2cSJim Jagielski File::remove( m_aLockname ); 233*b1cdbd2cSJim Jagielski m_bRemove = sal_False; 234*b1cdbd2cSJim Jagielski } 235*b1cdbd2cSJim Jagielski } 236*b1cdbd2cSJim Jagielski ~Lockfile(void)237*b1cdbd2cSJim Jagielski Lockfile::~Lockfile( void ) 238*b1cdbd2cSJim Jagielski { 239*b1cdbd2cSJim Jagielski // unlock userdata by removing file 240*b1cdbd2cSJim Jagielski if ( m_bRemove ) 241*b1cdbd2cSJim Jagielski File::remove( m_aLockname ); 242*b1cdbd2cSJim Jagielski } 243*b1cdbd2cSJim Jagielski } 244*b1cdbd2cSJim Jagielski 245*b1cdbd2cSJim Jagielski 246*b1cdbd2cSJim Jagielski 247*b1cdbd2cSJim Jagielski 248*b1cdbd2cSJim Jagielski 249*b1cdbd2cSJim Jagielski 250*b1cdbd2cSJim Jagielski 251*b1cdbd2cSJim Jagielski 252*b1cdbd2cSJim Jagielski 253