-
Notifications
You must be signed in to change notification settings - Fork 0
/
detection.c
276 lines (248 loc) · 8.79 KB
/
detection.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
/* USB Storage Backup Daemon
Copyright 2012, Taco steemers. This program is distributed under the terms of
the GNU General Public License. A version of this license should have been
provided. It can also be found on: http://www.gnu.org/licenses/gpl-3.0.txt */
/* Many thanks to Orwellophile and his answer on
http://stackoverflow.com/questions/2432759/ */
#include <dirent.h>
#include <unistd.h> /* read, readlink */
#include <string.h>
#include <stdio.h> /* fopen, feof, fgets, FILE */
#include <stdlib.h> /* exit */
#include <fcntl.h> /* File control options (contains open) */
#include <syslog.h>
#include "detection.h"
#include "global.h"
#include "bookKeeping.h"
#include "backup.h"
#include "util.h"
void doCheck(void)
{
DIR *directory;
struct dirent *entry;
char* dirToCheck = "/sys/block/";
char devicePath[MAXDEVICEPATHLENGTH];
char* partitions[MAXNUMPARTITIONS];
int count;
int *pCount = &count;
initializeRun();
directory = openDirOrHang(dirToCheck);
do
{ /* Proccess each item in /sys/block/ */
if ((entry = readdir(directory)) == NULL)
continue;
if(entry->d_name[0]!='s' || entry->d_name[1]!='d')
continue;
/* sda3, sdb1, sdc5, ... */
/* We will now check via /proc/mounts
which partitions have been mounted */
sprintf(devicePath, "/dev/%s", entry->d_name);
count = 0;
findMountedPartitions(partitions, pCount, devicePath);
int i;
for(i = 0; i < count; i++)
{
processPartition(devicePath, entry->d_name, partitions[i]);
free(partitions[i]);
}
} while (entry != NULL);
free(directory);
free(entry);
finalizeRun();
}
void processPartition(char *devicePath,
char *deviceName, char *partition)
{
/* Examples of arguments:
processItem("/dev/sdh", "sdh", "/dev/sdh1");
processItem("/dev/sdh", "sdh", "/dev/sdh2");
*/
ssize_t len; /* Length of the path to the symbolic link */
char buf[MAXIDLENGTH];
/* strLocation will contain the symbolic link in /sys/block/,
that leads to the device that we want to investigate */
char strLocation[MAXIDLENGTH];
/* strDevice will contain the path to the device location in
/sys/devices */
char strDevice[MAXIDLENGTH];
/* strId will contain the identifier for the device, that will be
used by this code base */
char strId[MAXIDLENGTH];
/* mountPoint will contain the path to which the partition
has been mounted */
char mountPoint[MAXMOUNTPOINTLENGTH];
getMountPoint(mountPoint, partition);
/* Next we get the relative path to the device location in
/sys/devices, from the symbolic link in /sys/block */
snprintf(strLocation, sizeof strLocation,
"/sys/block/%s", deviceName);
len = readlink(strLocation, buf, MAXIDLENGTH);
buf[len] = 0;
sprintf(strDevice, "%s/%s", "/sys/block/", buf);
/* Now we try to gather device information
such as manufacturer, product and serial number.
strDevice will be changed in the process.
We use a variable to make note of the length,
to be sure that we can properly zero-terminate. */
int intIdLen = 0;
getDeviceInfo(strId, &intIdLen, strDevice);
if(intIdLen==0)
{
/* Some kind of device that is not of interest
Most likely it doesn't have a 'serial' file, in which case
it isn't a normal USB storage device
*/
return;
}
/* strId will end with the number of the partition */
strcat(strId, partition + strlen(devicePath));
if(gModeSetting == LISTMODE)
{ /* In list mode, we are only interested in
listing the devices */
if(gPrintDetailsInListMode == 1)
{
printf("%s, %s, %s\n", devicePath, mountPoint, strId);
}
else
{
printf("%s\n", strId);
}
return;
}
/* It appears we have a valid device, we should
back it up if we are configured to do so */
perhapsPerformBackup(mountPoint, strId); /* Defined in backup.c */
}
void getDeviceInfo(char* out, int *pOutLen, const char device[])
{
int i;
char *p;
/* strModel will contain the identifier for the model of this device,
as reported by the device.
This is of interest in the case of multi-card readers. */
char strModel[MAXIDLENGTH];
int intModelLen = 0;
/* strrchr: Locate last occurrence of character in string
Returns a pointer to the last occurrence of
character in the C string str.
We will be using that function to deconstruct the device
variable into the parts that interest us.
We do this to get the proper device location (which
USB connector our device is plugged in to), and the
subsystem number. That number we use to get the device
model.
In the case of a simple thumb drive, the subsystem number
will be 0.
A card reader with multiple slots will have multiple
subsystems, each with it's own number.
If we are looking at a SATA device instead of a USB device,
then this is where things will start to look different
than expected. */
/* Retrieving subsystem (ends in subsystem id) */
for (i=0; i<2; i++) {
p = strrchr(device, '/');
*p = 0;
}
/* Retrieving model name from subsystem */
addDeviceInfo(strModel, &intModelLen, device, "/model");
/* Retrieving the general system information */
for (i=0; i<4; i++) {
p = strrchr(device, '/');
*p = 0;
}
addDeviceInfo(out, pOutLen, device, "/manufacturer");
if (pOutLen > 0)
out[*pOutLen-1] = ' ';
addDeviceInfo(out, pOutLen, device, "/product");
if (pOutLen > 0)
out[*pOutLen-1] = ' ';
addDeviceInfo(out, pOutLen, device, "/serial");
if (pOutLen <= 0)
return; /* Apparently this is not a storage device
that is compatible with this daemon.
An example of that is a SATA device. */
tidyStringUp(out);
tidyStringUp(strModel);
/* Process device model name, if any */
if(strlen(strModel) != 0)
{
if((strlen(strModel) + strlen(out) + 2) >= MAXIDLENGTH)
{
/* There is not enough space to add a space and
the model to the id, so we create that space. */
out[MAXIDLENGTH - strlen(strModel) - 2] = 0;
}
strcat(out, " ");
strcat(out, strModel);
}
}
void addDeviceInfo(char *out, int *pOutLen, const char device[], const char property[])
{
char source[MAXIDLENGTH];
char buf[MAXIDLENGTH];
/* Make sure that out has a null character to terminate it,
this is necessary when using strcat */
out[*pOutLen] = 0;
/* Constructing source of desired info */
strcpy(source, device);
strcat(source, property);
/* Concatenating desired info to target,
if such info appears to be found */
int f = open(source, 0);
if (f == -1)
return;
int len = read(f, buf, MAXIDLENGTH);
if (len <= 0)
return;
/* Update the out variables */
*pOutLen += len;
buf[len-1] = 0;
strcat(out, (const char*) buf);
tidyStringUp(out);
*pOutLen = strlen(out) + 1;
}
char* findMountedPartitions(char* output[],
int* pCount, char *devicePath)
{
char buf[MAXDEVICEPATHLENGTH];
FILE *file = openOrHang("/proc/mounts", "r"); /* util.c */
while(!feof(file)) {
if (fgets(buf,sizeof(buf),file)) {
/* Check if this line starts with our item */
if(strncmp(buf, devicePath, strlen(devicePath)) != 0)
continue;
/* It does */
char* p = strchr(buf, ' ');
//p = p +1;
*p = 0;
output[*pCount] = malloc(MAXDEVICEPATHLENGTH);
memcpy(output[*pCount], buf, strlen(buf)+1);
*pCount = *pCount + 1;
}
}
fclose(file);
return 0;
}
void getMountPoint(char *out, char *devicePath)
{
char buf[MAXMOUNTPOINTLENGTH];
char *p1; /* To point at the start of the mount point */
char *p2; /* To point at the end of the mount point */
FILE *file = openOrHang("/proc/mounts", "r"); /* util.c */
out[0] = '\0'; /* Necessary for strcat */
while(!feof(file)) {
if (fgets(buf,sizeof(buf),file)) {
/* Check if this line starts with our item */
if(strncmp(buf, devicePath, strlen(devicePath)) != 0)
continue;
/* It does */
p1 = strchr(buf, ' ');
p1 = p1 + 1;
p2 = strchr(p1, ' ');
*p2 = 0;
strcat(out, p1);
break;
}
}
fclose(file);
}