4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
23 /* All Rights Reserved */
27 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
33 /* 5-20-92 added newroot functions */
42 #include <sys/types.h>
51 static void initpkg(struct pkginfo
*);
52 static int rdconfig(struct pkginfo
*, char *, char *);
53 static int ckinfo(char *, char *, char *);
54 static int ckinst(char *, char *, char *, char *, char *);
55 static int verscmp(char *, char *);
56 static int archcmp(char *, char *);
57 static int compver(char *, char *);
61 * pkgdir - specifies the directory where information about packages
62 * resides, i.e. the pkginfo file is located in a subdirectory
65 * The structure provided via "info" will contain malloc'd information;
66 * this will be free'd upon the next call to pkginfo with this
67 * same structure. Application calls must make sure this structure
68 * is null on the first call, or else we'll free static memory areas
69 * If the "pkg" argument is a wildcard specification, the next found
70 * instance available which matches the request will be returned
71 * If the "pkg" argument is a NULL pointer, the structure pointed to
72 * via "info" will have its elements deallocated and all files
73 * associated with this routine will be closed
76 * A non-zero exit code indicates error with "errno" appropriately set:
77 * EINVAL - invalid argument
78 * ESRCH - there are no more instances of this package around
79 * EACCESS - unable to access files which should have been there
84 pkginfo(struct pkginfo
*info
, char *pkginst
, ...)
86 char *ckarch
, *ckvers
;
90 va_start(ap
, pkginst
);
95 if (pkginst
== NULL
) {
97 (void) fpkginfo(info
, NULL
);
98 (void) fpkginst(NULL
);
101 ckarch
= va_arg(ap
, char *);
102 ckvers
= va_arg(ap
, char *);
106 if (pkgnmchk(pkginst
, "all", 1)) {
107 /* wild card specification */
108 pkginst
= fpkginst(pkginst
, ckarch
, ckvers
);
112 /* request to check indicated instance */
113 if (ckarch
|| ckvers
)
117 info
->pkginst
= NULL
;
118 if (fpkginfo(info
, pkginst
))
123 * verify that the provided instance matches
124 * any arch & vers specs that were provided
126 if (ckinst(pkginst
, info
->arch
, info
->version
, ckarch
,
137 fpkginfo(struct pkginfo
*info
, char *pkginst
)
149 else if (pkgnmchk(pkginst
, "all", 1)) {
150 errno
= EINVAL
; /* not an instance identifier */
154 pkgdir
= get_PKGLOC();
156 if (rdconfig(info
, pkginst
, NULL
)) {
164 initpkg(struct pkginfo
*info
)
166 /* free previously allocated space */
177 info
->pkginst
= NULL
;
178 info
->arch
= info
->version
= NULL
;
179 info
->basedir
= info
->name
= NULL
;
180 info
->vendor
= info
->catg
= NULL
;
181 info
->status
= PI_UNKNOWN
;
185 rdconfig(struct pkginfo
*info
, char *pkginst
, char *ckvers
)
189 char *value
, *pt
, *copy
, **memloc
;
192 if ((fp
= pkginfopen(pkgdir
, pkginst
)) == NULL
) {
199 while (value
= fpkgparam(fp
, temp
)) {
200 if (strcmp(temp
, "ARCH") == 0 ||
201 strcmp(temp
, "CATEGORY") == 0) {
202 /* remove all whitespace from value */
205 if (!isspace((unsigned char)*pt
))
213 if (strcmp(temp
, "NAME") == 0)
214 memloc
= &info
->name
;
215 else if (strcmp(temp
, "VERSION") == 0)
216 memloc
= &info
->version
;
217 else if (strcmp(temp
, "ARCH") == 0)
218 memloc
= &info
->arch
;
219 else if (strcmp(temp
, "VENDOR") == 0)
220 memloc
= &info
->vendor
;
221 else if (strcmp(temp
, "BASEDIR") == 0)
222 memloc
= &info
->basedir
;
223 else if (strcmp(temp
, "CATEGORY") == 0)
224 memloc
= &info
->catg
;
228 continue; /* not a parameter we're looking for */
230 *memloc
= strdup(value
);
234 return (-1); /* malloc from strdup failed */
244 info
->status
= (strcmp(pkgdir
, get_PKGLOC()) ? PI_SPOOLED
:
247 if (info
->status
== PI_INSTALLED
) {
248 (void) snprintf(temp
, sizeof (temp
),
249 "%s/%s/!I-Lock!", pkgdir
, pkginst
);
250 if (access(temp
, 0) == 0)
251 info
->status
= PI_PARTIAL
;
253 (void) snprintf(temp
, sizeof (temp
),
254 "%s/%s/!R-Lock!", pkgdir
, pkginst
);
255 if (access(temp
, 0) == 0)
256 info
->status
= PI_PARTIAL
;
259 info
->pkginst
= strdup(pkginst
);
264 ckinst(char *pkginst
, char *pkgarch
, char *pkgvers
, char *ckarch
, char *ckvers
)
266 if (ckarch
&& archcmp(ckarch
, pkgarch
))
269 /* Check for exact version match */
270 if (verscmp(ckvers
, pkgvers
)) {
271 /* Check for compatable version */
272 if (compver(pkginst
, ckvers
))
281 fpkginst(char *pkg
, ...)
283 static char pkginst
[PKGSIZ
+1];
286 char *ckarch
, *ckvers
;
292 /* request to close or rewind the file */
294 (void) closedir(pdirfp
);
300 ckarch
= va_arg(ap
, char *);
301 ckvers
= va_arg(ap
, char *);
305 pkgdir
= get_PKGLOC();
307 if (!pdirfp
&& ((pdirfp
= opendir(pkgdir
)) == NULL
)) {
312 while ((dp
= readdir64(pdirfp
)) != NULL
) {
313 if (dp
->d_name
[0] == '.')
316 if (pkgnmchk(dp
->d_name
, pkg
, 0))
317 continue; /* ignore invalid SVR4 package names */
319 if (ckinfo(dp
->d_name
, ckarch
, ckvers
))
323 * Leave directory open in case user requests another
326 (void) strcpy(pkginst
, dp
->d_name
);
331 /* close any file we might have open */
332 (void) closedir(pdirfp
);
338 verscmp(char *request
, char *actual
)
340 /* eat leading white space */
341 while (isspace((unsigned char)*actual
))
343 while (isspace((unsigned char)*request
))
346 while (*request
|| *actual
) {
348 * Once the pointers don't match, return an error condition.
351 if (*request
++ != *actual
++)
354 /* eat white space if any in both the strings */
355 if (isspace((unsigned char)*request
)) {
356 if (*actual
&& !isspace((unsigned char)*actual
))
358 while (isspace((unsigned char)*request
))
360 while (isspace((unsigned char)*actual
))
370 compver(char *pkginst
, char *version
)
375 (void) snprintf(temp
, sizeof (temp
),
376 "%s/%s/install/compver", get_PKGLOC(), pkginst
);
377 if ((fp
= fopen(temp
, "r")) == NULL
)
380 while (fgets(temp
, 256, fp
)) {
383 if (verscmp(temp
, version
) == 0) {
393 archcmp(char *arch
, char *archlist
)
400 /* arch and archlist must not contain whitespace! */
403 for (pt
= arch
; *pt
&& (*pt
== *archlist
); )
405 if (!*pt
&& (!*archlist
|| (*archlist
== ',')))
408 if (*archlist
++ == ',')
416 ckinfo(char *inst
, char *arch
, char *vers
)
421 char *pt
, *copy
, *value
, *myarch
, *myvers
;
424 (void) snprintf(file
, sizeof (file
), "%s/%s/pkginfo", pkgdir
, inst
);
425 if ((fp
= fopen(file
, "r")) == NULL
)
428 if ((arch
== NULL
) && (vers
== NULL
)) {
433 myarch
= myvers
= NULL
;
434 while (value
= fpkgparam(fp
, temp
)) {
435 if (strcmp(temp
, "ARCH") == 0) {
436 /* remove all whitespace from value */
439 if (!isspace((unsigned char)*pt
))
447 } else if (strcmp(temp
, "VERSION") == 0) {
458 if (ckinst(inst
, myarch
, myvers
, arch
, vers
))