8354 sync regcomp(3C) with upstream (fix make catalog)
[unleashed/tickless.git] / usr / src / cmd / svr4pkg / libinst / isreloc.c
blob73bed3160b50b93808d814da4ec2547a8775ee18
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
29 #include <stdio.h>
30 #include <sys/types.h>
31 #include <sys/param.h>
32 #include <dirent.h>
33 #include <limits.h>
34 #include <errno.h>
35 #include <ctype.h>
36 #include <fcntl.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40 #include <pkglib.h>
41 #include <libintl.h>
42 #include <libinst.h>
43 #include <install.h>
45 #define ERR_NOPKGMAP "Cannot open pkgmap file."
47 #define ENTRY_MAX (PATH_MAX + 38)
48 #define IGNORE_START ":#!"
49 #define IGNORE_TYPE "i"
51 static int has_rel_path(char *entry);
52 static int is_relative(char *entry);
55 * This routine attempts to determine with certainty whether or not
56 * the package is relocatable or not. It first attempts to determine if
57 * there is a reloc directory by scanning pkginstdir. If that fails to
58 * provide a definite result (pkg is coming from a stream device and
59 * the directories aren't in place) it inspects the pkgmap in pkginstdir
60 * in order to determine if the package has relocatable elements. If
61 * there is a single relative pathname or $BASEDIR/... construct,
62 * this returns 1. If no relative pathnames are found it returns 0
63 * meaning absolute package and all the things that implies.
65 * This does not determine the validity of the pkgmap file. If the pkgmap
66 * is corrupted, this returns 0.
68 int
69 isreloc(char *pkginstdir)
71 FILE *pkg_fp;
72 struct dirent *drp;
73 DIR *dirfp;
74 int retcode = 0;
76 /* First look in the directory */
77 if ((dirfp = opendir(pkginstdir)) != NULL) {
78 while ((drp = readdir(dirfp)) != NULL) {
79 if (drp->d_name[0] == '.')
80 continue;
81 if (strlen(drp->d_name) < (size_t)5)
82 continue;
83 if (strncmp(drp->d_name, "reloc", 5) == 0) {
84 retcode = 1;
85 break;
88 (void) closedir(dirfp);
92 * If retcode == 0, meaning we didn't find a reloc directory then we
93 * probably don't have a complete directory structure available to
94 * us. We'll have to determine what type of package it is by scanning
95 * the pkgmap file.
97 if (retcode == 0) {
98 char path_buffer[ENTRY_MAX];
100 (void) snprintf(path_buffer, sizeof (path_buffer),
101 "%s/pkgmap", pkginstdir);
103 canonize(path_buffer);
105 if ((pkg_fp = fopen(path_buffer, "r")) != NULL) {
106 while (fgets(path_buffer, sizeof (path_buffer), pkg_fp))
107 if (has_rel_path(path_buffer)) {
108 retcode = 1;
109 break;
111 (void) fclose(pkg_fp);
112 } else {
113 progerr(gettext(ERR_NOPKGMAP));
114 quit(99);
118 return (retcode);
122 * Test the string for the presence of a relative path. If found, return
123 * 1 otherwise return 0. If we get past the IGNORE_TYPE test, we're working
124 * with a line of the form :
126 * dpart type classname pathname ...
128 * It's pathname we're going to test here.
130 * Yes, yes, I know about sscanf(); but, I don't need to reserve 4K of
131 * space and parse the whole string, I just need to get to two tokens.
132 * We're in a hurry.
134 static int
135 has_rel_path(char *entry)
137 register int entry_pos = 1;
139 /* If the line is a comment or special directive, return 0 */
140 if (*entry == NULL || strchr(IGNORE_START, *entry))
141 return (0);
143 /* Skip past this data entry if it is volume number. */
144 if (isdigit(*entry)) {
145 while (*entry && !isspace(*entry)) {
146 entry++;
150 /* Skip past this white space */
151 while (*entry && isspace(*entry)) {
152 entry++;
156 * Now we're either pointing at the type or we're pointing at
157 * the termination of a degenerate entry. If the line is degenerate
158 * or the type indicates this line should be ignored, we return
159 * as though not relative.
161 if (*entry == NULL || strchr(IGNORE_TYPE, *entry))
162 return (0);
164 /* The pathname is in the third position */
165 do {
166 /* Skip past this data entry */
167 while (*entry && !isspace(*entry)) {
168 entry++;
171 /* Skip past this white space and call this the next entry */
172 while (*entry && isspace(*entry)) {
173 entry++;
175 } while (++entry_pos < 3 && *entry != NULL);
178 * Now we're pointing at the first character of the pathname.
179 * If the file is corrupted, we're pointing at NULL. is_relative()
180 * will return FALSE for NULL which will yield the correct return
181 * value.
183 return (is_relative(entry));
187 * If the path doesn't begin with a variable, the first character in the
188 * path is tested for '/' to determine if it is absolute or not. If the
189 * path begins with a '$', that variable is resolved if possible. If it
190 * isn't defined yet, we exit with error code 1.
192 static int
193 is_relative(char *entry)
195 register char *eopath = entry; /* end of full pathname pointer */
196 register char **lasts = &entry;
198 /* If there is a path, test it */
199 if (entry && *entry) {
200 if (*entry == '$') { /* it's an environment parameter */
201 entry++; /* skip the '$' */
203 while (*eopath && !isspace(*eopath))
204 eopath++;
206 *eopath = '\0'; /* terminate the pathname */
208 /* isolate the variable */
209 entry = strtok_r(entry, "/", lasts);
212 * Some packages call out $BASEDIR for relative
213 * paths in the pkgmap even though that is
214 * redundant. This special case is actually
215 * an indication that this is a relative
216 * path.
218 if (strcmp(entry, "BASEDIR") == 0)
219 return (1);
221 * Since entry is pointing to a now-expendable PATH_MAX
222 * size buffer, we can expand the path variable into it
223 * here.
225 entry = getenv(entry);
229 * Return type of path. If pathname was unresolvable
230 * variable, assume relative. This looks like a strange
231 * assumption since the resolved path may end up
232 * absolute and pkgadd may prompt the user for a basedir
233 * incorrectly because of this assumption. Unfortunately,
234 * the request script MUST have a final BASEDIR in the
235 * environment before it executes.
237 if (entry && *entry)
238 return (RELATIVE(entry));
239 else
240 return (1);
241 } else /* no path, so we skip it */
242 return (0);