77 static application_t *application_load (
const char *filename);
79 static void application_free_cb (gpointer
self);
80 static gint application_compare_cb(gconstpointer a, gconstpointer b);
86 static void applist_free(GList *list);
87 static GList *applist_load(
const char *conf_dir);
98 static int appsync_mark_active_locked (
const char *name,
int post);
101 static gboolean appsync_enumerate_usb_cb (gpointer data);
102 static void appsync_start_enumerate_usb_timer (
void);
103 static void appsync_cancel_enumerate_usb_timer(
void);
104 static void appsync_enumerate_usb (
void);
106 static void appsync_stop_apps (
int post);
117 static pthread_mutex_t appsync_mutex = PTHREAD_MUTEX_INITIALIZER;
119 #define APPSYNC_LOCKED_ENTER do {\
120 if( pthread_mutex_lock(&appsync_mutex) != 0 ) { \
121 log_crit("APPSYNC LOCK FAILED");\
122 _exit(EXIT_FAILURE);\
126 #define APPSYNC_LOCKED_LEAVE do {\
127 if( pthread_mutex_unlock(&appsync_mutex) != 0 ) { \
128 log_crit("APPSYNC UNLOCK FAILED");\
129 _exit(EXIT_FAILURE);\
134 static GList *appsync_apps_curr = NULL;
137 static GList *appsync_apps_next = NULL;
138 static bool appsync_apps_updated =
false;
141 static guint appsync_enumerate_usb_id = 0;
142 static struct timeval appsync_sync_tv = {0, 0};
143 static int appsync_no_dbus = 0;
145 static int appsync_no_dbus = 1;
163 return self &&
self->name &&
self->mode && (
self->systemd ||
self->launch);
174 LOG_REGISTER_CONTEXT;
177 GKeyFile *keyfile = NULL;
179 log_debug(
"loading appsync file: %s", filename);
181 if( !(keyfile = g_key_file_new()) )
184 if( !g_key_file_load_from_file(keyfile, filename, G_KEY_FILE_NONE, NULL) ) {
185 log_warning(
"failed to load appsync file: %s", filename);
189 if( !(
self = calloc(1,
sizeof *
self)) )
192 self->name = g_key_file_get_string(keyfile, APP_INFO_ENTRY, APP_INFO_NAME_KEY, NULL);
193 log_debug(
"Appname = %s\n", self->name ?:
"<unset>");
195 self->launch = g_key_file_get_string(keyfile, APP_INFO_ENTRY, APP_INFO_LAUNCH_KEY, NULL);
196 log_debug(
"Launch = %s\n", self->launch ?:
"<unset>");
198 self->mode = g_key_file_get_string(keyfile, APP_INFO_ENTRY, APP_INFO_MODE_KEY, NULL);
199 log_debug(
"Launch mode = %s\n", self->mode ?:
"<unset>");
201 self->systemd = g_key_file_get_integer(keyfile, APP_INFO_ENTRY, APP_INFO_SYSTEMD_KEY, NULL);
202 log_debug(
"Systemd control = %d\n", self->systemd);
204 self->systemd_wait = g_key_file_get_integer(keyfile, APP_INFO_ENTRY, APP_INFO_SYSTEMD_WAIT_KEY, NULL);
205 log_debug(
"Systemd wait = %d\n", self->systemd_wait);
207 self->post = g_key_file_get_integer(keyfile, APP_INFO_ENTRY, APP_INFO_POST, NULL);
208 log_debug(
"post = %d\n", self->post);
215 g_key_file_free(keyfile);
218 if(
self && !application_is_valid(
self) ) {
219 log_warning(
"discarding invalid appsync file: %s", filename);
220 application_free(
self),
233 LOG_REGISTER_CONTEXT;
237 g_free(self->launch);
247 static void application_free_cb(gpointer
self)
249 LOG_REGISTER_CONTEXT;
251 application_free(
self);
261 static gint application_compare_cb(gconstpointer a, gconstpointer b)
263 LOG_REGISTER_CONTEXT;
267 return strcasecmp(application_a->
name, application_b->
name);
278 static void applist_free(GList *list)
280 g_list_free_full(list, application_free_cb);
290 static GList *applist_load(
const char *conf_dir)
292 LOG_REGISTER_CONTEXT;
298 if( !(pat = g_strdup_printf(
"%s/*.ini", conf_dir)) )
301 if( glob(pat, 0, 0, &gb) != 0 ) {
302 log_debug(
"no appsync ini-files found");
306 for(
size_t i = 0; i < gb.gl_pathc; ++i ) {
307 application_t *application = application_load(gb.gl_pathv[i]);
309 list = g_list_append(list, application);
315 list = g_list_sort(list, application_compare_cb);
334 LOG_REGISTER_CONTEXT;
336 APPSYNC_LOCKED_ENTER;
338 if( appsync_apps_updated ) {
339 appsync_apps_updated =
false;
340 log_debug(
"Switch appsync config");
341 applist_free(appsync_apps_curr),
342 appsync_apps_curr = appsync_apps_next,
343 appsync_apps_next = 0;
346 APPSYNC_LOCKED_LEAVE;
353 LOG_REGISTER_CONTEXT;
355 APPSYNC_LOCKED_ENTER;
357 if( appsync_apps_curr ) {
358 log_debug(
"Release current appsync config");
359 applist_free(appsync_apps_curr),
360 appsync_apps_curr = 0;
363 if( appsync_apps_next ) {
364 log_debug(
"Release future appsync config");
365 applist_free(appsync_apps_next),
366 appsync_apps_next = 0;
369 APPSYNC_LOCKED_LEAVE;
386 LOG_REGISTER_CONTEXT;
388 GList *applist = applist_load(usbmoded_get_diag_mode() ?
389 CONF_DIR_DIAG_PATH : CONF_DIR_PATH);
391 APPSYNC_LOCKED_ENTER;
393 if( !appsync_apps_curr ) {
394 log_debug(
"Update current appsync config");
395 appsync_apps_curr = applist;
397 applist_free(appsync_apps_next),
398 appsync_apps_next = 0;
399 appsync_apps_updated =
false;
402 log_debug(
"Update future appsync config");
403 applist_free(appsync_apps_next),
404 appsync_apps_next = applist;
405 appsync_apps_updated =
true;
408 if( appsync_apps_curr ) {
409 log_debug(
"Sync list available");
418 APPSYNC_LOCKED_LEAVE;
432 LOG_REGISTER_CONTEXT;
435 gboolean has_systemd_wait_app = FALSE;
437 log_debug(
"activate-pre mode=%s", mode);
439 APPSYNC_LOCKED_ENTER;
443 gettimeofday(&appsync_sync_tv, 0);
446 if( appsync_apps_curr == 0 )
448 log_debug(
"No sync list!");
450 appsync_enumerate_usb();
457 for( GList *iter = appsync_apps_curr; iter; iter = g_list_next(iter) )
461 if(!strcmp(application->
mode, mode))
475 log_debug(
"Nothing to launch\n");
477 appsync_enumerate_usb();
486 log_debug(
"dbus setup failed => skipping dbus launched apps");
491 appsync_start_enumerate_usb_timer();
495 for( GList *iter = appsync_apps_curr; iter; iter = g_list_next(iter) )
498 if(!strcmp(mode, application->
mode))
501 if(application->
post)
505 log_debug(
"launching pre-enum-app %s", application->
name);
509 has_systemd_wait_app |= add_to_waitlist;
511 if(!systemd_control_service(application->
name, SYSTEMD_START, add_to_waitlist)) {
512 log_debug(
"systemd pre-enum-app %s failed", application->
name);
516 appsync_mark_active_locked(application->
name, 0);
518 else if(application->
launch)
522 if( appsync_no_dbus ) {
523 log_debug(
"dbus pre-enum-app %s ignored", application->
name);
529 appsync_mark_active_locked(application->
name, 0);
534 log_debug(
"dbus pre-enum-app %s failed", application->
name);
538 appsync_mark_active_locked(application->
name, 0);
545 APPSYNC_LOCKED_LEAVE;
547 if (has_systemd_wait_app && ret == 0)
548 ret = systemd_control_wait_for_waitlist() ? 0 : 1;
564 LOG_REGISTER_CONTEXT;
567 gboolean has_systemd_wait_app = FALSE;
569 log_debug(
"activate-post mode=%s", mode);
571 APPSYNC_LOCKED_ENTER;
573 if( !appsync_apps_curr ) {
574 log_debug(
"No sync list! skipping post sync");
582 log_debug(
"dbus setup failed => skipping dbus launched apps");
588 for( GList *iter = appsync_apps_curr; iter; iter = g_list_next(iter) )
592 if( !strcmp(application->
mode, mode) ) {
594 if(!application->
post)
597 log_debug(
"launching post-enum-app %s\n", application->
name);
600 has_systemd_wait_app |= add_to_waitlist;
602 if(!systemd_control_service(application->
name, SYSTEMD_START, add_to_waitlist)) {
603 log_err(
"systemd post-enum-app %s failed", application->
name);
607 appsync_mark_active_locked(application->
name, 1);
609 else if( application->
launch ) {
612 if( appsync_no_dbus ) {
613 log_debug(
"dbus pre-enum-app %s ignored", application->
name);
618 log_err(
"dbus post-enum-app %s failed", application->
name);
622 appsync_mark_active_locked(application->
name, 1);
629 APPSYNC_LOCKED_LEAVE;
631 if (has_systemd_wait_app && ret == 0)
632 ret = systemd_control_wait_for_waitlist() ? 0 : 1;
648 static int appsync_mark_active_locked(
const char *name,
int post)
650 LOG_REGISTER_CONTEXT;
655 log_debug(
"%s-enum-app %s is started\n", post ?
"post" :
"pre", name);
657 for( GList *iter = appsync_apps_curr; iter; iter = g_list_next(iter) )
661 if(!strcmp(application->
name, name))
675 if( ret != -1 )
break;
678 if( !post && !missing )
680 log_debug(
"All pre-enum-apps active");
682 appsync_enumerate_usb();
710 LOG_REGISTER_CONTEXT;
712 APPSYNC_LOCKED_ENTER;
713 int ret = appsync_mark_active_locked(name, post);
714 APPSYNC_LOCKED_LEAVE;
720 static gboolean appsync_enumerate_usb_cb(gpointer data)
722 LOG_REGISTER_CONTEXT;
725 appsync_enumerate_usb_id = 0;
726 log_debug(
"handling enumeration timeout");
727 appsync_enumerate_usb();
732 static void appsync_start_enumerate_usb_timer(
void)
734 LOG_REGISTER_CONTEXT;
736 log_debug(
"scheduling enumeration timeout");
737 if( appsync_enumerate_usb_id )
738 g_source_remove(appsync_enumerate_usb_id), appsync_enumerate_usb_id = 0;
745 appsync_enumerate_usb_id = g_timeout_add_seconds(2, appsync_enumerate_usb_cb, NULL);
748 static void appsync_cancel_enumerate_usb_timer(
void)
750 LOG_REGISTER_CONTEXT;
752 if( appsync_enumerate_usb_id )
754 log_debug(
"canceling enumeration timeout");
755 g_source_remove(appsync_enumerate_usb_id), appsync_enumerate_usb_id = 0;
759 static void appsync_enumerate_usb(
void)
761 LOG_REGISTER_CONTEXT;
765 log_debug(
"Enumerating");
768 appsync_cancel_enumerate_usb_timer();
771 gettimeofday(&tv, 0);
772 timersub(&tv, &appsync_sync_tv, &tv);
773 log_debug(
"sync to enum: %.3f seconds", tv.tv_sec + tv.tv_usec * 1e-6);
786 static void appsync_stop_apps(
int post)
788 LOG_REGISTER_CONTEXT;
790 for( GList *iter = appsync_apps_curr; iter; iter = g_list_next(iter) )
794 if( application->
post == post &&
797 log_debug(
"stopping %s-enum-app %s", post ?
"post" :
"pre",
801 if( !systemd_control_service(application->
name, SYSTEMD_STOP, FALSE) )
802 log_debug(
"Failed to stop %s\n", application->
name);
804 else if( application->
launch ) {
817 APPSYNC_LOCKED_ENTER;
818 appsync_stop_apps(0);
819 APPSYNC_LOCKED_LEAVE;
826 APPSYNC_LOCKED_ENTER;
827 appsync_stop_apps(1);
828 APPSYNC_LOCKED_LEAVE;
844 LOG_REGISTER_CONTEXT;
846 APPSYNC_LOCKED_ENTER;
852 log_debug(
"assuming all applications are active");
854 for( GList *iter = appsync_apps_curr; iter; iter = g_list_next(iter) )
862 appsync_stop_apps(1);
865 appsync_stop_apps(0);
869 appsync_cancel_enumerate_usb_timer();
872 APPSYNC_LOCKED_LEAVE;