1 /* aurblup - AUR blacklist updater
3 * Small utility to update the AUR package blacklist. Can be used in a cronjob.
4 * Check the "README" file for details.
15 #define alpm_die(...) die(__VA_ARGS__, alpm_strerror(alpm_errno(handle)));
16 #define mysql_die(...) die(__VA_ARGS__, mysql_error(c));
18 static void die(const char *, ...);
19 static alpm_list_t
*pkglist_append(alpm_list_t
*, const char *);
20 static alpm_list_t
*blacklist_get_pkglist();
21 static void blacklist_add(const char *);
22 static void blacklist_remove(const char *);
23 static void blacklist_sync(alpm_list_t
*, alpm_list_t
*);
24 static alpm_list_t
*dblist_get_pkglist(alpm_list_t
*);
25 static alpm_list_t
*dblist_create(void);
26 static int parse_options(int, char **);
27 static void init(void);
28 static void cleanup(void);
30 static char *mysql_host
= "localhost";
31 static char *mysql_socket
= NULL
;
32 static char *mysql_user
= "aur";
33 static char *mysql_passwd
= "aur";
34 static char *mysql_db
= "AUR";
38 static alpm_handle_t
*handle
;
41 die(const char *format
, ...)
45 va_start(arg
, format
);
46 fprintf(stderr
, "aurblup: ");
47 vfprintf(stderr
, format
, arg
);
55 pkglist_append(alpm_list_t
*pkglist
, const char *pkgname
)
57 int len
= strcspn(pkgname
, "<=>");
59 len
= strlen(pkgname
);
61 char *s
= malloc(len
+ 1);
63 strncpy(s
, pkgname
, len
);
66 if (alpm_list_find_str(pkglist
, s
))
69 pkglist
= alpm_list_add(pkglist
, s
);
75 blacklist_get_pkglist()
79 alpm_list_t
*pkglist
= NULL
;
81 if (mysql_query(c
, "SELECT Name FROM PackageBlacklist"))
82 mysql_die("failed to read blacklist from MySQL database: %s\n");
84 if (!(res
= mysql_store_result(c
)))
85 mysql_die("failed to store MySQL result: %s\n");
87 while ((row
= mysql_fetch_row(res
)))
88 pkglist
= pkglist_append(pkglist
, row
[0]);
90 mysql_free_result(res
);
96 blacklist_add(const char *name
)
98 char *esc
= malloc(strlen(name
) * 2 + 1);
101 mysql_real_escape_string(c
, esc
, name
, strlen(name
));
102 snprintf(query
, 1024, "INSERT INTO PackageBlacklist (Name) "
103 "VALUES ('%s')", esc
);
106 if (mysql_query(c
, query
))
107 mysql_die("failed to query MySQL database (\"%s\"): %s\n", query
);
111 blacklist_remove(const char *name
)
113 char *esc
= malloc(strlen(name
) * 2 + 1);
116 mysql_real_escape_string(c
, esc
, name
, strlen(name
));
117 snprintf(query
, 1024, "DELETE FROM PackageBlacklist WHERE Name = '%s'", esc
);
120 if (mysql_query(c
, query
))
121 mysql_die("failed to query MySQL database (\"%s\"): %s\n", query
);
125 blacklist_sync(alpm_list_t
*pkgs_cur
, alpm_list_t
*pkgs_new
)
127 alpm_list_t
*pkgs_add
, *pkgs_rem
, *p
;
129 pkgs_add
= alpm_list_diff(pkgs_new
, pkgs_cur
, (alpm_list_fn_cmp
)strcmp
);
130 pkgs_rem
= alpm_list_diff(pkgs_cur
, pkgs_new
, (alpm_list_fn_cmp
)strcmp
);
132 if (mysql_query(c
, "START TRANSACTION"))
133 mysql_die("failed to start MySQL transaction: %s\n");
135 for (p
= pkgs_add
; p
; p
= alpm_list_next(p
))
136 blacklist_add(p
->data
);
138 for (p
= pkgs_rem
; p
; p
= alpm_list_next(p
))
139 blacklist_remove(p
->data
);
141 if (mysql_query(c
, "COMMIT"))
142 mysql_die("failed to commit MySQL transaction: %s\n");
144 alpm_list_free(pkgs_add
);
145 alpm_list_free(pkgs_rem
);
149 dblist_get_pkglist(alpm_list_t
*dblist
)
151 alpm_list_t
*d
, *p
, *q
;
152 alpm_list_t
*pkglist
= NULL
;
154 for (d
= dblist
; d
; d
= alpm_list_next(d
)) {
155 alpm_db_t
*db
= d
->data
;
157 if (alpm_trans_init(handle
, 0))
158 alpm_die("failed to initialize ALPM transaction: %s\n");
159 if (alpm_db_update(0, db
) < 0)
160 alpm_die("failed to update ALPM database: %s\n");
161 if (alpm_trans_release(handle
))
162 alpm_die("failed to release ALPM transaction: %s\n");
164 for (p
= alpm_db_get_pkgcache(db
); p
; p
= alpm_list_next(p
)) {
165 alpm_pkg_t
*pkg
= p
->data
;
167 pkglist
= pkglist_append(pkglist
, alpm_pkg_get_name(pkg
));
169 for (q
= alpm_pkg_get_replaces(pkg
); q
; q
= alpm_list_next(q
)) {
170 alpm_depend_t
*replace
= q
->data
;
171 pkglist
= pkglist_append(pkglist
, replace
->name
);
183 alpm_list_t
*dblist
= NULL
;
186 for (i
= 0; i
< sizeof(alpm_repos
) / sizeof(char *); i
++) {
187 if (!alpm_register_syncdb(handle
, alpm_repos
[i
], 0))
188 alpm_die("failed to register sync db \"%s\": %s\n", alpm_repos
[i
]);
191 if (!(dblist
= alpm_get_syncdbs(handle
)))
192 alpm_die("failed to get sync DBs: %s\n");
194 for (d
= dblist
; d
; d
= alpm_list_next(d
)) {
195 alpm_db_t
*db
= d
->data
;
198 snprintf(server
, 1024, ALPM_MIRROR
, alpm_db_get_name(db
));
200 if (alpm_db_add_server(db
, server
))
201 alpm_die("failed to set server \"%s\": %s\n", server
);
207 static int parse_options(int argc
, char **argv
)
211 static const struct option opts
[] = {
212 { "mysql-host", required_argument
, 0, 'h' },
213 { "mysql-socket", required_argument
, 0, 'S' },
214 { "mysql-user", required_argument
, 0, 'u' },
215 { "mysql-passwd", required_argument
, 0, 'p' },
216 { "mysql-db", required_argument
, 0, 'D' },
220 while((opt
= getopt_long(argc
, argv
, "h:S:u:p:D:", opts
, NULL
)) != -1) {
226 mysql_socket
= optarg
;
232 mysql_passwd
= optarg
;
248 enum _alpm_errno_t alpm_err
;
249 if (mysql_library_init(0, NULL
, NULL
))
250 mysql_die("could not initialize MySQL library: %s\n");
251 if (!(c
= mysql_init(NULL
)))
252 mysql_die("failed to setup MySQL client: %s\n");
253 if (!mysql_real_connect(c
, mysql_host
, mysql_user
, mysql_passwd
,
254 mysql_db
, 0, mysql_socket
, 0))
255 mysql_die("failed to initiate MySQL connection to %s: %s\n", mysql_host
);
257 if ((handle
= alpm_initialize("/", ALPM_DBPATH
, &alpm_err
)) == NULL
)
258 die("failed to initialize ALPM: %s\n", alpm_strerror(alpm_err
));
264 alpm_release(handle
);
269 int main(int argc
, char *argv
[])
271 alpm_list_t
*pkgs_cur
, *pkgs_new
;
273 if (!parse_options(argc
, argv
))
278 pkgs_cur
= blacklist_get_pkglist();
279 pkgs_new
= dblist_get_pkglist(dblist_create());
280 blacklist_sync(pkgs_cur
, pkgs_new
);