Sleuth Kit Java Bindings (JNI)  4.12.1
Java bindings for using The Sleuth Kit
LibraryLock.java
Go to the documentation of this file.
1 /*
2  * Sleuth Kit Data Model
3  *
4  * Copyright 2024 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.datamodel;
20 
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.RandomAccessFile;
24 import java.nio.channels.FileChannel;
25 import java.nio.channels.FileLock;
26 import java.util.Arrays;
27 import java.util.logging.Level;
28 
38 public class LibraryLock implements AutoCloseable {
39 
40  private static final String LIB_FILE_LOCK_TEXT = "lib_lock";
41 
42  private static final String TMP_DIR_KEY = "java.io.tmpdir";
43  private static final String USER_NAME_KEY = "user.name";
44 
45  private static final byte[] UTF8_BOM = {(byte) 0XEF, (byte) 0xBB, (byte) 0XBF};
46 
47  private static LibraryLock libLock = null;
48 
59  public static LibraryLock acquireLibLock() {
60  if (libLock == null) {
61  libLock = getLibLock();
62  }
63  return libLock;
64  }
65 
71  public static void removeLibLock() throws Exception {
72  if (libLock != null) {
73  libLock.close();
74  }
75  }
76 
86  private static LibraryLock getLibLock() {
87  File libTskJniFile = LibraryUtils.getTempFile(
88  System.getProperty(TMP_DIR_KEY, ""),
89  LibraryUtils.Lib.TSK_JNI.getLibName(),
90  System.getProperty(USER_NAME_KEY, ""),
91  LibraryUtils.getExtByPlatform());
92 
93  // if the lock file exists
94  if (libTskJniFile.isFile() && !libTskJniFile.canWrite()) {
95  // get the random access file as read only
96  try (RandomAccessFile lockFileRaf = new RandomAccessFile(libTskJniFile, "r")) {
97  LockState lockState = isNewLock(lockFileRaf)
98  ? LockState.HELD_BY_NEW
99  : LockState.HELD_BY_OLD;
100 
101  return new LibraryLock(lockState, libTskJniFile, lockFileRaf, null, null);
102  } catch (IOException ex) {
103  // if there is an error getting read only access, then it is the old application dll
104  java.util.logging.Logger.getLogger(LibraryLock.class.getCanonicalName()).log(Level.WARNING, "An error occurred while acquiring the TSK lib lock", ex);
105  return new LibraryLock(LockState.HELD_BY_OLD, libTskJniFile, null, null, null);
106  }
107  } else {
108  // make directories leading up to that
109  libTskJniFile.getParentFile().mkdirs();
110 
111  // get file access to the file
112  RandomAccessFile lockFileRaf = null;
113  FileChannel lockFileChannel = null;
114  FileLock lockFileLock = null;
115  try {
116  lockFileRaf = new RandomAccessFile(libTskJniFile, "rw");
117  lockFileChannel = lockFileRaf.getChannel();
118  lockFileLock = lockFileChannel == null
119  ? null
120  : lockFileChannel.tryLock(1024L, 1L, false);
121 
122  if (lockFileLock != null) {
123  lockFileRaf.setLength(0);
124  lockFileRaf.write(UTF8_BOM);
125  lockFileRaf.writeChars(LIB_FILE_LOCK_TEXT);
126 
127  return new LibraryLock(LockState.ACQUIRED, libTskJniFile, lockFileRaf, lockFileChannel, lockFileLock);
128  } else {
129  LockState lockState = isNewLock(lockFileRaf)
130  ? LockState.HELD_BY_NEW
131  : LockState.HELD_BY_OLD;
132 
133  return new LibraryLock(lockState, libTskJniFile, lockFileRaf, lockFileChannel, null);
134  }
135  } catch (IOException ex) {
136  // if there is an error getting read only access, then it is the old application dll
137  java.util.logging.Logger.getLogger(LibraryLock.class.getCanonicalName()).log(Level.WARNING, "An error occurred while acquiring the TSK lib lock", ex);
138  return new LibraryLock(LockState.HELD_BY_OLD, libTskJniFile, lockFileRaf, lockFileChannel, lockFileLock);
139  }
140  }
141  }
142 
153  private static boolean isNewLock(RandomAccessFile libRaf) throws IOException {
154  libRaf.seek(0);
155  byte[] startFileArr = new byte[UTF8_BOM.length];
156  int read = libRaf.read(startFileArr);
157  return read == startFileArr.length && Arrays.equals(UTF8_BOM, startFileArr);
158 
159  }
160 
161  private File libTskJniFile;
162  private RandomAccessFile lockFileRaf;
163  private FileChannel lockFileChannel;
164  private FileLock lockFileLock;
165  private LockState lockState;
166 
176  private LibraryLock(
177  LockState lockState,
178  File lockFile,
179  RandomAccessFile lockFileRaf,
180  FileChannel lockFileChannel,
181  FileLock lockFileLock) {
182 
183  this.libTskJniFile = lockFile;
184  this.lockFileRaf = lockFileRaf;
185  this.lockFileChannel = lockFileChannel;
186  this.lockFileLock = lockFileLock;
187  this.lockState = lockState;
188  }
189 
197  return lockState;
198  }
199 
206  return libTskJniFile;
207  }
208 
209  @Override
210  public void close() throws Exception {
211  // close lock file resources in reverse acquisition order
212  if (this.lockFileLock != null) {
213  this.lockFileLock.close();
214  this.lockFileLock = null;
215  }
216 
217  if (this.lockFileChannel != null) {
218  this.lockFileChannel.close();
219  this.lockFileChannel = null;
220  }
221 
222  if (this.lockFileRaf != null) {
223  this.lockFileRaf.close();
224  this.lockFileRaf = null;
225  }
226 
227  if (this.libTskJniFile != null) {
228  this.libTskJniFile.delete();
229  this.libTskJniFile = null;
230  }
231  }
232 
236  public enum LockState {
248  ACQUIRED
249  }
250 }
static LibraryLock acquireLibLock()

Copyright © 2011-2024 Brian Carrier. (carrier -at- sleuthkit -dot- org)
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.