2 * Copyright (C) 2012 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 #include "imv_os_database.h"
18 #include <utils/debug.h>
22 typedef struct private_imv_os_database_t private_imv_os_database_t
;
25 * Private data of a imv_os_database_t object.
28 struct private_imv_os_database_t
{
31 * Public imv_os_database_t interface.
33 imv_os_database_t
public;
42 METHOD(imv_os_database_t
, check_packages
, status_t
,
43 private_imv_os_database_t
*this, imv_os_state_t
*state
,
44 enumerator_t
*package_enumerator
)
46 char *product
, *package
, *release
, *cur_release
;
48 chunk_t os_name
, os_version
, name
, version
;
50 size_t os_version_len
;
51 os_package_state_t package_state
;
53 int count
= 0, count_ok
= 0, count_no_match
= 0, count_blacklist
= 0;
55 status_t status
= SUCCESS
;
58 state
->get_info(state
, &os_type
, &os_name
, &os_version
);
60 if (os_type
== OS_TYPE_ANDROID
)
62 /*no package dependency on Android version */
63 product
= strdup(enum_to_name(os_type_names
, os_type
));
67 /* remove appended platform info */
68 pos
= memchr(os_version
.ptr
, ' ', os_version
.len
);
69 os_version_len
= pos ?
(pos
- os_version
.ptr
) : os_version
.len
;
70 product
= malloc(os_name
.len
+ 1 + os_version_len
+ 1);
71 sprintf(product
, "%.*s %.*s", (int)os_name
.len
, os_name
.ptr
,
72 (int)os_version_len
, os_version
.ptr
);
74 DBG1(DBG_IMV
, "processing installed '%s' packages", product
);
76 /* Get primary key of product */
77 e
= this->db
->query(this->db
,
78 "SELECT id FROM products WHERE name = ?",
79 DB_TEXT
, product
, DB_INT
);
85 if (!e
->enumerate(e
, &pid
))
93 while (package_enumerator
->enumerate(package_enumerator
, &name
, &version
))
95 /* Convert package name chunk to a string */
96 package
= strndup(name
.ptr
, name
.len
);
99 /* Get primary key of package */
100 e
= this->db
->query(this->db
,
101 "SELECT id FROM packages WHERE name = ?",
102 DB_TEXT
, package
, DB_INT
);
109 if (!e
->enumerate(e
, &gid
))
111 /* package not present in database for any product - skip */
112 if (os_type
== OS_TYPE_ANDROID
)
114 DBG2(DBG_IMV
, "package '%s' (%.*s) not found",
115 package
, version
.len
, version
.ptr
);
123 /* Convert package version chunk to a string */
124 release
= strndup(version
.ptr
, version
.len
);
126 /* Enumerate over all acceptable versions */
127 e
= this->db
->query(this->db
,
128 "SELECT release, security FROM versions "
129 "WHERE product = ? AND package = ?",
130 DB_INT
, pid
, DB_INT
, gid
, DB_TEXT
, DB_INT
);
141 while (e
->enumerate(e
, &cur_release
, &package_state
))
144 if (streq(release
, cur_release
) || streq("*", cur_release
))
156 if (package_state
== OS_PACKAGE_STATE_BLACKLIST
)
158 DBG2(DBG_IMV
, "package '%s' (%s) is blacklisted",
161 state
->add_bad_package(state
, package
, package_state
);
165 DBG2(DBG_IMV
, "package '%s' (%s)%N is ok", package
, release
,
166 os_package_state_names
, package_state
);
172 DBG1(DBG_IMV
, "package '%s' (%s) no match", package
, release
);
174 state
->add_bad_package(state
, package
, package_state
);
179 /* package not present in database for this product - skip */
185 state
->set_count(state
, count
, count_no_match
, count_blacklist
, count_ok
);
190 METHOD(imv_os_database_t
, get_device_id
, int,
191 private_imv_os_database_t
*this, chunk_t value
)
196 /* get primary key of device ID */
197 e
= this->db
->query(this->db
, "SELECT id FROM devices WHERE value = ?",
198 DB_BLOB
, value
, DB_INT
);
203 if (e
->enumerate(e
, &id
))
205 /* device ID already exists in database - return primary key */
210 /* register new device ID in database and return primary key */
211 return (this->db
->execute(this->db
, &id
,
212 "INSERT INTO devices (value) VALUES (?)", DB_BLOB
, value
) == 1) ?
216 METHOD(imv_os_database_t
, set_device_info
, void,
217 private_imv_os_database_t
*this, int device_id
, char *os_info
,
218 int count
, int count_update
, int count_blacklist
, u_int flags
)
222 int pid
= 0, last_pid
= 0, last_count_update
= 0, last_count_blacklist
= 0;
226 /* get primary key of OS info string if it exists */
227 e
= this->db
->query(this->db
,
228 "SELECT id FROM products WHERE name = ?", DB_TEXT
, os_info
,
232 e
->enumerate(e
, &pid
);
236 /* if OS ifo string has not been found - register it */
239 this->db
->execute(this->db
, &pid
,
240 "INSERT INTO products (name) VALUES (?)", DB_TEXT
, os_info
);
243 /* get latest device info record if it exists */
244 e
= this->db
->query(this->db
,
245 "SELECT time, product, count_update, count_blacklist, flags "
246 "FROM device_infos WHERE device = ? ORDER BY time DESC",
247 DB_INT
, device_id
, DB_UINT
, DB_INT
, DB_INT
, DB_INT
, DB_UINT
);
250 found
= e
->enumerate(e
, &last_time
, &last_pid
, &last_count_update
,
251 &last_count_blacklist
, &last_flags
);
254 if (found
&& !last_count_update
&& !last_count_blacklist
&& !last_flags
&&
257 /* update device info */
258 this->db
->execute(this->db
, NULL
,
259 "UPDATE device_infos SET time = ?, count = ?, count_update = ?, "
260 "count_blacklist = ?, flags = ? WHERE device = ? AND time = ?",
261 DB_UINT
, time(NULL
), DB_INT
, count
, DB_INT
, count_update
,
262 DB_INT
, count_blacklist
, DB_UINT
, flags
,
263 DB_INT
, device_id
, DB_UINT
, last_time
);
267 /* insert device info */
268 this->db
->execute(this->db
, NULL
,
269 "INSERT INTO device_infos (device, time, product, count, "
270 "count_update, count_blacklist, flags) VALUES (?, ?, ?, ?, ?, ?, ?)",
271 DB_INT
, device_id
, DB_UINT
, time(NULL
), DB_INT
, pid
,
272 DB_INT
, count
, DB_INT
, count_update
, DB_INT
, count_blacklist
,
277 METHOD(imv_os_database_t
, destroy
, void,
278 private_imv_os_database_t
*this)
280 this->db
->destroy(this->db
);
287 imv_os_database_t
*imv_os_database_create(char *uri
)
289 private_imv_os_database_t
*this;
293 .check_packages
= _check_packages
,
294 .get_device_id
= _get_device_id
,
295 .set_device_info
= _set_device_info
,
298 .db
= lib
->db
->create(lib
->db
, uri
),
304 "failed to connect to OS database '%s'", uri
);
309 return &this->public;