Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add exclude command line option. Excludes files based on a glob string #56

Merged
merged 13 commits into from
Jan 25, 2021
63 changes: 23 additions & 40 deletions ftw.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#include <unistd.h>
#include <dirent.h>
#include <stdbool.h>
#include <glob.h>
#include <fnmatch.h>

#include "export.h"
#include "mktorrent.h" /* DIRSEP_CHAR */
Expand Down Expand Up @@ -111,7 +111,7 @@ static unsigned int dir_state_close(struct dir_state *ds)
return 0;
}

static unsigned int cleanup(struct dir_state *ds, char *path, struct ll *exclude_list, int ret)
static unsigned int cleanup(struct dir_state *ds, char *path, int ret)
{
while (ds->prev)
ds = ds->prev;
Expand All @@ -125,9 +125,6 @@ static unsigned int cleanup(struct dir_state *ds, char *path, struct ll *exclude
if (path)
free(path);

if( exclude_list )
ll_free(exclude_list, NULL);

return ret;
}

Expand All @@ -149,7 +146,7 @@ EXPORT int file_tree_walk(const char *dirname, unsigned int nfds,
path = malloc(path_size);
if (path == NULL) {
fprintf(stderr, "fatal error: out of memory\n");
return cleanup(ds, NULL, NULL, -1);
return cleanup(ds, NULL, -1);
}
path_max = path + path_size;

Expand All @@ -164,7 +161,7 @@ EXPORT int file_tree_walk(const char *dirname, unsigned int nfds,
new_path = realloc(path, 2*path_size);
if (new_path == NULL) {
fprintf(stderr, "fatal error: out of memory\n");
return cleanup(ds, path, NULL, -1);
return cleanup(ds, path, -1);
}
end = new_path + path_size;
path_size *= 2;
Expand All @@ -180,29 +177,13 @@ EXPORT int file_tree_walk(const char *dirname, unsigned int nfds,
}

if (dir_state_open(ds, path, end - path))
return cleanup(ds, path, NULL, -1);
return cleanup(ds, path, -1);

first_open = ds;
nopen = 1;

*end = DIRSEP_CHAR;

struct ll *exclude_file_list = ll_new();
FATAL_IF0(exclude_file_list == NULL, "out of memory\n");

LL_FOR(tier_node, m->exclude_list) {
LL_FOR(exclude_node, LL_DATA_AS(tier_node, struct ll*)) {
const char *exclude_glob = LL_DATA_AS(exclude_node, const char*);
glob_t globbuf;

if( glob(exclude_glob, 0, NULL, &globbuf) == 0 ) {
for(size_t i=0; i<globbuf.gl_pathc; ++i) {
ll_append(exclude_file_list, globbuf.gl_pathv[i], 0);
}
}
}
}

while (1) {
struct dirent *de = readdir(ds->dir);

Expand All @@ -217,14 +198,16 @@ EXPORT int file_tree_walk(const char *dirname, unsigned int nfds,
&& de->d_name[2] == '\0'))) {
continue;
}

zordtk marked this conversation as resolved.
Show resolved Hide resolved
bool should_skip = false;
LL_FOR(exclude_file_node, exclude_file_list) {
const char *exclude_file = LL_DATA_AS(exclude_file_node, const char*);
if(strncmp(de->d_name, exclude_file, strlen(exclude_file)) == 0 ) {
if(m->verbose)
printf("skipping %s\n", de->d_name);
should_skip = true;
LL_FOR(tier_node, m->exclude_list) {
zordtk marked this conversation as resolved.
Show resolved Hide resolved
LL_FOR(exclude_node, LL_DATA_AS(tier_node, struct ll*)) {
const char *exclude_pattern = LL_DATA_AS(exclude_node, const char*);
zordtk marked this conversation as resolved.
Show resolved Hide resolved
if (fnmatch(exclude_pattern, de->d_name, 0) != FNM_NOMATCH) {
if (m->verbose)
printf("skipping %s\n", de->d_name);
should_skip = true;
zordtk marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

Expand All @@ -242,7 +225,7 @@ EXPORT int file_tree_walk(const char *dirname, unsigned int nfds,
new_path = realloc(path, 2*path_size);
if (new_path == NULL) {
fprintf(stderr, "fatal error: out of memory\n");
return cleanup(ds, path, exclude_file_list, -1);
return cleanup(ds, path, -1);
}
end = new_path + path_size;
path_size *= 2;
Expand All @@ -254,29 +237,29 @@ EXPORT int file_tree_walk(const char *dirname, unsigned int nfds,
if (stat(path, &sbuf)) {
fprintf(stderr, "fatal error: cannot stat '%s': %s\n",
path, strerror(errno));
return cleanup(ds, path, exclude_file_list, -1);
return cleanup(ds, path, -1);
}

r = callback(path, &sbuf, data);
if (r)
return cleanup(ds, path, exclude_file_list, r);
return cleanup(ds, path, r);

if (S_ISDIR(sbuf.st_mode)) {
if (ds->next == NULL &&
(ds->next = dir_state_new(ds, NULL)) == NULL)
return cleanup(ds, path, exclude_file_list, -1);
return cleanup(ds, path, -1);

ds = ds->next;

if (nopen == nfds) {
if (dir_state_close(first_open))
return cleanup(ds, path, exclude_file_list, -1);
return cleanup(ds, path, -1);
first_open = first_open->next;
nopen--;
}

if (dir_state_open(ds, path, end - path))
return cleanup(ds, path, exclude_file_list, -1);
return cleanup(ds, path, -1);

nopen++;

Expand All @@ -287,7 +270,7 @@ EXPORT int file_tree_walk(const char *dirname, unsigned int nfds,
path[ds->length] = '\0';
fprintf(stderr, "fatal error: cannot close '%s': %s\n",
path, strerror(errno));
return cleanup(ds, path, exclude_file_list, -1);
return cleanup(ds, path, -1);
}

if (ds->prev == NULL)
Expand All @@ -298,12 +281,12 @@ EXPORT int file_tree_walk(const char *dirname, unsigned int nfds,

if (ds->dir == NULL) {
if (dir_state_reopen(ds, path))
return cleanup(ds, path, exclude_file_list, -1);
return cleanup(ds, path, -1);
first_open = ds;
nopen++;
}
}
}

return cleanup(ds, path, exclude_file_list, 0);
return cleanup(ds, path, 0);
}
86 changes: 45 additions & 41 deletions init.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,52 +253,55 @@ static void print_help()
"Usage: mktorrent [OPTIONS] <target directory or filename>\n\n"
"Options:\n"
#ifdef USE_LONG_OPTIONS
"-a, --announce=<url>[,<url>]* : specify the full announce URLs\n"
" additional -a adds backup trackers\n"
"-c, --comment=<comment> : add a comment to the metainfo\n"
"-d, --no-date : don't write the creation date\n"
"-f, --force : overwrite output file if it exists\n"
"-h, --help : show this help screen\n"
"-l, --piece-length=<n> : set the piece length to 2^n bytes,\n"
" default is calculated from the total size\n"
"-n, --name=<name> : set the name of the torrent\n"
" default is the basename of the target\n"
"-o, --output=<filename> : set the path and filename of the created file\n"
" default is <name>.torrent\n"
"-p, --private : set the private flag\n"
"-s, --source=<source> : add source string embedded in infohash\n"
"-a, --announce=<url>[,<url>]* : specify the full announce URLs\n"
" additional -a adds backup trackers\n"
"-c, --comment=<comment> : add a comment to the metainfo\n"
"-d, --no-date : don't write the creation date\n"
"-e, --exclude=<match>[,<match>]* : exclude files based on filename pattern\n"
zordtk marked this conversation as resolved.
Show resolved Hide resolved
" matching, see fnmatch man page\n"
zordtk marked this conversation as resolved.
Show resolved Hide resolved
"-f, --force : overwrite output file if it exists\n"
"-h, --help : show this help screen\n"
"-l, --piece-length=<n> : set the piece length to 2^n bytes,\n"
" default is calculated from the total size\n"
"-n, --name=<name> : set the name of the torrent\n"
" default is the basename of the target\n"
"-o, --output=<filename> : set the path and filename of the created file\n"
" default is <name>.torrent\n"
"-p, --private : set the private flag\n"
"-s, --source=<source> : add source string embedded in infohash\n"
#ifdef USE_PTHREADS
"-t, --threads=<n> : use <n> threads for calculating hashes\n"
" default is the number of CPU cores\n"
"-t, --threads=<n> : use <n> threads for calculating hashes\n"
" default is the number of CPU cores\n"
#endif
"-v, --verbose : be verbose\n"
"-w, --web-seed=<url>[,<url>]* : add web seed URLs\n"
" additional -w adds more URLs\n"
"-x, --cross-seed : ensure info hash is unique for easier cross-seeding\n"
"-v, --verbose : be verbose\n"
"-w, --web-seed=<url>[,<url>]* : add web seed URLs\n"
" additional -w adds more URLs\n"
"-x, --cross-seed : ensure info hash is unique for easier cross-seeding\n"
#else
"-a <url>[,<url>]* : specify the full announce URLs\n"
" additional -a adds backup trackers\n"
"-c <comment> : add a comment to the metainfo\n"
"-d : don't write the creation date\n"
"-e <glob> : exclude file based on glob\n"
"-f : overwrite output file if it exists\n"
"-h : show this help screen\n"
"-l <n> : set the piece length to 2^n bytes,\n"
" default is calculated from the total size\n"
"-n <name> : set the name of the torrent,\n"
" default is the basename of the target\n"
"-o <filename> : set the path and filename of the created file\n"
" default is <name>.torrent\n"
"-p : set the private flag\n"
"-s : add source string embedded in infohash\n"
"-a <url>[,<url>]* : specify the full announce URLs\n"
" additional -a adds backup trackers\n"
"-c <comment> : add a comment to the metainfo\n"
"-d : don't write the creation date\n"
"-e <match>[,<match>]* : exclude files based on filename pattern\n"
" matching, see fnmatch man page\n"
"-f : overwrite output file if it exists\n"
"-h : show this help screen\n"
"-l <n> : set the piece length to 2^n bytes,\n"
" default is calculated from the total size\n"
"-n <name> : set the name of the torrent,\n"
" default is the basename of the target\n"
"-o <filename> : set the path and filename of the created file\n"
" default is <name>.torrent\n"
"-p : set the private flag\n"
"-s : add source string embedded in infohash\n"
#ifdef USE_PTHREADS
"-t <n> : use <n> threads for calculating hashes\n"
" default is the number of CPU cores\n"
"-t <n> : use <n> threads for calculating hashes\n"
" default is the number of CPU cores\n"
#endif
"-v : be verbose\n"
"-w <url>[,<url>]* : add web seed URLs\n"
" additional -w adds more URLs\n"
"-x : ensure info hash is unique for easier cross-seeding\n"
"-v : be verbose\n"
"-w <url>[,<url>]* : add web seed URLs\n"
" additional -w adds more URLs\n"
"-x : ensure info hash is unique for easier cross-seeding\n"
#endif
"\nPlease send bug reports, patches, feature requests, praise and\n"
"general gossip about the program to: mktorrent@rudde.org\n");
Expand Down Expand Up @@ -430,6 +433,7 @@ EXPORT void init(struct metafile *m, int argc, char *argv[])
{"announce", 1, NULL, 'a'},
{"comment", 1, NULL, 'c'},
{"no-date", 0, NULL, 'd'},
{"exclude", 1, NULL, 'e'},
{"force", 0, NULL, 'f'},
{"help", 0, NULL, 'h'},
{"piece-length", 1, NULL, 'l'},
Expand Down
1 change: 1 addition & 0 deletions mktorrent.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ struct metafile {
int cross_seed; /* ensure info hash is unique for easier cross-seeding */
int verbose; /* be verbose */
int force_overwrite; /* overwrite existing output file */
struct ll *exclude_list; /* exclude list */
#ifdef USE_PTHREADS
long threads; /* number of threads used for hashing */
#endif
Expand Down