]>
Commit | Line | Data |
---|---|---|
e2faeb46 AF |
1 | /* |
2 | * be_files.c | |
23229097 | 3 | * |
d37ad048 AG |
4 | * Copyright (c) 2006 by Christian Hamar <krics@linuxforum.hu> |
5 | * Copyright (c) 2006 by Miklos Vajna <vmiklos@frugalware.org> | |
23229097 | 6 | * |
e2faeb46 AF |
7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation; either version 2 of the License, or | |
10 | * (at your option) any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
9781d0d6 | 18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
e2faeb46 AF |
19 | */ |
20 | ||
21 | #include "config.h" | |
869e81e1 | 22 | |
e2faeb46 AF |
23 | #include <unistd.h> |
24 | #include <stdio.h> | |
25 | #include <stdlib.h> | |
26 | #include <errno.h> | |
27 | #include <string.h> | |
0669c9bf | 28 | #include <stdint.h> /* uintmax_t, intmax_t */ |
e2faeb46 AF |
29 | #include <sys/stat.h> |
30 | #include <dirent.h> | |
47622eef AG |
31 | #include <ctype.h> |
32 | #include <time.h> | |
e2faeb46 | 33 | #include <limits.h> /* PATH_MAX */ |
aa942a12 | 34 | #include <locale.h> /* setlocale */ |
869e81e1 DM |
35 | |
36 | /* libalpm */ | |
37 | #include "db.h" | |
38 | #include "alpm_list.h" | |
04600384 | 39 | #include "cache.h" |
e2faeb46 AF |
40 | #include "log.h" |
41 | #include "util.h" | |
e2faeb46 | 42 | #include "alpm.h" |
d37ad048 | 43 | #include "handle.h" |
aa1c0ba9 | 44 | #include "package.h" |
0c2cc108 | 45 | #include "delta.h" |
c244cfec | 46 | #include "deps.h" |
04600384 | 47 | #include "dload.h" |
d37ad048 | 48 | |
e8275fa9 | 49 | |
34e1413d XC |
50 | static int checkdbdir(pmdb_t *db) |
51 | { | |
52 | struct stat buf; | |
72883e3b | 53 | const char *path = _alpm_db_path(db); |
34e1413d XC |
54 | |
55 | if(stat(path, &buf) != 0) { | |
56 | _alpm_log(PM_LOG_DEBUG, "database dir '%s' does not exist, creating it\n", | |
57 | path); | |
58 | if(_alpm_makepath(path) != 0) { | |
59 | RET_ERR(PM_ERR_SYSTEM, -1); | |
60 | } | |
61 | } else if(!S_ISDIR(buf.st_mode)) { | |
1df3b919 | 62 | _alpm_log(PM_LOG_WARNING, _("removing invalid database: %s\n"), path); |
34e1413d XC |
63 | if(unlink(path) != 0 || _alpm_makepath(path) != 0) { |
64 | RET_ERR(PM_ERR_SYSTEM, -1); | |
65 | } | |
66 | } | |
67 | return(0); | |
68 | } | |
69 | ||
04600384 | 70 | /** Update a package database |
63fc9360 SN |
71 | * |
72 | * An update of the package database \a db will be attempted. Unless | |
73 | * \a force is true, the update will only be performed if the remote | |
74 | * database was modified since the last update. | |
75 | * | |
76 | * A transaction is necessary for this operation, in order to obtain a | |
77 | * database lock. During this transaction the front-end will be informed | |
78 | * of the download progress of the database via the download callback. | |
79 | * | |
80 | * Example: | |
81 | * @code | |
82 | * pmdb_t *db; | |
83 | * int result; | |
84 | * db = alpm_list_getdata(alpm_option_get_syncdbs()); | |
8ff3b870 | 85 | * if(alpm_trans_init(0, NULL, NULL, NULL) == 0) { |
63fc9360 SN |
86 | * result = alpm_db_update(0, db); |
87 | * alpm_trans_release(); | |
88 | * | |
89 | * if(result > 0) { | |
90 | * printf("Unable to update database: %s\n", alpm_strerrorlast()); | |
91 | * } else if(result < 0) { | |
92 | * printf("Database already up to date\n"); | |
93 | * } else { | |
94 | * printf("Database updated\n"); | |
95 | * } | |
96 | * } | |
97 | * @endcode | |
98 | * | |
99 | * @ingroup alpm_databases | |
100 | * @note After a successful update, the \link alpm_db_get_pkgcache() | |
101 | * package cache \endlink will be invalidated | |
04600384 DM |
102 | * @param force if true, then forces the update, otherwise update only in case |
103 | * the database isn't up to date | |
104 | * @param db pointer to the package database to update | |
105 | * @return 0 on success, > 0 on error (pm_errno is set accordingly), < 0 if up | |
106 | * to date | |
e8275fa9 | 107 | */ |
04600384 | 108 | int SYMEXPORT alpm_db_update(int force, pmdb_t *db) |
e8275fa9 | 109 | { |
0966c33a | 110 | char *dbfile, *dbfilepath; |
04600384 | 111 | const char *dbpath; |
0966c33a XC |
112 | size_t len; |
113 | ||
04600384 DM |
114 | int ret; |
115 | ||
da648bc2 AG |
116 | ALPM_LOG_FUNC; |
117 | ||
04600384 DM |
118 | /* Sanity checks */ |
119 | ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); | |
120 | ASSERT(db != NULL && db != handle->db_local, RET_ERR(PM_ERR_WRONG_ARGS, -1)); | |
121 | /* Verify we are in a transaction. This is done _mainly_ because we need a DB | |
122 | * lock - if we update without a db lock, we may kludge some other pacman | |
123 | * process that _has_ a lock. | |
124 | */ | |
125 | ASSERT(handle->trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); | |
126 | ASSERT(handle->trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); | |
04600384 DM |
127 | |
128 | if(!alpm_list_find_ptr(handle->dbs_sync, db)) { | |
129 | RET_ERR(PM_ERR_DB_NOT_FOUND, -1); | |
130 | } | |
131 | ||
0966c33a XC |
132 | len = strlen(db->treename) + strlen(DBEXT) + 1; |
133 | MALLOC(dbfile, len, RET_ERR(PM_ERR_MEMORY, -1)); | |
134 | sprintf(dbfile, "%s" DBEXT, db->treename); | |
135 | ||
04600384 DM |
136 | dbpath = alpm_option_get_dbpath(); |
137 | ||
d2dbb04a | 138 | ret = _alpm_download_single_file(dbfile, db->servers, dbpath, force); |
0966c33a | 139 | free(dbfile); |
04600384 DM |
140 | |
141 | if(ret == 1) { | |
d2dbb04a | 142 | /* files match, do nothing */ |
04600384 DM |
143 | pm_errno = 0; |
144 | return(1); | |
145 | } else if(ret == -1) { | |
146 | /* pm_errno was set by the download code */ | |
147 | _alpm_log(PM_LOG_DEBUG, "failed to sync db: %s\n", alpm_strerrorlast()); | |
148 | return(-1); | |
149 | } else { | |
72883e3b | 150 | const char *syncdbpath = _alpm_db_path(db); |
04600384 | 151 | /* remove the old dir */ |
72883e3b | 152 | if(_alpm_rmrf(syncdbpath) != 0) { |
34e1413d XC |
153 | _alpm_log(PM_LOG_ERROR, _("could not remove database %s\n"), db->treename); |
154 | RET_ERR(PM_ERR_DB_REMOVE, -1); | |
d2dbb04a DM |
155 | } else { |
156 | _alpm_log(PM_LOG_DEBUG, "database dir %s removed\n", _alpm_db_path(db)); | |
04600384 DM |
157 | } |
158 | ||
d2dbb04a | 159 | |
04600384 DM |
160 | /* Cache needs to be rebuilt */ |
161 | _alpm_db_free_pkgcache(db); | |
e8275fa9 | 162 | |
0966c33a XC |
163 | /* form the path to the db location */ |
164 | len = strlen(dbpath) + strlen(db->treename) + strlen(DBEXT) + 1; | |
165 | MALLOC(dbfilepath, len, RET_ERR(PM_ERR_MEMORY, -1)); | |
166 | sprintf(dbfilepath, "%s%s" DBEXT, dbpath, db->treename); | |
167 | ||
04600384 | 168 | /* uncompress the sync database */ |
34e1413d | 169 | checkdbdir(db); |
14ab02e2 | 170 | ret = _alpm_unpack(dbfilepath, syncdbpath, NULL, 0); |
0966c33a XC |
171 | if(ret) { |
172 | free(dbfilepath); | |
04600384 DM |
173 | RET_ERR(PM_ERR_SYSTEM, -1); |
174 | } | |
0966c33a | 175 | free(dbfilepath); |
e8275fa9 AG |
176 | } |
177 | ||
04600384 | 178 | return(0); |
e8275fa9 AG |
179 | } |
180 | ||
e2faeb46 | 181 | |
ccc1c731 | 182 | static int splitname(const char *target, pmpkg_t *pkg) |
f7bbfe40 DM |
183 | { |
184 | /* the format of a db entry is as follows: | |
185 | * package-version-rel/ | |
186 | * package name can contain hyphens, so parse from the back- go back | |
187 | * two hyphens and we have split the version from the name. | |
188 | */ | |
189 | char *tmp, *p, *q; | |
190 | ||
ccc1c731 | 191 | if(target == NULL || pkg == NULL) { |
f7bbfe40 DM |
192 | return(-1); |
193 | } | |
ccc1c731 | 194 | STRDUP(tmp, target, RET_ERR(PM_ERR_MEMORY, -1)); |
f7bbfe40 DM |
195 | p = tmp + strlen(tmp); |
196 | ||
197 | /* do the magic parsing- find the beginning of the version string | |
198 | * by doing two iterations of same loop to lop off two hyphens */ | |
199 | for(q = --p; *q && *q != '-'; q--); | |
200 | for(p = --q; *p && *p != '-'; p--); | |
201 | if(*p != '-' || p == tmp) { | |
202 | return(-1); | |
203 | } | |
204 | ||
205 | /* copy into fields and return */ | |
ccc1c731 DM |
206 | if(pkg->version) { |
207 | FREE(pkg->version); | |
f7bbfe40 | 208 | } |
ccc1c731 | 209 | STRDUP(pkg->version, p+1, RET_ERR(PM_ERR_MEMORY, -1)); |
f7bbfe40 DM |
210 | /* insert a terminator at the end of the name (on hyphen)- then copy it */ |
211 | *p = '\0'; | |
ccc1c731 DM |
212 | if(pkg->name) { |
213 | FREE(pkg->name); | |
f7bbfe40 | 214 | } |
ccc1c731 | 215 | STRDUP(pkg->name, tmp, RET_ERR(PM_ERR_MEMORY, -1)); |
f7bbfe40 DM |
216 | |
217 | free(tmp); | |
218 | return(0); | |
219 | } | |
220 | ||
f6711472 | 221 | int _alpm_db_populate(pmdb_t *db) |
e2faeb46 | 222 | { |
f6711472 | 223 | int count = 0; |
e2faeb46 AF |
224 | struct dirent *ent = NULL; |
225 | struct stat sbuf; | |
226 | char path[PATH_MAX]; | |
72883e3b | 227 | const char *dbpath; |
14230869 | 228 | DIR *dbdir; |
e2faeb46 | 229 | |
da648bc2 AG |
230 | ALPM_LOG_FUNC; |
231 | ||
f6711472 | 232 | ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); |
e2faeb46 | 233 | |
72883e3b DM |
234 | dbpath = _alpm_db_path(db); |
235 | dbdir = opendir(dbpath); | |
14230869 | 236 | if(dbdir == NULL) { |
34e1413d | 237 | return(0); |
14230869 XC |
238 | } |
239 | while((ent = readdir(dbdir)) != NULL) { | |
f6711472 XC |
240 | const char *name = ent->d_name; |
241 | pmpkg_t *pkg; | |
ccc1c731 | 242 | |
f6711472 XC |
243 | if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { |
244 | continue; | |
245 | } | |
246 | /* stat the entry, make sure it's a directory */ | |
72883e3b | 247 | snprintf(path, PATH_MAX, "%s%s", dbpath, name); |
f6711472 XC |
248 | if(stat(path, &sbuf) != 0 || !S_ISDIR(sbuf.st_mode)) { |
249 | continue; | |
e2faeb46 | 250 | } |
0adceabe | 251 | |
dd98aa85 | 252 | pkg = _alpm_pkg_new(); |
0adceabe | 253 | if(pkg == NULL) { |
14230869 | 254 | closedir(dbdir); |
f6711472 | 255 | return(-1); |
e2faeb46 | 256 | } |
f7bbfe40 | 257 | /* split the db entry name */ |
f6711472 | 258 | if(splitname(name, pkg) != 0) { |
f7bbfe40 | 259 | _alpm_log(PM_LOG_ERROR, _("invalid name for database entry '%s'\n"), |
f6711472 XC |
260 | name); |
261 | _alpm_pkg_free(pkg); | |
9d9ac66b | 262 | continue; |
0adceabe | 263 | } |
7f5dada8 | 264 | |
444ff956 NG |
265 | /* duplicated database entries are not allowed */ |
266 | if(_alpm_pkg_find(db->pkgcache, pkg->name)) { | |
267 | _alpm_log(PM_LOG_ERROR, _("duplicated database entry '%s'\n"), pkg->name); | |
268 | _alpm_pkg_free(pkg); | |
269 | continue; | |
270 | } | |
271 | ||
7f5dada8 AG |
272 | /* explicitly read with only 'BASE' data, accessors will handle the rest */ |
273 | if(_alpm_db_read(db, pkg, INFRQ_BASE) == -1) { | |
f6711472 | 274 | _alpm_log(PM_LOG_ERROR, _("corrupted database entry '%s'\n"), name); |
a3491224 | 275 | _alpm_pkg_free(pkg); |
f6711472 | 276 | continue; |
e2faeb46 | 277 | } |
f6711472 XC |
278 | pkg->origin = PKG_FROM_CACHE; |
279 | pkg->origin_data.db = db; | |
280 | /* add to the collection */ | |
281 | _alpm_log(PM_LOG_FUNCTION, "adding '%s' to package cache for db '%s'\n", | |
282 | pkg->name, db->treename); | |
283 | db->pkgcache = alpm_list_add(db->pkgcache, pkg); | |
284 | count++; | |
e2faeb46 AF |
285 | } |
286 | ||
14230869 | 287 | closedir(dbdir); |
f6711472 XC |
288 | db->pkgcache = alpm_list_msort(db->pkgcache, count, _alpm_pkg_cmp); |
289 | return(count); | |
e2faeb46 AF |
290 | } |
291 | ||
0966c33a XC |
292 | /* Note: the return value must be freed by the caller */ |
293 | static char *get_pkgpath(pmdb_t *db, pmpkg_t *info) | |
294 | { | |
295 | size_t len; | |
296 | char *pkgpath; | |
72883e3b | 297 | const char *dbpath; |
0966c33a | 298 | |
72883e3b DM |
299 | dbpath = _alpm_db_path(db); |
300 | len = strlen(dbpath) + strlen(info->name) + strlen(info->version) + 3; | |
0966c33a | 301 | MALLOC(pkgpath, len, RET_ERR(PM_ERR_MEMORY, NULL)); |
72883e3b | 302 | sprintf(pkgpath, "%s%s-%s/", dbpath, info->name, info->version); |
0966c33a XC |
303 | return(pkgpath); |
304 | } | |
305 | ||
a5f630fd | 306 | int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) |
e2faeb46 AF |
307 | { |
308 | FILE *fp = NULL; | |
7fccfc78 | 309 | char path[PATH_MAX]; |
86b136bb | 310 | char line[513]; |
4281a1a7 | 311 | int sline = sizeof(line)-1; |
0966c33a | 312 | char *pkgpath = NULL; |
e2faeb46 | 313 | |
da648bc2 AG |
314 | ALPM_LOG_FUNC; |
315 | ||
e8275fa9 AG |
316 | if(db == NULL) { |
317 | RET_ERR(PM_ERR_DB_NULL, -1); | |
318 | } | |
319 | ||
ccc1c731 | 320 | if(info == NULL || info->name == NULL || info->version == NULL) { |
5c9eec55 | 321 | _alpm_log(PM_LOG_DEBUG, "invalid package entry provided to _alpm_db_read, skipping\n"); |
e2faeb46 AF |
322 | return(-1); |
323 | } | |
324 | ||
3bf918dc | 325 | if(info->origin == PKG_FROM_FILE) { |
5c9eec55 | 326 | _alpm_log(PM_LOG_DEBUG, "request to read database info for a file-based package '%s', skipping...\n", info->name); |
3bf918dc AG |
327 | return(-1); |
328 | } | |
329 | ||
ba1806f5 DM |
330 | /* bitmask logic here: |
331 | * infolevel: 00001111 | |
332 | * inforeq: 00010100 | |
333 | * & result: 00000100 | |
334 | * == to inforeq? nope, we need to load more info. */ | |
335 | if((info->infolevel & inforeq) == inforeq) { | |
986409f9 AG |
336 | /* already loaded this info, do nothing */ |
337 | return(0); | |
338 | } | |
4abd710e DM |
339 | _alpm_log(PM_LOG_FUNCTION, "loading package data for %s : level=0x%x\n", |
340 | info->name, inforeq); | |
3bf918dc | 341 | |
aa1c0ba9 | 342 | /* clear out 'line', to be certain - and to make valgrind happy */ |
4281a1a7 | 343 | memset(line, 0, sline+1); |
aa1c0ba9 | 344 | |
0966c33a XC |
345 | pkgpath = get_pkgpath(db, info); |
346 | ||
29bf6814 | 347 | if(access(pkgpath, F_OK)) { |
e2faeb46 | 348 | /* directory doesn't exist or can't be opened */ |
5c9eec55 | 349 | _alpm_log(PM_LOG_DEBUG, "cannot find '%s-%s' in db '%s'\n", |
ea1fef69 | 350 | info->name, info->version, db->treename); |
0966c33a | 351 | goto error; |
e2faeb46 AF |
352 | } |
353 | ||
354 | /* DESC */ | |
355 | if(inforeq & INFRQ_DESC) { | |
0966c33a | 356 | snprintf(path, PATH_MAX, "%sdesc", pkgpath); |
170d6319 | 357 | if((fp = fopen(path, "r")) == NULL) { |
5c9eec55 | 358 | _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno)); |
e2faeb46 AF |
359 | goto error; |
360 | } | |
361 | while(!feof(fp)) { | |
362 | if(fgets(line, 256, fp) == NULL) { | |
363 | break; | |
364 | } | |
365 | _alpm_strtrim(line); | |
da1c11cc | 366 | if(strcmp(line, "%NAME%") == 0) { |
4281a1a7 | 367 | if(fgets(line, sline, fp) == NULL) { |
da1c11cc NG |
368 | goto error; |
369 | } | |
370 | if(strcmp(_alpm_strtrim(line), info->name) != 0) { | |
371 | _alpm_log(PM_LOG_ERROR, _("%s database is inconsistent: name " | |
372 | "mismatch on package %s\n"), db->treename, info->name); | |
373 | } | |
374 | } else if(strcmp(line, "%VERSION%") == 0) { | |
4281a1a7 | 375 | if(fgets(line, sline, fp) == NULL) { |
da1c11cc NG |
376 | goto error; |
377 | } | |
378 | if(strcmp(_alpm_strtrim(line), info->version) != 0) { | |
379 | _alpm_log(PM_LOG_ERROR, _("%s database is inconsistent: version " | |
380 | "mismatch on package %s\n"), db->treename, info->name); | |
381 | } | |
382 | } else if(strcmp(line, "%FILENAME%") == 0) { | |
4281a1a7 | 383 | if(fgets(line, sline, fp) == NULL) { |
986409f9 AG |
384 | goto error; |
385 | } | |
ccc1c731 | 386 | STRDUP(info->filename, _alpm_strtrim(line), goto error); |
da1c11cc | 387 | } else if(strcmp(line, "%DESC%") == 0) { |
4281a1a7 | 388 | if(fgets(line, sline, fp) == NULL) { |
af48c695 AG |
389 | goto error; |
390 | } | |
ccc1c731 DM |
391 | STRDUP(info->desc, _alpm_strtrim(line), goto error); |
392 | } else if(strcmp(line, "%GROUPS%") == 0) { | |
4281a1a7 | 393 | while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { |
ccc1c731 DM |
394 | char *linedup; |
395 | STRDUP(linedup, _alpm_strtrim(line), goto error); | |
396 | info->groups = alpm_list_add(info->groups, linedup); | |
e2faeb46 | 397 | } |
ccc1c731 | 398 | } else if(strcmp(line, "%URL%") == 0) { |
4281a1a7 | 399 | if(fgets(line, sline, fp) == NULL) { |
e2faeb46 AF |
400 | goto error; |
401 | } | |
ccc1c731 DM |
402 | STRDUP(info->url, _alpm_strtrim(line), goto error); |
403 | } else if(strcmp(line, "%LICENSE%") == 0) { | |
4281a1a7 | 404 | while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { |
ccc1c731 DM |
405 | char *linedup; |
406 | STRDUP(linedup, _alpm_strtrim(line), goto error); | |
407 | info->licenses = alpm_list_add(info->licenses, linedup); | |
e2faeb46 | 408 | } |
ccc1c731 | 409 | } else if(strcmp(line, "%ARCH%") == 0) { |
4281a1a7 | 410 | if(fgets(line, sline, fp) == NULL) { |
e2faeb46 AF |
411 | goto error; |
412 | } | |
ccc1c731 DM |
413 | STRDUP(info->arch, _alpm_strtrim(line), goto error); |
414 | } else if(strcmp(line, "%BUILDDATE%") == 0) { | |
4281a1a7 | 415 | if(fgets(line, sline, fp) == NULL) { |
e2faeb46 AF |
416 | goto error; |
417 | } | |
ccc1c731 | 418 | _alpm_strtrim(line); |
47622eef | 419 | |
caea098c | 420 | char first = tolower((unsigned char)line[0]); |
47622eef | 421 | if(first > 'a' && first < 'z') { |
ed848b1c | 422 | struct tm tmp_tm = {0}; /* initialize to null in case of failure */ |
e6673544 | 423 | setlocale(LC_TIME, "C"); |
ccc1c731 | 424 | strptime(line, "%a %b %e %H:%M:%S %Y", &tmp_tm); |
47622eef | 425 | info->builddate = mktime(&tmp_tm); |
e6673544 | 426 | setlocale(LC_TIME, ""); |
47622eef | 427 | } else { |
ccc1c731 | 428 | info->builddate = atol(line); |
47622eef | 429 | } |
ccc1c731 | 430 | } else if(strcmp(line, "%INSTALLDATE%") == 0) { |
4281a1a7 | 431 | if(fgets(line, sline, fp) == NULL) { |
e2faeb46 AF |
432 | goto error; |
433 | } | |
ccc1c731 | 434 | _alpm_strtrim(line); |
47622eef | 435 | |
caea098c | 436 | char first = tolower((unsigned char)line[0]); |
47622eef | 437 | if(first > 'a' && first < 'z') { |
ed848b1c | 438 | struct tm tmp_tm = {0}; /* initialize to null in case of failure */ |
e6673544 | 439 | setlocale(LC_TIME, "C"); |
ccc1c731 | 440 | strptime(line, "%a %b %e %H:%M:%S %Y", &tmp_tm); |
47622eef | 441 | info->installdate = mktime(&tmp_tm); |
e6673544 | 442 | setlocale(LC_TIME, ""); |
47622eef | 443 | } else { |
ccc1c731 | 444 | info->installdate = atol(line); |
47622eef | 445 | } |
ccc1c731 | 446 | } else if(strcmp(line, "%PACKAGER%") == 0) { |
4281a1a7 | 447 | if(fgets(line, sline, fp) == NULL) { |
e2faeb46 AF |
448 | goto error; |
449 | } | |
ccc1c731 DM |
450 | STRDUP(info->packager, _alpm_strtrim(line), goto error); |
451 | } else if(strcmp(line, "%REASON%") == 0) { | |
4281a1a7 | 452 | if(fgets(line, sline, fp) == NULL) { |
e2faeb46 AF |
453 | goto error; |
454 | } | |
f7192b59 | 455 | info->reason = (pmpkgreason_t)atol(_alpm_strtrim(line)); |
ccc1c731 | 456 | } else if(strcmp(line, "%SIZE%") == 0 || strcmp(line, "%CSIZE%") == 0) { |
e2faeb46 AF |
457 | /* NOTE: the CSIZE and SIZE fields both share the "size" field |
458 | * in the pkginfo_t struct. This can be done b/c CSIZE | |
459 | * is currently only used in sync databases, and SIZE is | |
460 | * only used in local databases. | |
461 | */ | |
4281a1a7 | 462 | if(fgets(line, sline, fp) == NULL) { |
e2faeb46 AF |
463 | goto error; |
464 | } | |
ccc1c731 | 465 | info->size = atol(_alpm_strtrim(line)); |
5e12d3de DM |
466 | /* also store this value to isize if isize is unset */ |
467 | if(info->isize == 0) { | |
ccc1c731 | 468 | info->isize = info->size; |
5e12d3de | 469 | } |
ccc1c731 | 470 | } else if(strcmp(line, "%ISIZE%") == 0) { |
986409f9 | 471 | /* ISIZE (installed size) tag only appears in sync repositories, |
d37ad048 | 472 | * not the local one. */ |
4281a1a7 | 473 | if(fgets(line, sline, fp) == NULL) { |
d37ad048 AG |
474 | goto error; |
475 | } | |
ccc1c731 DM |
476 | info->isize = atol(_alpm_strtrim(line)); |
477 | } else if(strcmp(line, "%MD5SUM%") == 0) { | |
e2faeb46 AF |
478 | /* MD5SUM tag only appears in sync repositories, |
479 | * not the local one. */ | |
4281a1a7 | 480 | if(fgets(line, sline, fp) == NULL) { |
e2faeb46 AF |
481 | goto error; |
482 | } | |
ccc1c731 DM |
483 | STRDUP(info->md5sum, _alpm_strtrim(line), goto error); |
484 | } else if(strcmp(line, "%REPLACES%") == 0) { | |
4281a1a7 | 485 | while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { |
ccc1c731 DM |
486 | char *linedup; |
487 | STRDUP(linedup, _alpm_strtrim(line), goto error); | |
488 | info->replaces = alpm_list_add(info->replaces, linedup); | |
e2faeb46 | 489 | } |
ccc1c731 | 490 | } else if(strcmp(line, "%FORCE%") == 0) { |
e2faeb46 AF |
491 | info->force = 1; |
492 | } | |
493 | } | |
494 | fclose(fp); | |
495 | fp = NULL; | |
496 | } | |
497 | ||
498 | /* FILES */ | |
499 | if(inforeq & INFRQ_FILES) { | |
0966c33a | 500 | snprintf(path, PATH_MAX, "%sfiles", pkgpath); |
170d6319 | 501 | if((fp = fopen(path, "r")) == NULL) { |
5c9eec55 | 502 | _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno)); |
e2faeb46 AF |
503 | goto error; |
504 | } | |
505 | while(fgets(line, 256, fp)) { | |
506 | _alpm_strtrim(line); | |
ccc1c731 | 507 | if(strcmp(line, "%FILES%") == 0) { |
4281a1a7 | 508 | while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { |
ccc1c731 DM |
509 | char *linedup; |
510 | STRDUP(linedup, _alpm_strtrim(line), goto error); | |
511 | info->files = alpm_list_add(info->files, linedup); | |
e2faeb46 | 512 | } |
ccc1c731 | 513 | } else if(strcmp(line, "%BACKUP%") == 0) { |
4281a1a7 | 514 | while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { |
ccc1c731 DM |
515 | char *linedup; |
516 | STRDUP(linedup, _alpm_strtrim(line), goto error); | |
517 | info->backup = alpm_list_add(info->backup, linedup); | |
e2faeb46 AF |
518 | } |
519 | } | |
520 | } | |
521 | fclose(fp); | |
522 | fp = NULL; | |
523 | } | |
524 | ||
525 | /* DEPENDS */ | |
526 | if(inforeq & INFRQ_DEPENDS) { | |
0966c33a | 527 | snprintf(path, PATH_MAX, "%sdepends", pkgpath); |
170d6319 | 528 | if((fp = fopen(path, "r")) == NULL) { |
5c9eec55 | 529 | _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno)); |
e2faeb46 AF |
530 | goto error; |
531 | } | |
532 | while(!feof(fp)) { | |
533 | fgets(line, 255, fp); | |
534 | _alpm_strtrim(line); | |
ccc1c731 | 535 | if(strcmp(line, "%DEPENDS%") == 0) { |
4281a1a7 | 536 | while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { |
b2914bf0 | 537 | pmdepend_t *dep = _alpm_splitdep(_alpm_strtrim(line)); |
c244cfec | 538 | info->depends = alpm_list_add(info->depends, dep); |
e2faeb46 | 539 | } |
ccc1c731 | 540 | } else if(strcmp(line, "%OPTDEPENDS%") == 0) { |
4281a1a7 | 541 | while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { |
ccc1c731 DM |
542 | char *linedup; |
543 | STRDUP(linedup, _alpm_strtrim(line), goto error); | |
544 | info->optdepends = alpm_list_add(info->optdepends, linedup); | |
fc0e83f0 | 545 | } |
ccc1c731 | 546 | } else if(strcmp(line, "%CONFLICTS%") == 0) { |
4281a1a7 | 547 | while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { |
ccc1c731 DM |
548 | char *linedup; |
549 | STRDUP(linedup, _alpm_strtrim(line), goto error); | |
550 | info->conflicts = alpm_list_add(info->conflicts, linedup); | |
e2faeb46 | 551 | } |
ccc1c731 | 552 | } else if(strcmp(line, "%PROVIDES%") == 0) { |
4281a1a7 | 553 | while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { |
ccc1c731 DM |
554 | char *linedup; |
555 | STRDUP(linedup, _alpm_strtrim(line), goto error); | |
556 | info->provides = alpm_list_add(info->provides, linedup); | |
e2faeb46 | 557 | } |
13e21110 | 558 | } |
e2faeb46 AF |
559 | } |
560 | fclose(fp); | |
561 | fp = NULL; | |
562 | } | |
563 | ||
0c2cc108 NJ |
564 | /* DELTAS */ |
565 | if(inforeq & INFRQ_DELTAS) { | |
0966c33a | 566 | snprintf(path, PATH_MAX, "%sdeltas", pkgpath); |
0c2cc108 NJ |
567 | if((fp = fopen(path, "r"))) { |
568 | while(!feof(fp)) { | |
569 | fgets(line, 255, fp); | |
570 | _alpm_strtrim(line); | |
ccc1c731 | 571 | if(strcmp(line, "%DELTAS%") == 0) { |
4281a1a7 | 572 | while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { |
b99bebc0 DM |
573 | pmdelta_t *delta = _alpm_delta_parse(line); |
574 | if(delta) { | |
575 | info->deltas = alpm_list_add(info->deltas, delta); | |
576 | } | |
0c2cc108 NJ |
577 | } |
578 | } | |
579 | } | |
580 | fclose(fp); | |
581 | fp = NULL; | |
582 | } | |
583 | } | |
584 | ||
e2faeb46 | 585 | /* INSTALL */ |
aa1c0ba9 | 586 | if(inforeq & INFRQ_SCRIPTLET) { |
0966c33a | 587 | snprintf(path, PATH_MAX, "%sinstall", pkgpath); |
29bf6814 | 588 | if(access(path, F_OK) == 0) { |
e2faeb46 AF |
589 | info->scriptlet = 1; |
590 | } | |
591 | } | |
592 | ||
593 | /* internal */ | |
594 | info->infolevel |= inforeq; | |
595 | ||
0966c33a | 596 | free(pkgpath); |
e2faeb46 AF |
597 | return(0); |
598 | ||
599 | error: | |
0966c33a | 600 | free(pkgpath); |
e2faeb46 AF |
601 | if(fp) { |
602 | fclose(fp); | |
603 | } | |
604 | return(-1); | |
605 | } | |
606 | ||
a73ad4f0 AM |
607 | int _alpm_db_prepare(pmdb_t *db, pmpkg_t *info) |
608 | { | |
609 | mode_t oldmask; | |
610 | int retval = 0; | |
611 | char *pkgpath = NULL; | |
612 | ||
34e1413d XC |
613 | if(checkdbdir(db) != 0) { |
614 | return(-1); | |
615 | } | |
a73ad4f0 | 616 | |
34e1413d | 617 | oldmask = umask(0000); |
a73ad4f0 AM |
618 | pkgpath = get_pkgpath(db, info); |
619 | ||
620 | if((retval = mkdir(pkgpath, 0755)) != 0) { | |
34e1413d XC |
621 | _alpm_log(PM_LOG_ERROR, _("could not create directory %s: %s\n"), |
622 | pkgpath, strerror(errno)); | |
a73ad4f0 AM |
623 | } |
624 | ||
625 | free(pkgpath); | |
626 | umask(oldmask); | |
627 | ||
628 | return(retval); | |
629 | } | |
630 | ||
a5f630fd | 631 | int _alpm_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) |
e2faeb46 AF |
632 | { |
633 | FILE *fp = NULL; | |
634 | char path[PATH_MAX]; | |
635 | mode_t oldmask; | |
61670172 | 636 | alpm_list_t *lp = NULL; |
e2faeb46 AF |
637 | int retval = 0; |
638 | int local = 0; | |
0966c33a | 639 | char *pkgpath = NULL; |
e2faeb46 | 640 | |
da648bc2 AG |
641 | ALPM_LOG_FUNC; |
642 | ||
e2faeb46 AF |
643 | if(db == NULL || info == NULL) { |
644 | return(-1); | |
645 | } | |
646 | ||
0966c33a XC |
647 | pkgpath = get_pkgpath(db, info); |
648 | ||
e2faeb46 | 649 | /* make sure we have a sane umask */ |
a73ad4f0 | 650 | oldmask = umask(0022); |
e2faeb46 AF |
651 | |
652 | if(strcmp(db->treename, "local") == 0) { | |
653 | local = 1; | |
654 | } | |
af48c695 | 655 | |
e2faeb46 AF |
656 | /* DESC */ |
657 | if(inforeq & INFRQ_DESC) { | |
5c9eec55 | 658 | _alpm_log(PM_LOG_DEBUG, "writing %s-%s DESC information back to db\n", |
ea1fef69 | 659 | info->name, info->version); |
0966c33a | 660 | snprintf(path, PATH_MAX, "%sdesc", pkgpath); |
e2faeb46 | 661 | if((fp = fopen(path, "w")) == NULL) { |
5c9eec55 | 662 | _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno)); |
170d6319 | 663 | retval = -1; |
e2faeb46 AF |
664 | goto cleanup; |
665 | } | |
666 | fprintf(fp, "%%NAME%%\n%s\n\n" | |
af48c695 | 667 | "%%VERSION%%\n%s\n\n", info->name, info->version); |
ccc1c731 | 668 | if(info->desc) { |
af48c695 AG |
669 | fprintf(fp, "%%DESC%%\n" |
670 | "%s\n\n", info->desc); | |
e2faeb46 AF |
671 | } |
672 | if(info->groups) { | |
673 | fputs("%GROUPS%\n", fp); | |
674 | for(lp = info->groups; lp; lp = lp->next) { | |
675 | fprintf(fp, "%s\n", (char *)lp->data); | |
676 | } | |
677 | fprintf(fp, "\n"); | |
678 | } | |
b262ddb2 XC |
679 | if(info->replaces) { |
680 | fputs("%REPLACES%\n", fp); | |
681 | for(lp = info->replaces; lp; lp = lp->next) { | |
682 | fprintf(fp, "%s\n", (char *)lp->data); | |
683 | } | |
684 | fprintf(fp, "\n"); | |
685 | } | |
686 | if(info->force) { | |
687 | fprintf(fp, "%%FORCE%%\n\n"); | |
688 | } | |
e2faeb46 | 689 | if(local) { |
ccc1c731 | 690 | if(info->url) { |
e2faeb46 | 691 | fprintf(fp, "%%URL%%\n" |
af48c695 | 692 | "%s\n\n", info->url); |
e2faeb46 | 693 | } |
7f5dada8 | 694 | if(info->licenses) { |
e2faeb46 | 695 | fputs("%LICENSE%\n", fp); |
7f5dada8 | 696 | for(lp = info->licenses; lp; lp = lp->next) { |
e2faeb46 AF |
697 | fprintf(fp, "%s\n", (char *)lp->data); |
698 | } | |
699 | fprintf(fp, "\n"); | |
700 | } | |
ccc1c731 | 701 | if(info->arch) { |
e2faeb46 | 702 | fprintf(fp, "%%ARCH%%\n" |
af48c695 | 703 | "%s\n\n", info->arch); |
e2faeb46 | 704 | } |
47622eef | 705 | if(info->builddate) { |
e2faeb46 | 706 | fprintf(fp, "%%BUILDDATE%%\n" |
bd15c23e | 707 | "%ju\n\n", (uintmax_t)info->builddate); |
e2faeb46 | 708 | } |
47622eef | 709 | if(info->installdate) { |
e2faeb46 | 710 | fprintf(fp, "%%INSTALLDATE%%\n" |
bd15c23e | 711 | "%ju\n\n", (uintmax_t)info->installdate); |
e2faeb46 | 712 | } |
ccc1c731 | 713 | if(info->packager) { |
e2faeb46 | 714 | fprintf(fp, "%%PACKAGER%%\n" |
af48c695 | 715 | "%s\n\n", info->packager); |
e2faeb46 | 716 | } |
0669c9bf | 717 | if(info->isize) { |
38784a7e | 718 | /* only write installed size, csize is irrelevant once installed */ |
e2faeb46 | 719 | fprintf(fp, "%%SIZE%%\n" |
9519d22d | 720 | "%jd\n\n", (intmax_t)info->isize); |
e2faeb46 AF |
721 | } |
722 | if(info->reason) { | |
723 | fprintf(fp, "%%REASON%%\n" | |
af48c695 | 724 | "%u\n\n", info->reason); |
e2faeb46 AF |
725 | } |
726 | } else { | |
727 | if(info->size) { | |
728 | fprintf(fp, "%%CSIZE%%\n" | |
9519d22d | 729 | "%jd\n\n", (intmax_t)info->size); |
e2faeb46 | 730 | } |
986409f9 AG |
731 | if(info->isize) { |
732 | fprintf(fp, "%%ISIZE%%\n" | |
9519d22d | 733 | "%jd\n\n", (intmax_t)info->isize); |
d37ad048 | 734 | } |
ba67fdae | 735 | if(info->md5sum) { |
e2faeb46 | 736 | fprintf(fp, "%%MD5SUM%%\n" |
af48c695 | 737 | "%s\n\n", info->md5sum); |
e2faeb46 AF |
738 | } |
739 | } | |
740 | fclose(fp); | |
741 | fp = NULL; | |
742 | } | |
743 | ||
744 | /* FILES */ | |
745 | if(local && (inforeq & INFRQ_FILES)) { | |
5c9eec55 | 746 | _alpm_log(PM_LOG_DEBUG, "writing %s-%s FILES information back to db\n", |
ea1fef69 | 747 | info->name, info->version); |
0966c33a | 748 | snprintf(path, PATH_MAX, "%sfiles", pkgpath); |
e2faeb46 | 749 | if((fp = fopen(path, "w")) == NULL) { |
5c9eec55 | 750 | _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno)); |
e2faeb46 AF |
751 | retval = -1; |
752 | goto cleanup; | |
753 | } | |
754 | if(info->files) { | |
755 | fprintf(fp, "%%FILES%%\n"); | |
756 | for(lp = info->files; lp; lp = lp->next) { | |
757 | fprintf(fp, "%s\n", (char *)lp->data); | |
758 | } | |
759 | fprintf(fp, "\n"); | |
760 | } | |
761 | if(info->backup) { | |
762 | fprintf(fp, "%%BACKUP%%\n"); | |
763 | for(lp = info->backup; lp; lp = lp->next) { | |
764 | fprintf(fp, "%s\n", (char *)lp->data); | |
765 | } | |
766 | fprintf(fp, "\n"); | |
767 | } | |
768 | fclose(fp); | |
769 | fp = NULL; | |
770 | } | |
771 | ||
772 | /* DEPENDS */ | |
773 | if(inforeq & INFRQ_DEPENDS) { | |
5c9eec55 | 774 | _alpm_log(PM_LOG_DEBUG, "writing %s-%s DEPENDS information back to db\n", |
ea1fef69 | 775 | info->name, info->version); |
0966c33a | 776 | snprintf(path, PATH_MAX, "%sdepends", pkgpath); |
e2faeb46 | 777 | if((fp = fopen(path, "w")) == NULL) { |
5c9eec55 | 778 | _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno)); |
e2faeb46 AF |
779 | retval = -1; |
780 | goto cleanup; | |
781 | } | |
782 | if(info->depends) { | |
783 | fputs("%DEPENDS%\n", fp); | |
784 | for(lp = info->depends; lp; lp = lp->next) { | |
4da70d80 | 785 | char *depstring = alpm_dep_compute_string(lp->data); |
c244cfec DM |
786 | fprintf(fp, "%s\n", depstring); |
787 | free(depstring); | |
e2faeb46 AF |
788 | } |
789 | fprintf(fp, "\n"); | |
790 | } | |
fc0e83f0 DM |
791 | if(info->optdepends) { |
792 | fputs("%OPTDEPENDS%\n", fp); | |
793 | for(lp = info->optdepends; lp; lp = lp->next) { | |
794 | fprintf(fp, "%s\n", (char *)lp->data); | |
795 | } | |
796 | fprintf(fp, "\n"); | |
797 | } | |
e2faeb46 AF |
798 | if(info->conflicts) { |
799 | fputs("%CONFLICTS%\n", fp); | |
800 | for(lp = info->conflicts; lp; lp = lp->next) { | |
801 | fprintf(fp, "%s\n", (char *)lp->data); | |
802 | } | |
803 | fprintf(fp, "\n"); | |
804 | } | |
805 | if(info->provides) { | |
806 | fputs("%PROVIDES%\n", fp); | |
807 | for(lp = info->provides; lp; lp = lp->next) { | |
808 | fprintf(fp, "%s\n", (char *)lp->data); | |
809 | } | |
810 | fprintf(fp, "\n"); | |
811 | } | |
e2faeb46 AF |
812 | fclose(fp); |
813 | fp = NULL; | |
814 | } | |
815 | ||
816 | /* INSTALL */ | |
d37ad048 | 817 | /* nothing needed here (script is automatically extracted) */ |
e2faeb46 AF |
818 | |
819 | cleanup: | |
820 | umask(oldmask); | |
0966c33a | 821 | free(pkgpath); |
e2faeb46 AF |
822 | |
823 | if(fp) { | |
824 | fclose(fp); | |
825 | } | |
826 | ||
827 | return(retval); | |
828 | } | |
829 | ||
830 | int _alpm_db_remove(pmdb_t *db, pmpkg_t *info) | |
831 | { | |
0966c33a XC |
832 | int ret = 0; |
833 | char *pkgpath = NULL; | |
e2faeb46 | 834 | |
da648bc2 AG |
835 | ALPM_LOG_FUNC; |
836 | ||
e2faeb46 | 837 | if(db == NULL || info == NULL) { |
e8275fa9 | 838 | RET_ERR(PM_ERR_DB_NULL, -1); |
e2faeb46 AF |
839 | } |
840 | ||
0966c33a | 841 | pkgpath = get_pkgpath(db, info); |
e2faeb46 | 842 | |
0966c33a XC |
843 | ret = _alpm_rmrf(pkgpath); |
844 | free(pkgpath); | |
845 | if(ret != 0) { | |
846 | ret = -1; | |
847 | } | |
848 | return(ret); | |
e2faeb46 AF |
849 | } |
850 | ||
851 | /* vim: set ts=2 sw=2 noet: */ |