LibreOffice Module desktop (master)  1
lockfile.cxx
Go to the documentation of this file.
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 <sal/config.h>
21 
22 #include <memory>
23 
24 #include <stdlib.h>
25 #include <time.h>
26 #ifndef _WIN32
27 #include <unistd.h>
28 #else
29 #if !defined WIN32_LEAN_AND_MEAN
30 # define WIN32_LEAN_AND_MEAN
31 #endif
32 #include <windows.h>
33 #endif
34 #include <comphelper/random.hxx>
35 #include <sal/types.h>
36 #include <osl/file.hxx>
37 #include <osl/socket.hxx>
38 #include <osl/security.hxx>
39 #include <unotools/bootstrap.hxx>
40 #include <tools/config.hxx>
41 
42 #include <lockfile.hxx>
43 
44 using namespace ::osl;
45 using namespace ::utl;
46 
47 
48 static OString impl_getHostname()
49 {
50  OString aHost;
51 #ifdef _WIN32
52  /*
53  prevent windows from connecting to the net to get its own
54  hostname by using the netbios name
55  */
56  DWORD sz = MAX_COMPUTERNAME_LENGTH + 1;
57  auto szHost = std::make_unique<char[]>(sz);
58  if (GetComputerNameA(szHost.get(), &sz))
59  aHost = OString(szHost.get());
60  else
61  aHost = OString("UNKNOWN");
62 #else
63  /* Don't do dns lookup on Linux either */
64  sal_Char pHostName[1024];
65 
66  if ( gethostname( pHostName, sizeof( pHostName ) - 1 ) == 0 )
67  {
68  pHostName[sizeof( pHostName ) - 1] = '\0';
69  aHost = OString( pHostName );
70  }
71  else
72  aHost = OString("UNKNOWN");
73 #endif
74 
75  return aHost;
76 }
77 
78 namespace desktop {
79 
80  Lockfile::Lockfile( bool bIPCserver )
81  :m_bIPCserver(bIPCserver)
82  ,m_bRemove(false)
83  ,m_bIsLocked(false)
84  {
85  // build the file-url to use for the lock
86  OUString aUserPath;
88  m_aLockname = aUserPath + "/.lock";
89 
90  // generate ID
91  const int nIdBytes = 16;
92  char tmpId[nIdBytes*2+1];
93  time_t t = time(nullptr);
94  for (int i = 0; i<nIdBytes; i++) {
95  int tmpByte = comphelper::rng::uniform_int_distribution(0, 0xFF);
96  sprintf( tmpId+i*2, "%02X", tmpByte );
97  }
98  tmpId[nIdBytes*2]=0x00;
99  m_aId = OUString::createFromAscii( tmpId );
100 
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);
108  }
109 
110 
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;
120  }
121  }
122 
123  bool Lockfile::check( fpExecWarning execWarning )
124  {
125 
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;
142  }
143  } else {
144  // lock was created by us
145  return true;
146  }
147  }
148 
149  bool Lockfile::isStale() const
150  {
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);
157  OString aIPCserver = aConfig.ReadKey( LOCKFILE_IPCKEY );
158  if (!aIPCserver.equalsIgnoreAsciiCase("true"))
159  return false;
160 
161  OString aHost = aConfig.ReadKey( LOCKFILE_HOSTKEY );
162  OString aUser = aConfig.ReadKey( LOCKFILE_USERKEY );
163 
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;
174  }
175  return false;
176  }
177 
178  void Lockfile::syncToFile() const
179  {
180  OUString aLockname = m_aLockname;
181  Config aConfig(aLockname);
182  aConfig.SetGroup(LOCKFILE_GROUP);
183 
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 );
192 
193  // write information
194  aConfig.WriteKey( LOCKFILE_USERKEY, aUser );
195  aConfig.WriteKey( LOCKFILE_HOSTKEY, aHost );
196  aConfig.WriteKey( LOCKFILE_STAMPKEY, aStamp );
197  aConfig.WriteKey( LOCKFILE_TIMEKEY, aTime );
198  aConfig.WriteKey(
200  m_bIPCserver ? OString("true") : OString("false") );
201  aConfig.Flush( );
202  }
203 
205  {
206  // unlock userdata by removing file
207  if ( m_bRemove )
208  File::remove( m_aLockname );
209  }
210 }
211 
212 
213 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool check(fpExecWarning execWarning)
Definition: lockfile.cxx:123
static PathStatus locateUserInstallation(OUString &_rURL)
static OString impl_getHostname()
Definition: lockfile.cxx:48
Definition: app.cxx:166
void SetGroup(const OString &rGroup)
#define LOCKFILE_HOSTKEY
Definition: lockfile.hxx:46
OUString m_aLockname
Definition: lockfile.hxx:76
Lockfile(bool bIPCserver=true)
Definition: lockfile.cxx:80
void Flush()
char sal_Char
OString ReadKey(const OString &rKey) const
void WriteKey(const OString &rKey, const OString &rValue)
#define LOCKFILE_STAMPKEY
Definition: lockfile.hxx:47
int i
OUString m_aDate
Definition: lockfile.hxx:82
#define LOCKFILE_USERKEY
Definition: lockfile.hxx:45
bool isStale() const
Definition: lockfile.cxx:149
XPropertyListType t
OUString m_aId
Definition: lockfile.hxx:81
OString OUStringToOString(const OUString &str, ConnectionSettings const *settings)
#define LOCKFILE_GROUP
Definition: lockfile.hxx:44
#define LOCKFILE_IPCKEY
Definition: lockfile.hxx:49
int uniform_int_distribution(int a, int b)
void syncToFile() const
Definition: lockfile.cxx:178
#define LOCKFILE_TIMEKEY
Definition: lockfile.hxx:48
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo