dpkg (1.18.25) stretch; urgency=medium
[dpkg] / lib / dpkg / deb-version.c
CommitLineData
1479465f
GJ
1/*
2 * libdpkg - Debian packaging suite library routines
3 * deb-version.c - deb format version handling routines
4 *
5 * Copyright © 2012-2013 Guillem Jover <guillem@debian.org>
6 *
7 * This is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <config.h>
22#include <compat.h>
23
24#include <limits.h>
25#include <string.h>
26#include <stdlib.h>
27
28#include <dpkg/i18n.h>
29#include <dpkg/c-ctype.h>
30#include <dpkg/dpkg.h>
31#include <dpkg/deb-version.h>
32
33/**
34 * Parse a .deb format version.
35 *
36 * It takes a string and parses a .deb archive format version in the form
37 * of "X.Y", without any leading whitespace, and ending in either a newline
38 * or a NUL. If there is any syntax error a descriptive error string is
39 * returned.
40 *
41 * @param version The version to return.
42 * @param str The string to parse.
43 *
44 * @return An error string, or NULL if there was no error.
45 */
46const char *
47deb_version_parse(struct deb_version *version, const char *str)
48{
49 const char *str_minor, *end;
50 unsigned int major = 0;
51 unsigned int minor = 0;
52 unsigned int divlimit = INT_MAX / 10;
53 int modlimit = INT_MAX % 10;
54
55 for (end = str; *end && c_isdigit(*end); end++) {
56 int ord = *end - '0';
57
58 if (major > divlimit || (major == divlimit && ord > modlimit))
59 return _("format version with too big major component");
60
61 major = major * 10 + ord;
62 }
63
64 if (end == str)
65 return _("format version with empty major component");
66 if (*end != '.')
67 return _("format version has no dot");
68
69 for (end = str_minor = end + 1; *end && c_isdigit(*end); end++) {
70 int ord = *end - '0';
71
72 if (minor > divlimit || (minor == divlimit && ord > modlimit))
73 return _("format version with too big minor component");
74
75 minor = minor * 10 + ord;
76 }
77
78 if (end == str_minor)
79 return _("format version with empty minor component");
80 if (*end != '\n' && *end != '\0')
81 return _("format version followed by junk");
82
83 version->major = major;
84 version->minor = minor;
85
86 return NULL;
87}