Esempio n. 1
0
struct fieldtoadd *addfield_newn(const char *field, const char *data, size_t len, struct fieldtoadd *next) {
	struct fieldtoadd *n;

	n = NEW(struct fieldtoadd);
	if (FAILEDTOALLOC(n)) {
		addfield_free(next);
		return NULL;
	}
	n->field = field;
	n->len_field = strlen(field);
	n->data = data;
	n->len_data = len;
	n->next = next;
	return n;
}
Esempio n. 2
0
static bool *preparefoundlist(const struct atomlist *list) {
	bool *found;
	int i, j;

	found = nzNEW(list->count, bool);
	if (FAILEDTOALLOC(found))
		return found;
	for (i = 0 ; i < list->count ; i++) {
		if (found[i])
			continue;
		for (j = i + 1 ; j < list->count ; j++)
			if (list->atoms[i] == list->atoms[j])
				found[j] = true;
	}
	return found;
}
Esempio n. 3
0
struct fieldtoadd *deletefield_new(const char *field, struct fieldtoadd *next) {
	struct fieldtoadd *n;

	assert(field != NULL);

	n = NEW(struct fieldtoadd);
	if (FAILEDTOALLOC(n)) {
		addfield_free(next);
		return NULL;
	}
	n->field = field;
	n->len_field = strlen(field);
	n->data = NULL;
	n->len_data = 0;
	n->next = next;
	return n;
}
Esempio n. 4
0
retvalue files_checkpool(bool fast) {
	retvalue result, r;
	struct cursor *cursor;
	const char *filekey, *combined;
	size_t combinedlen;
	struct checksums *expected;
	char *fullfilename;
	bool improveable = false;

	result = RET_NOTHING;
	r = table_newglobalcursor(rdb_checksums, &cursor);
	if (!RET_IS_OK(r))
		return r;
	while (cursor_nexttempdata(rdb_checksums, cursor,
				&filekey, &combined, &combinedlen)) {
		r = checksums_setall(&expected, combined, combinedlen);
		if (RET_WAS_ERROR(r)) {
			RET_UPDATE(result, r);
			continue;
		}
		fullfilename = files_calcfullfilename(filekey);
		if (FAILEDTOALLOC(fullfilename)) {
			result = RET_ERROR_OOM;
			checksums_free(expected);
			break;
		}
		if (fast)
			r = checksums_cheaptest(fullfilename, expected, true);
		else
			r = checkpoolfile(fullfilename, expected, &improveable);
		if (r == RET_NOTHING) {
			fprintf(stderr, "Missing file '%s'!\n", fullfilename);
			r = RET_ERROR_MISSING;
		}
		free(fullfilename);
		checksums_free(expected);
		RET_UPDATE(result, r);
	}
	r = cursor_close(rdb_checksums, cursor);
	RET_ENDUPDATE(result, r);
	if (improveable && verbose >= 0)
		printf(
"There were files with only some of the checksums this version of reprepro\n"
"can compute recorded. To add those run reprepro collectnewchecksums.\n");
	return result;
}
Esempio n. 5
0
static retvalue parse_stringpart(/*@out@*/struct strlist *strings, const char **pp, const struct filebeingparsed *fbp, int column) {
	const char *p = *pp;
	retvalue r;

	strlist_init(strings);
	do {
		const char *startp, *endp;
		char *n;

		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++;
		if (*p == '\0') {
			errorcol(fbp, column + (int)(p - *pp),
"closing \"'\" expected!");
			return RET_ERROR;
		}
		assert (*p == '\'');
		endp = p;
		p++;
		n = strndup(startp, endp - startp);
		if (FAILEDTOALLOC(n))
			return RET_ERROR_OOM;
		r = strlist_adduniq(strings, n);
		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;
}
Esempio n. 6
0
retvalue chunk_getextralinelist(const char *chunk, const char *name, struct strlist *strlist) {
	retvalue r;
	const char *f, *b, *e;
	char *v;

	f = chunk_getfield(name, chunk);
	if (f == NULL)
		return RET_NOTHING;
	strlist_init(strlist);
	/* walk over the first line */
	while (*f != '\0' && *f != '\n')
		f++;
	/* nothing there is an empty list */
	if (*f == '\0')
		return RET_OK;
	f++;
	/* while lines begin with ' ' or '\t', add them */
	while (*f == ' ' || *f == '\t') {
		while (*f != '\0' && xisblank(*f))
			f++;
		b = f;
		while (*f != '\0' && *f != '\n')
			f++;
		e = f;
		while (e > b && *e != '\0' && xisspace(*e))
			e--;
		if (!xisspace(*e))
			v = strndup(b, e - b + 1);
		else
			v = strdup("");
		if (FAILEDTOALLOC(v)) {
			strlist_done(strlist);
			return RET_ERROR_OOM;
		}
		r = strlist_add(strlist, v);
		if (!RET_IS_OK(r)) {
			strlist_done(strlist);
			return r;
		}
		if (*f == '\0')
			return RET_OK;
		f++;
	}
	return RET_OK;
}
Esempio n. 7
0
struct chunkeditfield *cef_newfield(const char *field, enum cefaction action, enum cefwhen when, unsigned int linecount, struct chunkeditfield *next) {
	struct chunkeditfield *n;

	n = calloc(1, sizeof(struct chunkeditfield) +
			linecount * sizeof(struct cef_line));
	if (FAILEDTOALLOC(n)) {
		cef_free(next);
		return NULL;
	}
	assert(field != NULL);
	n->field = field;
	n->len_field = strlen(field);
	n->action = action;
	n->when = when;
	n->linecount = linecount;
	n->next = next;
	return n;
}
Esempio n. 8
0
static inline retvalue trackedpackage_removeall(trackingdb tracks, struct trackedpackage *pkg) {
	retvalue result = RET_OK, r;
	char *id;

//	printf("[trackedpackage_removeall %s %s %s]\n", tracks->codename, pkg->sourcename, pkg->sourceversion);
	id = calc_trackreferee(tracks->codename, pkg->sourcename,
			pkg->sourceversion);
	if (FAILEDTOALLOC(id))
		return RET_ERROR_OOM;

	pkg->flags.deleted = true;
	r = references_delete(id, &pkg->filekeys, NULL);
	RET_UPDATE(result, r);
	free(id);
	strlist_done(&pkg->filekeys);
	strlist_init(&pkg->filekeys);
	free(pkg->refcounts); pkg->refcounts = NULL;
	return result;
}
Esempio n. 9
0
retvalue tracking_remove(trackingdb t, const char *sourcename, const char *version) {
	retvalue result, r;
	struct cursor *cursor;
	const char *data;
	size_t datalen;
	char *id;
	struct trackedpackage *pkg SETBUTNOTUSED(= NULL);

	r = table_newpairedcursor(t->table, sourcename, version, &cursor,
			&data, &datalen);
	if (!RET_IS_OK(r))
		return r;

	id = calc_trackreferee(t->codename, sourcename, version);
	if (FAILEDTOALLOC(id)) {
		(void)cursor_close(t->table, cursor);
		return RET_ERROR_OOM;
	}

	result = parse_data(sourcename, version, data, datalen, &pkg);
	if (RET_IS_OK(r)) {
		assert (pkg != NULL);
		r = references_delete(id, &pkg->filekeys, NULL);
		RET_UPDATE(result, r);
		trackedpackage_free(pkg);
	} else {
		RET_UPDATE(result, r);
		fprintf(stderr,
"Could not parse data, removing all references blindly...\n");
		r = references_remove(id);
		RET_UPDATE(result, r);
	}
	free(id);
	r = cursor_delete(t->table, cursor, sourcename, version);
	if (RET_IS_OK(r))
		fprintf(stderr, "Removed %s_%s from %s.\n",
				sourcename, version, t->codename);
	RET_UPDATE(result, r);
	r = cursor_close(t->table, cursor);
	RET_ENDUPDATE(result, r);
	return result;
}
Esempio n. 10
0
struct fieldtoadd *aodfield_new(const char *field, const char *data, struct fieldtoadd *next) {
	struct fieldtoadd *n;

	assert(field != NULL);

	n = NEW(struct fieldtoadd);
	if (FAILEDTOALLOC(n)) {
		addfield_free(next);
		return NULL;
	}
	n->field = field;
	n->len_field = strlen(field);
	n->data = data;
	if (data != NULL)
		n->len_data = strlen(data);
	else
		n->len_data = 0;
	n->next = next;
	return n;
}
Esempio n. 11
0
static retvalue parsetype(enum term_comparison c, const char *value, size_t len, struct compare_with *v) {
	if (c == tc_none) {
		fprintf(stderr,
"Error: $Type is always defined, it does not make sense without parameter\n"
"to compare against!\n");
		return RET_ERROR;
	}
	if (c != tc_equal && c != tc_notequal) {
		v->pointer = strndup(value, len);
		if (FAILEDTOALLOC(v->pointer))
			return RET_ERROR_OOM;
		return RET_OK;
	}
	v->number = packagetype_find_l(value, len);
	if (atom_defined(v->number))
		return RET_OK;
	fprintf(stderr, "Unknown package type '%.*s' in formula!\n",
			(int)len, value);
	return RET_ERROR;
}
Esempio n. 12
0
static retvalue tracking_recreatereferences(trackingdb t) {
	struct cursor *cursor;
	retvalue result, r;
	struct trackedpackage *pkg;
	char *id;
	int i;
	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)) {
			(void)cursor_close(t->table, cursor);
			return r;
		}
		id = calc_trackreferee(t->codename, pkg->sourcename,
				                    pkg->sourceversion);
		if (FAILEDTOALLOC(id)) {
			trackedpackage_free(pkg);
			(void)cursor_close(t->table, cursor);
			return RET_ERROR_OOM;
		}
		for (i = 0 ; i < pkg->filekeys.count ; i++) {
			const char *filekey = pkg->filekeys.values[i];
			r = references_increment(filekey, id);
			RET_UPDATE(result, r);
		}
		free(id);
		trackedpackage_free(pkg);
	}
	r = cursor_close(t->table, cursor);
	RET_UPDATE(result, r);
	return result;
}
Esempio n. 13
0
/* create recursively all parent directories before the last '/' */
retvalue dirs_make_parent(const char *filename) {
	const char *p;
	char *h;
	int i;
	retvalue r;

	for (p = filename+1, i = 1 ; *p != '\0' ; p++, i++) {
		if (*p == '/') {
			h = strndup(filename, i);
			if (FAILEDTOALLOC(h))
				return RET_ERROR_OOM;
			r = dirs_create(h);
			if (RET_WAS_ERROR(r)) {
				free(h);
				return r;
			}
			free(h);
		}
	}
	return RET_OK;
}
Esempio n. 14
0
static retvalue parsecomponent(enum term_comparison c, const char *value, size_t len, struct compare_with *v) {
	if (c == tc_none) {
		fprintf(stderr,
"Error: $Component is always defined, it does not make sense without parameter\n"
"to compare against!\n");
		return RET_ERROR;
	}
	if (c != tc_equal && c != tc_notequal) {
		v->pointer = strndup(value, len);
		if (FAILEDTOALLOC(v->pointer))
			return RET_ERROR_OOM;
		return RET_OK;
	}
	v->number = component_find_l(value, len);
	if (atom_defined(v->number))
		return RET_OK;
	fprintf(stderr,
"Unknown component '%.*s' in formula (must be listed in conf/distributions to be known)!\n",
			(int)len, value);
	return RET_ERROR;
}
Esempio n. 15
0
static retvalue requeue_or_fail(struct aptmethod *method, /*@only@*/struct tobedone *todo) {
	retvalue r;

	if (todo->ignore)
		return RET_NOTHING;

	if (todo->lasttry) {
		if (todo->callback == NULL)
			r = RET_ERROR;
		else
			r = todo->callback(qa_error,
				todo->privdata1, todo->privdata2,
				todo->uri, NULL, todo->filename,
				NULL, method->name);
		todo_free(todo);
		return r;
	} else {
		size_t l, old_len, new_len;
		char *s;

		assert (method->fallbackbaseuri != NULL);

		old_len = strlen(method->baseuri);
		new_len = strlen(method->fallbackbaseuri);
		l = strlen(todo->uri);
		s = malloc(l+new_len+1-old_len);
		if (FAILEDTOALLOC(s)) {
			todo_free(todo);
			return RET_ERROR_OOM;
		}
		memcpy(s, method->fallbackbaseuri, new_len);
		strcpy(s+new_len, todo->uri + old_len);
		free(todo->uri);
		todo->uri = s;
		todo->lasttry = true;
		todo->redirect_count = 0;
		enqueue(method, todo);
		return RET_OK;
	}
}
Esempio n. 16
0
static inline retvalue trackedpackage_removeunneeded(trackingdb tracks, struct trackedpackage *pkg) {
	retvalue result = RET_OK, r;
	char *id = NULL;
	int i, j, count;

	assert(tracks->type == dt_MINIMAL);

	count = pkg->filekeys.count;
	j = 0;
	for (i = 0 ; i < count ; i++) {
		if (tracking_needed(tracks, pkg, i)) {
			if (j < i) {
				pkg->filekeys.values[j] = pkg->filekeys.values[i];
				pkg->refcounts[j] = pkg->refcounts[i];
				pkg->filetypes[j] = pkg->filetypes[i];
			}
			j++;
		} else {
			char *filekey = pkg->filekeys.values[i];
			pkg->filekeys.values[i] = NULL;
			if (FAILEDTOALLOC(id)) {
				id = calc_trackreferee(tracks->codename,
					pkg->sourcename, pkg->sourceversion);
				if (id == NULL)
					result = RET_ERROR_OOM;
			}
			if (id != NULL) {
//				printf("[trackedpackage_removeunneeded %s %s %s: '%s']\n", tracks->codename, pkg->sourcename, pkg->sourceversion, filekey);
				r = references_decrement(filekey, id);
				RET_UPDATE(result, r);
			}
			free(filekey);
		}
	}
	assert (j <= pkg->filekeys.count);
	pkg->filekeys.count = j;
	free(id);
	return result;
}
Esempio n. 17
0
retvalue files_detect(const char *filekey) {
	struct checksums *checksums;
	char *fullfilename;
	retvalue r;

	fullfilename = files_calcfullfilename(filekey);
	if (FAILEDTOALLOC(fullfilename))
		return RET_ERROR_OOM;
	r = checksums_read(fullfilename, &checksums);
	if (r == RET_NOTHING) {
		fprintf(stderr, "Error opening '%s'!\n", fullfilename);
		r = RET_ERROR_MISSING;
	}
	if (RET_WAS_ERROR(r)) {
		free(fullfilename);
		return r;
	}
	free(fullfilename);
	r = files_add_checksums(filekey, checksums);
	checksums_free(checksums);
	return r;
}
Esempio n. 18
0
static retvalue pull_initdistribution(struct pull_distribution **pp,
		struct distribution *distribution,
		struct pull_rule *rules) {
	struct pull_distribution *p;
	int i;

	assert(distribution != NULL);
	if (distribution->pulls.count == 0)
		return RET_NOTHING;

	p = malloc(sizeof(struct pull_distribution)+
		sizeof(struct pull_rules *)*distribution->pulls.count);
	if (FAILEDTOALLOC(p))
		return RET_ERROR_OOM;
	p->next = NULL;
	p->distribution = distribution;
	p->targets = NULL;
	for (i = 0 ; i < distribution->pulls.count ; i++) {
		const char *name = distribution->pulls.values[i];
		if (strcmp(name, "-") == 0) {
			p->rules[i] = NULL;
		} else {
			struct pull_rule *rule = rules;
			while (rule && strcmp(rule->name, name) != 0)
				rule = rule->next;
			if (rule == NULL) {
				fprintf(stderr,
"Error: Unknown pull rule '%s' in distribution '%s'!\n",
						name, distribution->codename);
				free(p);
				return RET_ERROR_MISSING;
			}
			p->rules[i] = rule;
			rule->used = true;
		}
	}
	*pp = p;
	return RET_OK;
}
Esempio n. 19
0
retvalue chunk_getuniqwordlist(const char *chunk, const char *name, struct strlist *strlist) {
	retvalue r;
	const char *f, *b;
	char *v;

	f = chunk_getfield(name, chunk);
	if (f == NULL)
		return RET_NOTHING;
	strlist_init(strlist);
	while (*f != '\0') {
		/* walk over spaces */
		while (*f != '\0' && xisspace(*f)) {
			if (*f == '\n') {
				f++;
				if (*f != ' ' && *f != '\t')
					return RET_OK;
			} else
				f++;
		}
		if (*f == '\0')
			return RET_OK;
		b = f;
		/* search for end of word */
		while (*f != '\0' && !xisspace(*f))
			f++;
		v = strndup(b, f - b);
		if (FAILEDTOALLOC(v)) {
			strlist_done(strlist);
			return RET_ERROR_OOM;
		}
		r = strlist_adduniq(strlist, v);
		if (!RET_IS_OK(r)) {
			strlist_done(strlist);
			return r;
		}
	}
	return RET_OK;
}
Esempio n. 20
0
static retvalue gotfilename(const char *relname, size_t l, struct release *release) {

    if (l > 12 && memcmp(relname+l-12, ".tobedeleted", 12) == 0) {
        char *filename;

        filename = strndup(relname, l - 12);
        if (FAILEDTOALLOC(filename))
            return RET_ERROR_OOM;
        return release_adddel(release, filename);

    } else if (l > 4 && memcmp(relname+(l-4), ".new", 4) == 0) {
        char *filename, *tmpfilename;

        filename = strndup(relname, l - 4);
        if (FAILEDTOALLOC(filename))
            return RET_ERROR_OOM;
        tmpfilename = strndup(relname, l);
        if (FAILEDTOALLOC(tmpfilename)) {
            free(filename);
            return RET_ERROR_OOM;
        }
        return release_addnew(release, tmpfilename, filename);
    } else if (l > 5 && memcmp(relname + (l-5), ".new.", 5) == 0) {
        char *filename, *tmpfilename;

        filename = strndup(relname, l-5);
        if (FAILEDTOALLOC(filename))
            return RET_ERROR_OOM;
        tmpfilename = strndup(relname, l-1);
        if (FAILEDTOALLOC(tmpfilename)) {
            free(filename);
            return RET_ERROR_OOM;
        }
        return release_addsilentnew(release, tmpfilename, filename);
    } else if (l > 5 && memcmp(relname + (l-5), ".keep", 5) == 0) {
        return RET_OK;
    } else {
        char *filename;

        filename = strndup(relname, l);
        if (FAILEDTOALLOC(filename))
            return RET_ERROR_OOM;
        return release_addold(release, filename);
    }
}
Esempio n. 21
0
static retvalue regenerate_filelist(void *data, const char *filekey) {
	bool reread = ((struct rfd*)data)->reread;
	size_t l = strlen(filekey);
	char *debfilename;
	char *filelist;
	size_t fls;
	retvalue r;

	if (l <= 4 || memcmp(filekey+l-4, ".deb", 4) != 0)
		return RET_NOTHING;

	if (!reread && !table_recordexists(rdb_contents, filekey))
		return RET_NOTHING;

	debfilename = files_calcfullfilename(filekey);
	if (FAILEDTOALLOC(debfilename))
		return RET_ERROR_OOM;

	r = getfilelist(&filelist, &fls, debfilename);
	free(debfilename);
	if (RET_IS_OK(r)) {
		if (verbose > 0)
			(void)puts(filekey);
		if (verbose > 6) {
			const char *p = filelist;
			while (*p != '\0') {
				(void)putchar(' ');
				(void)puts(p);
				p += strlen(p)+1;
			}
		}
		r = table_adduniqsizedrecord(rdb_contents,
				filekey, filelist, fls, true, true);
		free(filelist);
	}
	return r;
}
Esempio n. 22
0
static retvalue upload_conditions_add(struct upload_conditions **c_p, const struct upload_condition *a) {
	int newcount;
	struct upload_conditions *n;

	if (a->type == uc_REJECTED) {
		/* due to groups, there can be empty conditions.
		 * Don't include those in this list... */
		return RET_OK;
	}

	if (*c_p == NULL)
		newcount = 1;
	else
		newcount = (*c_p)->count + 1;
	n = realloc(*c_p, sizeof(struct upload_conditions)
			+ newcount * sizeof(const struct upload_condition*));
	if (FAILEDTOALLOC(n))
		return RET_ERROR_OOM;
	n->current = NULL;
	n->count = newcount;
	n->conditions[newcount - 1] = a;
	*c_p = n;
	return RET_OK;
}
Esempio n. 23
0
void dir_remove_new(const char *directory, int created) {
	size_t len = strlen(directory);
	char *this;
	int ret;

	while (len > 0 && directory[len-1] == '/')
		len--;
	while (created > 0 && len > 0) {
		this = strndup(directory, len);
		if (FAILEDTOALLOC(this))
			return;
		ret = rmdir(this);
		if (ret == 0) {
			if (verbose > 1)
				printf(
"Removed empty directory \"%s\"\n",
					this);
		} else {
			int e = errno;
			if (e != ENOTEMPTY) {
				fprintf(stderr,
"Error removing directory \"%s\": %s(%d)\n",
						this, strerror(e), e);
			}
			free(this);
			return;
		}
		free(this);
		created--;
		while (len > 0 && directory[len-1] != '/')
			len--;
		while (len > 0 && directory[len-1] == '/')
			len--;
	}
	return;
}
Esempio n. 24
0
/* Include a yet unknown file into the pool */
retvalue files_preinclude(const char *sourcefilename, const char *filekey, struct checksums **checksums_p) {
	retvalue r;
	struct checksums *checksums, *realchecksums;
	bool improves;
	char *fullfilename;

	r = files_get_checksums(filekey, &checksums);
	if (RET_WAS_ERROR(r))
		return r;
	if (RET_IS_OK(r)) {
		r = checksums_read(sourcefilename, &realchecksums);
		if (r == RET_NOTHING)
			r = RET_ERROR_MISSING;
		if (RET_WAS_ERROR(r)) {
			checksums_free(checksums);
			return r;
		}
		if (!checksums_check(checksums, realchecksums, &improves)) {
			fprintf(stderr,
"ERROR: '%s' cannot be included as '%s'.\n"
"Already existing files can only be included again, if they are the same, but:\n",
				sourcefilename, filekey);
			checksums_printdifferences(stderr, checksums,
					realchecksums);
			checksums_free(checksums);
			checksums_free(realchecksums);
			return RET_ERROR_WRONG_MD5;
		}
		if (improves) {
			r = checksums_combine(&checksums, realchecksums, NULL);
			if (RET_WAS_ERROR(r)) {
				checksums_free(realchecksums);
				checksums_free(checksums);
				return r;
			}
			r = files_replace_checksums(filekey, checksums);
			if (RET_WAS_ERROR(r)) {
				checksums_free(realchecksums);
				checksums_free(checksums);
				return r;
			}
		}
		checksums_free(realchecksums);
		// args, this breaks retvalue semantics!
		if (checksums_p != NULL)
			*checksums_p = checksums;
		else
			checksums_free(checksums);
		return RET_NOTHING;
	}
	assert (sourcefilename != NULL);
	fullfilename = files_calcfullfilename(filekey);
	if (FAILEDTOALLOC(fullfilename))
		return RET_ERROR_OOM;
	(void)dirs_make_parent(fullfilename);
	r = checksums_copyfile(fullfilename, sourcefilename, true, &checksums);
	if (r == RET_ERROR_EXIST) {
		// TODO: deal with already existing files!
		fprintf(stderr, "File '%s' does already exist!\n",
				fullfilename);
	}
	if (r == RET_NOTHING) {
		fprintf(stderr, "Could not open '%s'!\n", sourcefilename);
		r = RET_ERROR_MISSING;
	}
	if (RET_WAS_ERROR(r)) {
		free(fullfilename);
		return r;
	}
	free(fullfilename);

	r = files_add_checksums(filekey, checksums);
	if (RET_WAS_ERROR(r)) {
		checksums_free(checksums);
		return r;
	}
	if (checksums_p != NULL)
		*checksums_p = checksums;
	else
		checksums_free(checksums);
	return RET_OK;
}
Esempio n. 25
0
static retvalue parseatom(const char **formula, /*@out@*/struct term_atom **atom, int options, const struct term_special *specials) {
	struct term_atom *a;
	const char *f = *formula;
#define overspace() while (*f != '\0' && xisspace(*f)) f++
	const char *keystart, *keyend;
	const char *valuestart, *valueend;
	enum term_comparison comparison = tc_none;
	bool negated = false;
	const struct term_special *s;


	overspace();
	if (*f == '!' && ISSET(options, T_NEGATION)) {
		negated = true;
		f++;
	}
	keystart = f;
	// TODO: allow more strict checking again with some option?
	while (*f != '\0' && *f != '(' && !xisspace(*f) && *f != ','
			&& *f != '|' && *f !='(' && *f != ')'
			&& *f != '[' && *f != '!')
		f++;
	keyend = f;
	if (keystart == keyend) {
		*formula = f;
		return RET_NOTHING;
	}
	overspace();
	if (ISSET(options, T_VERSION) && *f == '(') {
		f++;
		overspace();
		switch (*f) {
			case '>':
				f++;
				if (*f == '=') {
					comparison = tc_moreorequal;
					f++;
				} else if (*f == '>') {
					comparison = tc_strictmore;
					f++;
				} else {
					comparison = tc_moreorequal;
					fprintf(stderr,
"Warning: Found a '(>' without '=' or '>'  in '%s'(beginning cut), will be treated as '>='.\n",
							*formula);
				}
				break;
			case '<':
				f++;
				if (*f == '=') {
					comparison = tc_lessorequal;
					f++;
				} else if (*f == '<') {
					comparison = tc_strictless;
					f++;
				} else {
					comparison = tc_lessorequal;
					fprintf(stderr,
"Warning: Found a '(<' without '=' or '<'  in '%s'(begin cut), will be treated as '<='.\n",
							*formula);
				}
				break;
			case '=':
				f++;
				if (*f == '=')
					f++;
				else if (*f != ' ') {
					*formula = f;
					return RET_NOTHING;
				}
				comparison = tc_equal;
				break;
			case '%':
				if (ISSET(options, T_GLOBMATCH)) {
					f++;
					comparison = tc_globmatch;
					break;
				}
				*formula = f;
				return RET_NOTHING;
			case '!':
				if (f[1] == '%' &&
						ISSET(options, T_GLOBMATCH)) {
					f += 2;
					comparison = tc_notglobmatch;
					break;
				}
				if (ISSET(options, T_NOTEQUAL)) {
					f++;
					if (*f != '=') {
						*formula = f;
						return RET_NOTHING;
					}
					f++;
					comparison = tc_notequal;
					break;
				}
				// no break here...
			default:
				*formula = f;
				return RET_NOTHING;
		}
		overspace();
		valueend = valuestart = f;
		while (*f != '\0' && *f != ')') {
			valueend = f+1;
			f++;
			while (*f != '\0' && xisspace(*f))
				f++;
		}
		if (*f != ')' || valueend == valuestart) {
			*formula = f;
			return RET_NOTHING;
		}
		f++;

	} else {
		comparison = tc_none;
		valuestart = valueend = NULL;
	}
	overspace();
	if (ISSET(options, T_ARCHITECTURES) && *f == '[') {
		//TODO: implement this one...
		assert ("Not yet implemented!" == NULL);
	}
	for (s = specials ; s->name != NULL ; s++) {
		if (strncasecmp(s->name, keystart, keyend-keystart) == 0 &&
				s->name[keyend-keystart] == '\0')
			break;
	}
	a = zNEW(struct term_atom);
	if (FAILEDTOALLOC(a))
		return RET_ERROR_OOM;
	a->negated = negated;
	a->comparison = comparison;
	if (s->name != NULL) {
		retvalue r;

		a->isspecial = true;
		a->special.type = s;
		r = s->parse(comparison, valuestart, valueend-valuestart,
				&a->special.comparewith);
		if (RET_WAS_ERROR(r)) {
			term_free(a);
			return r;
		}
	} else {
		a->isspecial = false;
		a->generic.key = strndup(keystart, keyend - keystart);
		if (FAILEDTOALLOC(a->generic.key)) {
			term_free(a);
			return RET_ERROR_OOM;
		}
		if (comparison != tc_none) {
			if (valueend - valuestart > 2048 &&
					(comparison == tc_globmatch ||
					 comparison == tc_notglobmatch)) {
				fprintf(stderr,
"Ridicilous long globmatch '%.10s...'!\n",
						valuestart);
				term_free(a);
				return RET_ERROR;
			}
			a->generic.comparewith = strndup(valuestart,
					valueend - valuestart);
			if (FAILEDTOALLOC(a->generic.comparewith)) {
				term_free(a);
				return RET_ERROR_OOM;
			}
		}
	}
	//TODO: here architectures, too

	*atom = a;
	*formula = f;
	return RET_OK;
#undef overspace
}
Esempio n. 26
0
retvalue signature_check(const struct signature_requirement *requirements, const char *releasegpg, const char *release) {
	gpg_error_t err;
	int fd, gpgfd;
	gpgme_data_t dh, dh_gpg;
	gpgme_verify_result_t result;
	int i;
	const struct signature_requirement *req;

	assert (requirements != NULL);

	if (FAILEDTOALLOC(release) || FAILEDTOALLOC(releasegpg))
		return RET_ERROR_OOM;

	assert (context != NULL);

	/* Read the file and its signature into memory: */
	gpgfd = open(releasegpg, O_RDONLY|O_NOCTTY);
	if (gpgfd < 0) {
		int e = errno;
		fprintf(stderr, "Error opening '%s': %s\n",
				releasegpg, strerror(e));
		return RET_ERRNO(e);
	}
	fd = open(release, O_RDONLY|O_NOCTTY);
	if (fd < 0) {
		int e = errno;
		(void)close(gpgfd);
		fprintf(stderr, "Error opening '%s': %s\n",
			       release, strerror(e));
		return RET_ERRNO(e);
	}
	err = gpgme_data_new_from_fd(&dh_gpg, gpgfd);
	if (err != 0) {
		(void)close(gpgfd); (void)close(fd);
		fprintf(stderr, "Error reading '%s':\n", releasegpg);
		return gpgerror(err);
	}
	err = gpgme_data_new_from_fd(&dh, fd);
	if (err != 0) {
		gpgme_data_release(dh_gpg);
		(void)close(gpgfd); (void)close(fd);
		fprintf(stderr, "Error reading '%s':\n", release);
		return gpgerror(err);
	}

	/* Verify the signature */

	err = gpgme_op_verify(context, dh_gpg, dh, NULL);
	gpgme_data_release(dh_gpg);
	gpgme_data_release(dh);
	close(gpgfd); close(fd);
	if (err != 0) {
		fprintf(stderr, "Error verifying '%s':\n", releasegpg);
		return gpgerror(err);
	}

	result = gpgme_op_verify_result(context);
	if (result == NULL) {
		fprintf(stderr,
"Internal error communicating with libgpgme: no result record!\n\n");
		return RET_ERROR_GPGME;
	}

	for (req = requirements ; req != NULL ; req = req->next) {
		bool fullfilled = false;

		/* check first for good signatures, and then for good enough
		   signatures, to not pester the user with warnings of one
		   of the alternate keys, if the last one is good enough */

		for (i = 0 ; (size_t)i < req->num_keys ; i++) {

			if (key_good(&req->keys[i], result->signatures)) {
				fullfilled = true;
				break;
			}
		}
		for (i = 0 ; !fullfilled && (size_t)i < req->num_keys ; i++) {

			if (key_good_enough(&req->keys[i], result->signatures,
						releasegpg, release)) {
				fullfilled = true;
				break;
			}
		}
		if (!fullfilled) {
			fprintf(stderr,
"ERROR: Condition '%s' not fullfilled for '%s'.\n",
					req->condition, releasegpg);
			print_signatures(stderr, result->signatures,
					releasegpg);
			return RET_ERROR_BADSIG;
		}
		if (verbose > 10) {
			fprintf(stdout, "Condition '%s' fullfilled for '%s'.\n",
					req->condition, releasegpg);
		}
	}
	if (verbose > 20)
		print_signatures(stdout, result->signatures, releasegpg);
	return RET_OK;
}
Esempio n. 27
0
retvalue signature_requirement_add(struct signature_requirement **list_p, const char *condition) {
	struct signature_requirement *req;
	const char *full_condition = condition;
	retvalue r;

	r = signature_init(false);
	if (RET_WAS_ERROR(r))
		return r;

	if (condition == NULL || strcmp(condition, "blindtrust") == 0)
		return RET_NOTHING;

	/* no need to add the same condition multiple times */
	for (req = *list_p ; req != NULL ; req = req->next) {
		if (strcmp(req->condition, condition) == 0)
			return RET_NOTHING;
	}

	req = malloc(sizeof_requirement(1));
	if (FAILEDTOALLOC(req))
		return RET_ERROR_OOM;
	req->next = NULL;
	req->condition = strdup(condition);
	if (FAILEDTOALLOC(req->condition)) {
		free(req);
		return RET_ERROR_OOM;
	}
	req->num_keys = 0;
	do {
		bool allow_subkeys, allow_bad;
		char *next_key IFSTUPIDCC(=NULL);

		r = parse_condition_part(&allow_subkeys, &allow_bad,
				full_condition, &condition, &next_key);
		ASSERT_NOT_NOTHING(r);
		if (RET_WAS_ERROR(r)) {
			signature_requirements_free(req);
			return r;
		}
		req->keys[req->num_keys].allow_bad = allow_bad;
		r = load_key(next_key, allow_subkeys, allow_bad,
				full_condition,
				&req->keys[req->num_keys].key,
				&req->keys[req->num_keys].subkey);
		free(next_key);
		if (RET_WAS_ERROR(r)) {
			signature_requirements_free(req);
			return r;
		}
		req->num_keys++;

		if (*condition != '\0') {
			struct signature_requirement *h;

			h = realloc(req, sizeof_requirement(req->num_keys+1));
			if (FAILEDTOALLOC(h)) {
				signature_requirements_free(req);
				return r;
			}
			req = h;
		} else
			break;
	} while (true);
	req->next = *list_p;
	*list_p = req;
	return RET_OK;
}
Esempio n. 28
0
static retvalue checkimproveorinclude(const char *sourcedir, const char *basefilename, const char *filekey, struct checksums **checksums_p, bool *improving) {
	retvalue r;
	struct checksums *checksums = NULL;
	bool improves, copied = false;
	char *fullfilename = files_calcfullfilename(filekey);

	if (FAILEDTOALLOC(fullfilename))
		return RET_ERROR_OOM;

	if (checksums_iscomplete(*checksums_p)) {
		r = checksums_cheaptest(fullfilename, *checksums_p, true);
		if (r != RET_NOTHING) {
			free(fullfilename);
			return r;
		}
	} else {
		r = checksums_read(fullfilename, &checksums);
		if (RET_WAS_ERROR(r)) {
			free(fullfilename);
			return r;
		}
	}
	if (r == RET_NOTHING) {
		char *sourcefilename = calc_dirconcat(sourcedir, basefilename);

		if (FAILEDTOALLOC(sourcefilename)) {
			free(fullfilename);
			return RET_ERROR_OOM;
		}

		fprintf(stderr,
"WARNING: file %s was lost!\n"
"(i.e. found in the database, but not in the pool)\n"
"trying to compensate...\n",
				filekey);
		(void)dirs_make_parent(fullfilename);
		r = checksums_copyfile(fullfilename, sourcefilename, false,
				&checksums);
		if (r == RET_ERROR_EXIST) {
			fprintf(stderr,
"File '%s' seems to be missing and existing at the same time!\n"
"To confused to continue...\n",
					fullfilename);
		}
		if (r == RET_NOTHING) {
			fprintf(stderr, "Could not open '%s'!\n",
					sourcefilename);
			r = RET_ERROR_MISSING;
		}
		free(sourcefilename);
		if (RET_WAS_ERROR(r)) {
			free(fullfilename);
			return r;
		}
		copied = true;
	}

	assert (checksums != NULL);

	if (!checksums_check(*checksums_p, checksums, &improves)) {
		if (copied) {
			deletefile(fullfilename);
			fprintf(stderr,
"ERROR: Unexpected content of file '%s/%s'!\n", sourcedir, basefilename);
		} else
// TODO: if the database only listed some of the currently supported checksums,
// and the caller of checkincludefile supplied some (which none yet does), but
// not all (which needs at least three checksums, i.e. not applicaple before
// sha256 get added), then this might also be called if the file in the pool
// just has the same checksums as previously recorded (e.g. a md5sum collision)
// but the new file was listed with another secondary hash than the original.
// In that situation it might be a bit misleading...
			fprintf(stderr,
"ERROR: file %s is damaged!\n"
"(i.e. found in the database, but with different checksums in the pool)\n",
				filekey);
		checksums_printdifferences(stderr, *checksums_p, checksums);
		r = RET_ERROR_WRONG_MD5;
	}
	if (improves) {
		r = checksums_combine(checksums_p, checksums, NULL);
		if (RET_IS_OK(r))
			*improving = true;
	}
	checksums_free(checksums);
	free(fullfilename);
	return r;
}
Esempio n. 29
0
retvalue files_checkincludefile(const char *sourcedir, const char *basefilename, const char *filekey, struct checksums **checksums_p) {
	char *sourcefilename, *fullfilename;
	struct checksums *checksums;
	retvalue r;
	bool improves;

	assert (*checksums_p != NULL);

	r = files_get_checksums(filekey, &checksums);
	if (RET_WAS_ERROR(r))
		return r;
	if (RET_IS_OK(r)) {
		/* there are three sources now:
		 *  - the checksums from the database (may have some we
		 *    do not even know about, and may miss some we can
		 *    generate)
		 *  - the checksums provided (typically only md5sum,
		 *    as this comes from a .changes or .dsc)
		 *  - the checksums of the file
		 *
		 *  to make things more complicated, the file should only
		 *  be read if needed, as this needs time.
		 *  And it can happen the file got lost in the pool, then
		 *  this is the best place to replace it.
		 */
		if (!checksums_check(checksums, *checksums_p, &improves)) {
			fprintf(stderr,
"ERROR: '%s/%s' cannot be included as '%s'.\n"
"Already existing files can only be included again, if they are the same, but:\n",
				sourcedir, basefilename, filekey);
			checksums_printdifferences(stderr, checksums,
					*checksums_p);
			checksums_free(checksums);
			return RET_ERROR_WRONG_MD5;
		}
		r = RET_NOTHING;
		if (improves)
			r = checksums_combine(&checksums, *checksums_p, NULL);
		if (!RET_WAS_ERROR(r))
			r = checkimproveorinclude(sourcedir,
				basefilename, filekey, &checksums, &improves);
		if (!RET_WAS_ERROR(r) && improves)
			r = files_replace_checksums(filekey, checksums);
		if (RET_IS_OK(r))
			r = RET_NOTHING;
		/* return the combined checksum */
		checksums_free(*checksums_p);
		*checksums_p = checksums;
		return r;
	}

	assert (sourcedir != NULL);
	sourcefilename = calc_dirconcat(sourcedir, basefilename);
	if (FAILEDTOALLOC(sourcefilename))
		return RET_ERROR_OOM;

	fullfilename = files_calcfullfilename(filekey);
	if (FAILEDTOALLOC(fullfilename)) {
		free(sourcefilename);
		return RET_ERROR_OOM;
	}

	(void)dirs_make_parent(fullfilename);
	r = checksums_copyfile(fullfilename, sourcefilename, true, &checksums);
	if (r == RET_NOTHING) {
		fprintf(stderr, "Could not open '%s'!\n", sourcefilename);
		r = RET_ERROR_MISSING;
	}
	if (RET_WAS_ERROR(r)) {
		free(fullfilename);
		free(sourcefilename);
		return r;
	}
	if (!checksums_check(*checksums_p, checksums, &improves)) {
		deletefile(fullfilename);
		fprintf(stderr, "ERROR: Unexpected content of file '%s'!\n",
				sourcefilename);
		checksums_printdifferences(stderr, *checksums_p, checksums);
		r = RET_ERROR_WRONG_MD5;
	}
	free(sourcefilename);
	free(fullfilename);
	if (RET_WAS_ERROR(r)) {
		return r;
	}
	if (improves) {
		r = checksums_combine(checksums_p, checksums, NULL);
		checksums_free(checksums);
		if (RET_WAS_ERROR(r))
			return r;
	} else
		checksums_free(checksums);

	return files_add_checksums(filekey, *checksums_p);
}
Esempio n. 30
0
static retvalue parse_condition_part(bool *allow_subkeys_p, bool *allow_bad_p, const char *full_condition, const char **condition_p, /*@out@*/ char **next_key_p) {
	const char *key = *condition_p, *p;
	char *next_key, *q;
	size_t kl;

	*allow_bad_p = false;
	*allow_subkeys_p = false;

	while (*key != '\0' && xisspace(*key))
		key++;
	if (*key == '\0') {
		fprintf(stderr,
"Error: unexpected end of VerifyRelease condition '%s'!\n",
				full_condition);
		return RET_ERROR;
	}

	p = key;
	while ((*p >= 'A' && *p <= 'F') || (*p >= 'a' && *p <= 'f')
			|| (*p >= '0' && *p <= '9'))
		p++;
	if (*p != '\0' && !xisspace(*p) && *p != '|' && *p != '!' && *p != '+') {
		fprintf(stderr,
"Error: Unexpected character 0x%02hhx='%c' in VerifyRelease condition '%s'!\n",
				*p, *p, full_condition);
		return RET_ERROR;
	}
	kl = p - key;
	if (kl < 8) {
		fprintf(stderr,
"Error: Too short key id '%.*s' in VerifyRelease condition '%s'!\n",
				(int)kl, key, full_condition);
		return RET_ERROR;
	}
	next_key = strndup(key, kl);
	if (FAILEDTOALLOC(next_key))
		return RET_ERROR_OOM;
	key = p;
	for (q = next_key ; *q != '\0' ; q++) {
		if (*q >= 'a' && *q <= 'f')
			*q -= 'a' - 'A';
	}
	while (*key != '\0' && xisspace(*key))
		key++;
	if (*key == '!') {
		*allow_bad_p = true;
		key++;
	}
	while (*key != '\0' && xisspace(*key))
		key++;
	if (*key == '+') {
		*allow_subkeys_p = true;
		key++;
	}
	while (*key != '\0' && xisspace(*key))
		key++;
	if ((*key >= 'A' && *key <= 'F')
			|| (*key >= 'a' && *key <= 'f')
			|| (*key >= '0' && *key <= '9')) {
		free(next_key);
		fprintf(stderr,
"Error: Space separated key-ids in VerifyRelease condition '%s'!\n"
"(Alternate keys can be separated with '|'. Do not put spaces in key-ids.)\n",
				full_condition);
		return RET_ERROR;
	}
	if (*key != '\0' && *key != '|') {
		free(next_key);
		fprintf(stderr,
"Error: Unexpected character 0x%02hhx='%c' in VerifyRelease condition '%s'!\n",
				*key, *key, full_condition);
		return RET_ERROR;
	}
	if (*key == '|')
		key++;
	*next_key_p = next_key;
	*condition_p = key;
	return RET_OK;
}