Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <stdlib.h>
21 : #include <time.h>
22 : #ifndef WNT
23 : #include <unistd.h>
24 : #else
25 : #include <windows.h>
26 : #endif
27 : #include <comphelper/random.hxx>
28 : #include <sal/types.h>
29 : #include <osl/file.hxx>
30 : #include <osl/socket.hxx>
31 : #include <osl/security.hxx>
32 : #include <unotools/bootstrap.hxx>
33 : #include <tools/config.hxx>
34 :
35 : #include "lockfile.hxx"
36 :
37 : using namespace ::osl;
38 : using namespace ::utl;
39 :
40 :
41 160 : static OString impl_getHostname()
42 : {
43 160 : OString aHost;
44 : #ifdef WNT
45 : /*
46 : prevent windows from connecting to the net to get its own
47 : hostname by using the netbios name
48 : */
49 : sal_Int32 sz = MAX_COMPUTERNAME_LENGTH + 1;
50 : char* szHost = new char[sz];
51 : if (GetComputerName(szHost, (LPDWORD)&sz))
52 : aHost = OString(szHost);
53 : else
54 : aHost = OString("UNKNOWN");
55 : delete[] szHost;
56 : #else
57 : /* Don't do dns lookup on Linux either */
58 : sal_Char pHostName[1024];
59 :
60 160 : if ( gethostname( pHostName, sizeof( pHostName ) - 1 ) == 0 )
61 : {
62 160 : pHostName[sizeof( pHostName ) - 1] = '\0';
63 160 : aHost = OString( pHostName );
64 : }
65 : else
66 0 : aHost = OString("UNKNOWN");
67 : #endif
68 :
69 160 : return aHost;
70 : }
71 :
72 : namespace desktop {
73 :
74 160 : Lockfile::Lockfile( bool bIPCserver )
75 : :m_bIPCserver(bIPCserver)
76 : ,m_bRemove(false)
77 160 : ,m_bIsLocked(false)
78 : {
79 : // build the file-url to use for the lock
80 160 : OUString aUserPath;
81 160 : utl::Bootstrap::locateUserInstallation( aUserPath );
82 160 : m_aLockname = aUserPath + LOCKFILE_SUFFIX;
83 :
84 : // generate ID
85 160 : const int nIdBytes = 16;
86 : char tmpId[nIdBytes*2+1];
87 160 : time_t t = time(NULL);
88 2720 : for (int i = 0; i<nIdBytes; i++) {
89 2560 : int tmpByte = comphelper::rng::uniform_int_distribution(0, 0xFF);
90 2560 : sprintf( tmpId+i*2, "%02X", tmpByte );
91 : }
92 160 : tmpId[nIdBytes*2]=0x00;
93 160 : m_aId = OUString::createFromAscii( tmpId );
94 :
95 : // generate date string
96 160 : char *tmpTime = ctime( &t );
97 160 : if (tmpTime != NULL) {
98 160 : m_aDate = OUString::createFromAscii( tmpTime );
99 160 : sal_Int32 i = m_aDate.indexOf('\n');
100 160 : if (i > 0)
101 160 : m_aDate = m_aDate.copy(0, i);
102 : }
103 :
104 :
105 : // try to create file
106 320 : File aFile(m_aLockname);
107 160 : if (aFile.open( osl_File_OpenFlag_Create ) == File::E_EXIST) {
108 0 : m_bIsLocked = true;
109 : } else {
110 : // new lock created
111 160 : aFile.close( );
112 160 : syncToFile( );
113 160 : m_bRemove = true;
114 160 : }
115 160 : }
116 :
117 0 : bool Lockfile::check( fpExecWarning execWarning )
118 : {
119 :
120 0 : if (m_bIsLocked) {
121 : // lock existed, ask user what to do
122 0 : if (isStale() ||
123 0 : (execWarning != 0 && (*execWarning)( this ))) {
124 : // remove file and create new
125 0 : File::remove( m_aLockname );
126 0 : File aFile(m_aLockname);
127 0 : aFile.open( osl_File_OpenFlag_Create );
128 0 : aFile.close( );
129 0 : syncToFile( );
130 0 : m_bRemove = true;
131 0 : return true;
132 : } else {
133 : //leave alone and return false
134 0 : m_bRemove = false;
135 0 : return false;
136 : }
137 : } else {
138 : // lock was created by us
139 0 : return true;
140 : }
141 : }
142 :
143 0 : bool Lockfile::isStale( void ) const
144 : {
145 : // this checks whether the lockfile was created on the same
146 : // host by the same user. Should this be the case it is safe
147 : // to assume that it is a stale lockfile which can be overwritten
148 0 : OUString aLockname = m_aLockname;
149 0 : Config aConfig(aLockname);
150 0 : aConfig.SetGroup(LOCKFILE_GROUP);
151 0 : OString aIPCserver = aConfig.ReadKey( LOCKFILE_IPCKEY );
152 0 : if (!aIPCserver.equalsIgnoreAsciiCase(OString("true")))
153 0 : return false;
154 :
155 0 : OString aHost = aConfig.ReadKey( LOCKFILE_HOSTKEY );
156 0 : OString aUser = aConfig.ReadKey( LOCKFILE_USERKEY );
157 :
158 : // lockfile from same host?
159 0 : OString myHost( impl_getHostname() );
160 0 : if (aHost == myHost) {
161 : // lockfile by same UID
162 0 : OUString myUserName;
163 0 : Security aSecurity;
164 0 : aSecurity.getUserName( myUserName );
165 0 : OString myUser(OUStringToOString(myUserName, RTL_TEXTENCODING_ASCII_US));
166 0 : if (aUser == myUser)
167 0 : return true;
168 : }
169 0 : return false;
170 : }
171 :
172 160 : void Lockfile::syncToFile( void ) const
173 : {
174 160 : OUString aLockname = m_aLockname;
175 320 : Config aConfig(aLockname);
176 160 : aConfig.SetGroup(LOCKFILE_GROUP);
177 :
178 : // get information
179 320 : OString aHost( impl_getHostname() );
180 320 : OUString aUserName;
181 320 : Security aSecurity;
182 160 : aSecurity.getUserName( aUserName );
183 320 : OString aUser = OUStringToOString( aUserName, RTL_TEXTENCODING_ASCII_US );
184 320 : OString aTime = OUStringToOString( m_aDate, RTL_TEXTENCODING_ASCII_US );
185 320 : OString aStamp = OUStringToOString( m_aId, RTL_TEXTENCODING_ASCII_US );
186 :
187 : // write information
188 160 : aConfig.WriteKey( LOCKFILE_USERKEY, aUser );
189 160 : aConfig.WriteKey( LOCKFILE_HOSTKEY, aHost );
190 160 : aConfig.WriteKey( LOCKFILE_STAMPKEY, aStamp );
191 160 : aConfig.WriteKey( LOCKFILE_TIMEKEY, aTime );
192 : aConfig.WriteKey(
193 : LOCKFILE_IPCKEY,
194 160 : m_bIPCserver ? OString("true") : OString("false") );
195 320 : aConfig.Flush( );
196 160 : }
197 :
198 320 : Lockfile::~Lockfile( void )
199 : {
200 : // unlock userdata by removing file
201 160 : if ( m_bRemove )
202 160 : File::remove( m_aLockname );
203 160 : }
204 : }
205 :
206 :
207 :
208 :
209 :
210 :
211 :
212 :
213 :
214 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|