reference.c 5.11 KB
Newer Older
Bernhard Link's avatar
Bernhard Link committed
1
/*  This file is part of "reprepro"
2
 *  Copyright (C) 2003,2004,2005,2007 Bernhard R. Link
3
 *  This program is free software; you can redistribute it and/or modify
4
 *  it under the terms of the GNU General Public License version 2 as
Bernhard Link's avatar
Bernhard Link committed
5
 *  published by the Free Software Foundation.
6 7 8 9 10 11 12 13
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
Bernhard Link's avatar
Bernhard Link committed
14
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02111-1301  USA
15
 */
Bernhard Link's avatar
Bernhard Link committed
16 17
#include <config.h>

18
#include <assert.h>
Bernhard Link's avatar
Bernhard Link committed
19 20 21 22 23
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
#include <malloc.h>
24
#include <stdlib.h>
Bernhard Link's avatar
Bernhard Link committed
25
#include <string.h>
26

Bernhard Link's avatar
Bernhard Link committed
27
#include "error.h"
28
#include "strlist.h"
29
#include "names.h"
Bernhard Link's avatar
Bernhard Link committed
30
#include "dirs.h"
31
#include "database_p.h"
32
#include "pool.h"
Bernhard Link's avatar
Bernhard Link committed
33
#include "reference.h"
Bernhard Link's avatar
Bernhard Link committed
34

35
retvalue references_isused(struct database *database,const char *what) {
36
	return table_gettemprecord(database->references, what, NULL, NULL);
37 38
}

39
retvalue references_check(struct database *database,const char *referee,const struct strlist *filekeys) {
40
	int i;
41
	retvalue result, r;
42

43
	result = RET_NOTHING;
44
	for( i = 0 ; i < filekeys->count ; i++ ) {
45 46 47 48 49 50 51 52
		r = table_checkrecord(database->references,
				filekeys->values[i], referee);
		if( r == RET_NOTHING ) {
			fprintf(stderr,"Missing reference to '%s' by '%s'\n",
					filekeys->values[i], referee);
			r = RET_ERROR;
		}
		RET_UPDATE(result, r);
53
	}
54
	return result;
55
}
56

57
/* add an reference to a file for an identifier. multiple calls */
58
retvalue references_increment(struct database *database,const char *needed,const char *neededby) {
59
	retvalue r;
Bernhard Link's avatar
Bernhard Link committed
60

61 62 63
	r = table_addrecord(database->references, needed,
			neededby, strlen(neededby), false);
	if( RET_IS_OK(r) && verbose > 8 )
64 65
		printf("Adding reference to '%s' by '%s'\n", needed,neededby);
	return r;
Bernhard Link's avatar
Bernhard Link committed
66 67
}

68
/* remove reference for a file from a given reference */
69
retvalue references_decrement(struct database *database,const char *needed,const char *neededby) {
70 71
	retvalue r;

72 73 74 75 76 77 78 79
	r = table_removerecord(database->references, needed, neededby);
	if( r == RET_NOTHING )
		return r;
	if( RET_WAS_ERROR(r) ) {
		fprintf(stderr,
"Error while trying to removing reference to '%s' by '%s'\n",
				needed, neededby);
		return r;
80
	}
81 82 83
	if( verbose > 8 )
		fprintf(stderr,"Removed reference to '%s' by '%s'\n",
				needed, neededby);
84 85 86 87 88
	if( RET_IS_OK(r) ) {
		retvalue r2;
		r2 = pool_dereferenced(needed);
		RET_UPDATE(r, r2);
	}
89 90 91
	return r;
}

92 93
/* Add an reference by <identifer> for the given <files>,
 * excluding <exclude>, if it is nonNULL. */
94
retvalue references_insert(struct database *database,const char *identifier,
95 96 97 98 99 100 101 102 103 104
		const struct strlist *files,const struct strlist *exclude) {
	retvalue result,r;
	int i;

	result = RET_NOTHING;

	for( i = 0 ; i < files->count ; i++ ) {
		const char *filename = files->values[i];

		if( exclude == NULL || !strlist_in(exclude,filename) ) {
105
			r = references_increment(database, filename, identifier);
106 107 108 109 110 111
			RET_UPDATE(result,r);
		}
	}
	return result;
}

Bernhard Link's avatar
Bernhard Link committed
112
/* add possible already existing references */
113
retvalue references_add(struct database *database,const char *identifier,const struct strlist *files) {
Bernhard Link's avatar
Bernhard Link committed
114
	int i;
115
	retvalue r;
Bernhard Link's avatar
Bernhard Link committed
116 117 118

	for( i = 0 ; i < files->count ; i++ ) {
		const char *filekey = files->values[i];
119 120
		r = table_addrecord(database->references, filekey,
				identifier, strlen(identifier), true);
121 122
		if( RET_WAS_ERROR(r) )
			return r;
Bernhard Link's avatar
Bernhard Link committed
123 124 125 126
	}
	return RET_OK;
}

127 128
/* Remove reference by <identifer> for the given <oldfiles>,
 * excluding <exclude>, if it is nonNULL. */
129
retvalue references_delete(struct database *database, const char *identifier, struct strlist *files, const struct strlist *exclude) {
130 131 132
	retvalue result,r;
	int i;

133 134
	assert( files != NULL );

135 136 137
	result = RET_NOTHING;

	for( i = 0 ; i < files->count ; i++ ) {
138
		const char *filekey = files->values[i];
139

140
		if( exclude == NULL || !strlist_in(exclude,filekey) ) {
141
			r = references_decrement(database, filekey, identifier);
142
			RET_UPDATE(result,r);
143
		}
144 145
	}
	return result;
146

147 148
}

149
/* remove all references from a given identifier */
150
retvalue references_remove(struct database *database, const char *neededby) {
151 152 153 154 155 156 157 158
	struct cursor *cursor;
	retvalue result, r;
	const char *found_to, *found_by;
	size_t datalen, l;

	r = table_newglobalcursor(database->references, &cursor);
	if( !RET_IS_OK(r) )
		return r;
Bernhard Link's avatar
Bernhard Link committed
159

160
	l = strlen(neededby);
161 162 163 164 165 166

	result = RET_NOTHING;
	while( cursor_nexttempdata(database->references, cursor,
				&found_to, &found_by, &datalen) ) {

		if( datalen >= l && strncmp(found_by, neededby, l) == 0 &&
167
		    (found_by[l] == '\0' || found_by[l] == ' ')) {
Bernhard Link's avatar
Bernhard Link committed
168
			if( verbose > 8 )
169
				fprintf(stderr,"Removing reference to '%s' by '%s'\n",
170
					found_to,neededby);
171 172
			r = cursor_delete(database->references, cursor,
					found_to, NULL);
173
			RET_UPDATE(result, r);
174 175
			if( RET_IS_OK(r) ) {
				r = pool_dereferenced(found_to);
176
				RET_ENDUPDATE(result, r);
Bernhard Link's avatar
Bernhard Link committed
177 178 179
			}
		}
	}
180 181
	r = cursor_close(database->references, cursor);
	RET_ENDUPDATE(result, r);
Bernhard Link's avatar
Bernhard Link committed
182
	return result;
183
}
184