2
* libdpkg - Debian packaging suite library routines
3
* fields.c - parsing of all the different fields, when reading in
5
* Copyright © 1995 Ian Jackson <ian@chiark.greenend.org.uk>
6
* Copyright © 2001 Wichert Akkerman
8
* This is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as
10
* published by the Free Software Foundation; either version 2,
11
* or (at your option) any later version.
13
* This is distributed in the hope that it will be useful, but
14
* WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public
19
* License along with dpkg; if not, write to the Free Software
20
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25
#include <dpkg/i18n.h>
31
#include <dpkg/dpkg.h>
32
#include <dpkg/dpkg-db.h>
33
#include <dpkg/path.h>
34
#include <dpkg/parsedump.h>
37
convert_string(struct parsedb_state *ps, const char *what, int otherwise,
38
const struct pkginfo *pigp,
39
const char *startp, const struct namevalue *ivip,
43
const struct namevalue *nvip = ivip;
46
parse_error(ps, pigp, _("%s is missing"), what);
48
if (strncasecmp(nvip->name, startp, nvip->length))
54
if (otherwise != -1) return otherwise;
55
parse_error(ps, pigp, _("`%.*s' is not allowed for %s"),
56
(int)strnlen(startp, 50), startp, what);
59
ep = startp + nvip->length;
63
parse_error(ps, pigp, _("junk after %s"), what);
64
if (endpp) *endpp= ep;
69
f_name(struct pkginfo *pigp, struct pkginfoperfile *pifp,
70
struct parsedb_state *ps,
71
const char *value, const struct fieldinfo *fip)
74
if ((e= illegal_packagename(value,NULL)) != NULL)
75
parse_error(ps, pigp, _("invalid package name (%.250s)"), e);
76
pigp->name= findpackage(value)->name;
77
/* We use the new name, as findpackage() may have
78
done a tolower for us.
82
void f_filecharf(struct pkginfo *pigp, struct pkginfoperfile *pifp,
83
struct parsedb_state *ps,
84
const char *value, const struct fieldinfo *fip) {
85
struct filedetails *fdp, **fdpp;
90
parse_error(ps, pigp, _("empty file details field `%s'"), fip->name);
91
if (!(ps->flags & pdb_recordavailable))
93
_("file details field `%s' not allowed in status file"),
95
allowextend= !pigp->files;
97
cpos= nfstrsave(value);
99
space= cpos; while (*space && !isspace(*space)) space++;
105
parse_error(ps, pigp,
106
_("too many values in file details field `%s' "
107
"(compared to others)"), fip->name);
108
fdp= nfmalloc(sizeof(struct filedetails));
110
fdp->name= fdp->msdosname= fdp->size= fdp->md5sum= NULL;
113
FILEFFIELD(fdp,fip->integer,const char*)= cpos;
115
while (*space && isspace(*space)) space++;
119
parse_error(ps, pigp,
120
_("too few values in file details field `%s' "
121
"(compared to others)"), fip->name);
124
void f_charfield(struct pkginfo *pigp, struct pkginfoperfile *pifp,
125
struct parsedb_state *ps,
126
const char *value, const struct fieldinfo *fip) {
127
if (*value) PKGPFIELD(pifp,fip->integer,char*)= nfstrsave(value);
130
void f_boolean(struct pkginfo *pigp, struct pkginfoperfile *pifp,
131
struct parsedb_state *ps,
132
const char *value, const struct fieldinfo *fip) {
138
boolean = convert_string(ps, _("yes/no in boolean field"),
139
-1, pigp, value, booleaninfos, NULL);
140
PKGPFIELD(pifp, fip->integer, int) = boolean;
143
void f_section(struct pkginfo *pigp, struct pkginfoperfile *pifp,
144
struct parsedb_state *ps,
145
const char *value, const struct fieldinfo *fip) {
147
pigp->section= nfstrsave(value);
150
void f_priority(struct pkginfo *pigp, struct pkginfoperfile *pifp,
151
struct parsedb_state *ps,
152
const char *value, const struct fieldinfo *fip) {
154
pigp->priority = convert_string(ps, _("word in `priority' field"),
155
pri_other, pigp, value, priorityinfos, NULL);
156
if (pigp->priority == pri_other) pigp->otherpriority= nfstrsave(value);
159
void f_status(struct pkginfo *pigp, struct pkginfoperfile *pifp,
160
struct parsedb_state *ps,
161
const char *value, const struct fieldinfo *fip) {
164
if (ps->flags & pdb_rejectstatus)
165
parse_error(ps, pigp,
166
_("value for `status' field not allowed in this context"));
167
if (ps->flags & pdb_recordavailable)
170
pigp->want = convert_string(ps, _("first (want) word in `status' field"),
171
-1, pigp, value, wantinfos, &ep);
172
pigp->eflag = convert_string(ps, _("second (error) word in `status' field"),
173
-1, pigp, ep, eflaginfos, &ep);
174
pigp->status = convert_string(ps, _("third (status) word in `status' field"),
175
-1, pigp, ep, statusinfos, NULL);
178
void f_version(struct pkginfo *pigp, struct pkginfoperfile *pifp,
179
struct parsedb_state *ps,
180
const char *value, const struct fieldinfo *fip) {
183
emsg= parseversion(&pifp->version,value);
185
parse_error(ps, pigp,
186
_("error in Version string `%.250s': %.250s"), value, emsg);
189
void f_revision(struct pkginfo *pigp, struct pkginfoperfile *pifp,
190
struct parsedb_state *ps,
191
const char *value, const struct fieldinfo *fip) {
195
_("obsolete `Revision' or `Package-Revision' field used"));
197
if (pifp->version.revision && *pifp->version.revision) {
198
newversion= nfmalloc(strlen(pifp->version.version)+strlen(pifp->version.revision)+2);
199
sprintf(newversion,"%s-%s",pifp->version.version,pifp->version.revision);
200
pifp->version.version= newversion;
202
pifp->version.revision= nfstrsave(value);
205
void f_configversion(struct pkginfo *pigp, struct pkginfoperfile *pifp,
206
struct parsedb_state *ps,
207
const char *value, const struct fieldinfo *fip) {
210
if (ps->flags & pdb_rejectstatus)
211
parse_error(ps, pigp,
212
_("value for `config-version' field not allowed in this context"));
213
if (ps->flags & pdb_recordavailable)
216
emsg= parseversion(&pigp->configversion,value);
218
parse_error(ps, pigp,
219
_("error in Config-Version string `%.250s': %.250s"),
223
static void conffvalue_lastword(const char *value, const char *from,
225
const char **word_start_r, int *word_len_r,
226
const char **new_from_r,
227
struct parsedb_state *ps,
228
struct pkginfo *pigp)
230
/* the code in f_conffiles ensures that value[-1]==' ', which is helpful */
233
if (from <= value+1) goto malformed;
234
for (lastspc= from-1; *lastspc != ' '; lastspc--);
235
if (lastspc <= value+1 || lastspc >= endent-1) goto malformed;
237
*new_from_r= lastspc;
238
*word_start_r= lastspc + 1;
239
*word_len_r= (int)(from - *word_start_r);
243
parse_error(ps, pigp,
244
_("value for `conffiles' has malformatted line `%.*s'"),
245
(int)min(endent - value, 250), value);
248
void f_conffiles(struct pkginfo *pigp, struct pkginfoperfile *pifp,
249
struct parsedb_state *ps,
250
const char *value, const struct fieldinfo *fip) {
251
static const char obsolete_str[]= "obsolete";
252
struct conffile **lastp, *newlink;
253
const char *endent, *endfn, *hashstart;
254
int c, namelen, hashlen, obsolete;
257
lastp= &pifp->conffiles;
260
if (c == '\n') continue;
262
parse_error(ps, pigp,
263
_("value for `conffiles' has line starting with non-space `%c'"),
265
for (endent = value; (c = *endent) != '\0' && c != '\n'; endent++) ;
266
conffvalue_lastword(value, endent, endent,
267
&hashstart, &hashlen, &endfn,
269
obsolete= (hashlen == sizeof(obsolete_str)-1 &&
270
!memcmp(hashstart, obsolete_str, hashlen));
272
conffvalue_lastword(value, endfn, endent,
273
&hashstart, &hashlen, &endfn,
275
newlink= nfmalloc(sizeof(struct conffile));
276
value = path_skip_slash_dotslash(value);
277
namelen= (int)(endfn-value);
279
parse_error(ps, pigp,
280
_("root or null directory is listed as a conffile"));
281
newptr = nfmalloc(namelen+2);
283
memcpy(newptr+1,value,namelen);
284
newptr[namelen+1] = '\0';
285
newlink->name= newptr;
286
newptr= nfmalloc(hashlen+1);
287
memcpy(newptr, hashstart, hashlen);
288
newptr[hashlen] = '\0';
289
newlink->hash= newptr;
290
newlink->obsolete= obsolete;
293
lastp= &newlink->next;
298
void f_dependency(struct pkginfo *pigp, struct pkginfoperfile *pifp,
299
struct parsedb_state *ps,
300
const char *value, const struct fieldinfo *fip) {
302
const char *p, *emsg;
303
const char *depnamestart, *versionstart;
304
int depnamelength, versionlength;
305
static int depnameused= 0, versionused= 0;
306
static char *depname= NULL, *version= NULL;
308
struct dependency *dyp, **ldypp;
309
struct deppossi *dop, **ldopp;
311
if (!*value) return; /* empty fields are ignored */
313
ldypp= &pifp->depends; while (*ldypp) ldypp= &(*ldypp)->next;
314
for (;;) { /* loop creating new struct dependency's */
315
dyp= nfmalloc(sizeof(struct dependency));
316
dyp->up= NULL; /* Set this to zero for now, as we don't know what our real
317
* struct pkginfo address (in the database) is going to be yet.
319
dyp->next= NULL; *ldypp= dyp; ldypp= &dyp->next;
320
dyp->list= NULL; ldopp= &dyp->list;
321
dyp->type= fip->integer;
322
for (;;) { /* loop creating new struct deppossi's */
324
/* skip over package name characters */
325
while (*p && !isspace(*p) && *p != '(' && *p != ',' && *p != '|') {
328
depnamelength= p - depnamestart ;
329
if (depnamelength >= depnameused) {
330
depnameused= depnamelength;
331
depname = m_realloc(depname, depnamelength + 1);
333
strncpy(depname, depnamestart, depnamelength);
334
*(depname + depnamelength) = '\0';
336
parse_error(ps, pigp,
337
_("`%s' field, missing package name, or garbage where "
338
"package name expected"), fip->name);
339
emsg= illegal_packagename(depname,NULL);
341
parse_error(ps, pigp,
342
_("`%s' field, invalid package name `%.255s': %s"),
343
fip->name, depname, emsg);
344
dop= nfmalloc(sizeof(struct deppossi));
346
dop->ed= findpackage(depname);
347
dop->next= NULL; *ldopp= dop; ldopp= &dop->next;
348
dop->nextrev= NULL; /* Don't link this (which is after all only `newpig' from */
349
dop->backrev= NULL; /* the main parsing loop in parsedb) into the depended on
350
* packages' lists yet. This will be done later when we
351
* install this (in parse.c). For the moment we do the
352
* `forward' links in deppossi (`ed') only, and the backward
353
* links from the depended on packages to dop are left undone.
356
/* skip whitespace after packagename */
357
while (isspace(*p)) p++;
358
if (*p == '(') { /* if we have a versioned relation */
359
p++; while (isspace(*p)) p++;
361
if (c1 == '<' || c1 == '>') {
363
dop->verrel= (c1 == '<') ? dvrf_earlier : dvrf_later;
365
dop->verrel |= (dvrf_orequal | dvrf_builtup);
367
} else if (c2 == c1) {
368
dop->verrel |= (dvrf_strict | dvrf_builtup);
370
} else if (c2 == '<' || c2 == '>') {
371
parse_error(ps, pigp,
372
_("`%s' field, reference to `%.255s':\n"
373
" bad version relationship %c%c"),
374
fip->name, depname, c1, c2);
375
dop->verrel= dvr_none;
378
_("`%s' field, reference to `%.255s':\n"
379
" `%c' is obsolete, use `%c=' or `%c%c' instead"),
380
fip->name, depname, c1, c1, c1, c1);
381
dop->verrel |= (dvrf_orequal | dvrf_builtup);
383
} else if (c1 == '=') {
384
dop->verrel= dvr_exact;
388
_("`%s' field, reference to `%.255s':\n"
389
" implicit exact match on version number, "
390
"suggest using `=' instead"),
392
dop->verrel= dvr_exact;
394
if ((dop->verrel!=dvr_exact) && (fip->integer==dep_provides))
396
_("Only exact versions may be used for Provides"));
398
if (!isspace(*p) && !isalnum(*p)) {
400
_("`%s' field, reference to `%.255s':\n"
401
" version value starts with non-alphanumeric, "
402
"suggest adding a space"),
405
/* skip spaces between the relation and the version */
406
while (isspace(*p)) p++;
409
while (*p && *p != ')' && *p != '(') {
410
if (isspace(*p)) break;
413
versionlength= p - versionstart;
414
while (isspace(*p)) p++;
416
parse_error(ps, pigp,
417
_("`%s' field, reference to `%.255s': "
418
"version contains `%c'"), fip->name,depname, ')');
420
parse_error(ps, pigp,
421
_("`%s' field, reference to `%.255s': "
422
"version contains `%c'"), fip->name,depname, ' ');
424
parse_error(ps, pigp,
425
_("`%s' field, reference to `%.255s': "
426
"version unterminated"), fip->name, depname);
427
if (versionlength >= versionused) {
428
versionused= versionlength;
429
version = m_realloc(version, versionlength + 1);
431
strncpy(version, versionstart, versionlength);
432
*(version + versionlength) = '\0';
433
emsg= parseversion(&dop->version,version);
435
parse_error(ps, pigp,
436
_("`%s' field, reference to `%.255s': "
437
"error in version: %.255s"), fip->name, depname, emsg);
438
p++; while (isspace(*p)) p++;
440
dop->verrel= dvr_none;
441
blankversion(&dop->version);
443
if (!*p || *p == ',') break;
445
parse_error(ps, pigp,
446
_("`%s' field, syntax error after reference to package `%.255s'"),
447
fip->name, dop->ed->name);
448
if (fip->integer == dep_conflicts ||
449
fip->integer == dep_breaks ||
450
fip->integer == dep_provides ||
451
fip->integer == dep_replaces)
452
parse_error(ps, pigp,
453
_("alternatives (`|') not allowed in %s field"), fip->name);
454
p++; while (isspace(*p)) p++;
457
p++; while (isspace(*p)) p++;
462
scan_word(const char **valp)
468
const char *p, *start, *end;
484
if (*p && !cisspace(*p)) {
494
buf = m_realloc(buf, avail);
496
memcpy(buf, start, l);
504
f_trigpend(struct pkginfo *pend, struct pkginfoperfile *pifp,
505
struct parsedb_state *ps,
506
const char *value, const struct fieldinfo *fip)
508
const char *word, *emsg;
510
if (ps->flags & pdb_rejectstatus)
511
parse_error(ps, pend,
512
_("value for `triggers-pending' field not allowed in "
515
while ((word = scan_word(&value))) {
516
emsg = illegal_triggername(word);
518
parse_error(ps, pend,
519
_("illegal pending trigger name `%.255s': %s"), word, emsg);
521
if (!trig_note_pend_core(pend, nfstrsave(word)))
522
parse_error(ps, pend,
523
_("duplicate pending trigger `%.255s'"), word);
528
f_trigaw(struct pkginfo *aw, struct pkginfoperfile *pifp,
529
struct parsedb_state *ps,
530
const char *value, const struct fieldinfo *fip)
532
const char *word, *emsg;
533
struct pkginfo *pend;
535
if (ps->flags & pdb_rejectstatus)
537
_("value for `triggers-awaited' field not allowed in "
540
while ((word = scan_word(&value))) {
541
emsg = illegal_packagename(word, NULL);
544
_("illegal package name in awaited trigger `%.255s': %s"),
546
pend = findpackage(word);
548
if (!trig_note_aw(pend, aw))
550
_("duplicate awaited trigger package `%.255s'"), word);
552
trig_enqueue_awaited_pend(pend);