Coverage Report

Created: 2025-07-23 06:45

/src/sleuthkit/tsk/img/logical_img.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
** The Sleuth Kit
3
**
4
** Copyright (c) 2022 Basis Technology Corp.  All rights reserved
5
** Contact: Brian Carrier [carrier <at> sleuthkit [dot] org]
6
**
7
** This software is distributed under the Common Public License 1.0
8
**
9
*/
10
11
/**
12
 * Internal code to open and read logical directories
13
 */
14
15
#include "tsk_img_i.h"
16
#include "legacy_cache.h"
17
#include "logical_img.h"
18
#include "tsk/util/file_system_utils.h"
19
20
/**
21
 * \internal
22
 * Display information about the disk image set.
23
 *
24
 * @param img_info Disk image to analyze
25
 * @param hFile Handle to print information to
26
 */
27
static void
28
logical_imgstat(TSK_IMG_INFO * img_info, FILE * hFile)
29
0
{
30
0
  IMG_LOGICAL_INFO *dir_info = (IMG_LOGICAL_INFO *) img_info;
31
0
32
0
    tsk_fprintf(hFile, "IMAGE FILE INFORMATION\n");
33
0
    tsk_fprintf(hFile, "--------------------------------------------\n");
34
0
    tsk_fprintf(hFile, "Image Type: logical directory\n");
35
0
  tsk_fprintf(hFile,
36
0
    "Base Directory Path: %" PRIttocTSK "\n",
37
0
    dir_info->base_path);
38
0
}
39
40
/*
41
 * Clear a cache entry. Assumes we acquired the cache_lock already or are in the process
42
 * of closing the image and don't need it.
43
 */
44
void
45
0
clear_inum_cache_entry(IMG_LOGICAL_INFO *logical_img_info, int index) {
46
0
  logical_img_info->inum_cache[index].inum = LOGICAL_INVALID_INUM;
47
0
  if (logical_img_info->inum_cache[index].path != NULL) {
48
0
    free(logical_img_info->inum_cache[index].path);
49
0
    logical_img_info->inum_cache[index].path = NULL;
50
0
  }
51
0
  logical_img_info->inum_cache[index].cache_age = 0;
52
0
}
53
54
/**
55
 * \internal
56
 *
57
 *
58
 * @param img_info logical directory to close
59
 */
60
static void
61
logical_close(TSK_IMG_INFO * img_info)
62
0
{
63
0
  IMG_LOGICAL_INFO *logical_img_info = (IMG_LOGICAL_INFO *)img_info;
64
0
  free(logical_img_info->base_path);
65
0
  for (int i = 0; i < LOGICAL_FILE_HANDLE_CACHE_LEN; i++) {
66
0
#ifdef TSK_WIN32
67
0
    if (logical_img_info->file_handle_cache[i].fd != 0) {
68
0
      CloseHandle(logical_img_info->file_handle_cache[i].fd);
69
0
    }
70
0
#endif
71
0
  }
72
0
  for (int i = 0; i < LOGICAL_INUM_CACHE_LEN; i++) {
73
0
    clear_inum_cache_entry(logical_img_info, i);
74
0
  }
75
0
76
0
  delete logical_img_info->cache;
77
0
78
0
  tsk_img_free(img_info);
79
0
}
80
81
static ssize_t
82
logical_read(
83
  [[maybe_unused]] TSK_IMG_INFO * img_info,
84
  [[maybe_unused]] TSK_OFF_T offset,
85
  [[maybe_unused]] char *buf,
86
  [[maybe_unused]] size_t len)
87
0
{
88
0
  tsk_error_reset();
89
0
  tsk_error_set_errno(TSK_ERR_IMG_READ);
90
0
  tsk_error_set_errstr("logical_read: Logical image read is not supported");
91
0
  return 0;
92
0
}
93
94
/**
95
 * \internal
96
 *
97
 *
98
 * @param a_num_img Number of images in set
99
 * @param a_images List of disk image paths (in sorted order)
100
 * @param a_ssize Size of device sector in bytes (or 0 for default)
101
 *
102
 * @return NULL on error
103
 */
104
TSK_IMG_INFO *
105
logical_open(
106
  int a_num_img,
107
  const TSK_TCHAR * const a_images[],
108
  [[maybe_unused]] unsigned int a_ssize)
109
0
{
110
0
  IMG_LOGICAL_INFO *logical_info;
111
0
  TSK_IMG_INFO *img_info;
112
113
0
  if (LOGICAL_IMG_DEBUG_PRINT) fprintf(stderr, "logical_open - Opening image\n");
114
0
  fflush(stderr);
115
116
0
#ifndef TSK_WIN32
117
0
  tsk_error_reset();
118
0
  tsk_error_set_errno(TSK_ERR_IMG_ARG);
119
0
  tsk_error_set_errstr("logical_open: Logical directories not supported for non-Windows systems");
120
0
  return NULL;
121
0
#endif
122
123
0
  if (a_num_img != 1) {
124
0
    tsk_error_reset();
125
0
    tsk_error_set_errno(TSK_ERR_IMG_ARG);
126
0
    tsk_error_set_errstr("logical_open: Only one directory (image name) is supported for logical directories");
127
0
    return NULL;
128
0
  }
129
130
0
  if ((logical_info =
131
0
    (IMG_LOGICAL_INFO *)tsk_img_malloc(sizeof(IMG_LOGICAL_INFO))) == NULL)
132
0
    return NULL;
133
0
  img_info = (TSK_IMG_INFO *)logical_info;
134
135
0
  logical_info->is_winobj = 0;
136
#ifdef TSK_WIN32
137
  logical_info->is_winobj = is_windows_device_path(a_images[0]);
138
#endif
139
140
  // Check that the given path exists and is a directory (return value = -3)
141
0
  TSK_OFF_T size_result = get_size_of_file_on_disk(a_images[0], logical_info->is_winobj);
142
0
  if (size_result != -3) {
143
0
    tsk_error_reset();
144
0
    tsk_error_set_errno(TSK_ERR_IMG_ARG);
145
0
    tsk_error_set_errstr("logical_open: Image path is not a directory");
146
0
    tsk_img_free(img_info);
147
0
    return NULL;
148
0
  }
149
150
0
  img_info->size = INT64_MAX;
151
0
  img_info->itype = TSK_IMG_TYPE_LOGICAL;
152
153
  // Initialize file handle cache
154
0
  for (int i = 0; i < LOGICAL_FILE_HANDLE_CACHE_LEN; i++) {
155
0
    logical_info->file_handle_cache[i].fd = 0;
156
0
    logical_info->file_handle_cache[i].inum = LOGICAL_INVALID_INUM;
157
0
  }
158
0
  logical_info->next_file_handle_cache_slot = 0;
159
160
  // Initialize the inum cache
161
0
  for (int i = 0; i < LOGICAL_INUM_CACHE_LEN; i++) {
162
0
    logical_info->inum_cache[i].inum = LOGICAL_INVALID_INUM;
163
0
    logical_info->inum_cache[i].path = NULL;
164
0
    logical_info->inum_cache[i].cache_age = 0;
165
0
  }
166
167
0
  logical_info->img_info.read = logical_read;
168
0
  logical_info->img_info.close = logical_close;
169
0
  logical_info->img_info.imgstat = logical_imgstat;
170
171
0
  size_t len = TSTRLEN(a_images[0]);
172
0
  logical_info->base_path =
173
0
    (TSK_TCHAR *)tsk_malloc(sizeof(TSK_TCHAR) * (len + 1));
174
0
  if (logical_info->base_path == NULL) {
175
0
    tsk_img_free(img_info);
176
0
    return NULL;
177
0
  }
178
0
  TSTRNCPY(logical_info->base_path, a_images[0], len + 1);
179
  // Remove trailing slash
180
#ifdef TSK_WIN32
181
  if ((logical_info->base_path[TSTRLEN(logical_info->base_path) - 1] == L'/')
182
      || (logical_info->base_path[TSTRLEN(logical_info->base_path) - 1] == L'\\')) {
183
    logical_info->base_path[TSTRLEN(logical_info->base_path) - 1] = '\0';
184
  }
185
#else
186
0
  if (logical_info->base_path[TSTRLEN(logical_info->base_path) - 1] == '/') {
187
0
    logical_info->base_path[TSTRLEN(logical_info->base_path) - 1] = '\0';
188
0
  }
189
0
#endif
190
191
0
  logical_info->cache = new LegacyCache();
192
193
0
  if (LOGICAL_IMG_DEBUG_PRINT) fprintf(stderr, "logical_open - Image opened successfully\n");
194
0
  fflush(stderr);
195
0
    return img_info;
196
0
}