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