2 * libdpkg - Debian packaging suite library routines
3 * parsehelp.c - helpful routines for parsing and writing
5 * Copyright © 1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
6 * Copyright © 2006-2012 Guillem Jover <guillem@debian.org>
8 * This is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This is distributed in the hope that it will be useful,
14 * but 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 License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
31 #include <dpkg/i18n.h>
32 #include <dpkg/c-ctype.h>
33 #include <dpkg/dpkg.h>
34 #include <dpkg/dpkg-db.h>
35 #include <dpkg/string.h>
36 #include <dpkg/error.h>
37 #include <dpkg/parsedump.h>
40 parse_error_msg(struct parsedb_state
*ps
, const char *fmt
)
42 static char msg
[1024];
45 str_escape_fmt(filename
, ps
->filename
, sizeof(filename
));
47 if (ps
->pkg
&& ps
->pkg
->set
->name
) {
50 str_escape_fmt(pkgname
, pkgbin_name(ps
->pkg
, ps
->pkgbin
, pnaw_nonambig
),
52 sprintf(msg
, _("parsing file '%.255s' near line %d package '%.255s':\n"
53 " %.255s"), filename
, ps
->lno
, pkgname
, fmt
);
55 sprintf(msg
, _("parsing file '%.255s' near line %d:\n"
56 " %.255s"), filename
, ps
->lno
, fmt
);
62 parse_error(struct parsedb_state
*ps
, const char *fmt
, ...)
67 ohshitv(parse_error_msg(ps
, fmt
), args
);
71 parse_warn(struct parsedb_state
*ps
, const char *fmt
, ...)
76 warningv(parse_error_msg(ps
, fmt
), args
);
80 const struct fieldinfo
*
81 find_field_info(const struct fieldinfo
*fields
, const char *fieldname
)
83 const struct fieldinfo
*field
;
85 for (field
= fields
; field
->name
; field
++)
86 if (strcasecmp(field
->name
, fieldname
) == 0)
92 const struct arbitraryfield
*
93 find_arbfield_info(const struct arbitraryfield
*arbs
, const char *fieldname
)
95 const struct arbitraryfield
*arbfield
;
97 for (arbfield
= arbs
; arbfield
; arbfield
= arbfield
->next
)
98 if (strcasecmp(arbfield
->name
, fieldname
) == 0)
105 pkg_name_is_illegal(const char *p
)
107 /* FIXME: _ is deprecated, remove sometime. */
108 static const char alsoallowed
[] = "-+._";
109 static char buf
[150];
112 if (!*p
) return _("may not be empty string");
114 return _("must start with an alphanumeric character");
115 while ((c
= *p
++) != '\0')
116 if (!c_isalnum(c
) && !strchr(alsoallowed
, c
))
120 snprintf(buf
, sizeof(buf
), _(
121 "character '%c' not allowed (only letters, digits and characters '%s')"),
128 const struct dpkg_version
*version
,
129 enum versiondisplayepochwhen vdew
)
135 if (!version
->epoch
&&
136 (!version
->version
|| !strchr(version
->version
,':')) &&
137 (!version
->revision
|| !strchr(version
->revision
,':'))) break;
140 varbuf_printf(vb
, "%u:", version
->epoch
);
143 internerr("unknown versiondisplayepochwhen '%d'", vdew
);
145 if (version
->version
)
146 varbuf_add_str(vb
, version
->version
);
147 if (str_is_set(version
->revision
)) {
148 varbuf_add_char(vb
, '-');
149 varbuf_add_str(vb
, version
->revision
);
153 const char *versiondescribe
154 (const struct dpkg_version
*version
,
155 enum versiondisplayepochwhen vdew
)
157 static struct varbuf bufs
[10];
162 if (!dpkg_version_is_informative(version
))
163 return C_("version", "<none>");
165 vb
= &bufs
[bufnum
]; bufnum
++; if (bufnum
== 10) bufnum
= 0;
167 varbufversion(vb
,version
,vdew
);
174 * Parse a version string and check for invalid syntax.
176 * Distinguish between lax (warnings) and strict (error) parsing.
178 * @param rversion The parsed version.
179 * @param string The version string to parse.
180 * @param err The warning or error message if any.
182 * @retval 0 On success.
183 * @retval -1 On failure, and err is set accordingly.
186 parseversion(struct dpkg_version
*rversion
, const char *string
,
187 struct dpkg_error
*err
)
189 char *hyphen
, *colon
, *eepochcolon
;
190 const char *end
, *ptr
;
192 /* Trim leading and trailing space. */
193 while (*string
&& c_isblank(*string
))
197 return dpkg_put_error(err
, _("version string is empty"));
199 /* String now points to the first non-whitespace char. */
201 /* Find either the end of the string, or a whitespace char. */
202 while (*end
&& !c_isblank(*end
))
204 /* Check for extra chars after trailing space. */
206 while (*ptr
&& c_isblank(*ptr
))
209 return dpkg_put_error(err
, _("version string has embedded spaces"));
211 colon
= strchr(string
,':');
216 epoch
= strtol(string
, &eepochcolon
, 10);
217 if (string
== eepochcolon
)
218 return dpkg_put_error(err
, _("epoch in version is empty"));
219 if (colon
!= eepochcolon
)
220 return dpkg_put_error(err
, _("epoch in version is not number"));
222 return dpkg_put_error(err
, _("epoch in version is negative"));
223 if (epoch
> INT_MAX
|| errno
== ERANGE
)
224 return dpkg_put_error(err
, _("epoch in version is too big"));
226 return dpkg_put_error(err
, _("nothing after colon in version number"));
228 rversion
->epoch
= epoch
;
232 rversion
->version
= nfstrnsave(string
,end
-string
);
233 hyphen
= strrchr(rversion
->version
,'-');
238 return dpkg_put_error(err
, _("revision number is empty"));
240 rversion
->revision
= hyphen ? hyphen
: "";
242 /* XXX: Would be faster to use something like cisversion and cisrevision. */
243 ptr
= rversion
->version
;
245 return dpkg_put_error(err
, _("version number is empty"));
246 if (*ptr
&& !c_isdigit(*ptr
++))
247 return dpkg_put_warn(err
, _("version number does not start with digit"));
248 for (; *ptr
; ptr
++) {
249 if (!c_isdigit(*ptr
) && !c_isalpha(*ptr
) && strchr(".-+~:", *ptr
) == NULL
)
250 return dpkg_put_warn(err
, _("invalid character in version number"));
252 for (ptr
= rversion
->revision
; *ptr
; ptr
++) {
253 if (!c_isdigit(*ptr
) && !c_isalpha(*ptr
) && strchr(".+~", *ptr
) == NULL
)
254 return dpkg_put_warn(err
, _("invalid character in revision number"));
261 * Parse a version string coming from a database file.
263 * It parses a version string, and prints a warning or an error depending
264 * on the parse options.
266 * @param ps The parsedb state.
267 * @param version The version to parse into.
268 * @param value The version string to parse from.
269 * @param fmt The error format string.
272 parse_db_version(struct parsedb_state
*ps
, struct dpkg_version
*version
,
273 const char *value
, const char *fmt
, ...)
275 struct dpkg_error err
;
279 if (parseversion(version
, value
, &err
) == 0)
283 vsnprintf(buf
, sizeof(buf
), fmt
, args
);
286 if (err
.type
== DPKG_MSG_WARN
&& (ps
->flags
& pdb_lax_version_parser
))
287 parse_warn(ps
, "%s: %.250s", buf
, err
.str
);
289 parse_error(ps
, "%s: %.250s", buf
, err
.str
);
291 dpkg_error_destroy(&err
);
295 parse_must_have_field(struct parsedb_state
*ps
,
296 const char *value
, const char *what
)
299 parse_error(ps
, _("missing %s"), what
);
301 parse_error(ps
, _("empty value for %s"), what
);
305 parse_ensure_have_field(struct parsedb_state
*ps
,
306 const char **value
, const char *what
)
308 static const char empty
[] = "";
311 parse_warn(ps
, _("missing %s"), what
);
313 } else if (!**value
) {
314 parse_warn(ps
, _("empty value for %s"), what
);