static void GCC_INLINE fc_solve_cache_stacks( fc_solve_hard_thread_t * hard_thread, fcs_state_t * new_state_key, fcs_state_extra_info_t * new_state_val ) { int a; #if (FCS_STACK_STORAGE == FCS_STACK_STORAGE_INTERNAL_HASH) #ifdef FCS_ENABLE_SECONDARY_HASH_VALUE SFO_hash_value_t hash_value_int; #endif #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_JUDY) PWord_t * PValue; #endif void * cached_stack; char * new_ptr; fc_solve_instance_t * instance = hard_thread->instance; #ifndef HARD_CODED_NUM_STACKS DECLARE_AND_SET_GAME_PARAMS(); #endif fcs_cards_column_t column; register int col_len; fcs_compact_allocator_t * stacks_allocator; stacks_allocator = &(hard_thread->allocator); for(a=0 ; a < LOCAL_STACKS_NUM ; a++) { /* * If the stack is not a copy - it is already cached so skip * to the next stack * */ if (! (new_state_val->stacks_copy_on_write_flags & (1 << a))) { continue; } column = fcs_state_get_col(*new_state_key, a); col_len = (fcs_col_len(column)+1); new_ptr = (char*)fcs_compact_alloc_ptr(stacks_allocator, col_len); memcpy(new_ptr, column, col_len); new_state_key->stacks[a] = new_ptr; #if FCS_STACK_STORAGE == FCS_STACK_STORAGE_INTERNAL_HASH #ifdef FCS_ENABLE_SECONDARY_HASH_VALUE /* Calculate the hash value for the stack */ /* This hash function was ripped from the Perl source code. * (It is not derived work however). */ { const char * s_ptr = (char*)(new_state_key->stacks[a]); const char * s_end = s_ptr+fcs_col_len(s_ptr)+1; hash_value_int = 0; while (s_ptr < s_end) { hash_value_int += (hash_value_int << 5) + *(s_ptr++); } hash_value_int += (hash_value_int >> 5); } if (hash_value_int < 0) { /* * This is a bit mask that nullifies the sign bit of the * number so it will always be positive * */ hash_value_int &= (~(1<<((sizeof(hash_value_int)<<3)-1))); } #endif { void * dummy; int verdict; column = fcs_state_get_col(*new_state_key, a); verdict = fc_solve_hash_insert( &(instance->stacks_hash), column, column, &cached_stack, &dummy, perl_hash_function( (ub1 *)new_state_key->stacks[a], col_len ) #ifdef FCS_ENABLE_SECONDARY_HASH_VALUE , hash_value_int #endif ); replace_with_cached(verdict); } #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_GOOGLE_DENSE_HASH) { int verdict; void * dummy; column = fcs_state_get_col(*new_state_key, a); verdict = fc_solve_columns_google_hash_insert( instance->stacks_hash, column, column, &cached_stack, &dummy ); replace_with_cached(verdict); } #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_LIBAVL2_TREE) cached_stack = fcs_libavl2_stacks_tree_insert( instance->stacks_tree, new_state_key->stacks[a] ); replace_with_cached(cached_stack != NULL); #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_LIBREDBLACK_TREE) cached_stack = (void *)rbsearch( new_state_key->stacks[a], instance->stacks_tree ); replace_with_cached(cached_stack != new_state_key->stacks[a]); #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_GLIB_TREE) cached_stack = g_tree_lookup( instance->stacks_tree, (gpointer)new_state_key->stacks[a] ); /* replace_with_cached contains an if statement */ replace_with_cached(cached_stack != NULL) else { g_tree_insert( instance->stacks_tree, (gpointer)new_state_key->stacks[a], (gpointer)new_state_key->stacks[a] ); } #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_GLIB_HASH) cached_stack = g_hash_table_lookup( instance->stacks_hash, (gconstpointer)new_state_key->stacks[a] ); replace_with_cached(cached_stack != NULL) else { g_hash_table_insert( instance->stacks_hash, (gpointer)new_state_key->stacks[a], (gpointer)new_state_key->stacks[a] ); } #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_JUDY) column = fcs_state_get_col(*new_state_key, a); JHSI( PValue, instance->stacks_judy_array, column, (1+fcs_col_len(column)) ); /* later_todo : Handle out-of-memory. */ if (*PValue == 0) { /* A new stack */ *PValue = (PWord_t)column; } else { cached_stack = (void *)(*PValue); replace_with_cached(1); } #else #error FCS_STACK_STORAGE is not set to a good value. #endif } }
static int edit_read_syntax_rules (WEdit * edit, FILE * f, char **args, int args_size) { FILE *g = NULL; char *fg, *bg, *attrs; char last_fg[32] = "", last_bg[32] = "", last_attrs[64] = ""; char whole_right[512]; char whole_left[512]; char *l = 0; int save_line = 0, line = 0; struct context_rule **r, *c = NULL; int num_words = -1, num_contexts = -1; int result = 0; int alloc_contexts = MAX_CONTEXTS, alloc_words_per_context = MAX_WORDS_PER_CONTEXT, max_alloc_words_per_context = MAX_WORDS_PER_CONTEXT; args[0] = NULL; edit->is_case_insensitive = FALSE; strcpy (whole_left, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_01234567890"); strcpy (whole_right, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_01234567890"); r = edit->rules = g_malloc0 (alloc_contexts * sizeof (struct context_rule *)); if (!edit->defines) edit->defines = g_tree_new ((GCompareFunc) strcmp); while (TRUE) { char **a; size_t len; int argc; line++; l = 0; len = read_one_line (&l, f); if (len != 0) xx_lowerize_line (edit, l, len); else { if (g == NULL) break; fclose (f); f = g; g = NULL; line = save_line + 1; MC_PTR_FREE (error_file_name); MC_PTR_FREE (l); len = read_one_line (&l, f); if (len == 0) break; xx_lowerize_line (edit, l, len); } argc = get_args (l, args, args_size); a = args + 1; if (args[0] == NULL) { /* do nothing */ } else if (strcmp (args[0], "include") == 0) { if (g != NULL || argc != 2) { result = line; break; } g = f; f = open_include_file (args[1]); if (f == NULL) { MC_PTR_FREE (error_file_name); result = line; break; } save_line = line; line = 0; } else if (strcmp (args[0], "caseinsensitive") == 0) { edit->is_case_insensitive = TRUE; } else if (strcmp (args[0], "wholechars") == 0) { check_a; if (strcmp (*a, "left") == 0) { a++; g_strlcpy (whole_left, *a, sizeof (whole_left)); } else if (strcmp (*a, "right") == 0) { a++; g_strlcpy (whole_right, *a, sizeof (whole_right)); } else { g_strlcpy (whole_left, *a, sizeof (whole_left)); g_strlcpy (whole_right, *a, sizeof (whole_right)); } a++; check_not_a; } else if (strcmp (args[0], "context") == 0) { check_a; if (num_contexts == -1) { if (strcmp (*a, "default") != 0) { /* first context is the default */ break_a; } a++; c = r[0] = g_malloc0 (sizeof (struct context_rule)); c->left = g_strdup (" "); c->right = g_strdup (" "); num_contexts = 0; } else { /* Terminate previous context. */ r[num_contexts - 1]->keyword[num_words] = NULL; c = r[num_contexts] = g_malloc0 (sizeof (struct context_rule)); if (strcmp (*a, "exclusive") == 0) { a++; c->between_delimiters = 1; } check_a; if (strcmp (*a, "whole") == 0) { a++; c->whole_word_chars_left = g_strdup (whole_left); c->whole_word_chars_right = g_strdup (whole_right); } else if (strcmp (*a, "wholeleft") == 0) { a++; c->whole_word_chars_left = g_strdup (whole_left); } else if (strcmp (*a, "wholeright") == 0) { a++; c->whole_word_chars_right = g_strdup (whole_right); } check_a; if (strcmp (*a, "linestart") == 0) { a++; c->line_start_left = 1; } check_a; c->left = g_strdup (*a++); check_a; if (strcmp (*a, "linestart") == 0) { a++; c->line_start_right = 1; } check_a; c->right = g_strdup (*a++); c->first_left = *c->left; c->first_right = *c->right; } c->keyword = g_malloc (alloc_words_per_context * sizeof (struct key_word *)); num_words = 1; c->keyword[0] = g_malloc0 (sizeof (struct key_word)); subst_defines (edit->defines, a, &args[1024]); fg = *a; if (*a != '\0') a++; bg = *a; if (*a != '\0') a++; attrs = *a; if (*a != '\0') a++; g_strlcpy (last_fg, fg != NULL ? fg : "", sizeof (last_fg)); g_strlcpy (last_bg, bg != NULL ? bg : "", sizeof (last_bg)); g_strlcpy (last_attrs, attrs != NULL ? attrs : "", sizeof (last_attrs)); c->keyword[0]->color = this_try_alloc_color_pair (fg, bg, attrs); c->keyword[0]->keyword = g_strdup (" "); check_not_a; alloc_words_per_context = MAX_WORDS_PER_CONTEXT; if (++num_contexts >= alloc_contexts) { struct context_rule **tmp; alloc_contexts += 128; tmp = g_realloc (r, alloc_contexts * sizeof (struct context_rule *)); r = tmp; } } else if (strcmp (args[0], "spellcheck") == 0) { if (c == NULL) { result = line; break; } c->spelling = TRUE; } else if (strcmp (args[0], "keyword") == 0) { struct key_word *k; if (num_words == -1) break_a; check_a; k = r[num_contexts - 1]->keyword[num_words] = g_malloc0 (sizeof (struct key_word)); if (strcmp (*a, "whole") == 0) { a++; k->whole_word_chars_left = g_strdup (whole_left); k->whole_word_chars_right = g_strdup (whole_right); } else if (strcmp (*a, "wholeleft") == 0) { a++; k->whole_word_chars_left = g_strdup (whole_left); } else if (strcmp (*a, "wholeright") == 0) { a++; k->whole_word_chars_right = g_strdup (whole_right); } check_a; if (strcmp (*a, "linestart") == 0) { a++; k->line_start = 1; } check_a; if (strcmp (*a, "whole") == 0) { break_a; } k->keyword = g_strdup (*a++); k->first = *k->keyword; subst_defines (edit->defines, a, &args[1024]); fg = *a; if (*a != '\0') a++; bg = *a; if (*a != '\0') a++; attrs = *a; if (*a != '\0') a++; if (fg == NULL) fg = last_fg; if (bg == NULL) bg = last_bg; if (attrs == NULL) attrs = last_attrs; k->color = this_try_alloc_color_pair (fg, bg, attrs); check_not_a; if (++num_words >= alloc_words_per_context) { struct key_word **tmp; alloc_words_per_context += 1024; if (alloc_words_per_context > max_alloc_words_per_context) max_alloc_words_per_context = alloc_words_per_context; tmp = g_realloc (c->keyword, alloc_words_per_context * sizeof (struct key_word *)); c->keyword = tmp; } } else if (*(args[0]) == '#') { /* do nothing for comment */ } else if (strcmp (args[0], "file") == 0) { break; } else if (strcmp (args[0], "define") == 0) { char *key = *a++; char **argv; if (argc < 3) break_a; argv = g_tree_lookup (edit->defines, key); if (argv != NULL) mc_defines_destroy (NULL, argv, NULL); else key = g_strdup (key); argv = g_new (char *, argc - 1); g_tree_insert (edit->defines, key, argv); while (*a != NULL) *argv++ = g_strdup (*a++); *argv = NULL; } else { /* anything else is an error */
GCC_INLINE int fc_solve_check_and_add_state( fc_solve_soft_thread_t * soft_thread, fcs_state_extra_info_t * new_state_val, fcs_state_extra_info_t * * existing_state_val ) { #if (FCS_STATE_STORAGE == FCS_STATE_STORAGE_INTERNAL_HASH) #ifdef FCS_ENABLE_SECONDARY_HASH_VALUE SFO_hash_value_t hash_value_int; #endif #endif #if (FCS_STATE_STORAGE == FCS_STATE_STORAGE_INDIRECT) fcs_standalone_state_ptrs_t * pos_ptr; int found; #endif fc_solve_hard_thread_t * hard_thread = soft_thread->hard_thread; fc_solve_instance_t * instance = hard_thread->instance; fcs_state_t * new_state_key = new_state_val->key; int is_state_new; if (check_if_limits_exceeded()) { return FCS_STATE_BEGIN_SUSPEND_PROCESS; } if ((instance->max_depth >= 0) && (new_state_val->depth >= instance->max_depth)) { return FCS_STATE_EXCEEDS_MAX_DEPTH; } fc_solve_cache_stacks(hard_thread, new_state_key, new_state_val); fc_solve_canonize_state(new_state_val, INSTANCE_FREECELLS_NUM, INSTANCE_STACKS_NUM ); /* The objective of this part of the code is: 1. To check if new_state_key / new_state_val is already in the prev_states collection. 2. If not, to add it and to set check to true. 3. If so, to set check to false. */ #if (FCS_STATE_STORAGE == FCS_STATE_STORAGE_INTERNAL_HASH) #ifdef FCS_ENABLE_SECONDARY_HASH_VALUE { const char * s_ptr = (char*)new_state_key; const char * s_end = s_ptr+sizeof(*new_state_key); hash_value_int = 0; while (s_ptr < s_end) { hash_value_int += (hash_value_int << 5) + *(s_ptr++); } hash_value_int += (hash_value_int>>5); } if (hash_value_int < 0) { /* * This is a bit mask that nullifies the sign bit of the * number so it will always be positive * */ hash_value_int &= (~(1<<((sizeof(hash_value_int)<<3)-1))); } #endif { void * existing_key_void, * existing_val_void; is_state_new = (fc_solve_hash_insert( &(instance->hash), new_state_key, new_state_val, &existing_key_void, &existing_val_void, perl_hash_function( (ub1 *)new_state_key, sizeof(*new_state_key) ) #ifdef FCS_ENABLE_SECONDARY_HASH_VALUE , hash_value_int #endif ) == 0); if (! is_state_new) { *existing_state_val = existing_val_void; } } #elif (FCS_STATE_STORAGE == FCS_STATE_STORAGE_GOOGLE_DENSE_HASH) { void * existing_key_void, * existing_val_void; is_state_new = (fc_solve_states_google_hash_insert( instance->hash, new_state_key, new_state_val, &existing_key_void, &existing_val_void ) == 0); if (! is_state_new) { *existing_state_val = existing_val_void; } } #elif (FCS_STATE_STORAGE == FCS_STATE_STORAGE_INDIRECT) /* Try to see if the state is found in indirect_prev_states */ if ((pos_ptr = (fcs_standalone_state_ptrs_t *)bsearch(&new_state_key, instance->indirect_prev_states, instance->num_indirect_prev_states, sizeof(instance->indirect_prev_states[0]), fc_solve_state_compare_indirect)) == NULL) { /* It isn't in prev_states, but maybe it's in the sort margin */ pos_ptr = (fcs_standalone_state_ptrs_t *)fc_solve_bsearch( &new_state_key, instance->indirect_prev_states_margin, instance->num_prev_states_margin, sizeof(instance->indirect_prev_states_margin[0]), fc_solve_state_compare_indirect_with_context, NULL, &found); if (found) { is_state_new = 0; *existing_state_val = pos_ptr->val; } else { /* Insert the state into its corresponding place in the sort * margin */ memmove((void*)(pos_ptr+1), (void*)pos_ptr, sizeof(*pos_ptr) * (instance->num_prev_states_margin- (pos_ptr-instance->indirect_prev_states_margin) )); pos_ptr->key = new_state_key; pos_ptr->val = new_state_val; instance->num_prev_states_margin++; if (instance->num_prev_states_margin >= PREV_STATES_SORT_MARGIN) { /* The sort margin is full, let's combine it with the main array */ instance->indirect_prev_states = realloc( instance->indirect_prev_states, sizeof(instance->indirect_prev_states[0]) * (instance->num_indirect_prev_states + instance->num_prev_states_margin ) ); fc_solve_merge_large_and_small_sorted_arrays( instance->indirect_prev_states, instance->num_indirect_prev_states, instance->indirect_prev_states_margin, instance->num_prev_states_margin, sizeof(instance->indirect_prev_states[0]), fc_solve_state_compare_indirect_with_context, NULL ); instance->num_indirect_prev_states += instance->num_prev_states_margin; instance->num_prev_states_margin=0; } is_state_new = 1; } } else { *existing_state_val = pos_ptr->val; is_state_new = 0; } #elif (FCS_STATE_STORAGE == FCS_STATE_STORAGE_LIBREDBLACK_TREE) *existing_state_val = (fcs_state_extra_info_t *)rbsearch(new_state_val, instance->tree ); is_state_new = ((*existing_state_val) == new_state_val); #elif (FCS_STATE_STORAGE == FCS_STATE_STORAGE_LIBAVL2_TREE) *existing_state_val = (fcs_state_extra_info_t *) fcs_libavl2_states_tree_insert(instance->tree, new_state_val); is_state_new = ((*existing_state_val) == NULL); #elif (FCS_STATE_STORAGE == FCS_STATE_STORAGE_GLIB_TREE) *existing_state_val = g_tree_lookup(instance->tree, (gpointer)new_state_key); if (*existing_state_val == NULL) { /* The new state was not found. Let's insert it. * The value must be the same as the key, so g_tree_lookup() * will return it. */ g_tree_insert( instance->tree, (gpointer)new_state_key, (gpointer)new_state_val ); is_state_new = 1; } else { is_state_new = 0; } #elif (FCS_STATE_STORAGE == FCS_STATE_STORAGE_GLIB_HASH) *existing_state_val = g_hash_table_lookup(instance->hash, (gpointer)new_state_key); if (*existing_state_val == NULL) { /* The new state was not found. Let's insert it. * The value must be the same as the key, so g_tree_lookup() * will return it. */ g_hash_table_insert( instance->hash, (gpointer)new_state_key, (gpointer)new_state_val ); is_state_new = 1; } else { is_state_new = 0; } #elif (FCS_STATE_STORAGE == FCS_STATE_STORAGE_DB_FILE) { DBT key, value; key.data = new_state; key.size = sizeof(*new_state); if (instance->db->get( instance->db, NULL, &key, &value, 0 ) == 0) { /* The new state was not found. Let's insert it. * The value must be the same as the key, so g_tree_lookup() * will return it. */ value.data = key.data; value.size = key.size; instance->db->put( instance->db, NULL, &key, &value, 0); is_state_new = 1; } else { is_state_new = 0; } } #elif (FCS_STATE_STORAGE == FCS_STATE_STORAGE_JUDY) { PWord_t * PValue; JHSI(PValue, instance->judy_array, new_state_key, sizeof(*new_state_key)); /* later_todo : Handle out-of-memory. */ if (*PValue == 0) { /* A new state. */ is_state_new = 1; *PValue = (PWord_t)(*existing_state_val = new_state_val); } else { /* Already exists. */ is_state_new = 0; *existing_state_val = (fcs_state_extra_info_t *)(*PValue); } } #else #error no define #endif if (is_state_new) { /* The new state was not found in the cache, and it was already inserted */ if (new_state_val->parent_val) { new_state_val->parent_val->num_active_children++; } instance->num_states_in_collection++; if (new_state_val->moves_to_parent != NULL) { new_state_val->moves_to_parent = fc_solve_move_stack_compact_allocate( hard_thread, new_state_val->moves_to_parent ); } return FCS_STATE_DOES_NOT_EXIST; } else { return FCS_STATE_ALREADY_EXISTS; } }
void dir_crawl(GTree *t, GHashTable *linkhash, GHashTable *userhash, GHashTable *grouphash, char *path) { DIR *dir; struct dirent *dent; struct rdup *directory; struct chown_pack *cp; char *curpath; gchar *lnk; struct stat s; struct rdup pop; struct remove_path rp; dev_t current_dev; size_t curpath_len; /* dir stack */ gint32 d = 0; gint32 dstack_cnt = 1; struct rdup **dirstack = g_malloc(dstack_cnt * D_STACKSIZE * sizeof(struct rdup *)); if (!(dir = opendir(path))) { /* non-dirs are also allowed, check for this, if it isn't give the error */ if (access(path, R_OK) == 0) { g_free(dirstack); return; } msg(_("Cannot enter directory `%s\': %s"), path, strerror(errno)); g_free(dirstack); return; } /* get device */ #ifdef HAVE_DIRFD if (fstat(dirfd(dir), &s) != 0) { #else if (fstat(rdup_dirfd(dir), &s) != 0) { #endif msg(_("Cannot determine holding device of the directory `%s\': %s"), path, strerror(errno)); closedir(dir); g_free(dirstack); return; } current_dev = s.st_dev; while((dent = readdir(dir))) { if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) continue; if (opt_chown) { if ( !strncmp(dent->d_name, USRGRPINFO, LEN_USRGRPINFO) ) { continue; } } if (strcmp(path, "/") == 0) { curpath = g_strdup_printf("/%s", dent->d_name); curpath_len = strlen(curpath); } else { curpath = g_strdup_printf("%s/%s", path, dent->d_name); curpath_len = strlen(curpath); } if (lstat(curpath, &s) != 0) { msg(_("Could not stat path `%s\': %s"), curpath, strerror(errno)); g_free(curpath); continue; } if (strchr(curpath, '\n')) { msg(_("Newline (\\n) found in path `%s\', skipping"), curpath); g_free(curpath); continue; } if (S_ISREG(s.st_mode) || S_ISLNK(s.st_mode) || S_ISBLK(s.st_mode) || S_ISCHR(s.st_mode) || S_ISFIFO(s.st_mode) || S_ISSOCK(s.st_mode) ) { pop.f_name = curpath; pop.f_target = NULL; pop.f_name_size = curpath_len; pop.f_uid = s.st_uid; pop.f_user = lookup_user(userhash, pop.f_uid); pop.f_gid = s.st_gid; pop.f_group = lookup_group(grouphash, pop.f_gid); pop.f_ctime = s.st_ctime; pop.f_mtime = s.st_mtime; pop.f_atime = s.st_atime; pop.f_mode = s.st_mode; pop.f_size = s.st_size; pop.f_dev = s.st_dev; pop.f_rdev = s.st_rdev; pop.f_ino = s.st_ino; pop.f_lnk = 0; if (gfunc_regexp(pregex_list, curpath, curpath_len)) { g_free(curpath); continue; } if (opt_nobackup && !strcmp(dent->d_name, NOBACKUP)) { /* return after seeing .nobackup */ if (opt_verbose > 0) { msg(_("%s found in '%s\'"), NOBACKUP, path); } /* remove all files found in this path */ rp.tree = t; rp.len = strlen(path); rp.path = path; g_tree_foreach(t, gfunc_remove_path, (gpointer)&rp); /* add .nobackup back in */ g_tree_insert(t, (gpointer) entry_dup(&pop), VALUE); g_free(dirstack); closedir(dir); return; } /* hardlinks */ if (s.st_nlink > 1) { if ((lnk = hlink(linkhash, &pop))) { pop.f_target = lnk; pop.f_lnk = 1; } } if (S_ISLNK(s.st_mode)) pop.f_target = slink(&pop); if (S_ISLNK(s.st_mode) || pop.f_lnk) { /* fix the name and the sizes */ pop.f_size = pop.f_name_size; pop.f_name_size += 4 + strlen(pop.f_target); } /* check for USRGRPINFO file */ if ( opt_chown && (cp = chown_parse(path, dent->d_name)) != NULL ) { pop.f_uid = cp->u; pop.f_gid = cp->g; pop.f_user = cp->user; pop.f_group = cp->group; } g_tree_insert(t, (gpointer) entry_dup(&pop), VALUE); if (pop.f_target != NULL) g_free(pop.f_target); g_free(curpath); continue; } else if(S_ISDIR(s.st_mode)) { /* one filesystem */ if (opt_onefilesystem && s.st_dev != current_dev) { msg(_("Not walking into different filesystem `%s\'"), curpath); g_free(curpath); continue; } /* Exclude list */ if (gfunc_regexp(pregex_list, curpath, curpath_len)) { g_free(curpath); continue; } dirstack[d] = g_malloc(sizeof(struct rdup)); dirstack[d]->f_name = g_strdup(curpath); dirstack[d]->f_target = NULL; dirstack[d]->f_name_size = curpath_len; dirstack[d]->f_uid = s.st_uid; dirstack[d]->f_user = lookup_user(userhash, s.st_uid); dirstack[d]->f_gid = s.st_gid; dirstack[d]->f_group = lookup_group(grouphash, s.st_gid); dirstack[d]->f_ctime = s.st_ctime; dirstack[d]->f_mtime = s.st_mtime; dirstack[d]->f_atime = s.st_atime; dirstack[d]->f_mode = s.st_mode; dirstack[d]->f_size = s.st_size; dirstack[d]->f_dev = s.st_dev; dirstack[d]->f_rdev = s.st_rdev; dirstack[d]->f_ino = s.st_ino; dirstack[d]->f_lnk = 0; /* check for USRGRPINFO file */ if ( opt_chown && (cp = chown_parse(curpath, NULL)) != NULL ) { dirstack[d]->f_uid = cp->u; dirstack[d]->f_gid = cp->g; dirstack[d]->f_user = cp->user; dirstack[d]->f_group = cp->group; } if (d++ % D_STACKSIZE == 0) { dirstack = g_realloc(dirstack, ++dstack_cnt * D_STACKSIZE * sizeof(struct rdup *)); } g_free(curpath); continue; } else { if (opt_verbose > 0) { msg(_("Neither file nor directory `%s\'"), curpath); } g_free(curpath); } } closedir(dir); if (opt_atime) { /* reset dirs atime */ if (d > 0 && opt_atime) { struct utimbuf ut; ut.actime = dirstack[d - 1]->f_atime; ut.modtime = dirstack[d - 1]->f_mtime; if (utime(dirstack[d - 1]->f_name, &ut) == -1) msg(_("Failed to reset atime: '%s\': %s"), dirstack[d - 1]->f_name, strerror(errno)); } } while (d > 0) { directory = dirstack[--d]; g_tree_insert(t, (gpointer) entry_dup(directory), VALUE); /* recurse */ /* potentially expensive operation. Better would be to when we hit * .nobackup to go up the tree and delete some nodes.... or not */ dir_crawl(t, linkhash, userhash, grouphash, directory->f_name); entry_free(directory); } g_free(dirstack); return; }
/** * prepend path leading up to backup directory to the tree */ gboolean dir_prepend(GTree *t, char *path, GHashTable *u, GHashTable *g) { char *c; char *p; char *path2; size_t len; struct stat s; struct rdup e; path2 = g_strdup(path); len = strlen(path); /* add closing / */ if (path2[len - 1] != '/') { path2 = g_realloc(path2, len + 2); path2[len] = '/'; path2[len + 1] = '\0'; } for (p = path2 + 1; (c = strchr(p, '/')); p++) { *c = '\0'; if (lstat(path2, &s) != 0) { msg(_("Could not stat path `%s\': %s"), path2, strerror(errno)); g_free(path2); return FALSE; } e.f_name = path2; e.f_target = NULL; e.f_name_size = strlen(path2); e.f_uid = s.st_uid; e.f_user = lookup_user(u, e.f_uid); e.f_gid = s.st_gid; e.f_group = lookup_group(g, e.f_gid); e.f_ctime = s.st_ctime; e.f_mtime = s.st_mtime; e.f_atime = s.st_atime; e.f_mode = s.st_mode; e.f_size = s.st_size; e.f_dev = s.st_dev; e.f_rdev = s.st_rdev; e.f_ino = s.st_ino; e.f_lnk = 0; /* symlinks; also set the target */ if (S_ISLNK(s.st_mode)) { e.f_target = slink(&e); e.f_size = e.f_name_size; e.f_name_size += 4 + strlen(e.f_target); /* When we encounter a symlink on this level, it is very hard to make this * backup work, because the target may fall out of the backup. If this * is the case the entire backup fails. Gnu tar only show the symlink * and then stops. We do now the same, heance the return FALSE */ g_tree_insert(t, (gpointer) entry_dup(&e), VALUE); g_free(e.f_target); g_free(path2); return FALSE; } g_tree_insert(t, (gpointer) entry_dup(&e), VALUE); *c = '/'; p = c++; } g_free(path2); return TRUE; }
static void url_add (char *urltext, int len) { char *data; int size; /* we don't need any URLs if we have neither URL grabbing nor URL logging enabled */ if (!prefs.hex_url_grabber && !prefs.hex_url_logging) { return; } data = malloc (len + 1); if (!data) { return; } memcpy (data, urltext, len); data[len] = 0; if (data[len - 1] == '.') /* chop trailing dot */ { len--; data[len] = 0; } /* chop trailing ) but only if there's no counterpart */ if (data[len - 1] == ')' && strchr (data, '(') == NULL) { data[len - 1] = 0; } if (prefs.hex_url_logging) { url_save_node (data); } /* the URL is saved already, only continue if we need the URL grabber too */ if (!prefs.hex_url_grabber) { free (data); return; } if (!url_tree) { url_tree = tree_new ((tree_cmp_func *)strcasecmp, NULL); url_btree = g_tree_new ((GCompareFunc)strcasecmp); } if (url_find (data)) { free (data); return; } size = tree_size (url_tree); /* 0 is unlimited */ if (prefs.hex_url_grabber_limit > 0 && size >= prefs.hex_url_grabber_limit) { /* the loop is necessary to handle having the limit lowered while HexChat is running */ size -= prefs.hex_url_grabber_limit; for(; size > 0; size--) { char *pos; pos = tree_remove_at_pos (url_tree, 0); g_tree_remove (url_btree, pos); free (pos); } } tree_append (url_tree, data); g_tree_insert (url_btree, data, GINT_TO_POINTER (tree_size (url_tree) - 1)); fe_url_add (data); }
void tgenpool_add(TGenPool* pool, gpointer item) { TGEN_ASSERT(pool); gint* key = g_new(gint, 1); *key = (pool->counter)++; g_tree_insert(pool->items, key, item); }