aboutsummaryrefslogtreecommitdiff
path: root/src/wheel.c
blob: 4692d0abb163d2a33c2be66de37e7c703cd24222 (plain) (blame)
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include "wheel.h"

struct Wheel *get_wheel_info(const char *basepath, const char *name, char *to_match[], unsigned match_mode) {
    DIR *dp;
    struct dirent *rec;
    struct Wheel *result = NULL;
    char package_path[PATH_MAX];
    char package_name[NAME_MAX];

    strcpy(package_name, name);
    tolower_s(package_name);
    sprintf(package_path, "%s/%s", basepath, package_name);

    dp = opendir(package_path);
    if (!dp) {
        return NULL;
    }

    while ((rec = readdir(dp)) != NULL) {
        if (!strcmp(rec->d_name, ".") || !strcmp(rec->d_name, "..")) {
            continue;
        }
        char filename[NAME_MAX];
        strcpy(filename, rec->d_name);
        char *ext = strstr(filename, ".whl");
        if (ext) {
            *ext = '\0';
        } else {
            // not a wheel file. nothing to do
            continue;
        }

        size_t match = 0;
        size_t pattern_count = 0;
        for (; to_match[pattern_count] != NULL; pattern_count++) {
            if (strstr(filename, to_match[pattern_count])) {
                match++;
            }
        }

        if (!startswith(rec->d_name, name)) {
            continue;
        }

        if (match_mode == WHEEL_MATCH_EXACT && match != pattern_count) {
            continue;
        }

        result = calloc(1, sizeof(*result));
        if (!result) {
            SYSERROR("Unable to allocate %zu bytes for wheel struct", sizeof(*result));
            closedir(dp);
            return NULL;
        }

        result->path_name = realpath(package_path, NULL);
        if (!result->path_name) {
            SYSERROR("Unable to resolve absolute path to %s: %s", filename, strerror(errno));
            wheel_free(&result);
            closedir(dp);
            return NULL;
        }
        result->file_name = strdup(rec->d_name);
        if (!result->file_name) {
            SYSERROR("Unable to allocate bytes for %s: %s", rec->d_name, strerror(errno));
            wheel_free(&result);
            closedir(dp);
            return NULL;
        }

        size_t parts_total;
        char **parts = split(filename, "-", 0);
        if (!parts) {
            // This shouldn't happen unless a wheel file is present in the
            // directory with a malformed file name, or we've managed to
            // exhaust the system's memory
            SYSERROR("%s has no '-' separators! (Delete this file and try again)", filename);
            wheel_free(&result);
            closedir(dp);
            return NULL;
        }

        for (parts_total = 0; parts[parts_total] != NULL; parts_total++);
        if (parts_total == 5) {
            // no build tag
            result->distribution = strdup(parts[0]);
            result->version = strdup(parts[1]);
            result->build_tag = NULL;
            result->python_tag = strdup(parts[2]);
            result->abi_tag = strdup(parts[3]);
            result->platform_tag = strdup(parts[4]);
        } else if (parts_total == 6) {
            // has build tag
            result->distribution = strdup(parts[0]);
            result->version = strdup(parts[1]);
            result->build_tag = strdup(parts[2]);
            result->python_tag = strdup(parts[3]);
            result->abi_tag = strdup(parts[4]);
            result->platform_tag = strdup(parts[5]);
        } else {
            SYSERROR("Unknown wheel name format: %s. Expected 5 or 6 strings "
                     "separated by '-', but got %zu instead", filename, parts_total);
            GENERIC_ARRAY_FREE(parts);
            wheel_free(&result);
            closedir(dp);
            return NULL;
        }
        GENERIC_ARRAY_FREE(parts);
        break;
    }
    closedir(dp);
    return result;
}

void wheel_free(struct Wheel **wheel) {
    struct Wheel *w = (*wheel);
    guard_free(w->path_name);
    guard_free(w->file_name);
    guard_free(w->distribution);
    guard_free(w->version);
    guard_free(w->build_tag);
    guard_free(w->python_tag);
    guard_free(w->abi_tag);
    guard_free(w->python_tag);
    guard_free(w);
}