Adds filter capability in check and fix.

Fixes the context saving when only changed files are detected.
This commit is contained in:
Andrea Mazzoleni 2011-03-30 00:14:43 +02:00
parent ba73d0c574
commit a70eb4ed2b
13 changed files with 272 additions and 69 deletions

View file

@ -3,10 +3,10 @@ SnapRAID HISTORY
0.3 2011/4
==========
* Better ETA estimation.
* Added --filter option to select a subset of file in check and fix.
* Better ETA estimation in all the commands.
* Added support for OpenSSL crypto library to use its optimized MD5 implementation.
* Added test vector for MD5.
* Added a speed test option for MD5.
* Added test vectors and a speed test for MD5.
0.2 2011/3
==========

View file

@ -64,33 +64,39 @@ check-local:
mkdir test/disk2
mkdir test/disk3
echo --- As empty, sync and check
$(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf sync
$(TESTENV) ./snapraid$(EXEEXT) -v -c $(srcdir)/test.conf sync
$(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf check
echo --- Create some files, sync and check
$(TESTENV) ./mktest$(EXEEXT) generate 1 3 1000 4000
$(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf sync
$(TESTENV) ./snapraid$(EXEEXT) -v -c $(srcdir)/test.conf sync
$(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf check
echo --- Create some more files, sync and check
$(TESTENV) ./mktest$(EXEEXT) generate 2 3 1000 4000
$(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf sync
$(TESTENV) ./snapraid$(EXEEXT) -v -c $(srcdir)/test.conf sync
$(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf check
echo --- Delete some files and create some new, sync and check
rm test/disk1/1*
rm test/disk2/2*
rm test/disk2/3*
rm test/disk3/3*
$(TESTENV) ./mktest$(EXEEXT) generate 3 3 100 4000
$(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf sync
$(TESTENV) ./snapraid$(EXEEXT) -v -c $(srcdir)/test.conf sync
$(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf check
echo --- Move some files, sync and check
mv test/disk1/7* test/disk1/_a/
mv test/disk2/7* test/disk2/_a/
mv test/disk3/7* test/disk3/_a/
$(TESTENV) ./snapraid$(EXEEXT) -v -c $(srcdir)/test.conf sync
$(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf check
echo --- Delete some files and create some new, sync and check in multiple steps
rm test/disk1/4*
rm test/disk2/5*
rm test/disk2/6*
rm test/disk3/6*
$(TESTENV) ./mktest$(EXEEXT) generate 4 3 100 4000
$(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf -t 7 sync
$(TESTENV) ./snapraid$(EXEEXT) -v -c $(srcdir)/test.conf -t 7 sync
$(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf check
$(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf -t 11 sync
$(TESTENV) ./snapraid$(EXEEXT) -v -c $(srcdir)/test.conf -t 11 sync
$(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf check
$(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf sync
$(TESTENV) ./snapraid$(EXEEXT) -v -c $(srcdir)/test.conf sync
$(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf check
echo --- Delete some files, fix and check
rm test/disk1/1*
@ -109,6 +115,8 @@ check-local:
$(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf check 2>/dev/null
$(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf fix 2>/dev/null
$(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf check
echo --- Sync after all the fixes with an empty drive
$(TESTENV) ./snapraid$(EXEEXT) -v -E -c $(srcdir)/test.conf sync
echo --- Delete the parity, fix and check
rm test/parity
$(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf check 2>/dev/null
@ -124,6 +132,8 @@ check-local:
$(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf check 2>/dev/null
$(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf fix 2>/dev/null
$(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf check
echo --- Sync after all the fixes
$(TESTENV) ./snapraid$(EXEEXT) -v -c $(srcdir)/test.conf sync
echo Success!
# Manual testing

2
TODO
View file

@ -3,6 +3,8 @@ SnapRAID TODO
This is a list of possible TODO for SnapRAID. The order is not relevant.
* Easy way to find duplicates using the computed hash.
* Add RAID6 redundancy support.
There is the very good raid6 library from H. Peter Anvin (hpa) in the Linux Kernel ready to use:
See:

65
check.c
View file

@ -57,7 +57,31 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity
unrecoverable_error = 0;
recovered_error = 0;
countmax = blockmax - blockstart;
/* first count the number of blocks to process */
countmax = 0;
for(i=blockstart;i<blockmax;++i) {
int one_tocheck;
/* for each disk */
one_tocheck = 0;
for(j=0;j<diskmax;++j) {
struct snapraid_block* block = disk_block_get(handle[j].disk, i);
if (block
&& bit_has(block->flag, BLOCK_HAS_HASH) /* only if the block is hashed */
&& !block->file->is_filtered /* only if the file is not filtered out */
) {
one_tocheck = 1;
break;
}
}
/* if no block to check skip */
if (!one_tocheck)
continue;
++countmax;
}
countsize = 0;
countpos = 0;
start = time(0);
@ -66,21 +90,24 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity
int failed;
struct snapraid_block* failed_block;
struct snapraid_handle* failed_handle;
int one_hash;
int one_tocheck;
int all_parity;
/* for each disk */
one_hash = 0;
one_tocheck = 0;
for(j=0;j<diskmax;++j) {
struct snapraid_block* block = disk_block_get(handle[j].disk, i);
if (block && bit_has(block->flag, BLOCK_HAS_HASH)) {
one_hash = 1;
if (block
&& bit_has(block->flag, BLOCK_HAS_HASH) /* only if the block is hashed */
&& !block->file->is_filtered /* only if the file is not filtered out */
) {
one_tocheck = 1;
break;
}
}
/* if no hashed block skip */
if (!one_hash)
/* if no block to check skip */
if (!one_tocheck)
continue;
/* start with 0 */
@ -88,7 +115,7 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity
all_parity = 1; /* if all hashed block have parity computed */
failed = 0; /* number of failed block */
failed_block = 0; /* last failed block */
failed_block = 0; /* last failed block, but not filtered out */
failed_handle = 0;
/* for each disk, process the block */
@ -134,8 +161,10 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity
if (ret == -1) {
/* save the failed block for the parity check */
++failed;
failed_block = block;
failed_handle = &handle[j];
if (!block->file->is_filtered) {
failed_block = block;
failed_handle = &handle[j];
}
fprintf(stderr, "%u: Open error for file %s at position %u\n", i, block->file->sub, block_file_pos(block));
++error;
@ -147,8 +176,10 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity
if (read_size == -1) {
/* save the failed block for the parity check */
++failed;
failed_block = block;
failed_handle = &handle[j];
if (!block->file->is_filtered) {
failed_block = block;
failed_handle = &handle[j];
}
fprintf(stderr, "%u: Read error for file %s at position %u\n", i, block->file->sub, block_file_pos(block));
++error;
@ -162,8 +193,10 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity
if (memcmp(hash, block->hash, MD5_SIZE) != 0) {
/* save the failed block for the parity check */
++failed;
failed_block = block;
failed_handle = &handle[j];
if (!block->file->is_filtered) {
failed_block = block;
failed_handle = &handle[j];
}
fprintf(stderr, "%u: Data error for file %s at position %u\n", i, block->file->sub, block_file_pos(block));
++error;
@ -176,7 +209,9 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity
countsize += read_size;
}
if (parity_f == -1 || !all_parity) {
if (failed != 0 && !failed_block) {
/* if the failed blocks are filtered out, do nothing */
} else if (parity_f == -1 || !all_parity) {
/* all the cases with no parity file */
if (failed != 0) {
fprintf(stderr, "%u: UNRECOVERABLE errors for this block\n", i);

19
elem.c
View file

@ -78,7 +78,7 @@ void filter_free(struct snapraid_filter* filter)
free(filter);
}
int filter_filter(struct snapraid_filter* filter, const char* path, const char* name, int is_dir)
int filter_path(struct snapraid_filter* filter, const char* path, const char* name, int is_dir)
{
/* matches dirs with dirs and files with files */
if (filter->is_dir && !is_dir)
@ -98,6 +98,12 @@ int filter_filter(struct snapraid_filter* filter, const char* path, const char*
return -1;
}
int filter_file(struct snapraid_filter* filter, struct snapraid_file* file)
{
/* only partially correct as we are not filtering dirs */
return filter_path(filter, file->sub, file_name(file), 0);
}
block_off_t block_file_pos(struct snapraid_block* block)
{
struct snapraid_file* file = block->file;
@ -140,6 +146,7 @@ struct snapraid_file* file_alloc(unsigned block_size, const char* sub, uint64_t
file->mtime = mtime;
file->inode = inode;
file->is_present = 0;
file->is_filtered = 0;
file->blockvec = malloc_nofail(file->blockmax * sizeof(struct snapraid_block));
/* set the back pointer */
@ -158,6 +165,16 @@ void file_free(struct snapraid_file* file)
free(file);
}
const char* file_name(struct snapraid_file* file)
{
const char* r = strrchr(file->sub, '/');
if (!r)
r = file->sub;
else
++r;
return r;
}
int file_inode_compare(const void* void_arg, const void* void_data)
{
const uint64_t* arg = void_arg;

16
elem.h
View file

@ -79,6 +79,7 @@ struct snapraid_file {
uint64_t mtime; /**< Modification time. */
uint64_t inode; /**< Inode. */
int is_present; /**< If it's seen as present. */
int is_filtered; /**< If it's filtered out. */
/* nodes for data structures */
tommy_node nodelist;
@ -108,10 +109,16 @@ struct snapraid_filter* filter_alloc(const char* pattern);
void filter_free(struct snapraid_filter* filter);
/**
* Checks if a path/name matches the pattern.
* Filters a path/name.
* Returns 0 if it matches.
*/
int filter_filter(struct snapraid_filter* filter, const char* path, const char* name, int is_dir);
int filter_path(struct snapraid_filter* filter, const char* path, const char* name, int is_dir);
/**
* Filters a file.
* Returns 0 if it matches.
*/
int filter_file(struct snapraid_filter* filter, struct snapraid_file* file);
/**
* Gets the relative position of a block inside the file.
@ -134,6 +141,11 @@ struct snapraid_file* file_alloc(unsigned block_size, const char* sub, uint64_t
*/
void file_free(struct snapraid_file* file);
/**
* Returns the name of the file, without the dir.
*/
const char* file_name(struct snapraid_file* file);
/**
* Compares two files by inode.
*/

View file

@ -2,7 +2,7 @@
.SH NAME
snapraid \(hy SnapRAID Backup For Disk Arrays
.SH SYNOPSIS
snapraid [\(hyc, \(hy\(hyconf CONFIG]
snapraid [\(hyc, \(hy\(hyconf CONFIG] [\(hyf, \(hy\(hyfilter PATTERN]
.PD 0
.PP
.PD
@ -254,6 +254,14 @@ Selects the configuration file. If not specified is assumed
the file \(cq/etc/snapraid.conf\(cq in Unix, and \(cqsnapraid.conf\(cq
in Windows.
.TP
.B \(hyf, \(hy\(hyfilter PATTERN
Filters the files to operate on with the \(a"check\(a" and \(a"fix\(a"
commands. This option is ignored with the \(a"sync\(a" command.
See the PATTERN section for more details in the
pattern specifications.
This option can be used many times.
In Unix, ensure to quote globbing chars if used.
.TP
.B \(hyZ, \(hy\(hyforce\(hyzero
Forces the insecure operation of syncing a file with zero
size that before was not empty.
@ -326,7 +334,8 @@ You should use one option for each disk of the array.
.TP
.B exclude PATTERN
Defines the file or directory patterns to exclude from the sync
process. See the PATTERN section for more details in the
process.
See the PATTERN section for more details in the
pattern specifications.
This option can be used many times.
.TP
@ -400,37 +409,36 @@ block_size 256
.PD
.RE
.SH PATTERN
Patterns are used to define the files and directories to exclude
from the redundancy process.
.PP
It makes sense to exclude any file not worth to be saved or that
changes often.
Patterns are used select a subset of files to exclude or operate on.
.PP
There are four different types of patterns:
.TP
.B FILE
Excludes any file named as FILE. You can use any globbing
Selects any file named as FILE. You can use any globbing
character like * and ?.
This pattern is applied only to files and not to directories.
.TP
.B DIR/
Excludes any directory named DIR. You can use any globbing
Selects any directory named DIR. You can use any globbing
character like * and ?.
This pattern is applied only to directories and not to files.
.TP
.B /PATH/FILE
Excludes the exact specified file path. You can use any
Selects the exact specified file path. You can use any
globbing character like * and ? but they never matches a
directory slash.
This pattern is applied only to files and not to directories.
.TP
.B /PATH/DIR/
Excludes the exact specified directory path. You can use any
Selects the exact specified directory path. You can use any
globbing character like * and ? but they never matches a
directory slash.
This pattern is applied only to directories and not to files.
.PP
For example:
Note that when globbing char are used in the command line, you have to
quote them in Unix. Otherwise the shell will try to expand them.
.PP
For example, in the configuration file:
.PP
.RS 4
# Excludes any file named \(a"*.bak\(a"
@ -458,6 +466,23 @@ exclude tmp/
.PP
.PD
.RE
.PP
For example, in the command line:
.PP
.RS 4
# Checks only the .mp3 files.
.PD 0
.PP
.PD
# Note the \(a"\(a" use to avoid globbing expansion by the shell.
.PD 0
.PP
.PD
snapraid \(hyf \(a"*.mp3\(a" check
.PD 0
.PP
.PD
.RE
.SH CONTENT
SnapRAID creates a content file describing the content of your disk
array.

View file

@ -55,7 +55,7 @@ struct test_vector {
{ "abcdefghijklmnopqrstuvwxyz", { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } },
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } },
{ "12345678901234567890123456789012345678901234567890123456789012345678901234567890", { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a, } },
{ 0 }
{ 0, { 0 } }
};
void selftest(void)
@ -123,6 +123,7 @@ void usage(void)
printf("\n");
printf("Options:\n");
printf(" " SWITCH_GETOPT_LONG("-c, --conf FILE ", "-c") " Configuration file (default " CONF ")\n");
printf(" " SWITCH_GETOPT_LONG("-f, --filter PATTERN", "-f") " Filter the files to processs\n");
printf(" " SWITCH_GETOPT_LONG("-Z, --force-zero ", "-Z") " Force synching of files that get zero size\n");
printf(" " SWITCH_GETOPT_LONG("-E, --force-empty ", "-E") " Force synching of disks that get empty\n");
printf(" " SWITCH_GETOPT_LONG("-s, --start BLKSTART", "-s") " Start from the specified block number\n");
@ -136,6 +137,7 @@ void usage(void)
#if HAVE_GETOPT_LONG
struct option long_options[] = {
{ "conf", 1, 0, 'c' },
{ "filter", 1, 0, 'f' },
{ "force-zero", 0, 0, 'Z' },
{ "force-empty", 0, 0, 'E' },
{ "start", 1, 0, 's' },
@ -148,7 +150,7 @@ struct option long_options[] = {
};
#endif
#define OPTIONS "c:s:t:ZETvhV"
#define OPTIONS "c:f:s:t:ZETvhV"
volatile int global_interrupt = 0;
@ -177,6 +179,7 @@ int main(int argc, char* argv[])
block_off_t blockstart;
block_off_t blockcount;
int ret;
tommy_list filterlist;
/* defaults */
conf = CONF;
@ -185,6 +188,7 @@ int main(int argc, char* argv[])
force_empty = 0;
blockstart = 0;
blockcount = 0;
tommy_list_init(&filterlist);
opterr = 0;
while ((c =
@ -198,6 +202,14 @@ int main(int argc, char* argv[])
case 'c' :
conf = optarg;
break;
case 'f' : {
struct snapraid_filter* filter = filter_alloc(optarg);
if (!filter) {
fprintf(stderr, "Invalid filter specification '%s'\n", optarg);
exit(EXIT_FAILURE);
}
tommy_list_insert_tail(&filterlist, &filter->node, filter);
} break;
case 's' :
if (stru32(optarg, &blockstart) != 0) {
fprintf(stderr, "Invalid start position '%s'\n", optarg);
@ -257,6 +269,12 @@ int main(int argc, char* argv[])
state_config(&state, conf, verbose, force_zero, force_empty);
if (operation == OPERATION_SYNC) {
if (!tommy_list_empty(&filterlist)) {
fprintf(stderr, "You cannot filter with the sync command\n");
exit(EXIT_FAILURE);
}
state_read(&state);
state_scan(&state);
@ -276,6 +294,8 @@ int main(int argc, char* argv[])
} else {
state_read(&state);
state_filter(&state, &filterlist);
/* intercept Ctrl+C */
signal(SIGINT, &signal_handler);
@ -283,6 +303,7 @@ int main(int argc, char* argv[])
}
state_done(&state);
tommy_list_foreach(&filterlist, (tommy_foreach_func*)filter_free);
return EXIT_SUCCESS;
}

View file

@ -2,7 +2,7 @@ Name{number}
snapraid - SnapRAID Backup For Disk Arrays
Synopsis
:snapraid [-c, --conf CONFIG]
:snapraid [-c, --conf CONFIG] [-f, --filter PATTERN]
: [-Z, --force-zero] [-E, --force-empty]
: [-s, --start BLKSTART] [-t, --count BLKCOUNT]
: [-v, --verbose]
@ -169,6 +169,14 @@ Options
the file '/etc/snapraid.conf' in Unix, and 'snapraid.conf'
in Windows.
-f, --filter PATTERN
Filters the files to operate on with the "check" and "fix"
commands. This option is ignored with the "sync" command.
See the PATTERN section for more details in the
pattern specifications.
This option can be used many times.
In Unix, ensure to quote globbing chars if used.
-Z, --force-zero
Forces the insecure operation of syncing a file with zero
size that before was not empty.
@ -242,7 +250,8 @@ Configuration
=exclude PATTERN
Defines the file or directory patterns to exclude from the sync
process. See the PATTERN section for more details in the
process.
See the PATTERN section for more details in the
pattern specifications.
This option can be used many times.
@ -279,37 +288,36 @@ Configuration
:block_size 256
Pattern
Patterns are used to define the files and directories to exclude
from the redundancy process.
It makes sense to exclude any file not worth to be saved or that
changes often.
Patterns are used select a subset of files to exclude or operate on.
There are four different types of patterns:
=FILE
Excludes any file named as FILE. You can use any globbing
Selects any file named as FILE. You can use any globbing
character like * and ?.
This pattern is applied only to files and not to directories.
=DIR/
Excludes any directory named DIR. You can use any globbing
Selects any directory named DIR. You can use any globbing
character like * and ?.
This pattern is applied only to directories and not to files.
=/PATH/FILE
Excludes the exact specified file path. You can use any
Selects the exact specified file path. You can use any
globbing character like * and ? but they never matches a
directory slash.
This pattern is applied only to files and not to directories.
=/PATH/DIR/
Excludes the exact specified directory path. You can use any
Selects the exact specified directory path. You can use any
globbing character like * and ? but they never matches a
directory slash.
This pattern is applied only to directories and not to files.
For example:
Note that when globbing char are used in the command line, you have to
quote them in Unix. Otherwise the shell will try to expand them.
For example, in the configuration file:
:# Excludes any file named "*.bak"
:exclude *.bak
:# Excludes the root directory "/lost+found"
@ -317,6 +325,11 @@ Pattern
:# Excludes any directory named "tmp"
:exclude tmp/
For example, in the command line:
:# Checks only the .mp3 files.
:# Note the "" use to avoid globbing expansion by the shell.
:snapraid -f "*.mp3" check
Content
SnapRAID creates a content file describing the content of your disk
array.

View file

@ -6,7 +6,7 @@
1 SYNOPSIS
==========
snapraid [-c, --conf CONFIG]
snapraid [-c, --conf CONFIG] [-f, --filter PATTERN]
[-Z, --force-zero] [-E, --force-empty]
[-s, --start BLKSTART] [-t, --count BLKCOUNT]
[-v, --verbose]
@ -188,6 +188,14 @@ SnapRAID provides three simple commands that allow to:
the file '/etc/snapraid.conf' in Unix, and 'snapraid.conf'
in Windows.
-f, --filter PATTERN
Filters the files to operate on with the "check" and "fix"
commands. This option is ignored with the "sync" command.
See the PATTERN section for more details in the
pattern specifications.
This option can be used many times.
In Unix, ensure to quote globbing chars if used.
-Z, --force-zero
Forces the insecure operation of syncing a file with zero
size that before was not empty.
@ -264,7 +272,8 @@ it should contains the following options:
exclude PATTERN
Defines the file or directory patterns to exclude from the sync
process. See the PATTERN section for more details in the
process.
See the PATTERN section for more details in the
pattern specifications.
This option can be used many times.
@ -304,37 +313,36 @@ An example of a typical configuration is:
8 PATTERN
=========
Patterns are used to define the files and directories to exclude
from the redundancy process.
It makes sense to exclude any file not worth to be saved or that
changes often.
Patterns are used select a subset of files to exclude or operate on.
There are four different types of patterns:
FILE
Excludes any file named as FILE. You can use any globbing
Selects any file named as FILE. You can use any globbing
character like * and ?.
This pattern is applied only to files and not to directories.
DIR/
Excludes any directory named DIR. You can use any globbing
Selects any directory named DIR. You can use any globbing
character like * and ?.
This pattern is applied only to directories and not to files.
/PATH/FILE
Excludes the exact specified file path. You can use any
Selects the exact specified file path. You can use any
globbing character like * and ? but they never matches a
directory slash.
This pattern is applied only to files and not to directories.
/PATH/DIR/
Excludes the exact specified directory path. You can use any
Selects the exact specified directory path. You can use any
globbing character like * and ? but they never matches a
directory slash.
This pattern is applied only to directories and not to files.
For example:
Note that when globbing char are used in the command line, you have to
quote them in Unix. Otherwise the shell will try to expand them.
For example, in the configuration file:
# Excludes any file named "*.bak"
exclude *.bak
# Excludes the root directory "/lost+found"
@ -342,6 +350,11 @@ For example:
# Excludes any directory named "tmp"
exclude tmp/
For example, in the command line:
# Checks only the .mp3 files.
# Note the "" use to avoid globbing expansion by the shell.
snapraid -f "*.mp3" check
9 CONTENT
=========

50
state.c
View file

@ -510,6 +510,56 @@ void state_write(struct snapraid_state* state)
}
}
void state_filter(struct snapraid_state* state, tommy_list* filterlist)
{
unsigned i;
if (tommy_list_empty(filterlist))
return;
printf("Filtering...\n");
if (state->verbose) {
tommy_node* k;
for(k=tommy_list_head(filterlist);k!=0;k=k->next) {
struct snapraid_filter* filter = k->data;
printf("\t");
if (filter->is_path)
printf("/");
printf("%s", filter->pattern);
if (filter->is_dir)
printf("/");
printf("\n");
}
}
/* for each disk */
for(i=0;i<tommy_array_size(&state->diskarr);++i) {
tommy_node* j;
struct snapraid_disk* disk = tommy_array_get(&state->diskarr, i);
/* for each file */
for(j=tommy_list_head(&disk->filelist);j!=0;j=j->next) {
tommy_node* k;
struct snapraid_file* file = j->data;
/* filter it out as default */
file->is_filtered = 1;
/* for each filter */
for(k=tommy_list_head(filterlist);k!=0;k=k->next) {
struct snapraid_filter* filter = k->data;
if (filter_file(filter, file) == 0) {
/* mark it as filtered */
file->is_filtered = 0;
break;
}
}
}
}
}
#define PROGRESS_CLEAR " "
int state_progress(time_t* start, time_t* last, block_off_t countpos, block_off_t countmax, data_off_t countsize)

View file

@ -78,6 +78,11 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t
*/
void state_check(struct snapraid_state* state, int fix, block_off_t blockstart, block_off_t blockcount);
/**
* Filter files.
*/
void state_filter(struct snapraid_state* state, tommy_list* filterlist);
/**
* Writes the progress.
*/

2
util.c
View file

@ -180,7 +180,7 @@ void pathcpy(char* str, size_t size, const char* src)
void pathprint(char* str, size_t size, const char* format, ...)
{
int len;
size_t len;
va_list ap;
va_start(ap, format);