retvalue pull_checkupdate(struct pull_distribution *distributions) { struct pull_distribution *d; retvalue result, r; for (d=distributions ; d != NULL ; d=d->next) { r = distribution_loadalloverrides(d->distribution); if (RET_WAS_ERROR(r)) return r; } if (verbose >= 0) fprintf(stderr, "Calculating packages to get...\n"); result = RET_NOTHING; for (d=distributions ; d != NULL ; d=d->next) { r = pull_search(stderr, d); RET_UPDATE(result, r); if (RET_WAS_ERROR(r)) break; pull_dump(d); } return result; }
static inline retvalue gotcapabilities(struct aptmethod *method, const char *chunk) { retvalue r; r = chunk_gettruth(chunk, "Single-Instance"); if (RET_WAS_ERROR(r)) return r; // TODO: what to do with this? // if (r != RET_NOTHING) { // fprintf(stderr, "WARNING: Single-instance not yet supported!\n"); // } r = chunk_gettruth(chunk, "Send-Config"); if (RET_WAS_ERROR(r)) return r; if (r != RET_NOTHING) { assert(method->command == NULL); method->alreadywritten = 0; method->command = method->config; method->config = NULL; method->output_length = strlen(method->command); if (verbose > 11) { fprintf(stderr, "Sending config: '%s'\n", method->command); } } else { free(method->config); method->config = NULL; } method->status = ams_ok; return RET_OK; }
retvalue trackingdata_switch(struct trackingdata *data, const char *source, const char *version) { retvalue r; if (data->pkg != NULL) { if (strcmp(data->pkg->sourcename, source) == 0 && strcmp(data->pkg->sourceversion, version) == 0) return RET_OK; r = tracking_saveonly(data->tracks, data->pkg); if (RET_WAS_ERROR(r)) return r; r = trackingdata_remember(data, data->pkg->sourcename, data->pkg->sourceversion); strlist_done(&data->pkg->filekeys); free(data->pkg->refcounts); free(data->pkg->filetypes); free(data->pkg); data->pkg = NULL; if (RET_WAS_ERROR(r)) return r; } r = tracking_getornew(data->tracks, source, version, &data->pkg); assert (r != RET_NOTHING); if (RET_WAS_ERROR(r)) return r; return RET_OK; }
static inline retvalue gotredirect(struct aptmethod *method, const char *chunk) { char *uri, *newuri; retvalue r; r = chunk_getvalue(chunk, "URI", &uri); if (r == RET_NOTHING) { fprintf(stderr, "Missing URI header in uriredirect received from '%s' method!\n", method->name); r = RET_ERROR; } if (RET_WAS_ERROR(r)) return r; r = chunk_getvalue(chunk, "New-URI", &newuri); if (r == RET_NOTHING) { fprintf(stderr, "Missing New-URI header in uriredirect received from '%s' method!\n", method->name); r = RET_ERROR; } if (RET_WAS_ERROR(r)) { free(uri); return r; } r = uriredirect(method, uri, newuri); free(uri); return r; }
static inline retvalue goturierror(struct aptmethod *method, const char *chunk) { retvalue r; char *uri, *message; r = chunk_getvalue(chunk, "URI", &uri); if (r == RET_NOTHING) { fprintf(stderr, "Missing URI header in urierror received from '%s' method!\n", method->name); r = RET_ERROR; } if (RET_WAS_ERROR(r)) return r; r = chunk_getvalue(chunk, "Message", &message); if (r == RET_NOTHING) { message = NULL; } if (RET_WAS_ERROR(r)) { free(uri); return r; } r = urierror(method, uri, message); free(uri); return r; }
static retvalue addpackages(struct target *target, const char *packagename, const char *controlchunk, /*@null@*/const char *oldcontrolchunk, const char *version, /*@null@*/const char *oldversion, const struct strlist *files, /*@only@*//*@null@*/struct strlist *oldfiles, /*@null@*/struct logger *logger, /*@null@*/struct trackingdata *trackingdata, architecture_t architecture, /*@null@*/const char *oldsource, /*@null@*/const char *oldsversion, /*@null@*/const char *causingrule, /*@null@*/const char *suitefrom) { retvalue result, r; struct table *table = target->packages; enum filetype filetype; assert (atom_defined(architecture)); if (architecture == architecture_source) filetype = ft_SOURCE; else if (architecture == architecture_all) filetype = ft_ALL_BINARY; else filetype = ft_ARCH_BINARY; /* mark it as needed by this distribution */ r = references_insert(target->identifier, files, oldfiles); if (RET_WAS_ERROR(r)) { if (oldfiles != NULL) strlist_done(oldfiles); return r; } /* Add package to the distribution's database */ if (oldcontrolchunk != NULL) { result = table_replacerecord(table, packagename, controlchunk); } else { result = table_adduniqrecord(table, packagename, controlchunk); } if (RET_WAS_ERROR(result)) { if (oldfiles != NULL) strlist_done(oldfiles); return result; } if (logger != NULL) logger_log(logger, target, packagename, version, oldversion, controlchunk, oldcontrolchunk, files, oldfiles, causingrule, suitefrom); r = trackingdata_insert(trackingdata, filetype, files, oldsource, oldsversion, oldfiles); RET_UPDATE(result, r); /* remove old references to files */ if (oldfiles != NULL) { r = references_delete(target->identifier, oldfiles, files); RET_UPDATE(result, r); strlist_done(oldfiles); } return result; }
retvalue pull_update(struct pull_distribution *distributions) { retvalue result, r; struct pull_distribution *d; for (d=distributions ; d != NULL ; d=d->next) { r = distribution_prepareforwriting(d->distribution); if (RET_WAS_ERROR(r)) return r; r = distribution_loadalloverrides(d->distribution); if (RET_WAS_ERROR(r)) return r; } if (verbose >= 0) printf("Calculating packages to pull...\n"); result = RET_NOTHING; for (d=distributions ; d != NULL ; d=d->next) { r = pull_search(stdout, d); RET_UPDATE(result, r); if (RET_WAS_ERROR(r)) break; // TODO: make already here sure the files are ready? } if (RET_WAS_ERROR(result)) { for (d=distributions ; d != NULL ; d=d->next) { struct pull_target *u; for (u=d->targets ; u != NULL ; u=u->next) { upgradelist_free(u->upgradelist); u->upgradelist = NULL; } } return result; } if (verbose >= 0) printf("Installing (and possibly deleting) packages...\n"); for (d=distributions ; d != NULL ; d=d->next) { if (global.onlysmalldeletes) { if (pull_isbigdelete(d)) { fprintf(stderr, "Not processing '%s' because of --onlysmalldeletes\n", d->distribution->codename); continue; } } r = pull_install(d); RET_UPDATE(result, r); if (RET_WAS_ERROR(r)) break; } logger_wait(); return result; }
static retvalue upload_conditions_add_group(struct upload_conditions **c_p, const struct uploadergroup **groups) { const struct uploadergroup *group; retvalue r; while ((group = *(groups++)) != NULL) { r = upload_conditions_add(c_p, &group->permissions); if (!RET_WAS_ERROR(r) && group->memberof != NULL) r = upload_conditions_add_group(c_p, group->memberof); if (RET_WAS_ERROR(r)) return r; } return RET_OK; }
retvalue trackingdata_insert(struct trackingdata *data, enum filetype filetype, const struct strlist *filekeys, /*@null@*//*@only@*/char*oldsource, /*@null@*//*@only@*/char*oldversion, /*@null@*/const struct strlist *oldfilekeys) { retvalue result, r; struct trackedpackage *pkg; if (data == NULL) { assert(oldversion == NULL && oldsource == NULL); free(oldversion); free(oldsource); return RET_OK; } assert(data->pkg != NULL); result = trackedpackage_adddupfilekeys(data->tracks, data->pkg, filetype, filekeys, true); if (RET_WAS_ERROR(result)) { free(oldsource); free(oldversion); return result; } if (oldsource == NULL || oldversion == NULL || oldfilekeys == NULL) { assert(oldsource==NULL&&oldversion==NULL&&oldfilekeys==NULL); return RET_OK; } if (strcmp(oldversion, data->pkg->sourceversion) == 0 && strcmp(oldsource, data->pkg->sourcename) == 0) { /* Unlikely, but it may also be the same source version as * the package we are currently adding */ free(oldsource); free(oldversion); return trackedpackage_removefilekeys(data->tracks, data->pkg, oldfilekeys); } r = tracking_get(data->tracks, oldsource, oldversion, &pkg); if (RET_WAS_ERROR(r)) { free(oldsource); free(oldversion); return r; } if (r == RET_NOTHING) { fprintf(stderr, "Could not found tracking data for %s_%s in %s to remove old files from it.\n", oldsource, oldversion, data->tracks->codename); free(oldsource); free(oldversion); return result; } r = trackedpackage_removefilekeys(data->tracks, pkg, oldfilekeys); RET_UPDATE(result, r); r = tracking_save(data->tracks, pkg); RET_UPDATE(result, r); r = trackingdata_remember(data, oldsource, oldversion); RET_UPDATE(result, r); return result; }
retvalue tracking_tidyall(trackingdb t) { struct cursor *cursor; retvalue result, r; struct trackedpackage *pkg; const char *key, *value, *data; size_t datalen; r = table_newglobalcursor(t->table, &cursor); if (!RET_IS_OK(r)) return r; result = RET_NOTHING; while (cursor_nextpair(t->table, cursor, &key, &value, &data, &datalen)) { r = parse_data(key, value, data, datalen, &pkg); if (RET_WAS_ERROR(r)) { result = r; break; } r = trackedpackage_tidy(t, pkg); RET_UPDATE(result, r); r = tracking_saveatcursor(t, cursor, pkg); RET_UPDATE(result, r); trackedpackage_free(pkg); } r = cursor_close(t->table, cursor); RET_UPDATE(result, r); return result; }
retvalue set_ignore(const char *given, bool newvalue, enum config_option_owner newowner) { const char *g, *p; retvalue r; assert (given != NULL); g = given; while (true) { p = g; while (*p != '\0' && *p != ',') p++; if (p == g) { fprintf(stderr, "Empty ignore option in --ignore='%s'!\n", given); return RET_ERROR_MISSING; } r = set(g, p - g, newvalue, newowner); if (RET_WAS_ERROR(r)) return r; if (*p == '\0') return RET_OK; g = p+1; } }
retvalue space_needed(struct devices *devices, const char *filename, const struct checksums *checksums) { size_t l = strlen(filename); char buffer[l+1]; struct stat s; struct device *device; int ret; retvalue r; fsblkcnt_t blocks; off_t filesize; if (devices == NULL) return RET_NOTHING; while (l > 0 && filename[l-1] != '/') l--; assert (l > 0); memcpy(buffer, filename, l); buffer[l] = '\0'; ret = stat(buffer, &s); if (ret != 0) { int e = errno; fprintf(stderr, "Error stat'ing %s: %d=%s\n", filename, e, strerror(e)); return RET_ERRNO(e); } r = device_find_or_create(devices, s.st_dev, buffer, &device); if (RET_WAS_ERROR(r)) return r; filesize = checksums_getfilesize(checksums); blocks = (filesize + device->blocksize - 1) / device->blocksize; device->needed += 1 + blocks; return RET_OK; }
retvalue space_prepare(struct devices **devices, enum spacecheckmode mode, off_t reservedfordb, off_t reservedforothers) { struct devices *n; struct device *d; struct stat s; int ret; retvalue r; if (mode == scm_NONE) { *devices = NULL; return RET_OK; } assert (mode == scm_FULL); n = NEW(struct devices); if (FAILEDTOALLOC(n)) return RET_ERROR_OOM; n->root = NULL; n->reserved = reservedforothers; ret = stat(global.dbdir, &s); if (ret != 0) { int e = errno; fprintf(stderr, "Error stat'ing %s: %d=%s\n", global.dbdir, e, strerror(e)); free(n); return RET_ERRNO(e); } r = device_find_or_create(n, s.st_dev, global.dbdir, &d); if (RET_WAS_ERROR(r)) { space_free(n); return r; } d->reserved += reservedfordb/d->blocksize+1; *devices = n; return RET_OK; }
static inline retvalue add_patches(const char *diffindexfile, struct diffindex *n, const struct strlist *patches) { int i; assert (patches->count == n->patchcount); for (i = 0 ; i < n->patchcount; i++) { struct hashes hashes; const char *patchname; retvalue r; parse_sha1line(patches->values[i], &hashes, &patchname); if (hashes.hashes[cs_sha1sum].len == 0 || hashes.hashes[cs_length].len == 0 || *patchname == '\0') { r = RET_ERROR; } else r = checksums_initialize(&n->patches[i].checksums, hashes.hashes); ASSERT_NOT_NOTHING(r); if (RET_WAS_ERROR(r)) { fprintf(stderr, "Error parsing SHA1-Patches line %d in '%s':!\n'%s'\n", i, diffindexfile, patches->values[i]); return r; } n->patches[i].name = strdup(patchname); if (FAILEDTOALLOC(n)) return RET_ERROR_OOM; } return RET_OK; }
static retvalue generatepulltarget(struct pull_distribution *pd, struct target *target) { struct pull_source **s; struct pull_target *pt; retvalue r; int i; pt = NEW(struct pull_target); if (FAILEDTOALLOC(pt)) return RET_ERROR_OOM; pt->target = target; pt->next = pd->targets; pt->upgradelist = NULL; pt->sources = NULL; s = &pt->sources; pd->targets = pt; for (i = 0 ; i < pd->distribution->pulls.count ; i++) { struct pull_rule *rule = pd->rules[i]; if (rule == NULL) r = pull_createdelete(&s); else r = pull_createsource(rule, target, &s); if (RET_WAS_ERROR(r)) return r; } return RET_OK; }
static inline retvalue checkorimprove(const char *filekey, struct checksums **checksums_p) { const struct checksums *checksums = *checksums_p; struct checksums *indatabase; bool improves; retvalue r; r = files_get_checksums(filekey, &indatabase); if (r == RET_NOTHING) { fprintf(stderr, "Missing file %s\n", filekey); return RET_ERROR_MISSING; } if (RET_WAS_ERROR(r)) return r; if (!checksums_check(checksums, indatabase, &improves)) { fprintf(stderr, "File \"%s\" is already registered with different checksums!\n", filekey); checksums_printdifferences(stderr, indatabase, checksums); r = RET_ERROR_WRONG_MD5; } else if (improves) { r = checksums_combine(checksums_p, indatabase, NULL); } else r = RET_NOTHING; checksums_free(indatabase); return r; }
/* check if file is already there (RET_NOTHING) or could be added (RET_OK) * or RET_ERROR_WRONG_MD5SUM if filekey already has different md5sum */ retvalue files_canadd(const char *filekey, const struct checksums *checksums) { retvalue r; struct checksums *indatabase; bool improves; r = files_get_checksums(filekey, &indatabase); if (r == RET_NOTHING) return RET_OK; if (RET_WAS_ERROR(r)) return r; if (!checksums_check(indatabase, checksums, &improves)) { fprintf(stderr, "File \"%s\" is already registered with different checksums!\n", filekey); checksums_printdifferences(stderr, indatabase, checksums); checksums_free(indatabase); return RET_ERROR_WRONG_MD5; } // TODO: sometimes the caller might want to have additional // checksums from the database already, think about ways to // make them available... checksums_free(indatabase); return RET_NOTHING; }
/* read the data from a .deb, make some checks and extract some data */ static retvalue deb_read(/*@out@*/struct debpackage **pkg, const char *filename, bool needssourceversion) { retvalue r; struct debpackage *deb; deb = zNEW(struct debpackage); if (FAILEDTOALLOC(deb)) return RET_ERROR_OOM; r = binaries_readdeb(&deb->deb, filename, needssourceversion); if (RET_IS_OK(r)) r = properpackagename(deb->deb.name); if (RET_IS_OK(r)) r = propersourcename(deb->deb.source); if (RET_IS_OK(r) && needssourceversion) r = properversion(deb->deb.sourceversion); if (RET_IS_OK(r)) r = properversion(deb->deb.version); if (RET_WAS_ERROR(r)) { deb_free(deb); return r; } *pkg = deb; return RET_OK; }
retvalue getfilelist(/*@out@*/char **filelist, size_t *size, const char *debfile) { struct ar_archive *ar; retvalue r; bool hadcandidate = false; r = ar_open(&ar, debfile); if (RET_WAS_ERROR(r)) return r; assert (r != RET_NOTHING); do { char *filename; enum compression c; r = ar_nextmember(ar, &filename); if (RET_IS_OK(r)) { if (strncmp(filename, "data.tar", 8) != 0) { free(filename); continue; } hadcandidate = true; for (c = 0 ; c < c_COUNT ; c++) { if (strcmp(filename + 8, uncompression_suffix[c]) == 0) break; } if (c >= c_COUNT) { free(filename); continue; } ar_archivemember_setcompression(ar, c); if (uncompression_supported(c)) { struct archive *tar; tar = archive_read_new(); r = read_data_tar(filelist, size, debfile, ar, tar); // TODO: check how to get an error message here.. archive_read_finish(tar); if (r != RET_NOTHING) { ar_close(ar); free(filename); return r; } } free(filename); } } while (RET_IS_OK(r)); ar_close(ar); if (hadcandidate) fprintf(stderr, "Could not find a suitable data.tar file within '%s'!\n", debfile); else fprintf(stderr, "Could not find a data.tar file within '%s'!\n", debfile); return RET_ERROR_MISSING; }
retvalue tracking_retrack(struct distribution *d, bool needsretrack) { struct target *t; trackingdb tracks; retvalue r, rr; if (d->tracking == dt_NONE) return RET_NOTHING; for (t = d->targets ; !needsretrack && t != NULL ; t = t->next) { if (t->staletracking) needsretrack = true; } if (!needsretrack) return RET_NOTHING; if (verbose > 0) printf("Retracking %s...\n", d->codename); r = tracking_initialize(&tracks, d, false); if (!RET_IS_OK(r)) return r; /* first forget that any package is there*/ r = tracking_reset(tracks); if (!RET_WAS_ERROR(r)) { /* add back information about actually used files */ r = distribution_foreach_package(d, atom_unknown, atom_unknown, atom_unknown, package_retrack, NULL, tracks); } if (RET_IS_OK(r)) { for (t = d->targets ; t != NULL ; t = t->next) { t->staletracking = false; } } if (!RET_WAS_ERROR(r)) { /* now remove everything no longer needed */ r = tracking_tidyall(tracks); } rr = tracking_done(tracks); RET_ENDUPDATE(r, rr); return r; }
retvalue uploaders_permissions(struct uploaders *u, const struct signatures *signatures, struct upload_conditions **c_p) { struct upload_conditions *conditions = NULL; retvalue r; int j; r = upload_conditions_add(&conditions, &u->anybodypermissions); if (RET_WAS_ERROR(r)) return r; if (signatures == NULL) { /* signatures.count might be 0 meaning there is * something lile a gpg header but we could not get * keys, because of a gpg error or because of being * compiling without libgpgme */ r = upload_conditions_add(&conditions, &u->unsignedpermissions); if (RET_WAS_ERROR(r)) { free(conditions); return r; } } if (signatures != NULL && signatures->validcount > 0) { r = upload_conditions_add(&conditions, &u->anyvalidkeypermissions); if (RET_WAS_ERROR(r)) { free(conditions); return r; } } if (signatures != NULL) { for (j = 0 ; j < signatures->count ; j++) { r = find_key_and_add(u, &conditions, &signatures->signatures[j]); if (RET_WAS_ERROR(r)) { free(conditions); return r; } } } *c_p = conditions; return RET_OK; }
static retvalue parse_architectures(/*@out@*/struct atomlist *atoms, const char **pp, const struct filebeingparsed *fbp, int column) { const char *p = *pp; retvalue r; atomlist_init(atoms); do { const char *startp, *endp; atom_t atom; while (*p != '\0' && xisspace(*p)) p++; if (*p != '\'') { errorcol(fbp, column + (int)(p - *pp), "starting \"'\" expected!"); return RET_ERROR; } p++; startp = p; while (*p != '\0' && *p != '\'' && *p != '*' && *p != '?') p++; if (*p == '*' || *p == '?') { errorcol(fbp, column + (int)(p - *pp), "Wildcards are not allowed in architectures!"); return RET_ERROR; } if (*p == '\0') { errorcol(fbp, column + (int)(p - *pp), "closing \"'\" expected!"); return RET_ERROR; } assert (*p == '\''); endp = p; p++; atom = architecture_find_l(startp, endp - startp); if (!atom_defined(atom)) { errorcol(fbp, column + (int)(startp-*pp), "Unknown architecture '%.*s'! (Did you mistype?)", (int)(endp-startp), startp); return RET_ERROR; } r = atomlist_add_uniq(atoms, atom); if (RET_WAS_ERROR(r)) return r; while (*p != '\0' && xisspace(*p)) p++; column += (p - *pp); *pp = p; if (**pp == '|') { p++; } } while (**pp == '|'); *pp = p; return RET_OK; }
static retvalue tracking_foreachversion(trackingdb t, struct distribution *distribution, const char *sourcename, retvalue (action)(trackingdb t, struct trackedpackage *, struct distribution *)) { struct cursor *cursor; retvalue result, r; struct trackedpackage *pkg; const char *value, *data; size_t datalen; r = table_newduplicatecursor(t->table, sourcename, &cursor, &value, &data, &datalen); if (!RET_IS_OK(r)) return r; result = RET_NOTHING; do { r = parse_data(sourcename, value, data, datalen, &pkg); if (RET_WAS_ERROR(r)) { result = r; break; } if (verbose > 10) printf("Processing track of '%s' version '%s'\n", pkg->sourcename, pkg->sourceversion); r = action(t, pkg, distribution); RET_UPDATE(result, r); if (RET_WAS_ERROR(r)) { (void)cursor_close(t->table, cursor); trackedpackage_free(pkg); return r; } r = trackedpackage_tidy(t, pkg); RET_ENDUPDATE(result, r); r = tracking_saveatcursor(t, cursor, pkg); RET_UPDATE(result, r); trackedpackage_free(pkg); } while (cursor_nextpair(t->table, cursor, NULL, &value, &data, &datalen)); r = cursor_close(t->table, cursor); RET_UPDATE(result, r); return result; }
/* check for file in the database and if not found there, if it can be detected */ retvalue files_expect(const char *filekey, const struct checksums *checksums, bool warnifadded) { retvalue r; char *filename; struct checksums *improvedchecksums = NULL; r = files_canadd(filekey, checksums); if (r == RET_NOTHING) return RET_OK; if (RET_WAS_ERROR(r)) return r; /* ready to add means missing, so have to look for the file itself: */ filename = files_calcfullfilename(filekey); if (FAILEDTOALLOC(filename)) return RET_ERROR_OOM; /* first check if a possible manually put (or left over from previous * downloads attepts) file is there and is correct */ r = checksums_test(filename, checksums, &improvedchecksums); if (r == RET_ERROR_WRONG_MD5) { fprintf(stderr, "Deleting unexpected file '%s'!\n" "(not in database and wrong in pool)\n ", filename); if (unlink(filename) == 0) r = RET_NOTHING; else { int e = errno; fprintf(stderr, "Error %d deleting '%s': %s!\n", e, filename, strerror(e)); } } free(filename); if (!RET_IS_OK(r)) return r; if (warnifadded) fprintf(stderr, "Warning: readded existing file '%s' mysteriously missing from the checksum database.\n", filekey); // TODO: some callers might want the updated checksum when // improves is true, how to get them there? /* add found file to database */ if (improvedchecksums != NULL) { r = files_add_checksums(filekey, improvedchecksums); checksums_free(improvedchecksums); } else r = files_add_checksums(filekey, checksums); assert (r != RET_NOTHING); return r; }
/* add possible already existing references */ retvalue references_add(const char *identifier, const struct strlist *files) { int i; retvalue r; for (i = 0 ; i < files->count ; i++) { const char *filekey = files->values[i]; r = table_addrecord(rdb_references, filekey, identifier, strlen(identifier), true); if (RET_WAS_ERROR(r)) return r; } return RET_OK; }
retvalue pull_dumpupdate(struct pull_distribution *distributions) { struct pull_distribution *d; retvalue result, r; for (d=distributions ; d != NULL ; d=d->next) { r = distribution_loadalloverrides(d->distribution); if (RET_WAS_ERROR(r)) return r; } result = RET_NOTHING; for (d=distributions ; d != NULL ; d=d->next) { r = pull_search(NULL, d); RET_UPDATE(result, r); if (RET_WAS_ERROR(r)) break; pull_dumplist(d); } return result; }
static retvalue pull_search(/*@null@*/FILE *out, struct pull_distribution *d) { retvalue result, r; struct pull_target *u; result = RET_NOTHING; for (u=d->targets ; u != NULL ; u=u->next) { r = pull_searchformissing(out, u); RET_UPDATE(result, r); if (RET_WAS_ERROR(r)) break; } return result; }
retvalue tracking_reset(trackingdb t) { struct cursor *cursor; retvalue result, r; struct trackedpackage *pkg; const char *key, *value, *data; char *newdata; size_t datalen, newdatalen; int i; r = table_newglobalcursor(t->table, &cursor); if (!RET_IS_OK(r)) return r; result = RET_NOTHING; while (cursor_nextpair(t->table, cursor, &key, &value, &data, &datalen)) { // this would perhaps be more stable if it just replaced // everything within the string just received... result = parse_data(key, value, data, datalen, &pkg); if (RET_WAS_ERROR(result)) break; for (i = 0 ; i < pkg->filekeys.count ; i++) { pkg->refcounts[i] = 0; } result = gen_data(pkg, &newdata, &newdatalen); trackedpackage_free(pkg); if (RET_IS_OK(result)) result = cursor_replace(t->table, cursor, newdata, newdatalen); free(newdata); if (RET_WAS_ERROR(result)) break; } r = cursor_close(t->table, cursor); RET_UPDATE(result, r); return result; }
static inline retvalue pull_searchformissing(/*@null@*/FILE *out, struct pull_target *p) { struct pull_source *source; retvalue result, r; if (verbose > 2 && out != NULL) fprintf(out, " pulling into '%s'\n", p->target->identifier); assert(p->upgradelist == NULL); r = upgradelist_initialize(&p->upgradelist, p->target); if (RET_WAS_ERROR(r)) return r; result = RET_NOTHING; for (source=p->sources ; source != NULL ; source=source->next) { if (source->rule == NULL) { if (verbose > 4 && out != NULL) fprintf(out, " marking everything to be deleted\n"); r = upgradelist_deleteall(p->upgradelist); RET_UPDATE(result, r); if (RET_WAS_ERROR(r)) return result; continue; } if (verbose > 4 && out != NULL) fprintf(out, " looking what to get from '%s'\n", source->source->identifier); r = upgradelist_pull(p->upgradelist, source->source, ud_decide_by_rule, source->rule, source); RET_UPDATE(result, r); if (RET_WAS_ERROR(r)) return result; } return result; }
/* hardlink file with known checksums and add it to database */ retvalue files_hardlinkandadd(const char *tempfile, const char *filekey, const struct checksums *checksums) { retvalue r; /* an additional check to make sure nothing tricks us into * overwriting it by another file */ r = files_canadd(filekey, checksums); if (!RET_IS_OK(r)) return r; r = checksums_hardlink(global.outdir, filekey, tempfile, checksums); if (RET_WAS_ERROR(r)) return r; return files_add_checksums(filekey, checksums); }