Beispiel #1
0
static void check_saved_close_events(int fmodwait)
{
    time_t now = time(NULL);

    /* check if configured holdclose time has passed */
    if (last_close_event.time && ((last_close_event.time + fmodwait) < now)) {
        LOG(log_debug, logtype_afpd, "check_saved_close_events: sending event: %s", last_close_event.path);
        /* yes, send event */
        send_fce_event(&last_close_event.path[0], FCE_FILE_MODIFY);
        last_close_event.path[0] = 0;
        last_close_event.time = 0;
    }
}
Beispiel #2
0
static void save_close_event(const char *path)
{
    time_t now = time(NULL);

    /* Check if it's a close for the same event as the last one */
    if (last_close_event.time   /* is there any saved event ? */
        && (strcmp(path, last_close_event.path) != 0)) {
        /* no, so send the saved event out now */
        send_fce_event(last_close_event.path, FCE_FILE_MODIFY);
    }

    LOG(log_debug, logtype_afpd, "save_close_event: %s", path);

    last_close_event.time = now;
    strncpy(last_close_event.path, path, MAXPATHLEN);
}
/*
 *
 * Dispatcher for all incoming file change events
 *
 * */
static int register_fce(const char *u_name, int is_dir, int mode)
{
    if (udp_sockets == 0)
        /* No listeners configured */
        return AFP_OK;

    if (u_name == NULL)
        return AFPERR_PARAM;

    static int first_event = FCE_TRUE;

	/* do some initialization on the fly the first time */
	if (first_event) {
		fce_initialize_history();
	}

	/* 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]))
			return AFP_OK;
	}


	char full_path_buffer[MAXPATHLEN + 1] = {""};
	const char *cwd = getcwdpath();

    if (mode == FCE_TM_SIZE) {
        strlcpy(full_path_buffer, u_name, MAXPATHLEN);
    } else if (!is_dir || mode == FCE_DIR_DELETE) {
		if (strlen( cwd ) + strlen( u_name) + 1 >= MAXPATHLEN) {
			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 ) >= MAXPATHLEN) {
			LOG(log_error, logtype_afpd, "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 (!(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;
	}

	LOG(log_debug9, logtype_afpd, "Detected fc event <%d> for <%s>", mode, full_path_buffer );


    /* we do initilization on the fly, no blocking calls in here 
     * (except when using FQDN in broken DNS environment)
     */
    if (first_event == FCE_TRUE)
    {
        fce_init_udp();
        
        /* Notify listeners the we start from the beginning */
        send_fce_event( "", FCE_CONN_START );
        
        first_event = FCE_FALSE;
    }

	/* Handle UDP transport */
    send_fce_event( full_path_buffer, mode );

    return AFP_OK;
}
Beispiel #4
0
/*
 *
 * Dispatcher for all incoming file change events
 *
 * */
static int register_fce(const char *u_name, int is_dir, int mode)
{
    static int first_event = FCE_TRUE;

    if (udp_sockets == 0)
        /* No listeners configured */
        return AFP_OK;

    if (u_name == NULL)
        return AFPERR_PARAM;

	/* do some initialization on the fly the first time */
	if (first_event) {
		fce_initialize_history();
        first_event = FCE_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]))
			return AFP_OK;
	}


	char full_path_buffer[MAXPATHLEN + 1] = {""};
	const char *cwd = getcwdpath();

    if (mode == FCE_TM_SIZE) {
        strlcpy(full_path_buffer, u_name, MAXPATHLEN);
    } else if (!is_dir || mode == FCE_DIR_DELETE) {
		if (strlen( cwd ) + strlen( u_name) + 1 >= MAXPATHLEN) {
			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 ) >= MAXPATHLEN) {
			LOG(log_error, logtype_afpd, "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 (!(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;
	}

	LOG(log_debug9, logtype_afpd, "Detected fc event <%d> for <%s>", mode, full_path_buffer );

    if (mode & FCE_FILE_MODIFY) {
        save_close_event(full_path_buffer);
        return AFP_OK;
    }

    send_fce_event( full_path_buffer, mode );

    return AFP_OK;
}
Beispiel #5
0
/*
 * 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 int first_event = FCE_TRUE;

    struct fce_packet packet;
    void *data = &packet;
    static uint32_t event_id = 0; /* the unique packet couter to detect packet/data loss. Going from 0xFFFFFFFF to 0x0 is a valid increment */
    time_t now = time(NULL);

    LOG(log_debug, logtype_afpd, "send_fce_event: start");

    /* initialized ? */
    if (first_event == FCE_TRUE) {
        first_event = FCE_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 );
    pack_fce_packet(&packet, iobuf, MAXIOBUF);

    for (int i = 0; i < udp_sockets; i++)
    {
        int sent_data = 0;
        struct udp_entry *udp_entry = udp_socket_list + i;

        /* we had a problem earlier ? */
        if (udp_entry->sock == -1)
        {
            /* We still have to wait ?*/
            if (now < udp_entry->next_try_on_error)
                continue;

            /* Reopen socket */
            udp_entry->sock = socket(udp_entry->addrinfo.ai_family,
                                     udp_entry->addrinfo.ai_socktype,
                                     udp_entry->addrinfo.ai_protocol);
            
            if (udp_entry->sock == -1) {
                /* failed again, so go to rest again */
                LOG(log_error, logtype_afpd, "Cannot recreate socket for fce UDP connection: errno %d", errno  );

                udp_entry->next_try_on_error = now + FCE_SOCKET_RETRY_DELAY_S;
                continue;
            }

            udp_entry->next_try_on_error = 0;

            /* Okay, we have a running socket again, send server that we had a problem on our side*/
            data_len = build_fce_packet( &packet, "", FCE_CONN_BROKEN, 0 );
            pack_fce_packet(&packet, iobuf, MAXIOBUF);

            sendto(udp_entry->sock,
                   iobuf,
                   data_len,
                   0,
                   (struct sockaddr *)&udp_entry->sockaddr,
                   udp_entry->addrinfo.ai_addrlen);

            /* Rebuild our original data packet */
            data_len = build_fce_packet( &packet, path, mode, event_id );
            pack_fce_packet(&packet, iobuf, MAXIOBUF);
        }

        sent_data = sendto(udp_entry->sock,
                           iobuf,
                           data_len,
                           0,
                           (struct sockaddr *)&udp_entry->sockaddr,
                           udp_entry->addrinfo.ai_addrlen);

        /* Problems ? */
        if (sent_data != data_len) {
            /* Argh, socket broke, we close and retry later */
            LOG(log_error, logtype_afpd, "send_fce_event: error sending packet to %s:%s, transfered %d of %d: %s",
                udp_entry->addr, udp_entry->port, sent_data, data_len, strerror(errno));

            close( udp_entry->sock );
            udp_entry->sock = -1;
            udp_entry->next_try_on_error = now + FCE_SOCKET_RETRY_DELAY_S;
        }
    }
}