22 #include "opensync_internals.h" 40 flock(
int fd,
int operation)
44 switch (operation & ~LOCK_NB) {
46 flock.l_type = F_RDLCK;
49 flock.l_type = F_WRLCK;
52 flock.l_type = F_UNLCK;
63 return fcntl(fd, (operation & LOCK_NB) ? F_SETLK : F_SETLKW, &flock);
118 char *filename = NULL;
124 filename = g_strdup_printf(
"%s/%lli", group->configdir, i);
125 }
while (g_file_test(filename, G_FILE_TEST_EXISTS));
139 return group->conv_env;
155 GError *gerror = NULL;
156 char *filename = NULL;
158 dir = g_dir_open(path, 0, &gerror);
160 osync_debug(
"OSGRP", 3,
"Unable to open group configdir %s", gerror->message);
161 osync_error_set(error, OSYNC_ERROR_IO_ERROR,
"Unable to open group configdir %s", gerror->message);
162 g_error_free (gerror);
166 const gchar *de = NULL;
167 while ((de = g_dir_read_name(dir))) {
169 if (!g_file_test(filename, G_FILE_TEST_IS_DIR) || g_file_test(filename, G_FILE_TEST_IS_SYMLINK) || g_pattern_match_simple(
".*", de) || !strcmp(
"db", de)) {
175 osync_debug(
"OSGRP", 0,
"Unable to load one of the members");
243 if (group->configdir)
244 g_free(group->configdir);
271 g_assert(group->configdir);
273 osync_bool exists = FALSE;
274 osync_bool locked = FALSE;
276 if (group->lock_fd) {
281 char *lockfile = g_strdup_printf(
"%s/lock", group->configdir);
282 osync_debug(
"GRP", 4,
"locking file %s", lockfile);
284 if (g_file_test(lockfile, G_FILE_TEST_EXISTS)) {
285 osync_debug(
"GRP", 4,
"locking group: file exists");
289 if ((group->lock_fd = open(lockfile, O_CREAT | O_WRONLY, 00700)) == -1) {
291 osync_debug(
"GRP", 1,
"error opening file: %s", strerror(errno));
294 return OSYNC_LOCK_STALE;
300 int oldflags = fcntl(group->lock_fd, F_GETFD);
301 if (oldflags == -1) {
303 return OSYNC_LOCK_STALE;
306 if (fcntl(group->lock_fd, F_SETFD, oldflags|FD_CLOEXEC) == -1) {
308 return OSYNC_LOCK_STALE;
311 if (flock(group->lock_fd, LOCK_EX | LOCK_NB) == -1) {
312 if (errno == EWOULDBLOCK) {
313 osync_debug(
"GRP", 4,
"locking group: is locked2");
315 close(group->lock_fd);
318 osync_debug(
"GRP", 1,
"error setting lock: %s", strerror(errno));
326 return OSYNC_LOCK_OK;
333 return OSYNC_LOCK_STALE;
351 g_assert(group->configdir);
352 osync_debug(
"GRP", 4,
"unlocking group %s", group->name);
354 if (!group->lock_fd) {
355 osync_debug(
"GRP", 1,
"You have to lock the group before unlocking");
359 if (flock(group->lock_fd, LOCK_UN) == -1) {
360 osync_debug(
"GRP", 1,
"error releasing lock: %s", strerror(errno));
364 fsync(group->lock_fd);
365 close(group->lock_fd);
370 char *lockfile = g_strdup_printf(
"%s/lock", group->configdir);
389 group->name = g_strdup(name);
419 osync_assert_msg(group->env,
"You must specify a Environment prior to saving the group");
421 if (!group->configdir) {
423 group->configdir = g_strdup_printf(
"%s/group%lli", group->env->groupsdir, group->id);
426 char *filename = NULL;
427 osync_debug(
"OSGRP", 3,
"Trying to open configdirectory %s to save group %s", group->configdir, group->name);
430 if (!g_file_test(group->configdir, G_FILE_TEST_IS_DIR)) {
431 osync_debug(
"OSGRP", 3,
"Creating group configdirectory %s", group->configdir);
432 if (mkdir(group->configdir, 0700)) {
433 osync_error_set(error, OSYNC_ERROR_IO_ERROR,
"Unable to create directory for group %s\n", group->name);
438 filename = g_strdup_printf (
"%s/syncgroup.conf", group->configdir);
439 osync_debug(
"OSGRP", 3,
"Saving group to file %s", filename);
443 doc = xmlNewDoc((xmlChar*)
"1.0");
444 doc->children = xmlNewDocNode(doc, NULL, (xmlChar*)
"syncgroup", NULL);
448 for (f = group->filters; f; f = f->next) {
450 xmlNodePtr child = xmlNewTextChild(doc->children, NULL, (xmlChar*)
"filter", NULL);
452 if (filter->sourcememberid) {
453 char *sourcememberid = g_strdup_printf(
"%lli", filter->sourcememberid);
454 xmlNewTextChild(child, NULL, (xmlChar*)
"sourcemember", (xmlChar*)sourcememberid);
455 g_free(sourcememberid);
457 if (filter->destmemberid) {
458 char *destmemberid = g_strdup_printf(
"%lli", filter->destmemberid);
459 xmlNewTextChild(child, NULL, (xmlChar*)
"destmember", (xmlChar*)destmemberid);
460 g_free(destmemberid);
462 if (filter->sourceobjtype)
463 xmlNewTextChild(child, NULL, (xmlChar*)
"sourceobjtype", (xmlChar*)filter->sourceobjtype);
464 if (filter->destobjtype)
465 xmlNewTextChild(child, NULL, (xmlChar*)
"destobjtype", (xmlChar*)filter->destobjtype);
466 if (filter->detectobjtype)
467 xmlNewTextChild(child, NULL, (xmlChar*)
"detectobjtype", (xmlChar*)filter->detectobjtype);
468 if (filter->action) {
469 char *action = g_strdup_printf(
"%i", filter->action);
470 xmlNewTextChild(child, NULL, (xmlChar*)
"action", (xmlChar*)action);
473 if (filter->function_name)
474 xmlNewTextChild(child, NULL, (xmlChar*)
"function_name", (xmlChar*)filter->function_name);
476 xmlNewTextChild(child, NULL, (xmlChar*)
"config", (xmlChar*)filter->config);
479 xmlNewTextChild(doc->children, NULL, (xmlChar*)
"groupname", (xmlChar*)group->name);
481 char *tmstr = g_strdup_printf(
"%i", (
int)group->last_sync);
482 xmlNewTextChild(doc->children, NULL, (xmlChar*)
"last_sync", (xmlChar*)tmstr);
485 xmlSaveFile(filename, doc);
515 char *delcmd = g_strdup_printf(
"rm -rf %s", group->configdir);
516 if (system(delcmd)) {
517 osync_error_set(error, OSYNC_ERROR_GENERIC,
"Failed to delete group. command %s failed", delcmd);
539 char *filename = NULL;
540 char *real_path = NULL;
544 osync_debug(
"OSGRP", 3,
"Trying to load group from directory %s", path);
546 if (!g_path_is_absolute(path)) {
547 real_path = g_strdup_printf(
"%s/%s", g_get_current_dir(), path);
549 real_path = g_strdup(path);
551 filename = g_strdup_printf(
"%s/syncgroup.conf", real_path);
554 group->configdir = real_path;
558 xmlNodePtr filternode;
567 while (cur != NULL) {
568 if (!xmlStrcmp(cur->name, (
const xmlChar *)
"groupname"))
569 group->name = (
char*)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
571 if (!xmlStrcmp(cur->name, (
const xmlChar *)
"last_sync"))
572 group->last_sync = (time_t)atoi((
char*)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
574 if (!xmlStrcmp(cur->name, (
const xmlChar *)
"filter")) {
575 filternode = cur->xmlChildrenNode;
577 filter->group = group;
579 while (filternode != NULL) {
580 if (!xmlStrcmp(filternode->name, (
const xmlChar *)
"sourceobjtype"))
581 filter->sourceobjtype = (
char*)xmlNodeListGetString(doc, filternode->xmlChildrenNode, 1);
583 if (!xmlStrcmp(filternode->name, (
const xmlChar *)
"destobjtype"))
584 filter->destobjtype = (
char*)xmlNodeListGetString(doc, filternode->xmlChildrenNode, 1);
586 if (!xmlStrcmp(filternode->name, (
const xmlChar *)
"detectobjtype"))
587 filter->detectobjtype = (
char*)xmlNodeListGetString(doc, filternode->xmlChildrenNode, 1);
589 if (!xmlStrcmp(filternode->name, (
const xmlChar *)
"config"))
590 filter->config = (
char*)xmlNodeListGetString(doc, filternode->xmlChildrenNode, 1);
592 if (!xmlStrcmp(filternode->name, (
const xmlChar *)
"function_name")) {
593 char *str = (
char*)xmlNodeListGetString(doc, filternode->xmlChildrenNode, 1);
595 filternode = filternode->next;
598 osync_filter_update_hook(filter, group, str);
602 if (!xmlStrcmp(filternode->name, (
const xmlChar *)
"sourcemember")) {
603 char *str = (
char*)xmlNodeListGetString(doc, filternode->xmlChildrenNode, 1);
605 filternode = filternode->next;
608 filter->sourcememberid = atoll(str);
612 if (!xmlStrcmp(filternode->name, (
const xmlChar *)
"destmember")) {
613 char *str = (
char*)xmlNodeListGetString(doc, filternode->xmlChildrenNode, 1);
615 filternode = filternode->next;
618 filter->destmemberid = atoll(str);
622 if (!xmlStrcmp(filternode->name, (
const xmlChar *)
"action")) {
623 char *str = (
char*)xmlNodeListGetString(doc, filternode->xmlChildrenNode, 1);
625 filternode = filternode->next;
628 filter->action = atoi(str);
631 filternode = filternode->next;
642 osync_error_set(error, OSYNC_ERROR_MISCONFIGURATION,
"Loaded a group without a name");
643 osync_debug(
"OSGRP", 0,
"Loaded a group without a name");
670 osync_db_reset_group(group, &error);
673 for (m = group->members; m; m = m->next) {
675 osync_db_reset_member(member, &error);
690 group->members = g_list_append(group->members, member);
702 group->members = g_list_remove(group->members, member);
717 return (
OSyncMember *)g_list_nth_data(group->members, nth);
731 return g_list_length(group->members);
745 return group->configdir;
758 if (group->configdir)
759 g_free(group->configdir);
760 group->configdir = g_strdup(directory);
785 if (osync_conv_objtype_is_any(objtypestr)) {
787 for (element = conv_env->
objtypes; element; element = element->next) {
789 objtype->needs_slow_sync = slow_sync;
794 objtype->needs_slow_sync = slow_sync;
815 if (osync_conv_objtype_is_any(objtypestr)) {
817 for (element = conv_env->
objtypes; element; element = element->next) {
819 objtype->needs_slow_sync = FALSE;
824 objtype->needs_slow_sync = FALSE;
848 if (osync_objtype && osync_objtype->needs_slow_sync) {
853 g_assert(osync_objtype);
856 return osync_objtype->needs_slow_sync;
878 for (m = group->members; m; m = m->next) {
903 for (m = group->members; m; m = m->next) {
913 if (!osync_member_require_sink_info(member, NULL)) {
914 osync_debug(
"OSGRP", 0,
"%s: No sink information, can't load plugin, and I can't return error");
931 return g_list_length(group->filters);
947 return g_list_nth_data(group->filters, nth);
957 while (group->filters) {
958 OSyncFilter *f = g_list_nth_data(group->filters, 0);
962 group->filters = g_list_delete_link(group->filters, group->filters);
978 return osync_db_open_changelog(group, uids, objtype, memberids, changetypes, error);
990 return osync_db_save_changelog(group, change, error);
1002 return osync_db_remove_changelog(group, change, error);
1015 osync_assert_msg(group,
"Group missing");
1017 group->last_sync = last_sync;
1031 osync_assert_msg(group,
"Group missing");
1032 return group->last_sync;
void osync_env_remove_group(OSyncEnv *env, OSyncGroup *group)
Removes the given group from the enviroment.
void osync_filter_register(OSyncGroup *group, OSyncFilter *filter)
Registers a filter with a group.
OSyncGroup * osync_group_new(OSyncEnv *env)
Creates a new group for the given environment.
OSyncGroup * osync_group_load(OSyncEnv *env, const char *path, OSyncError **error)
Loads a group from a directory.
void osync_member_free(OSyncMember *member)
Frees a member.
void osync_group_remove_member(OSyncGroup *group, OSyncMember *member)
Removes a member from the group.
osync_bool osync_group_open_changelog(OSyncGroup *group, char ***uids, char ***objtype, long long int **memberids, int **changetypes, OSyncError **error)
Can be used to load all items from the changelog. Loaded items will be removed.
void osync_member_set_objtype_enabled(OSyncMember *member, const char *objtypestr, osync_bool enabled)
Enables or disables a object type on a member.
osync_bool _osync_open_xml_file(xmlDocPtr *doc, xmlNodePtr *cur, const char *path, const char *topentry, OSyncError **error)
Opens a xml document.
void osync_group_set_configdir(OSyncGroup *group, const char *directory)
Sets the configdir of the group.
OSyncFilter * osync_group_nth_filter(OSyncGroup *group, int nth)
Gets the nth filter of a group.
int osync_group_num_members(OSyncGroup *group)
Counts the members of the group.
osync_bool osync_group_save(OSyncGroup *group, OSyncError **error)
Saves the group to disc.
void osync_group_set_data(OSyncGroup *group, void *data)
Sets the custom data of a group.
OSyncEnv * osync_group_get_env(OSyncGroup *group)
Returns the environment in which a group is registered.
OSyncMember * osync_member_load(OSyncGroup *group, const char *path, OSyncError **error)
Loads a member from a directory where it has been saved.
int osync_group_num_filters(OSyncGroup *group)
Returns the number of filters registered in a group.
void osync_filter_free(OSyncFilter *filter)
Frees a filter.
void osync_env_append_group(OSyncEnv *env, OSyncGroup *group)
Adds the given group to the environment.
osync_bool osync_group_objtype_enabled(OSyncGroup *group, const char *objtype)
Returns if the object type is enabled for the group.
osync_bool osync_member_save(OSyncMember *member, OSyncError **error)
Saves a member to it config directory.
Represent a group of members that should be synchronized.
void osync_group_set_objtype_enabled(OSyncGroup *group, const char *objtypestr, osync_bool enabled)
Sets if the object type is accepted for ALL members.
osync_bool osync_group_save_changelog(OSyncGroup *group, OSyncChange *change, OSyncError **error)
Saves a change to the changelog.
void osync_group_reset(OSyncGroup *group)
Resets all databases of a group.
long long int osync_group_create_member_id(OSyncGroup *group)
Creates a new unique member if in this group.
A member of a group which represent a single device.
void osync_group_add_member(OSyncGroup *group, OSyncMember *member)
Appends a member to the group.
void osync_group_unlock(OSyncGroup *group, osync_bool remove)
Unlocks a group.
void osync_group_reset_slow_sync(OSyncGroup *group, const char *objtypestr)
Reset slow-sync for this group.
void osync_group_free(OSyncGroup *group)
Frees the given group.
OSyncObjType * osync_conv_find_objtype(OSyncFormatEnv *env, const char *name)
Finds the object type with the given name.
Represents a filter to filter changes.
OSyncLockState
The lock state of a group.
time_t osync_group_get_last_synchronization(OSyncGroup *group)
Gets the last synchronization date from this group.
void osync_debug(const char *subpart, int level, const char *message,...)
Used for debugging.
osync_bool osync_group_load_members(OSyncGroup *group, const char *path, OSyncError **error)
Loads all members of a group.
const char * osync_group_get_name(OSyncGroup *group)
Returns the name of a group.
long long int _osync_env_create_group_id(OSyncEnv *env)
Returns the next free number for a group in the environments configdir.
osync_bool osync_group_delete(OSyncGroup *group, OSyncError **error)
Deletes a group from disc.
OSyncFormatEnv * osync_conv_env_new(OSyncEnv *env)
This will create a new opensync format environment.
void * osync_group_get_data(OSyncGroup *group)
Gets the custom data of a group.
void osync_error_set(OSyncError **error, OSyncErrorType type, const char *format,...)
Sets the error.
const char * osync_error_print(OSyncError **error)
Returns the message of the error.
void osync_conv_env_free(OSyncFormatEnv *env)
Frees a osync format environment.
void osync_trace(OSyncTraceType type, const char *message,...)
Used for tracing the application.
void osync_group_set_last_synchronization(OSyncGroup *group, time_t last_sync)
Sets the last synchronization date of this group.
osync_bool osync_group_get_slow_sync(OSyncGroup *group, const char *objtype)
Returns if the group will perform a slow-sync for the object type.
osync_bool osync_member_objtype_enabled(OSyncMember *member, const char *objtype)
Returns if a certain object type is enabled on this member.
osync_bool osync_group_remove_changelog(OSyncGroup *group, OSyncChange *change, OSyncError **error)
Removes a change from the changelog.
Represent a abstract object type (like "contact")
OSyncLockState osync_group_lock(OSyncGroup *group)
Locks a group.
void osync_group_flush_filters(OSyncGroup *group)
Flushes the list of filters for a group.
OSyncMember * osync_group_nth_member(OSyncGroup *group, int nth)
Returns the nth member of the group.
void osync_group_set_name(OSyncGroup *group, const char *name)
Sets the name for the group.
OSyncFilter * osync_filter_new(void)
Creates a new filter.
void osync_group_set_slow_sync(OSyncGroup *group, const char *objtypestr, osync_bool slow_sync)
Sets if the group requires slow-sync for the given object type.
const char * osync_group_get_configdir(OSyncGroup *group)
Returns the configdir for the group.
OSyncFormatEnv * osync_group_get_format_env(OSyncGroup *group)
Returns the format environment of a group.