redmine

Initial commit

# objects:
*.o
# linked:
insync
insync-debug
# other:
build
exceptions
... ...
CFLAGS += -std=gnu11 -pipe -Wall -O2 -fstack-protector-all
DEBUGCFLAGS = -pipe -Wall -Werror -ggdb -Wno-error=unused-variable -fstack-protector-all
objs=\
main.o\
output.o\
fasync.o\
malloc.o
binary=fasync
binarydebug=$(binary)-debug
all: $(objs)
$(CC) $(CFLAGS) $(LDFLAGS) $(objs) -o $(binary)
%.o: %.c
$(CC) -pedantic $(CFLAGS) $< -c -o $@
debug:
$(CC) $(DEBUGCFLAGS) *.c -o $(binarydebug)
clean:
rm -f $(binary) $(binarydebug) $(objs)
... ...
This diff is collapsed. Click to expand it.
/*
fasync - sync utility based on fanotify
Copyright (C) 2013 Dmitry Yu Okunev <xai@mephi.ru> 0x8E30679C
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _LARGEFILE64_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <getopt.h>
#include <limits.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <iconv.h>
#include <errno.h>
#include <endian.h>
#include <ctype.h>
#include <regex.h>
#include <signal.h>
#include <wait.h>
#include <sys/fanotify.h>
#include "config.h"
#ifndef MIN
#define MIN(a,b) (a>b?b:a)
#endif
#ifndef MAX
#define MAX(a,b) (a>b?a:b)
#endif
/*
#define sizeof_bit(a) (sizeof(a)*CHAR_BIT)
#define intvalues(a) (1 << sizeof_bit(a))
#define parse_le32uint(ptr_p) le32toh(*(uint32_t *)*(ptr_p)); *(ptr_p) = (typeof(*(ptr_p)))((char *)*(ptr_p)) + sizeof(uint32_t);
*/
enum flags_enum {
BACKGROUND = 'b',
HELP = 'h',
DEBUG = 'd',
QUITE = 'q',
VERBOSE = 'v'
};
typedef enum flags_enum flags_t;
extern int flags[];
enum ruleaction_enum {
RULE_END = 0, // Terminator. To be able to end rules' chain
RULE_ACCEPT,
RULE_REJECT
};
typedef enum ruleaction_enum ruleaction_t;
struct rule {
regex_t expr;
ruleaction_t action;
};
typedef struct rule rule_t;
... ...
#ifndef BUFSIZ
#define BUFSIZ (1<<16)
#endif
#define MAXRULES (1<<8)
#define MAXARGUMENTS (1<<8)
#define FANOTIFY_FLAGS (FAN_CLOEXEC|FAN_UNLIMITED_QUEUE|FAN_UNLIMITED_MARKS)
#define FANOTIFY_EVFLAGS (O_LARGEFILE|O_RDWR|O_CLOEXEC)
... ...
/*
fasync - sync utility based on fanotify
Copyright (C) 2013 Dmitry Yu Okunev <xai@mephi.ru> 0x8E30679C
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "common.h"
#include "output.h"
int fasync_exec(const char *actfpath, ...) {
va_list list;
va_start(list, actfpath);
const char *argv[MAXARGUMENTS] = {NULL};
argv[0] = actfpath;
int i = 1;
do {
if(i >= MAXARGUMENTS) {
printf_e("Error: Too many arguments (%i >= %i).\n", i, MAXARGUMENTS);
return ENOMEM;
}
argv[i] = va_arg(list, const char *const);
printf_dd("Debug2: argv[%i] = %s\n", i, argv[i]);
} while(argv[i++] != NULL);
pid_t pid;
int status;
pid = fork();
switch(pid) {
case -1:
printf_e("Error: Cannot fork(): %s (errno: %i).\n", strerror(errno), errno);
return errno;
case 0:
execvp(actfpath, (char *const *)argv);
return errno;
}
if(waitpid(pid, &status, 0) != pid) {
printf_e("Error: Cannot waitid(): %s (errno: %i).\n", strerror(errno), errno);
return errno;
}
int exitcode = WEXITSTATUS(status);
if(exitcode) {
printf_e("Error: Got non-zero exitcode while running \"%s\", exitcode is %i.\n", actfpath, exitcode);
return exitcode;
}
return 0;
}
int fasync_initialsync(const char *path, const char *actfpath) {
return fasync_exec(actfpath, "initialsync", path, NULL);
}
int fasync_walk_inotifyset(const char *path, rule_t *rules) {
return 0;
}
int fasync_run(const char *path, const char *actfpath, rule_t *rules) {
int ret;
ret = fasync_initialsync(path, actfpath);
if(ret) return ret;
ret = fasync_walk_inotifyset(path, rules);
if(ret) return ret;
int fanotify_d = fanotify_init(FANOTIFY_FLAGS, FANOTIFY_EVFLAGS);
if(fanotify_d == -1) {
printf_e("Error: cannot fanotify_init(): %s (errno: %i).", strerror(errno), errno);
return errno;
}
return 0;
}
... ...
/*
fasync - sync utility based on fanotify
Copyright (C) 2013 Dmitry Yu Okunev <xai@mephi.ru> 0x8E30679C
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
extern int fasync_run(const char *dpath, const char *actfpath, rule_t *rules);
... ...
/*
fasync - sync utility based on fanotify
Copyright (C) 2013 Dmitry Yu Okunev <xai@mephi.ru> 0x8E30679C
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "common.h"
#include "output.h"
#include "fasync.h"
#include "malloc.h"
int flags[(1<<8)] = {0};
static struct option long_options[] =
{
{"background", no_argument, &flags[BACKGROUND], BACKGROUND},
{"verbose", no_argument, &flags[VERBOSE], VERBOSE},
{"debug", no_argument, &flags[DEBUG], DEBUG},
{"quite", no_argument, &flags[QUITE], QUITE},
{"help", no_argument, NULL, HELP},
{0, 0, 0, 0}
};
int syntax() {
printf("syntax: fasync [flags] <watch dir> <action script> [file with rules regexps]\npossible flags:\n");
int i=0;
while(long_options[i].name != NULL) {
printf("\t--%-16s-%c\n", long_options[i].name, long_options[i].val);
i++;
}
exit(0);
}
char *parse_arguments(int argc, char *argv[], char **actfpath, char **exfpath) {
int c;
int option_index = 0;
while(1) {
c = getopt_long (argc, argv, "bqvdh", long_options, &option_index);
if (c == -1) break;
switch (c) {
case '?':
case 'h':
syntax();
break;
default:
flags[c]++;
break;
}
}
if(optind+1 >= argc)
syntax();
*actfpath = argv[optind+1];
if(optind+2 < argc)
*exfpath = argv[optind+2];
return argv[optind];
}
int parse_rules_fromfile(const char *exfpath, rule_t *rules) {
char buf[BUFSIZ];
char *line;
FILE *f = fopen(exfpath, "r");
if(f == NULL) {
printf_e("Error: Cannot open \"%s\" for reading: %s (errno: %i).\n", exfpath, strerror(errno), errno);
return errno;
}
int i=0;
size_t linelen, size=0;
while((linelen = getline(&line, &size, f)) != -1) {
if(linelen>0) {
line[linelen-1] = 0;
switch(*line) {
case '+':
rules[i].action = RULE_ACCEPT;
break;
case '-':
rules[i].action = RULE_REJECT;
break;
default:
printf_e("Error: Wrong rule action <%c>.\n", *line);
return EINVAL;
}
line++;
linelen--;
printf_d("Debug2: Rule pattern <%s> (length: %i).\n", line, linelen);
int ret;
if(i >= MAXRULES) {
printf_e("Error: Too many rules (%i >= %i).\n", i, MAXRULES);
rules[i].action = RULE_END;
return ENOMEM;
}
if((ret = regcomp(&rules[i].expr, line, REG_EXTENDED | REG_NOSUB))) {
regerror(ret, &rules[i].expr, buf, BUFSIZ);
printf_e("Error: Invalid regexp pattern <%s>: %s (regex-errno: %i).\n", line, buf, ret);
rules[i].action = RULE_END;
return ret;
}
i++;
}
}
if(size)
free(line);
fclose(f);
rules[i].action = RULE_END; // Terminator. End of rules' chain.
return 0;
}
int becomedaemon() {
int pid;
signal(SIGPIPE, SIG_IGN);
switch((pid = fork())) {
case -1:
printf_e("Error: Cannot fork(): %s (errno: %i).\n", strerror(errno), errno);
return(errno);
case 0:
setsid();
break;
default:
printf_d("Debug: fork()-ed, pid is %i.\n", pid);
exit(0);
}
return 0;
}
int main(int argc, char *argv[]) {
int ret = 0;
rule_t rules[MAXRULES];
char *actfpath, *exfpath=NULL;
char *dpath = parse_arguments(argc, argv, &actfpath, &exfpath);
out_init();
if(flags[DEBUG])
debug_print_flags();
if(exfpath != NULL)
ret = parse_rules_fromfile(exfpath, rules);
if(access(actfpath, X_OK) == -1) {
printf_e("Error: \"%s\" is not executable: %s (errno: %i).\n", actfpath, strerror(errno), errno);
ret = errno;
}
if(flags[BACKGROUND])
ret = becomedaemon();
if(ret == 0)
ret = fasync_run(dpath, actfpath, rules);
out_flush();
printf_d("Debug: finished, exitcode: %i.\n", ret);
out_flush();
return ret;
}
... ...
/*
fasync - sync utility based on fanotify
Copyright (C) 2013 Dmitry Yu Okunev <xai@mephi.ru> 0x8E30679C
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "common.h"
#include "malloc.h"
#include "output.h"
char *xmalloc(size_t size) {
size++; // Just in case
char *ret = (char *)malloc(size);
if(ret == NULL) {
printf_e("xmalloc(%i): Cannot allocate memory (#%i: %s).\n", size, errno, strerror(errno));
exit(ENOMEM);
}
memset(ret, size, 0); // Just in case
return ret;
}
char *xcalloc(size_t nmemb, size_t size) {
nmemb++; // Just in case
size++; // Just in case
char *ret = (char *)calloc(nmemb, size);
if(ret == NULL) {
printf_e("xcalloc(%i): Cannot allocate memory (#%i: %s).\n", size, errno, strerror(errno));
exit(ENOMEM);
}
memset(ret, nmemb*size, 0); // Just in case
return ret;
}
... ...
/*
fasync - sync utility based on fanotify
Copyright (C) 2013 Dmitry Yu Okunev <xai@mephi.ru> 0x8E30679C
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
extern char *xmalloc(size_t size);
extern char *xcalloc(size_t nmemb, size_t size);
... ...
/*
fasync - sync utility based on fanotify
Copyright (C) 2013 Dmitry Yu Okunev <xai@mephi.ru> 0x8E30679C
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "common.h"
#include "output.h"
printf_funct _printf_dd=NULL;
printf_funct _printf_d=NULL;
printf_funct _printf_v=NULL;
write_funct _write_dd=NULL;
write_funct _write_d=NULL;
write_funct _write_v=NULL;
int out_init() {
// static char buf[OUTPUT_BUFSIZE];
if(flags[DEBUG]>0) {
_printf_d = printf_e;
_write_d = write_e;
}
if(flags[DEBUG]>1) {
_printf_dd = printf_e;
_write_dd = write_e;
}
if(flags[VERBOSE]) {
_printf_v = printf_e;
_write_v = write_e;
}
// setvbuf(stdout, buf, _IOFBF, OUTPUT_BUFSIZE);
return 0;
}
int debug_print_flags() {
int flag=0;
printf("current flags: ");
while(flag < (1<<8)) {
if(flags[flag]) {
int i=0;
while(i++ < flags[flag])
printf("%c", flag);
}
flag++;
}
printf("\n");
return 0;
}
int debug_log_e(const char *fmt, va_list args) {
// TODO: ...
return 0;
}
int printf_e(const char *fmt, ...) {
if(flags[QUITE])
return 0;
int ret_log, ret_print;
va_list args;
va_start(args, fmt);
ret_log = debug_log_e(fmt, args);
ret_print = vfprintf(stderr, fmt, args);
va_end(args);
return ret_log ? ret_log : ret_print;
}
int write_e(const char *buf, size_t len) {
return fwrite(buf, len, 1, stderr);
}
int write_out(const char *buf, size_t len) {
return fwrite(buf, len, 1, stdout);
}
int printf_out(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
int ret_print = vprintf(fmt, args);
va_end(args);
return ret_print;
}
void out_flush() {
fflush(stdout);
}
void hexdump_e(const unsigned char *buf, size_t len) {
int i=0;
while(i<len)
printf_e("%5p ", (void *)(unsigned long)buf[i++]);
write_e("\n", 1);
return;
}
void hexdump_d(const unsigned char *buf, size_t len) {
if(flags[DEBUG]<1)
return;
hexdump_e(buf, len);
}
void hexdump_dd(const unsigned char *buf, size_t len) {
if(flags[DEBUG]<2)
return;
hexdump_e(buf, len);
}
... ...
/*
fasync - sync utility based on fanotify
Copyright (C) 2013 Dmitry Yu Okunev <xai@mephi.ru> 0x8E30679C
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
extern int out_init();
extern int debug_print_flags();
typedef int (*printf_funct)(const char *fmt, ...);
typedef int (*write_funct)(const char *buf, size_t len);
extern printf_funct _printf_dd;
#define printf_dd if(_printf_dd!=NULL)_printf_dd
extern printf_funct _printf_d;
#define printf_d if(_printf_d!=NULL)_printf_d
extern printf_funct _printf_v;
#define printf_v if(_printf_v!=NULL)_printf_v
extern write_funct _write_dd;
#define write_dd if(_write_dd!=NULL)_write_dd
extern write_funct _write_d;
#define write_d if(_write_d!=NULL)_write_d
extern write_funct _write_v;
#define write_v if(_write_v!=NULL)_write_v
extern int printf_e(const char *fmt, ...);
extern int printf_out(const char *fmt, ...);
extern int write_e(const char *buf, size_t len);
extern int write_out(const char *buf, size_t len);
#define write_out_s(buf) write_out(buf, sizeof(buf)-1)
extern void out_flush();
extern void hexdump_e(const unsigned char *buf, size_t len);
extern void hexdump_d(const unsigned char *buf, size_t len);
extern void hexdump_dd(const unsigned char *buf, size_t len);
... ...