1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
static struct search_roots_ll {
    const char *path;
    struct search_roots_ll * next;
} roots_ll;

#ifdef APPLICATION
/*
 * This adds a path to the search roots, possibly during traveling through
 * the filesystem. It only adds if the path is not inside an already existing
 * search root.
 *
 * Returns true if it added the path to the search roots
 * 
 * Windows 2000 and greater supports symlinks, but they don't provide
 * realpath() or readlink(), and symlinks are rarely used on them so
 * ignore this for windows for now
 **/
static bool add_search_root(const char *name)
{
    (void)name;
#ifndef WIN32
    debugf("%s()\n", __func__);
    struct search_roots_ll *this, *prev = NULL;
    char target[MAX_PATH];
    char _abs_target[MAX_PATH];
    char * abs_target;
    ssize_t len;

    len = readlink(name, target, sizeof(target));
    if (len < 0)
        return false;

    debugf("%s() 1: %s\n", __func__, roots_ll.path?:"(null)");
    target[len] = '\0';
    debugf("%s() 2: %s\n", __func__, roots_ll.path?:"(null)");
    /* realpath(target, NULL) doesn't work on android ... */
    abs_target = realpath(target, _abs_target);
    debugf("%d", thread_stack_usage(thread_id_entry(THREAD_ID_CURRENT)));
    debugf("%s() 3: %s\n", __func__, roots_ll.path?:"(null)");
    if (abs_target == NULL)
    {
        debugf("foo");
        return false;
    }

    debugf("%s() 4: %s\n", __func__, roots_ll.path?:"(null)");
    for(this = &roots_ll; this; prev = this, this = this->next)
    {
        if (roots_ll.path)
            debugf("%s() %s\n", __func__, "path NULL");
        else
            debugf("%s() %s\n", __func__, roots_ll.path);
        size_t root_len = strlen(this->path);
        /* check if the link target is inside of an existing search root
         * don't add if target is inside, we'll scan it later */
        if (!strncmp(this->path, abs_target, root_len))
            return false;
    }

    if (prev)
    {
        size_t len = strlen(abs_target) + 1; /* count \0 */
        this = malloc(sizeof(struct search_roots_ll) + len );
        if (!this || len > MAX_PATH)
        {
            logf("Error at adding a search root: %s", this ? "path too long":"OOM");
            free(this);
            prev->next = NULL;
            return false;
        }
        this->path = ((char*)this) + sizeof(struct search_roots_ll);
        strcpy((char*)this->path, abs_target); /* ok to cast const away here */
        this->next = NULL;
        prev->next = this;
        logf("Added %s to the search roots\n", abs_target);
        return true;
    }
#endif
    return false;
}

static int free_search_roots(struct search_roots_ll * start)
{
    int ret = 0;
    if (start->next)
    {
        ret += free_search_roots(start->next);
        ret += sizeof(struct search_roots_ll);
        free(start->next);
    }
    return ret;
}
#else /* native, simulator */
#define add_search_root(a) do {} while(0)
#define free_search_roots(a) do {} while(0)
#endif