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