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
    }
}
Exemple #2
0
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;
    }
}
Exemple #4
0
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;
}
Exemple #5
0
/**
 * 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;
}
Exemple #6
0
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);
}
Exemple #7
0
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);
}