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