/
detection.c
269 lines (236 loc) · 7.87 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
/* 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 "logging.h"
#include "detection.h"
#include "global.h"
#include "bookKeeping.h"
#include "backup.h"
#include "util.h"
void doCheck(void)
{
#ifdef _WIN32
#else
DIR *directory;
struct dirent *entry;
char* dirToCheck = "/sys/block/";
char devicePath[MAXDEVICEPATHLENGTH];
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;
/* sda, sdb, sdc, ... */
/* We will now double check via /proc/mounts that the item exists */
sprintf(devicePath, "/dev/%s", entry->d_name);
if(checkIfItemMounted(devicePath)==0)
continue; /* Not mounted, not of interest */
processItem(devicePath, entry->d_name);
} while (entry != NULL);
free(directory);
free(entry);
#endif
finalizeRun();
}
void processItem(char *devicePath, char* entryName)
{
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 actual device,
(several versions of it, with varying detail)
rather than the symbolic link */
char strDevice[MAXIDLENGTH];
/* strId will contain the identifier for the device, that will be used by
this code base */
char strId[MAXIDLENGTH];
char mountPoint[MAXIDLENGTH];
/* Construct the path to /sys/block/... */
snprintf(strLocation, sizeof strLocation, "/sys/block/%s", entryName);
/* Read symbolink link 'location' into buf,
returns the number of bytes it has placed in buf */
len = readlink(strLocation, buf, MAXIDLENGTH);
buf[len] = 0;
/* strDevice will contain the path to the actual device,
rather than the symbolic link */
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)
return; /* Some kind of bogus device */
getMountPoint(mountPoint, devicePath);
if(strlen(mountPoint) == 0)
return ; /* Apparently the device has been dismounted by now */
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 */
processDevice(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;
}
int checkIfItemMounted(char *devicePath)
{
char outputBuffer[MAXDEVICEPATHLENGTH];
FILE *file = openOrHang("/proc/mounts", "r"); /* util.c */
while(!feof(file)) {
if (fgets(outputBuffer,sizeof(outputBuffer),file)) {
/* Check if this line starts with our item */
if(strncmp(outputBuffer, devicePath, strlen(devicePath)) != 0)
continue;
/* It does */
return 1;
}
}
fclose(file);
return 0;
}
void getMountPoint(char *out, char *devicePath)
{
char outputBuffer[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(outputBuffer,sizeof(outputBuffer),file)) {
/* Check if this line starts with our item */
if(strncmp(outputBuffer, devicePath, strlen(devicePath)) != 0)
continue;
/* It does */
p1 = strchr(outputBuffer, ' ');
if(!p1)
{
syslog(LOG_ERR, "Exiting with failure: getMountPoint received invalid device path \"%s\"", devicePath);
exit(EXIT_FAILURE);
}
p1++;
/* p1 now points at the start of the mount point*/
p2 = strchr(p1, ' ');
if(!p2)
{
syslog(LOG_ERR, "Exiting with failure: getMountPoint received invalid device path \"%s\"", devicePath);
exit(EXIT_FAILURE);
}
/* p2 now points at the end of the mount point*/
*p2 = 0;
/* Place only the mount point in the out parameter */
strcat(out, p1);
}
}
fclose(file);
}