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