Deleted Added
full compact
version.c (98766) version.c (101677)
1/*
1/*
2 * FreeBSD install - a package for the installation and maintainance
2 * FreeBSD install - a package for the installation and maintenance
3 * of non-core utilities.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * Maxim Sobolev
15 * 31 July 2001
16 *
17 */
18
19#include <sys/cdefs.h>
3 * of non-core utilities.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * Maxim Sobolev
15 * 31 July 2001
16 *
17 */
18
19#include <sys/cdefs.h>
20__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/lib/version.c 98766 2002-06-24 16:03:24Z markm $");
20__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/lib/version.c 101677 2002-08-11 13:05:30Z schweikh $");
21
22#include "lib.h"
23#include <err.h>
24
25/*
26 * Routines to assist with PLIST_FMT_VER numbers in the packing
27 * lists.
28 *
29 * Following is the PLIST_FMT_VER history:
30 * 1.0 - Initial revision;
31 * 1.1 - When recording/checking checksum of symlink use hash of readlink()
21
22#include "lib.h"
23#include <err.h>
24
25/*
26 * Routines to assist with PLIST_FMT_VER numbers in the packing
27 * lists.
28 *
29 * Following is the PLIST_FMT_VER history:
30 * 1.0 - Initial revision;
31 * 1.1 - When recording/checking checksum of symlink use hash of readlink()
32 * value insted of the hash of an object this links points to.
32 * value instead of the hash of an object this links points to.
33 *
34 */
35int
36verscmp(Package *pkg, int major, int minor)
37{
38 int rval = 0;
39
40 if ((pkg->fmtver_maj < major) || (pkg->fmtver_maj == major &&
41 pkg->fmtver_mnr < minor))
42 rval = -1;
43 else if ((pkg->fmtver_maj > major) || (pkg->fmtver_maj == major &&
44 pkg->fmtver_mnr > minor))
45 rval = 1;
46
47 return rval;
48}
49
50/*
51 * version_of(pkgname, epoch, revision) returns a pointer to the version
52 * portion of a package name and the two special components.
53 *
54 * Jeremy D. Lea.
55 */
56const char *
57version_of(const char *pkgname, int *epoch, int *revision)
58{
59 char *ch;
60
61 if (pkgname == NULL)
62 errx(2, "%s: Passed NULL pkgname.", __func__);
63 if (epoch != NULL) {
64 if ((ch = strrchr(pkgname, ',')) == NULL)
65 *epoch = 0;
66 else
67 *epoch = atoi(&ch[1]);
68 }
69 if (revision != NULL) {
70 if ((ch = strrchr(pkgname, '_')) == NULL)
71 *revision = 0;
72 else
73 *revision = atoi(&ch[1]);
74 }
75 /* Cheat if we are just passed a version, not a valid package name */
76 if ((ch = strrchr(pkgname, '-')) == NULL)
77 return pkgname;
78 else
79 return &ch[1];
80}
81
82/*
83 * version_cmp(pkg1, pkg2) returns -1, 0 or 1 depending on if the version
84 * components of pkg1 is less than, equal to or greater than pkg2. No
33 *
34 */
35int
36verscmp(Package *pkg, int major, int minor)
37{
38 int rval = 0;
39
40 if ((pkg->fmtver_maj < major) || (pkg->fmtver_maj == major &&
41 pkg->fmtver_mnr < minor))
42 rval = -1;
43 else if ((pkg->fmtver_maj > major) || (pkg->fmtver_maj == major &&
44 pkg->fmtver_mnr > minor))
45 rval = 1;
46
47 return rval;
48}
49
50/*
51 * version_of(pkgname, epoch, revision) returns a pointer to the version
52 * portion of a package name and the two special components.
53 *
54 * Jeremy D. Lea.
55 */
56const char *
57version_of(const char *pkgname, int *epoch, int *revision)
58{
59 char *ch;
60
61 if (pkgname == NULL)
62 errx(2, "%s: Passed NULL pkgname.", __func__);
63 if (epoch != NULL) {
64 if ((ch = strrchr(pkgname, ',')) == NULL)
65 *epoch = 0;
66 else
67 *epoch = atoi(&ch[1]);
68 }
69 if (revision != NULL) {
70 if ((ch = strrchr(pkgname, '_')) == NULL)
71 *revision = 0;
72 else
73 *revision = atoi(&ch[1]);
74 }
75 /* Cheat if we are just passed a version, not a valid package name */
76 if ((ch = strrchr(pkgname, '-')) == NULL)
77 return pkgname;
78 else
79 return &ch[1];
80}
81
82/*
83 * version_cmp(pkg1, pkg2) returns -1, 0 or 1 depending on if the version
84 * components of pkg1 is less than, equal to or greater than pkg2. No
85 * comparision of the basenames is done.
85 * comparison of the basenames is done.
86 *
86 *
87 * The port verison is defined by:
87 * The port version is defined by:
88 * ${PORTVERSION}[_${PORTREVISION}][,${PORTEPOCH}]
88 * ${PORTVERSION}[_${PORTREVISION}][,${PORTEPOCH}]
89 * ${PORTEPOCH} supercedes ${PORTVERSION} supercedes ${PORTREVISION}.
89 * ${PORTEPOCH} supersedes ${PORTVERSION} supersedes ${PORTREVISION}.
90 * See the commit log for revision 1.349 of ports/Mk/bsd.port.mk
91 * for more information.
92 *
93 * The epoch and revision are defined to be a single number, while the rest
94 * of the version should conform to the porting guidelines. It can contain
90 * See the commit log for revision 1.349 of ports/Mk/bsd.port.mk
91 * for more information.
92 *
93 * The epoch and revision are defined to be a single number, while the rest
94 * of the version should conform to the porting guidelines. It can contain
95 * multiple components, seperated by a period, including letters.
95 * multiple components, separated by a period, including letters.
96 *
97 * The tests below allow for significantly more latitude in the version
98 * numbers than is allowed in the guidelines. No point in wasting user's
99 * time enforcing them here. That's what flamewars are for.
100 *
101 * Jeremy D. Lea.
102 */
103int
104version_cmp(const char *pkg1, const char *pkg2)
105{
106 const char *c1, *c2, *v1, *v2;
107 char *t1, *t2;
108 int e1, e2, r1, r2, n1, n2;
109
110 v1 = version_of(pkg1, &e1, &r1);
111 v2 = version_of(pkg2, &e2, &r2);
112 /* Minor optimisation. */
113 if (strcmp(v1, v2) == 0)
114 return 0;
115 /* First compare epoch. */
116 if (e1 != e2)
117 return (e1 < e2 ? -1 : 1);
118 else {
119 /*
120 * We walk down the versions, trying to convert to numbers.
121 * We terminate when we reach an underscore, a comma or the
122 * string terminator, thanks to a nasty trick with strchr().
123 * strtol() conveniently gobbles up the chars it converts.
124 */
125 c1 = strchr("_,", v1[0]);
126 c2 = strchr("_,", v2[0]);
127 while (c1 == NULL && c2 == NULL) {
128 n1 = strtol(v1, &t1, 10);
129 n2 = strtol(v2, &t2, 10);
130 if (n1 != n2)
131 return (n1 < n2 ? -1 : 1);
132 /*
133 * The numbers are equal, check for letters. Assume they're
134 * letters purely because strtol() didn't chomp them.
135 */
136 c1 = strchr("_,.", t1[0]);
137 c2 = strchr("_,.", t2[0]);
138 if (c1 == NULL && c2 == NULL) {
139 /* Both have letters. Compare them. */
140 if (t1[0] != t2[0])
141 return (t1[0] < t2[0] ? -1 : 1);
142 /* Boring. The letters are equal. Carry on. */
143 v1 = &t1[1], v2 = &t2[1];
144 } else if (c1 == NULL) {
145 /*
146 * Letters are strange. After a number, a letter counts
147 * as greater, but after a period it's less.
148 */
149 return (isdigit(v1[0]) ? 1 : -1);
150 } else if (c2 == NULL) {
151 return (isdigit(v2[0]) ? -1 : 1);
152 } else {
153 /* Neither were letters. Advance over the period. */
154 v1 = (t1[0] == '.' ? &t1[1] : t1);
155 v2 = (t2[0] == '.' ? &t2[1] : t2);
156 }
157 c1 = strchr("_,", v1[0]);
158 c2 = strchr("_,", v2[0]);
159 }
160 /* If we got here, check if one version has something left. */
161 if (c1 == NULL)
162 return (isdigit(v1[0]) ? 1 : -1);
163 if (c2 == NULL)
164 return (isdigit(v2[0]) ? -1 : 1);
165 /* We've run out of version. Try the revision... */
166 if (r1 != r2)
167 return (r1 < r2 ? -1 : 1);
168 else
169 return 0;
170 }
171}
96 *
97 * The tests below allow for significantly more latitude in the version
98 * numbers than is allowed in the guidelines. No point in wasting user's
99 * time enforcing them here. That's what flamewars are for.
100 *
101 * Jeremy D. Lea.
102 */
103int
104version_cmp(const char *pkg1, const char *pkg2)
105{
106 const char *c1, *c2, *v1, *v2;
107 char *t1, *t2;
108 int e1, e2, r1, r2, n1, n2;
109
110 v1 = version_of(pkg1, &e1, &r1);
111 v2 = version_of(pkg2, &e2, &r2);
112 /* Minor optimisation. */
113 if (strcmp(v1, v2) == 0)
114 return 0;
115 /* First compare epoch. */
116 if (e1 != e2)
117 return (e1 < e2 ? -1 : 1);
118 else {
119 /*
120 * We walk down the versions, trying to convert to numbers.
121 * We terminate when we reach an underscore, a comma or the
122 * string terminator, thanks to a nasty trick with strchr().
123 * strtol() conveniently gobbles up the chars it converts.
124 */
125 c1 = strchr("_,", v1[0]);
126 c2 = strchr("_,", v2[0]);
127 while (c1 == NULL && c2 == NULL) {
128 n1 = strtol(v1, &t1, 10);
129 n2 = strtol(v2, &t2, 10);
130 if (n1 != n2)
131 return (n1 < n2 ? -1 : 1);
132 /*
133 * The numbers are equal, check for letters. Assume they're
134 * letters purely because strtol() didn't chomp them.
135 */
136 c1 = strchr("_,.", t1[0]);
137 c2 = strchr("_,.", t2[0]);
138 if (c1 == NULL && c2 == NULL) {
139 /* Both have letters. Compare them. */
140 if (t1[0] != t2[0])
141 return (t1[0] < t2[0] ? -1 : 1);
142 /* Boring. The letters are equal. Carry on. */
143 v1 = &t1[1], v2 = &t2[1];
144 } else if (c1 == NULL) {
145 /*
146 * Letters are strange. After a number, a letter counts
147 * as greater, but after a period it's less.
148 */
149 return (isdigit(v1[0]) ? 1 : -1);
150 } else if (c2 == NULL) {
151 return (isdigit(v2[0]) ? -1 : 1);
152 } else {
153 /* Neither were letters. Advance over the period. */
154 v1 = (t1[0] == '.' ? &t1[1] : t1);
155 v2 = (t2[0] == '.' ? &t2[1] : t2);
156 }
157 c1 = strchr("_,", v1[0]);
158 c2 = strchr("_,", v2[0]);
159 }
160 /* If we got here, check if one version has something left. */
161 if (c1 == NULL)
162 return (isdigit(v1[0]) ? 1 : -1);
163 if (c2 == NULL)
164 return (isdigit(v2[0]) ? -1 : 1);
165 /* We've run out of version. Try the revision... */
166 if (r1 != r2)
167 return (r1 < r2 ? -1 : 1);
168 else
169 return 0;
170 }
171}