use insert function instead of for loop
[LibreOffice.git] / desktop / source / deployment / misc / lockfile.cxx
blob1a87e8bc0f6f8002c70bfea94f1cd8ec28e8f85a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <memory>
24 #include <time.h>
25 #ifndef _WIN32
26 #include <unistd.h>
27 #else
28 #if !defined WIN32_LEAN_AND_MEAN
29 # define WIN32_LEAN_AND_MEAN
30 #endif
31 #include <windows.h>
32 #endif
33 #include <comphelper/random.hxx>
34 #include <sal/types.h>
35 #include <osl/file.hxx>
36 #include <osl/security.hxx>
37 #include <unotools/bootstrap.hxx>
38 #include <tools/config.hxx>
40 #include <lockfile.hxx>
42 using namespace ::osl;
43 using namespace ::utl;
46 static OString impl_getHostname()
48 OString aHost;
49 #ifdef _WIN32
51 prevent windows from connecting to the net to get its own
52 hostname by using the netbios name
54 DWORD sz = MAX_COMPUTERNAME_LENGTH + 1;
55 TCHAR szHost[MAX_COMPUTERNAME_LENGTH + 1];
56 if (GetComputerNameA(szHost, &sz))
57 aHost = OString(szHost);
58 else
59 aHost = OString("UNKNOWN");
60 #else
61 /* Don't do dns lookup on Linux either */
62 char pHostName[1024];
64 if ( gethostname( pHostName, sizeof( pHostName ) - 1 ) == 0 )
66 pHostName[sizeof( pHostName ) - 1] = '\0';
67 aHost = OString( pHostName );
69 else
70 aHost = "UNKNOWN"_ostr;
71 #endif
73 return aHost;
76 namespace desktop {
78 Lockfile::Lockfile( bool bIPCserver )
79 :m_bIPCserver(bIPCserver)
80 ,m_bRemove(false)
81 ,m_bIsLocked(false)
83 // build the file-url to use for the lock
84 OUString aUserPath;
85 utl::Bootstrap::locateUserInstallation( aUserPath );
86 m_aLockname = aUserPath + "/.lock";
88 // generate ID
89 const int nIdBytes = 16;
90 char tmpId[nIdBytes*2+1];
91 time_t t = time(nullptr);
92 for (int i = 0; i<nIdBytes; i++) {
93 int tmpByte = comphelper::rng::uniform_int_distribution(0, 0xFF);
94 SAL_WNODEPRECATED_DECLARATIONS_PUSH // sprintf (macOS 13 SDK)
95 sprintf( tmpId+i*2, "%02X", tmpByte );
96 SAL_WNODEPRECATED_DECLARATIONS_POP
98 tmpId[nIdBytes*2]=0x00;
99 m_aId = OUString::createFromAscii( tmpId );
101 // generate date string
102 char *tmpTime = ctime( &t );
103 if (tmpTime != nullptr) {
104 m_aDate = OUString::createFromAscii( tmpTime );
105 sal_Int32 i = m_aDate.indexOf('\n');
106 if (i > 0)
107 m_aDate = m_aDate.copy(0, i);
111 // try to create file
112 File aFile(m_aLockname);
113 if (aFile.open( osl_File_OpenFlag_Create ) == File::E_EXIST) {
114 m_bIsLocked = true;
115 } else {
116 // new lock created
117 aFile.close( );
118 syncToFile( );
119 m_bRemove = true;
123 bool Lockfile::check( fpExecWarning execWarning )
126 if (m_bIsLocked) {
127 // lock existed, ask user what to do
128 if (isStale() ||
129 (execWarning != nullptr && (*execWarning)( this ))) {
130 // remove file and create new
131 File::remove( m_aLockname );
132 File aFile(m_aLockname);
133 (void)aFile.open( osl_File_OpenFlag_Create );
134 aFile.close( );
135 syncToFile( );
136 m_bRemove = true;
137 return true;
138 } else {
139 //leave alone and return false
140 m_bRemove = false;
141 return false;
143 } else {
144 // lock was created by us
145 return true;
149 bool Lockfile::isStale() const
151 // this checks whether the lockfile was created on the same
152 // host by the same user. Should this be the case it is safe
153 // to assume that it is a stale lockfile which can be overwritten
154 OUString aLockname = m_aLockname;
155 Config aConfig(aLockname);
156 aConfig.SetGroup(LOCKFILE_GROUP ""_ostr);
157 OString aIPCserver = aConfig.ReadKey( LOCKFILE_IPCKEY ""_ostr );
158 if (!aIPCserver.equalsIgnoreAsciiCase("true"))
159 return false;
161 OString aHost = aConfig.ReadKey( LOCKFILE_HOSTKEY ""_ostr );
162 OString aUser = aConfig.ReadKey( LOCKFILE_USERKEY ""_ostr );
164 // lockfile from same host?
165 OString myHost( impl_getHostname() );
166 if (aHost == myHost) {
167 // lockfile by same UID
168 OUString myUserName;
169 Security aSecurity;
170 aSecurity.getUserName( myUserName );
171 OString myUser(OUStringToOString(myUserName, RTL_TEXTENCODING_ASCII_US));
172 if (aUser == myUser)
173 return true;
175 return false;
178 void Lockfile::syncToFile() const
180 OUString aLockname = m_aLockname;
181 Config aConfig(aLockname);
182 aConfig.SetGroup(LOCKFILE_GROUP ""_ostr);
184 // get information
185 OString aHost( impl_getHostname() );
186 OUString aUserName;
187 Security aSecurity;
188 aSecurity.getUserName( aUserName );
189 OString aUser = OUStringToOString( aUserName, RTL_TEXTENCODING_ASCII_US );
190 OString aTime = OUStringToOString( m_aDate, RTL_TEXTENCODING_ASCII_US );
191 OString aStamp = OUStringToOString( m_aId, RTL_TEXTENCODING_ASCII_US );
193 // write information
194 aConfig.WriteKey( LOCKFILE_USERKEY ""_ostr, aUser );
195 aConfig.WriteKey( LOCKFILE_HOSTKEY ""_ostr, aHost );
196 aConfig.WriteKey( LOCKFILE_STAMPKEY ""_ostr, aStamp );
197 aConfig.WriteKey( LOCKFILE_TIMEKEY ""_ostr, aTime );
198 aConfig.WriteKey(
199 LOCKFILE_IPCKEY ""_ostr,
200 m_bIPCserver ? "true"_ostr : "false"_ostr );
201 aConfig.Flush( );
204 Lockfile::~Lockfile()
206 // unlock userdata by removing file
207 if ( m_bRemove )
208 File::remove( m_aLockname );
213 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */