Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed #14 All partitions are now backed up. Adjust your black-/whitel…

…ists! Partition numbers are now added to the back of the device identifier.

Also replaced some \ts with four spaces.
  • Loading branch information...
commit 4e894303a2fe36d35286e7e1d38320d0c3405a90 1 parent 4d0702b
@TacoSteemers authored
View
21 README.md
@@ -2,8 +2,8 @@ usbud
=====
## USB Storage Back Up Daemon
-The daemon will back up USB storage devices the moment they are plugged in.
-The daemon supports blacklisting and whitelisting. Either list consists of a file that contains one device id on each line. One can use the 'uslist' executable to find the device ids.
+The daemon will back up all mounted partitions on USB storage devices.
+The daemon supports per-partition blacklisting and whitelisting. Either list consists of a file that contains one device id on each line. One can use the 'uslist' executable to find the device ids.
Log output can be found in syslog.
This project is known to work on GNU/Linux systems. usbud depends on the availability of items such as '/sys/block' and '/proc/mounts' and the application 'rsync'.
**Important note: the USB storage back up daemon should not be confused with a 'full' backup solution. It should be used in conjunction with a 'full' backup solution.**
@@ -31,17 +31,18 @@ Please note that re-inserting a device, even in a different slot, does not neces
Here are some examples of identifiers:
- Generic MultiCard Device 00000000000006 USB SD Reader
- InphiCHN Mass Storage Device USB Flash Disk
- Kingston DataTraveler 2.0 899000000000000000000073 DataTraveler 2.0
- Kingston DataTraveler 2.0 899000000000000000000094 DataTraveler 2.0
- Kingston DataTraveler 2.0 8998011620080115142551D9 DataTraveler 2.0
- Generic Mass Storage 0ABE6A52 Flash Disk
- Apple iPod 000A27001CB7AFED iPod
+ Generic MultiCard Device 00000000000006 USB SD Reader1
+ InphiCHN Mass Storage Device USB Flash Disk1
+ Kingston DataTraveler 2.0 899000000000000000000073 DataTraveler 2.01
+ Kingston DataTraveler 2.0 899000000000000000000094 DataTraveler 2.01
+ Kingston DataTraveler 2.0 8998011620080115142551D9 DataTraveler 2.01
+ Generic Mass Storage 0ABE6A52 Flash Disk1
+ Generic Mass Storage 0ABE6A52 Flash Disk2
+ Apple iPod 000A27001CB7AFED iPod1
The first is a card that has been inserted in an 'all-in-one' card reader. This is supported. You may encounter problems when you use several card readers that were created by the same manufacturer. Maybe they would have to be of the same model, before problems occur.
The second is a cheap thumb drive that does not carry any identifying meta data at all. If you plug in a second one that was made by the same manufacturer, the daemon system will become confused. Most likely it will remove the backup that it has for the first drive, and place the backup of the second drive in it's stead.
-The next four items are regular thumb drives that will work quite well.
+The next five items are regular thumb drives that will work quite well. One of them has two partitions on it.
The last item is an iPod shuffle. Not every audio device is supported. To the best of my knowledge, all Creative Zen devices are not and are unlikely to ever be supported, because they use the 'MTP' protocol (Media Transfer Protocol). I have a Zen that I have tested this with. MTP is related to the Picture Transfer Protocol, and as such I'm quite certain that PTP devices are not supported either.
## Notes on device labels and multi-card readers
View
2  code/backup.c
@@ -15,7 +15,7 @@
#include "bookKeeping.h"
#include "backup.h"
-void processDevice(char* mountPoint, char* deviceId)
+void perhapsPerformBackup(char* mountPoint, char* deviceId)
{
int index;
if(checkIfDeviceIsKnown(deviceId)==1)
View
2  code/backup.h
@@ -6,7 +6,7 @@
#ifndef BACKUP_H
#define BACKUP_H
-void processDevice(char *mountPoint, char *deviceId);
+void perhapsPerformBackup(char *mountPoint, char *deviceId);
int needsBackup(char* deviceId);
void createTargetDirectoryString(char* output, char* deviceId);
void doBackup(char *source, char *target);
View
122 code/bookKeeping.c
@@ -14,81 +14,81 @@ device* devices[MAXNUMDEVS];
void initializeDeviceBookKeeping(void)
{
- int i = 0;
- for(; i < MAXNUMDEVS; i++)
- {
- devices[i] = malloc(sizeof(device));
- if(!devices[i])
- {
- syslog(LOG_ERR, "Exiting with failure: malloc failed during initialization");
- exit(EXIT_FAILURE);
- }
- devices[i]->index = i;
- devices[i]->runId = 0;
- devices[i]->id = malloc(sizeof(char) * 256);
- if(!devices[i]->id)
- {
- syslog(LOG_ERR, "Exiting with failure: malloc failed during initialization");
- exit(EXIT_FAILURE);
- }
- devices[i]->id[0] = '\0';
- }
+ int i = 0;
+ for(; i < MAXNUMDEVS; i++)
+ {
+ devices[i] = malloc(sizeof(device));
+ if(!devices[i])
+ {
+ syslog(LOG_ERR, "Exiting with failure: malloc failed during initialization");
+ exit(EXIT_FAILURE);
+ }
+ devices[i]->index = i;
+ devices[i]->runId = 0;
+ devices[i]->id = malloc(sizeof(char) * 256);
+ if(!devices[i]->id)
+ {
+ syslog(LOG_ERR, "Exiting with failure: malloc failed during initialization");
+ exit(EXIT_FAILURE);
+ }
+ devices[i]->id[0] = '\0';
+ }
}
void initializeRun(void)
{
- /* Ensure that the previous gCurrentRunId is different
- from the current, and is not equal to zero. */
- gCurrentRunId += 1;
- if(gCurrentRunId > 2)
- {
- gCurrentRunId = 1;
- }
+ /* Ensure that the previous gCurrentRunId is different
+ from the current, and is not equal to zero. */
+ gCurrentRunId += 1;
+ if(gCurrentRunId > 2)
+ {
+ gCurrentRunId = 1;
+ }
}
void finalizeRun(void)
{
- int i = 0;
- /* Here we will remove stale data from bookkeeping */
- for(; i < MAXNUMDEVS; i++)
- {
- if(devices[i]->id[0] == 0)
- continue; /* No data, no need to remove */
- if(devices[i]->runId == gCurrentRunId)
- continue; /* Recent data, no need to remove */
- syslog(LOG_INFO, "Removing stale device \"%s\".", devices[i]->id);
- devices[i]->id[0] = '\0';
- devices[i]->runId = 0;
- }
+ int i = 0;
+ /* Here we will remove stale data from bookkeeping */
+ for(; i < MAXNUMDEVS; i++)
+ {
+ if(devices[i]->id[0] == 0)
+ continue; /* No data, no need to remove */
+ if(devices[i]->runId == gCurrentRunId)
+ continue; /* Recent data, no need to remove */
+ syslog(LOG_INFO, "Removing stale device \"%s\".", devices[i]->id);
+ devices[i]->id[0] = '\0';
+ devices[i]->runId = 0;
+ }
}
int checkIfDeviceIsKnown(char* deviceId)
{
- int i = 0;
- for(; i < MAXNUMDEVS; i++)
- {
- if(strncmp(devices[i]->id, deviceId, strlen(deviceId)) != 0)
- continue; /* Not the same */
- /* This is the same. We will update the runId,
- to show that this device is not stale */
- devices[i]->runId = gCurrentRunId;
- return 1;
- }
- return 0;
+ int i = 0;
+ for(; i < MAXNUMDEVS; i++)
+ {
+ if(strncmp(devices[i]->id, deviceId, strlen(deviceId)) != 0)
+ continue; /* Not the same */
+ /* This is the same. We will update the runId,
+ to show that this device is not stale */
+ devices[i]->runId = gCurrentRunId;
+ return 1;
+ }
+ return 0;
}
int registerDevice(char* deviceId)
{
- int i = 0;
- for(; i < MAXNUMDEVS; i++)
- {
- if(devices[i]->id[0] != '\0')
- continue; /* Not an empty spot */
- memcpy(devices[i]->id, deviceId, strlen(deviceId)+1);
- devices[i]->runId = gCurrentRunId;
- syslog(LOG_INFO, "Device \"%s\" has been registered.", deviceId);
- return i;
- }
- syslog(LOG_INFO, "Device \"%s\" could not be registered. Too many devices have been registered already.", deviceId);
- return -1;
+ int i = 0;
+ for(; i < MAXNUMDEVS; i++)
+ {
+ if(devices[i]->id[0] != '\0')
+ continue; /* Not an empty spot */
+ memcpy(devices[i]->id, deviceId, strlen(deviceId)+1);
+ devices[i]->runId = gCurrentRunId;
+ syslog(LOG_INFO, "Device \"%s\" has been registered.", deviceId);
+ return i;
+ }
+ syslog(LOG_INFO, "Device \"%s\" could not be registered. Too many devices have been registered already.", deviceId);
+ return -1;
}
View
122 code/detection.c
@@ -25,6 +25,9 @@ void doCheck(void)
struct dirent *entry;
char* dirToCheck = "/sys/block/";
char devicePath[MAXDEVICEPATHLENGTH];
+ char* partitions[MAXNUMPARTITIONS];
+ int count;
+ int *pCount = &count;
initializeRun();
@@ -35,15 +38,19 @@ void doCheck(void)
continue;
if(entry->d_name[0]!='s' || entry->d_name[1]!='d')
continue;
- /* sda, sdb, sdc, ... */
+ /* sda3, sdb1, sdc5, ... */
/* We will now check via /proc/mounts
which partitions have been mounted */
sprintf(devicePath, "/dev/%s", entry->d_name);
- if(checkIfItemMounted(devicePath)==0)
- continue; /* Not mounted, not of interest */
-
- processItem(devicePath, 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);
@@ -51,34 +58,38 @@ void doCheck(void)
finalizeRun();
}
-void processItem(char *devicePath, char* entryName)
+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 actual device,
- (several versions of it, with varying detail)
- rather than the symbolic link */
+ /* 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 */
+ /* strId will contain the identifier for the device, that will be
+ used by this code base */
char strId[MAXIDLENGTH];
- char mountPoint[MAXIDLENGTH];
+ /* mountPoint will contain the path to which the partition
+ has been mounted */
+ char mountPoint[MAXMOUNTPOINTLENGTH];
+ getMountPoint(mountPoint, partition);
- /* 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 */
+ /* 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;
-
- /* 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.
@@ -86,15 +97,22 @@ void processItem(char *devicePath, char* entryName)
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 */
+ {
+ /* 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));
- 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 */
+ { /* In list mode, we are only interested in
+ listing the devices */
if(gPrintDetailsInListMode == 1)
{
printf("%s, %s, %s\n", devicePath, mountPoint, strId);
@@ -106,8 +124,9 @@ void processItem(char *devicePath, char* entryName)
return;
}
- /* It appears we have a valid device */
- processDevice(mountPoint, strId); /* Defined in backup.c */
+ /* 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[])
@@ -209,17 +228,23 @@ void addDeviceInfo(char *out, int *pOutLen, const char device[], const char prop
*pOutLen = strlen(out) + 1;
}
-int checkIfItemMounted(char *devicePath)
+char* findMountedPartitions(char* output[],
+ int* pCount, char *devicePath)
{
- char outputBuffer[MAXDEVICEPATHLENGTH];
+ char buf[MAXDEVICEPATHLENGTH];
FILE *file = openOrHang("/proc/mounts", "r"); /* util.c */
while(!feof(file)) {
- if (fgets(outputBuffer,sizeof(outputBuffer),file)) {
+ if (fgets(buf,sizeof(buf),file)) {
/* Check if this line starts with our item */
- if(strncmp(outputBuffer, devicePath, strlen(devicePath)) != 0)
+ if(strncmp(buf, devicePath, strlen(devicePath)) != 0)
continue;
/* It does */
- return 1;
+ 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);
@@ -228,38 +253,23 @@ int checkIfItemMounted(char *devicePath)
void getMountPoint(char *out, char *devicePath)
{
- char outputBuffer[MAXMOUNTPOINTLENGTH];
+ 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(outputBuffer,sizeof(outputBuffer),file)) {
+ if (fgets(buf,sizeof(buf),file)) {
/* Check if this line starts with our item */
- if(strncmp(outputBuffer, devicePath, strlen(devicePath)) != 0)
+ if(strncmp(buf, 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*/
+ p1 = strchr(buf, ' ');
+ p1 = p1 + 1;
+ p2 = strchr(p1, ' ');
*p2 = 0;
-
- /* Place only the mount point in the out parameter */
strcat(out, p1);
+ break;
}
}
fclose(file);
View
8 code/detection.h
@@ -7,10 +7,14 @@
#define USB_H
void doCheck(void);
-void processItem(char *devicePath, char* entryName);
+void processPartition(char *devicePath,
+ char *deviceName, char *partition);
int checkIfItemMounted(char *devicePath);
void getMountPoint(char *out, char *devicePath);
void getDeviceInfo(char* out, int *pOutLen, const char device[]);
-void addDeviceInfo(char *id, int *p_len, const char *source, const char *property);
+void addDeviceInfo(char *id, int *p_len,
+ const char *source, const char *property);
+char* findMountedPartitions(char* output[],
+ int* pCount, char *devicePath);
#endif
View
1  code/global.h
@@ -18,6 +18,7 @@ const int gModeSetting; /* Defined in either daemon.c or uslist.c */
#define MAXIDLENGTH 256
#define MAXDEVICEPATHLENGTH 32
#define MAXMOUNTPOINTLENGTH 1024
+#define MAXNUMPARTITIONS 256 /* GPT primary partition limit * 2 */
/* The daemon expects the used slots to be at the start of the list,
without gaps.
View
6 code/uslist.c
@@ -21,13 +21,13 @@ int main(int argc, char *argv[])
gPrintDetailsInListMode = 1;
}
- doCheck();
+ doCheck();
- exit(EXIT_SUCCESS);
+ exit(EXIT_SUCCESS);
}
/* The following functions with empty body are here,
because it allows us to use an unmodified 'detection.c' */
void initializeRun() {}
void finalizeRun() {}
-void processDevice(char* deviceId) {}
+void perhapsPerformBackup(char* deviceId) {}
Please sign in to comment.
Something went wrong with that request. Please try again.