From d29ded52bda8d46bf341b8a91bac85b195e02dc4 Mon Sep 17 00:00:00 2001 From: Frank Lahm Date: Fri, 9 Nov 2012 11:53:24 +0100 Subject: [PATCH] FCE API change and cleanup Change the FCE API by using a single function (fce_register()) as a single point for callers to register events. Remove all individual event functions. Add types for events and file/directoy flag. Use standard bool type instead of special defines FCE_TRUE/FALSE. --- etc/afpd/directory.c | 2 +- etc/afpd/fce_api.c | 171 ++++++++---------------------------- etc/afpd/fce_api_internal.h | 18 ++-- etc/afpd/fce_util.c | 35 ++++---- etc/afpd/file.c | 2 +- etc/afpd/filedir.c | 6 +- etc/afpd/ofork.c | 2 +- include/atalk/fce_api.h | 12 ++- 8 files changed, 75 insertions(+), 173 deletions(-) diff --git a/etc/afpd/directory.c b/etc/afpd/directory.c index ed40a26a..8b36c99b 100644 --- a/etc/afpd/directory.c +++ b/etc/afpd/directory.c @@ -2195,7 +2195,7 @@ int afp_createdir(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_ ad_setname(&ad, s_path->m_name); ad_setid( &ad, s_path->st.st_dev, s_path->st.st_ino, dir->d_did, did, vol->v_stamp); - fce_register_new_dir(s_path); + fce_register(FCE_DIR_CREATE, bdata(curdir->d_fullpath), NULL, fce_dir); ad_flush(&ad); ad_close(&ad, ADFLAGS_HF); diff --git a/etc/afpd/fce_api.c b/etc/afpd/fce_api.c index 7be4336a..5f6b70ba 100644 --- a/etc/afpd/fce_api.c +++ b/etc/afpd/fce_api.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2010 Mark Williams + * Copyright (c) 2012 Frank Lahm * * File change event API for netatalk * @@ -29,13 +30,12 @@ #include #include #include - - #include #include #include #include #include +#include #include #include @@ -56,13 +56,10 @@ // ONLY USED IN THIS FILE #include "fce_api_internal.h" -#define FCE_TRUE 1 -#define FCE_FALSE 0 - /* We store our connection data here */ static struct udp_entry udp_socket_list[FCE_MAX_UDP_SOCKS]; static int udp_sockets = 0; -static int udp_initialized = FCE_FALSE; +static bool udp_initialized = false; static unsigned long fce_ev_enabled = (1 << FCE_FILE_MODIFY) | (1 << FCE_FILE_DELETE) | @@ -99,7 +96,7 @@ void fce_init_udp() int rv; struct addrinfo hints, *servinfo, *p; - if (udp_initialized == FCE_TRUE) + if (udp_initialized == true) return; memset(&hints, 0, sizeof hints); @@ -139,12 +136,12 @@ void fce_init_udp() freeaddrinfo(servinfo); } - udp_initialized = FCE_TRUE; + udp_initialized = true; } void fce_cleanup() { - if (udp_initialized == FCE_FALSE ) + if (udp_initialized == false ) return; for (int i = 0; i < udp_sockets; i++) @@ -158,13 +155,13 @@ void fce_cleanup() udp_entry->sock = -1; } } - udp_initialized = FCE_FALSE; + udp_initialized = false; } /* * Construct a UDP packet for our listeners and return packet size * */ -static ssize_t build_fce_packet( struct fce_packet *packet, char *path, int mode, uint32_t event_id ) +static ssize_t build_fce_packet( struct fce_packet *packet, const char *path, int event, uint32_t event_id ) { size_t pathlen = 0; ssize_t data_len = 0; @@ -173,7 +170,7 @@ static ssize_t build_fce_packet( struct fce_packet *packet, char *path, int mode /* Set content of packet */ memcpy(packet->magic, FCE_PACKET_MAGIC, sizeof(packet->magic) ); packet->version = FCE_PACKET_VERSION; - packet->mode = mode; + packet->mode = event; packet->event_id = event_id; @@ -227,9 +224,9 @@ static void pack_fce_packet(struct fce_packet *packet, unsigned char *buf, int m * Send the fce information to all (connected) listeners * We dont give return code because all errors are handled internally (I hope..) * */ -static void send_fce_event( char *path, int mode ) +static void send_fce_event(const char *path, int event) { - static int first_event = FCE_TRUE; + static bool first_event = true; struct fce_packet packet; void *data = &packet; @@ -239,15 +236,15 @@ static void send_fce_event( char *path, int mode ) LOG(log_debug, logtype_fce, "send_fce_event: start"); /* initialized ? */ - if (first_event == FCE_TRUE) { - first_event = FCE_FALSE; + if (first_event == true) { + first_event = false; fce_init_udp(); /* Notify listeners the we start from the beginning */ send_fce_event( "", FCE_CONN_START ); } /* build our data packet */ - ssize_t data_len = build_fce_packet( &packet, path, mode, ++event_id ); + ssize_t data_len = build_fce_packet( &packet, path, event, ++event_id ); pack_fce_packet(&packet, iobuf, MAXIOBUF); for (int i = 0; i < udp_sockets; i++) @@ -289,7 +286,7 @@ static void send_fce_event( char *path, int mode ) udp_entry->addrinfo.ai_addrlen); /* Rebuild our original data packet */ - data_len = build_fce_packet( &packet, path, mode, event_id ); + data_len = build_fce_packet(&packet, path, event, event_id); pack_fce_packet(&packet, iobuf, MAXIOBUF); } @@ -357,67 +354,55 @@ static void save_close_event(const char *path) * Dispatcher for all incoming file change events * * */ -static int register_fce(const char *u_name, int is_dir, int mode) +int fce_register(fce_ev_t event, const char *path, const char *oldpath, fce_obj_t type) { - static int first_event = FCE_TRUE; + static bool first_event = true; + const char *bname; - AFP_ASSERT(mode >= FCE_FIRST_EVENT && mode <= FCE_LAST_EVENT); + if (!(fce_ev_enabled & (1 << event))) + return AFP_OK; + + AFP_ASSERT(event >= FCE_FIRST_EVENT && event <= FCE_LAST_EVENT); LOG(log_debug, logtype_fce, "register_fce(path: %s, type: %s, event: %s", - fullpathname(u_name), is_dir ? "dir" : "file", fce_event_names[mode]); + path , type == fce_dir ? "dir" : "file", fce_event_names[event]); + + bname = basename_safe(path); if (udp_sockets == 0) /* No listeners configured */ return AFP_OK; - if (u_name == NULL) + if (path == NULL) return AFPERR_PARAM; /* do some initialization on the fly the first time */ if (first_event) { fce_initialize_history(); - first_event = FCE_FALSE; + first_event = false; } /* handle files which should not cause events (.DS_Store atc. ) */ - for (int i = 0; skip_files[i] != NULL; i++) - { - if (!strcmp( u_name, skip_files[i])) + for (int i = 0; skip_files[i] != NULL; i++) { + if (strcmp(bname, skip_files[i]) == 0) return AFP_OK; } - - /* FIXME: use fullpathname() for path? */ - char full_path_buffer[MAXPATHLEN + 1] = {""}; - const char *cwd = getcwdpath(); - - if (!is_dir || mode == FCE_DIR_DELETE) { - if (strlen( cwd ) + strlen( u_name) + 1 >= MAXPATHLEN) { - LOG(log_error, logtype_fce, "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 ) >= MAXPATHLEN) { - LOG(log_error, logtype_fce, "FCE directory name too long: %s", cwd); - return AFPERR_PARAM; - } - strcpy( full_path_buffer, cwd); - } - /* Can we ignore this event based on type or history? */ - if (fce_handle_coalescation(full_path_buffer, is_dir, mode)) { - LOG(log_debug9, logtype_fce, "Coalesced fc event <%d> for <%s>", mode, full_path_buffer ); + if (fce_handle_coalescation(event, path, type)) { + LOG(log_debug9, logtype_fce, "Coalesced fc event <%d> for <%s>", event, path); return AFP_OK; } - if (mode & FCE_FILE_MODIFY) { - save_close_event(full_path_buffer); - return AFP_OK; + switch (event) { + case FCE_FILE_MODIFY: + save_close_event(path); + break; + default: + send_fce_event(path, event); + break; } - send_fce_event( full_path_buffer, mode ); - return AFP_OK; } @@ -440,89 +425,11 @@ static void check_saved_close_events(int fmodwait) /* * API-Calls for file change api, called form outside (file.c directory.c ofork.c filedir.c) * */ -#ifndef FCE_TEST_MAIN - void fce_pending_events(AFPObj *obj) { check_saved_close_events(obj->options.fce_fmodwait); } -int fce_register_delete_file( struct path *path ) -{ - int ret = AFP_OK; - - 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 ); - - return ret; -} -int fce_register_delete_dir( char *name ) -{ - int ret = AFP_OK; - - if (name == NULL) - return AFPERR_PARAM; - - if (!(fce_ev_enabled & (1 << FCE_DIR_DELETE))) - return ret; - - ret = register_fce( name, true, FCE_DIR_DELETE); - - return ret; -} - -int fce_register_new_dir( struct path *path ) -{ - int ret = AFP_OK; - - 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; -} - - -int fce_register_new_file( struct path *path ) -{ - int ret = AFP_OK; - - 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 ) -{ - int ret = AFP_OK; - - if (ofork == NULL) - return AFPERR_PARAM; - - if (!(fce_ev_enabled & (1 << FCE_FILE_MODIFY))) - return ret; - - ret = register_fce(of_name(ofork), false, FCE_FILE_MODIFY ); - - return ret; -} -#endif - /* * * Extern connect to afpd parameter, can be called multiple times for multiple listeners (up to MAX_UDP_SOCKS times) @@ -646,7 +553,7 @@ int main( int argc, char*argv[] ) if (end_time && now >= end_time) break; - register_fce( path, 0, event_code ); + fce_register(event_code, path, NULL, 0); ev_cnt++; diff --git a/etc/afpd/fce_api_internal.h b/etc/afpd/fce_api_internal.h index 9ed185e5..fb5e58e3 100644 --- a/etc/afpd/fce_api_internal.h +++ b/etc/afpd/fce_api_internal.h @@ -10,6 +10,8 @@ #include +#include + #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 */ #define FCE_PACKET_VERSION 1 @@ -20,8 +22,7 @@ #define FCE_COALESCE_DELETE (1 << 1) #define FCE_COALESCE_ALL (FCE_COALESCE_CREATE | FCE_COALESCE_DELETE) -struct udp_entry -{ +struct udp_entry { int sock; char *addr; char *port; @@ -30,12 +31,11 @@ struct udp_entry time_t next_try_on_error; /* In case of error set next timestamp to retry */ }; -struct fce_history -{ - unsigned char mode; - int is_dir; - char path[MAXPATHLEN + 1]; - struct timeval tv; +struct fce_history { + fce_ev_t fce_h_event; + fce_obj_t fce_h_type; + char fce_h_path[MAXPATHLEN + 1]; + struct timeval fce_h_tv; }; struct fce_close_event { @@ -45,7 +45,7 @@ struct fce_close_event { #define PACKET_HDR_LEN (sizeof(struct fce_packet) - FCE_MAX_PATH_LEN) -bool fce_handle_coalescation( char *path, int is_dir, int mode ); +bool fce_handle_coalescation(int event, const char *path, fce_obj_t type); void fce_initialize_history(); diff --git a/etc/afpd/fce_util.c b/etc/afpd/fce_util.c index 07b59d73..69f6ea0d 100644 --- a/etc/afpd/fce_util.c +++ b/etc/afpd/fce_util.c @@ -54,9 +54,6 @@ // ONLY USED IN THIS FILE #include "fce_api_internal.h" -#define FCE_TRUE 1 -#define FCE_FALSE 0 - /* We store our connection data here */ static uint32_t coalesce = 0; static struct fce_history fce_history_list[FCE_HISTORY_LEN]; @@ -92,7 +89,7 @@ void fce_initialize_history() } } -bool fce_handle_coalescation( char *path, int is_dir, int mode ) +bool fce_handle_coalescation(int event, const char *path, fce_obj_t type) { /* These two are used to eval our next index in history */ /* the history is unsorted, speed should not be a problem, length is 10 */ @@ -104,7 +101,7 @@ bool fce_handle_coalescation( char *path, int is_dir, int mode ) return false; /* After a file creation *ALWAYS* a file modification is produced */ - if ((mode == FCE_FILE_CREATE) && (coalesce & FCE_COALESCE_CREATE)) + if ((event == FCE_FILE_CREATE) && (coalesce & FCE_COALESCE_CREATE)) return true; /* get timestamp */ @@ -115,7 +112,7 @@ bool fce_handle_coalescation( char *path, int is_dir, int mode ) struct fce_history *fh = &fce_history_list[i]; /* Not inited ? */ - if (fh->tv.tv_sec == 0) { + if (fh->fce_h_tv.tv_sec == 0) { /* we can use it for new elements */ oldest_entry = 0; oldest_entry_idx = i; @@ -123,9 +120,9 @@ bool fce_handle_coalescation( char *path, int is_dir, int mode ) } /* Too old ? */ - if (get_ms_difftime( &fh->tv, &tv ) > MAX_COALESCE_TIME_MS) { + if (get_ms_difftime(&fh->fce_h_tv, &tv ) > MAX_COALESCE_TIME_MS) { /* Invalidate entry */ - fh->tv.tv_sec = 0; + fh->fce_h_tv.tv_sec = 0; oldest_entry = 0; oldest_entry_idx = i; continue; @@ -133,33 +130,33 @@ bool fce_handle_coalescation( char *path, int is_dir, int mode ) /* If we find a parent dir wich was created we are done */ - if ((coalesce & FCE_COALESCE_CREATE) && (fh->mode == FCE_DIR_CREATE)) { + if ((coalesce & FCE_COALESCE_CREATE) && (fh->fce_h_event == FCE_DIR_CREATE)) { /* Parent dir ? */ - if (!strncmp(fh->path, path, strlen(fh->path))) + if (!strncmp(fh->fce_h_path, path, strlen(fh->fce_h_path))) return true; } /* If we find a parent dir we should be DELETED we are done */ if ((coalesce & FCE_COALESCE_DELETE) - && fh->is_dir - && (mode == FCE_FILE_DELETE || mode == FCE_DIR_DELETE)) { + && fh->fce_h_type + && (event == FCE_FILE_DELETE || event == FCE_DIR_DELETE)) { /* Parent dir ? */ - if (!strncmp(fh->path, path, strlen(fh->path))) + if (!strncmp(fh->fce_h_path, path, strlen(fh->fce_h_path))) return true; } /* Detect oldest entry for next new entry */ - if (oldest_entry_idx == -1 || fh->tv.tv_sec < oldest_entry) { - oldest_entry = fh->tv.tv_sec; + if (oldest_entry_idx == -1 || fh->fce_h_tv.tv_sec < oldest_entry) { + oldest_entry = fh->fce_h_tv.tv_sec; oldest_entry_idx = i; } } /* We have a new entry for the history, register it */ - fce_history_list[oldest_entry_idx].tv = tv; - fce_history_list[oldest_entry_idx].mode = mode; - fce_history_list[oldest_entry_idx].is_dir = is_dir; - strncpy( fce_history_list[oldest_entry_idx].path, path, MAXPATHLEN); + fce_history_list[oldest_entry_idx].fce_h_tv = tv; + fce_history_list[oldest_entry_idx].fce_h_event = event; + fce_history_list[oldest_entry_idx].fce_h_type = type; + strncpy(fce_history_list[oldest_entry_idx].fce_h_path, path, MAXPATHLEN); /* we have to handle this event */ return false; diff --git a/etc/afpd/file.c b/etc/afpd/file.c index 8d5d0ad0..94030454 100644 --- a/etc/afpd/file.c +++ b/etc/afpd/file.c @@ -747,7 +747,7 @@ int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, createfile_iderr: ad_flush(&ad); ad_close(&ad, ADFLAGS_DF|ADFLAGS_HF ); - fce_register_new_file(s_path); + fce_register(FCE_FILE_CREATE, fullpathname(upath), NULL, fce_file); createfile_done: curdir->d_offcnt++; diff --git a/etc/afpd/filedir.c b/etc/afpd/filedir.c index 56cbaccf..83f7f1aa 100644 --- a/etc/afpd/filedir.c +++ b/etc/afpd/filedir.c @@ -525,7 +525,7 @@ int afp_delete(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size delcnid = cnid_get(vol->v_cdb, curdir->d_did, upath, strlen(upath)); if (delcnid != CNID_INVALID) cnid_delete(vol->v_cdb, delcnid); - fce_register_delete_dir(upath); + fce_register(FCE_DIR_DELETE, fullpathname(upath), NULL, fce_dir); } else { /* we have to cache this, the structs are lost in deletcurdir*/ /* but we need the positive returncode to send our event */ @@ -533,7 +533,7 @@ int afp_delete(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size if ((dname = bstrcpy(curdir->d_u_name)) == NULL) return AFPERR_MISC; if ((rc = deletecurdir(vol)) == AFP_OK) - fce_register_delete_dir(cfrombstr(dname)); + fce_register(FCE_DIR_DELETE, fullpathname(cfrombstr(dname)), NULL, fce_dir); bdestroy(dname); } } else if (of_findname(s_path)) { @@ -547,7 +547,7 @@ int afp_delete(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size rc = AFPERR_NOOBJ; } else { if ((rc = deletefile(vol, -1, upath, 1)) == AFP_OK) { - fce_register_delete_file( s_path ); + fce_register(FCE_FILE_DELETE, fullpathname(upath), NULL, fce_file); if (vol->v_tm_used < s_path->st.st_size) vol->v_tm_used = 0; else diff --git a/etc/afpd/ofork.c b/etc/afpd/ofork.c index 3d690079..66228b63 100644 --- a/etc/afpd/ofork.c +++ b/etc/afpd/ofork.c @@ -407,7 +407,7 @@ int of_closefork(const AFPObj *obj, struct ofork *ofork) /* Somone has used write_fork, we assume file was changed, register it to file change event api */ if (ofork->of_flags & AFPFORK_MODIFIED) { - fce_register_file_modification(ofork); + fce_register(FCE_FILE_MODIFY, fullpathname(ofork->of_ad->ad_name), NULL, fce_file); } ad_unlock(ofork->of_ad, ofork->of_refnum, ofork->of_flags & AFPFORK_ERROR ? 0 : 1); diff --git a/include/atalk/fce_api.h b/include/atalk/fce_api.h index 211921b7..d11a2d49 100755 --- a/include/atalk/fce_api.h +++ b/include/atalk/fce_api.h @@ -32,6 +32,7 @@ * Format is network byte order. */ #define FCE_PACKET_HEADER_SIZE 8+1+1+4+2 + struct fce_packet { char magic[8]; @@ -42,17 +43,14 @@ struct fce_packet char data[MAXPATHLEN]; }; +typedef uint32_t fce_ev_t; +typedef enum { fce_file, fce_dir } fce_obj_t; + struct path; struct ofork; void fce_pending_events(AFPObj *obj); - -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(fce_ev_t event, const char *path, const char *oldpath, fce_obj_t type); int fce_add_udp_socket(const char *target ); // IP or IP:Port int fce_set_coalesce(const char *coalesce_opt ); // all|delete|create int fce_set_events(const char *events); /* fmod,fdel,ddel,fcre,dcre */ -- 2.39.2