Coverage Report

Created: 2026-01-10 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/sleuthkit/tsk/util/file_system_utils.cpp
Line
Count
Source
1
2
/*
3
** The Sleuth Kit
4
**
5
** Copyright (c) 2022 Basis Technology Corp.  All rights reserved
6
** Contact: Brian Carrier [carrier <at> sleuthkit [dot] org]
7
**
8
** This software is distributed under the Common Public License 1.0
9
**
10
*/
11
12
/*
13
 * Common code used by the raw and logical images.
14
 */
15
16
#include "tsk/base/tsk_base_i.h"
17
#include "tsk/img/tsk_img_i.h"
18
#include "file_system_utils.h"
19
20
#ifdef __APPLE__
21
#include <sys/disk.h>
22
#endif
23
24
#ifdef TSK_WIN32
25
#include <winioctl.h>
26
#else
27
#include <sys/types.h>
28
#include <sys/stat.h>
29
#include <unistd.h>
30
#include <fcntl.h>
31
#endif
32
33
#ifndef S_IFMT
34
#define S_IFMT __S_IFMT
35
#endif
36
37
#ifndef S_IFDIR
38
#define S_IFDIR __S_IFDIR
39
#endif
40
41
/**
42
* Test if the image is a Windows device
43
* @param The path to test
44
*
45
* Return 1 if the path represents a Windows device, 0 otherwise
46
*/
47
#ifdef TSK_WIN32
48
int is_windows_device_path(const TSK_TCHAR * image_name) {
49
  return (TSTRNCMP(image_name, _TSK_T("\\\\.\\"), 4) == 0);
50
}
51
#endif
52
53
/**
54
* Get the size in bytes of the given file.
55
*
56
* @param a_file The file to test
57
* @param is_winobj 1 if the file is a windows object and not a real file
58
*
59
* @return the size in bytes, or -1 on error/unknown,
60
*         -2 if unreadable, -3 if it's a directory.
61
*/
62
TSK_OFF_T
63
get_size_of_file_on_disk(const TSK_TCHAR * a_file, uint8_t a_is_winobj)
64
0
{
65
0
  TSK_OFF_T size = -1;
66
0
  struct STAT_STR sb;
67
68
0
  if (TSTAT(a_file, &sb) < 0) {
69
0
    if (a_is_winobj) {
70
      /* stat can fail for Windows objects; ignore that */
71
0
      if (tsk_verbose) {
72
0
        tsk_fprintf(stderr,
73
0
          "raw_open: ignoring stat result on Windows device %"
74
0
          PRIttocTSK "\n", a_file);
75
0
      }
76
0
    }
77
0
    else {
78
0
      tsk_error_reset();
79
0
      tsk_error_set_errno(TSK_ERR_IMG_STAT);
80
0
      tsk_error_set_errstr("raw_open: image \"%" PRIttocTSK
81
0
        "\" - %s", a_file, strerror(errno));
82
0
      return -2;
83
0
    }
84
0
  }
85
0
  else if ((sb.st_mode & S_IFMT) == S_IFDIR) {
86
0
    tsk_error_reset();
87
0
    tsk_error_set_errno(TSK_ERR_IMG_MAGIC);
88
0
    tsk_error_set_errstr("raw_open: image \"%" PRIttocTSK
89
0
      "\" - is a directory", a_file);
90
0
    return -3;
91
0
  }
92
93
#ifdef TSK_WIN32
94
  {
95
    HANDLE fd;
96
    DWORD dwHi, dwLo;
97
98
    if ((fd = CreateFile(a_file, FILE_READ_DATA,
99
      FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
100
      OPEN_EXISTING, 0, NULL)) ==
101
      INVALID_HANDLE_VALUE) {
102
      int lastError = (int)GetLastError();
103
      tsk_error_reset();
104
      tsk_error_set_errno(TSK_ERR_IMG_OPEN);
105
      // print string of commonly found errors
106
      if (lastError == ERROR_ACCESS_DENIED) {
107
        tsk_error_set_errstr("raw_open: file \"%" PRIttocTSK
108
          "\" - access denied", a_file);
109
      }
110
      else if (lastError == ERROR_SHARING_VIOLATION) {
111
        tsk_error_set_errstr("raw_open: file \"%" PRIttocTSK
112
          "\" - sharing violation", a_file);
113
      }
114
      else if (lastError == ERROR_FILE_NOT_FOUND) {
115
        tsk_error_set_errstr("raw_open: file \"%" PRIttocTSK
116
          "\" - file not found", a_file);
117
      }
118
      else {
119
        tsk_error_set_errstr("raw_open: file \"%" PRIttocTSK
120
          "\" - (error %d)", a_file, lastError);
121
      }
122
      return -2;
123
    }
124
125
    /* We need different techniques to determine the size of Windows physical
126
    * devices versus normal files */
127
    if (a_is_winobj == 0) {
128
      dwLo = GetFileSize(fd, &dwHi);
129
      if (dwLo == 0xffffffff) {
130
        int lastError = (int)GetLastError();
131
        tsk_error_reset();
132
        tsk_error_set_errno(TSK_ERR_IMG_OPEN);
133
        tsk_error_set_errstr("raw_open: file \"%" PRIttocTSK
134
          "\" - GetFileSize: %d", a_file, lastError);
135
        size = -1;
136
      }
137
      else {
138
        size = dwLo | ((TSK_OFF_T)dwHi << 32);
139
      }
140
    }
141
    else {
142
143
      //use GET_PARTITION_INFO_EX prior to IOCTL_DISK_GET_DRIVE_GEOMETRY
144
      // to determine the physical disk size because
145
      //calculating it with the help of GET_DRIVE_GEOMETRY gives only
146
      // approximate number
147
      DWORD junk;
148
149
      PARTITION_INFORMATION_EX partition;
150
      if (FALSE == DeviceIoControl(fd,
151
        IOCTL_DISK_GET_PARTITION_INFO_EX,
152
        NULL, 0, &partition, sizeof(partition), &junk,
153
        (LPOVERLAPPED)NULL)) {
154
        DISK_GEOMETRY pdg;
155
156
        if (FALSE == DeviceIoControl(fd, IOCTL_DISK_GET_DRIVE_GEOMETRY,
157
          NULL, 0, &pdg, sizeof(pdg), &junk, (LPOVERLAPPED)NULL)) {
158
          int lastError = (int)GetLastError();
159
          tsk_error_reset();
160
          tsk_error_set_errno(TSK_ERR_IMG_OPEN);
161
          tsk_error_set_errstr("raw_open: file \"%" PRIttocTSK
162
            "\" - DeviceIoControl: %d", a_file,
163
            lastError);
164
          size = -1;
165
        }
166
        else {
167
          size = pdg.Cylinders.QuadPart *
168
            (TSK_OFF_T)pdg.TracksPerCylinder *
169
            (TSK_OFF_T)pdg.SectorsPerTrack *
170
            (TSK_OFF_T)pdg.BytesPerSector;
171
        }
172
      }
173
      else {
174
        size = partition.PartitionLength.QuadPart;
175
      }
176
    }
177
178
    CloseHandle(fd);
179
  }
180
#else
181
182
0
  int fd;
183
184
0
  if ((fd = open(a_file, O_RDONLY | O_BINARY)) < 0) {
185
0
    tsk_error_reset();
186
0
    tsk_error_set_errno(TSK_ERR_IMG_OPEN);
187
0
    tsk_error_set_errstr("raw_open: file \"%" PRIttocTSK "\" - %s",
188
0
      a_file, strerror(errno));
189
0
    return -2;
190
0
  }
191
192
#ifdef __APPLE__
193
  /* OS X doesn't support SEEK_END on char devices */
194
  if ((sb.st_mode & S_IFMT) != S_IFCHR) {
195
    size = lseek(fd, 0, SEEK_END);
196
  }
197
198
  if (size <= 0) {
199
    int blkSize;
200
    long long blkCnt;
201
202
    if (ioctl(fd, DKIOCGETBLOCKSIZE, &blkSize) >= 0) {
203
      if (ioctl(fd, DKIOCGETBLOCKCOUNT, &blkCnt) >= 0) {
204
        size = blkCnt * (long long)blkSize;
205
      }
206
    }
207
  }
208
#else
209
  /* We don't use the stat output because it doesn't work on raw
210
  * devices and such */
211
0
  size = lseek(fd, 0, SEEK_END);
212
0
#endif
213
214
0
  close(fd);
215
216
0
#endif
217
218
0
  return size;
219
0
}