From 0387b4665bef6a5cb6851581e42cad0ecca3e90c Mon Sep 17 00:00:00 2001 From: Frank Lahm Date: Mon, 30 May 2011 15:26:38 +0200 Subject: [PATCH] Allow enabling/disabling notifications on a per event type basis --- etc/afpd/afp_options.c | 4 ++ etc/afpd/fce_api.c | 88 ++++++++++++++++++++++++++++++------- etc/afpd/fce_api_internal.h | 28 +----------- etc/afpd/volume.c | 2 + include/atalk/fce_api.h | 30 +++++++++++++ 5 files changed, 110 insertions(+), 42 deletions(-) diff --git a/etc/afpd/afp_options.c b/etc/afpd/afp_options.c index 7a2d405f..82db1c8e 100644 --- a/etc/afpd/afp_options.c +++ b/etc/afpd/afp_options.c @@ -487,6 +487,10 @@ int afp_options_parseline(char *buf, struct afp_options *options) LOG(log_note, logtype_afpd, "Fce coalesce: %s", c); fce_set_coalesce(c); } + if ((c = getoption(buf, "-fceevents"))) { + LOG(log_note, logtype_afpd, "Fce events: %s", c); + fce_set_events(c); + } return 1; } diff --git a/etc/afpd/fce_api.c b/etc/afpd/fce_api.c index 8df502b6..0240b547 100755 --- a/etc/afpd/fce_api.c +++ b/etc/afpd/fce_api.c @@ -65,8 +65,8 @@ static struct udp_entry udp_socket_list[FCE_MAX_UDP_SOCKS]; static int udp_sockets = 0; static int udp_initialized = FCE_FALSE; - - +static unsigned long fce_ev_enabled = 0; +static size_t tm_used; /* used for passing to event handler */ static const char *skip_files[] = { ".DS_Store", @@ -278,7 +278,7 @@ static int add_udp_socket(const char *target_ip, const char *target_port ) * Dispatcher for all incoming file change events * * */ -static int register_fce( char *u_name, int is_dir, int mode ) +static int register_fce(const char *u_name, int is_dir, int mode) { if (udp_sockets == 0) /* No listeners configured */ @@ -293,6 +293,12 @@ static int register_fce( char *u_name, int is_dir, int mode ) if (first_event) { fce_initialize_history(); + fce_ev_enabled = + (1 << FCE_FILE_MODIFY) | + (1 << FCE_FILE_DELETE) | + (1 << FCE_DIR_DELETE) | + (1 << FCE_FILE_CREATE) | + (1 << FCE_DIR_CREATE); } @@ -307,19 +313,16 @@ static int register_fce( char *u_name, int is_dir, int mode ) char full_path_buffer[FCE_MAX_PATH_LEN + 1] = {""}; const char *cwd = getcwdpath(); - if (!is_dir || mode == FCE_DIR_DELETE) - { - if (strlen( cwd ) + strlen( u_name) + 1 >= FCE_MAX_PATH_LEN) - { + if (mode & FCE_TM_SIZE) { + strncpy(full_path_buffer, u_name, FCE_MAX_PATH_LEN); + } else if (!is_dir || mode == FCE_DIR_DELETE) { + if (strlen( cwd ) + strlen( u_name) + 1 >= FCE_MAX_PATH_LEN) { LOG(log_error, logtype_afpd, "FCE file name too long: %s/%s", cwd, u_name ); return AFPERR_PARAM; } sprintf( full_path_buffer, "%s/%s", cwd, u_name ); - } - else - { - if (strlen( cwd ) >= FCE_MAX_PATH_LEN) - { + } else { + if (strlen( cwd ) >= FCE_MAX_PATH_LEN) { LOG(log_error, logtype_afpd, "FCE directory name too long: %s", cwd); return AFPERR_PARAM; } @@ -327,7 +330,7 @@ static int register_fce( char *u_name, int is_dir, int mode ) } /* Can we ignore this event based on type or history? */ - if (fce_handle_coalescation( full_path_buffer, is_dir, mode )) + if (!(mode & FCE_TM_SIZE) && fce_handle_coalescation( full_path_buffer, is_dir, mode )) { LOG(log_debug9, logtype_afpd, "Coalesced fc event <%d> for <%s>", mode, full_path_buffer ); return AFP_OK; @@ -363,7 +366,6 @@ static int register_fce( char *u_name, int is_dir, int mode ) * */ #ifndef FCE_TEST_MAIN - int fce_register_delete_file( struct path *path ) { int ret = AFP_OK; @@ -371,6 +373,8 @@ int fce_register_delete_file( struct path *path ) if (path == NULL) return AFPERR_PARAM; + if (!(fce_ev_enabled & (1 << FCE_FILE_DELETE))) + return ret; ret = register_fce( path->u_name, FALSE, FCE_FILE_DELETE ); @@ -383,6 +387,8 @@ int fce_register_delete_dir( char *name ) if (name == NULL) return AFPERR_PARAM; + if (!(fce_ev_enabled & (1 << FCE_DIR_DELETE))) + return ret; ret = register_fce( name, TRUE, FCE_DIR_DELETE); @@ -396,6 +402,9 @@ int fce_register_new_dir( struct path *path ) if (path == NULL) return AFPERR_PARAM; + if (!(fce_ev_enabled & (1 << FCE_DIR_CREATE))) + return ret; + ret = register_fce( path->u_name, TRUE, FCE_DIR_CREATE ); return ret; @@ -409,12 +418,14 @@ int fce_register_new_file( struct path *path ) if (path == NULL) return AFPERR_PARAM; + if (!(fce_ev_enabled & (1 << FCE_FILE_CREATE))) + return ret; + ret = register_fce( path->u_name, FALSE, FCE_FILE_CREATE ); return ret; } - int fce_register_file_modification( struct ofork *ofork ) { char *u_name = NULL; @@ -424,6 +435,9 @@ int fce_register_file_modification( struct ofork *ofork ) if (ofork == NULL || ofork->of_vol == NULL) return AFPERR_PARAM; + if (!(fce_ev_enabled & (1 << FCE_FILE_MODIFY))) + return ret; + vol = ofork->of_vol; if (NULL == (u_name = mtoupath(vol, of_name(ofork), ofork->of_did, utf8_encoding()))) @@ -435,6 +449,22 @@ int fce_register_file_modification( struct ofork *ofork ) return ret; } + +int fce_register_tm_size(const char *vol, size_t used) +{ + int ret = AFP_OK; + + if (vol == NULL) + return AFPERR_PARAM; + + if (!(fce_ev_enabled & (1 << FCE_TM_SIZE))) + return ret; + + tm_used = used; /* oh what a hack */ + ret = register_fce(vol, FALSE, FCE_TM_SIZE); + + return ret; +} #endif /* @@ -457,7 +487,35 @@ int fce_add_udp_socket(const char *target) return add_udp_socket(target_ip, port); } +int fce_set_events(const char *events) +{ + char *e; + char *p; + + if (events == NULL) + return AFPERR_PARAM; + + e = strdup(events); + fce_ev_enabled = 0; + + for (p = strtok(e, ","); p; p = strtok(NULL, ",")) { + if (strcmp(e, "fmod") == 0) { + fce_ev_enabled |= FCE_FILE_MODIFY; + } else if (strcmp(e, "fdel") == 0) { + fce_ev_enabled |= FCE_FILE_DELETE; + } else if (strcmp(e, "ddel") == 0) { + fce_ev_enabled |= FCE_DIR_DELETE; + } else if (strcmp(e, "fcre") == 0) { + fce_ev_enabled |= FCE_FILE_CREATE; + } else if (strcmp(e, "dcre") == 0) { + fce_ev_enabled |= FCE_DIR_CREATE; + } else if (strcmp(e, "tmsz") == 0) { + fce_ev_enabled |= FCE_TM_SIZE; + } + } + free(e); +} #ifdef FCE_TEST_MAIN diff --git a/etc/afpd/fce_api_internal.h b/etc/afpd/fce_api_internal.h index 9f2049fd..37988e89 100755 --- a/etc/afpd/fce_api_internal.h +++ b/etc/afpd/fce_api_internal.h @@ -8,18 +8,6 @@ #ifndef _FCE_API_INTERNAL_H #define _FCE_API_INTERNAL_H -/* fce_packet.mode */ -#define FCE_FILE_MODIFY 1 -#define FCE_FILE_DELETE 2 -#define FCE_DIR_DELETE 3 -#define FCE_FILE_CREATE 4 -#define FCE_DIR_CREATE 5 -#define FCE_CONN_START 42 -#define FCE_CONN_BROKEN 99 - -/* fce_packet.fce_magic */ -#define FCE_PACKET_MAGIC "at_fcapi" - #define FCE_MAX_PATH_LEN 1024 #define FCE_MAX_UDP_SOCKS 5 /* Allow a maximum of udp listeners for file change events */ #define FCE_SOCKET_RETRY_DELAY_S 600 /* Pause this time in s after socket was broken */ @@ -36,28 +24,14 @@ struct udp_entry time_t next_try_on_error; /* In case of error set next timestamp to retry */ }; -/* This packet goes over the network, so we want to - * be shure about datastructs and type sizes between platforms - */ -struct fce_packet -{ - char magic[8]; - unsigned char version; - unsigned char mode; - uint16_t len; /* network byte order */ - uint32_t event_id; /* network byte order */ - char data[FCE_MAX_PATH_LEN]; -}; - struct fce_history { unsigned char mode; int is_dir; - char path[FCE_MAX_PATH_LEN + 1]; + char path[MAXPATHLEN + 1]; struct timeval tv; }; - #define PACKET_HDR_LEN (sizeof(struct fce_packet) - FCE_MAX_PATH_LEN) int fce_handle_coalescation( char *path, int is_dir, int mode ); diff --git a/etc/afpd/volume.c b/etc/afpd/volume.c index b73d13c2..cc98e09a 100644 --- a/etc/afpd/volume.c +++ b/etc/afpd/volume.c @@ -47,6 +47,7 @@ char *strchr (), *strrchr (); #include #include #include +#include #ifdef CNID_DB @@ -1495,6 +1496,7 @@ getvolspace_done: /* now buf contains only digits */ long long used = atoll(buf) * multi; LOG(log_debug, logtype_afpd, "volparams: used on volume: %llu bytes", used); + fce_register_tm_size(vol->v_path, used); *xbtotal = min(*xbtotal, (vol->v_limitsize * 1024 * 1024)); *xbfree = min(*xbfree, *xbtotal < used ? 0 : *xbtotal - used); diff --git a/include/atalk/fce_api.h b/include/atalk/fce_api.h index 0e2f572d..969b9d5f 100755 --- a/include/atalk/fce_api.h +++ b/include/atalk/fce_api.h @@ -10,16 +10,46 @@ #ifndef _FCE_API_H #define _FCE_API_H +/* fce_packet.mode */ +#define FCE_FILE_MODIFY 1 +#define FCE_FILE_DELETE 2 +#define FCE_DIR_DELETE 3 +#define FCE_FILE_CREATE 4 +#define FCE_DIR_CREATE 5 +#define FCE_TM_SIZE 6 +#define FCE_CONN_START 42 +#define FCE_CONN_BROKEN 99 + + +/* fce_packet.fce_magic */ +#define FCE_PACKET_MAGIC "at_fcapi" + +/* This packet goes over the network, so we want to + * be shure about datastructs and type sizes between platforms + */ +struct fce_packet +{ + char magic[8]; + unsigned char version; + unsigned char mode; + uint16_t len; /* network byte order */ + uint32_t event_id; /* network byte order */ + char data[MAXPATHLEN]; +}; + struct path; struct ofork; + int fce_register_delete_file( struct path *path ); int fce_register_delete_dir( char *name ); int fce_register_new_dir( struct path *path ); int fce_register_new_file( struct path *path ); int fce_register_file_modification( struct ofork *ofork ); +int fce_register_tm_size(const char *vol, size_t used); int fce_add_udp_socket(const char *target ); // IP or IP:Port int fce_set_coalesce( char *coalesce_opt ); // all|delete|create +int fce_set_events(const char *events); /* fmod,fdel,ddel,fcre,dcre,tmsz (default is all) */ #define FCE_DEFAULT_PORT 12250 #define FCE_DEFAULT_PORT_STRING "12250" -- 2.39.2