Sleuth Kit Java Bindings (JNI)  4.12.1
Java bindings for using The Sleuth Kit
ReadContentInputStream.java
Go to the documentation of this file.
1 /*
2  * Sleuth Kit Data Model
3  *
4  * Copyright 2011-2018 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.IOException;
22 import java.io.InputStream;
23 
27 public final class ReadContentInputStream extends InputStream {
28 
29  private long currentOffset;
30  private final long contentSize;
31  private final Content content;
32 
33  public ReadContentInputStream(Content content) {
34  this.content = content;
35  this.currentOffset = 0;
36  this.contentSize = content.getSize();
37  }
38 
39  @Override
40  public int read() throws ReadContentInputStreamException {
41  byte[] buff = new byte[1];
42  return (read(buff) != -1) ? buff[0] : -1;
43  }
44 
45  @Override
46  public int read(byte[] b) throws ReadContentInputStreamException {
47  return read(b, 0, b.length);
48  }
49 
50  @Override
51  public int read(byte[] b, int off, int len) throws ReadContentInputStreamException {
52 
53  final int buffLen = b.length;
54  //must return 0 for zero-length arrays
55  if (buffLen == 0 || len == 0) {
56  return 0;
57  }
58 
59  //would get an error from TSK if we try to read an empty file
60  if (contentSize == 0) {
61  return -1;
62  }
63 
64  // check off. Must be in bounds of buffer
65  if (off < 0 || off >= buffLen) {
66  return -1;
67  }
68 
69  //eof, no data remains to be read
70  if (currentOffset >= contentSize) {
71  return -1;
72  }
73 
74  // Is the file big enough for the full request?
75  int lenToRead = (int) Math.min(contentSize - currentOffset, len);
76 
77  // is the buffer big enough?
78  lenToRead = Math.min(lenToRead, buffLen - off);
79 
80  byte[] retBuf;
81  if (off == 0) {
82  //write directly to user buffer
83  retBuf = b;
84  } else {
85  //write to a temp buffer, then copy to user buffer
86  retBuf = new byte[lenToRead];
87  }
88  try {
89  final int lenRead = content.read(retBuf, currentOffset, lenToRead);
90 
91  if (lenRead == 0 || lenRead == -1) {
92  //error or no more bytes to read, report EOF
93  return -1;
94  } else {
95  currentOffset += lenRead;
96 
97  //if read into user-specified offset, copy back from temp buffer to user
98  if (off != 0) {
99  System.arraycopy(retBuf, 0, b, off, lenRead);
100  }
101 
102  return lenRead;
103  }
104  } catch (TskCoreException ex) {
105  throw new ReadContentInputStreamException(String.format("Error reading file '%s' (id=%d) at offset %d.", content.getName(), content.getId(), currentOffset), ex);
106  }
107 
108  }
109 
110  @Override
111  public int available() throws IOException {
112  long len = contentSize - currentOffset;
113  if (len < 0) {
114  return 0;
115  }
116  return (int) len;
117  }
118 
119  @Override
120  public long skip(long n) throws IOException {
121  //more efficient skip() implementation than superclass
122  //as it does not involve reads
123  long toSkip = Math.min(n, contentSize - currentOffset); //allow to skip to EOF
124  currentOffset += toSkip;
125  return toSkip;
126  //0 1 2 3 4 5 len: 6
127  }
128 
129  @Override
130  public void close() throws IOException {
131  super.close();
132  //nothing to be done currently, file handles are closed when content is gc'ed
133  }
134 
135  @Override
136  public boolean markSupported() {
137  return false;
138  }
139 
141 
146  public long getLength() {
147  return contentSize;
148  }
149 
155  public long getCurPosition() {
156  return currentOffset;
157  }
158 
167  public long seek(long newPosition) {
168  if (newPosition < 0) {
169  throw new IllegalArgumentException("Illegal negative new position in the stream");
170  }
171 
172  currentOffset = Math.min(newPosition, contentSize);
173  return currentOffset;
174 
175  }
176 
181  public final static class ReadContentInputStreamException extends IOException {
182 
183  private static final long serialVersionUID = 1L;
184 
185  public ReadContentInputStreamException(String message) {
186  super(message);
187  }
188 
189  public ReadContentInputStreamException(String message, Throwable cause) {
190  super(message, cause);
191  }
192  }
193 }
int read(byte[] buf, long offset, long len)
long getLength()
additional methods to facilitate stream seeking

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