xref: /illumos-gate/usr/src/contrib/ast/src/lib/libast/path/pathkey.c (revision b30d193948be5a7794d7ae3ba0ed9c2f72c88e0f)
1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5 *                      and is licensed under the                       *
6 *                 Eclipse Public License, Version 1.0                  *
7 *                    by AT&T Intellectual Property                     *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *          http://www.eclipse.org/org/documents/epl-v10.html           *
11 *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12 *                                                                      *
13 *              Information and Software Systems Research               *
14 *                            AT&T Research                             *
15 *                           Florham Park NJ                            *
16 *                                                                      *
17 *                 Glenn Fowler <gsf@research.att.com>                  *
18 *                  David Korn <dgk@research.att.com>                   *
19 *                   Phong Vo <kpv@research.att.com>                    *
20 *                                                                      *
21 ***********************************************************************/
22 #pragma prototyped
23 /*
24  * Glenn Fowler
25  * AT&T Bell Laboratories
26  *
27  * generate 14 char lookup key for lang path in key
28  * based on 32-bit checksum on path
29  *
30  * if key==0 then space is malloc'd
31  * if attr != 0 then attribute var assignments placed here:
32  *	ATTRIBUTES	list of attribute names
33  */
34 
35 #define _AST_API_H	1
36 
37 #include <ast.h>
38 #include <ctype.h>
39 #include <fs3d.h>
40 #include <preroot.h>
41 #include <ls.h>
42 
43 char*
pathkey(char * key,char * attr,const char * lang,const char * tool,const char * path)44 pathkey(char* key, char* attr, const char* lang, const char* tool, const char* path)
45 {
46 	return pathkey_20100601(lang, tool, path, key, 16, attr, PATH_MAX);
47 }
48 
49 #undef	_AST_API_H
50 
51 #include <ast_api.h>
52 
53 char*
pathkey_20100601(const char * lang,const char * tool,const char * apath,char * key,size_t keysize,char * attr,size_t attrsize)54 pathkey_20100601(const char* lang, const char* tool, const char* apath, char* key, size_t keysize, char* attr, size_t attrsize)
55 {
56 	register char*		path = (char*)apath;
57 	register char*		s;
58 	register char*		k;
59 	char*			t;
60 	char*			flags;
61 	char**			p;
62 	int			c;
63 	unsigned long		n;
64 	char			buf[15];
65 	char*			usr[16];
66 	char*			env[elementsof(usr) + 3];
67 	char*			ver[2];
68 	char			tmp[PATH_MAX];
69 #if _UWIN
70 	struct stat		st;
71 #endif
72 
73 	static char		let[] = "ABCDEFGHIJKLMNOP";
74 
75 	if (!key)
76 		key = buf;
77 	if (tool && streq(tool, "mam"))
78 	{
79 		for (n = 0; *path; path++)
80 			n = n * 0x63c63cd9L + *path + 0x9c39c33dL;
81 		k = key;
82 		for (n &= 0xffffffffL; n; n >>= 4)
83 			*k++ = let[n & 0xf];
84 		*k = 0;
85 	}
86 	else
87 	{
88 		for (c = 0; c < elementsof(env); c++)
89 			env[c] = 0;
90 		n = 0;
91 
92 		/*
93 		 * trailing flags in path
94 		 */
95 
96 		if (flags = strchr(path, ' '))
97 		{
98 			if (flags == path)
99 				flags = 0;
100 			else
101 			{
102 				strlcpy(tmp, path, sizeof(tmp));
103 				*(flags = tmp + (flags - path)) = 0;
104 				path = tmp;
105 			}
106 		}
107 
108 		/*
109 		 * 3D
110 		 */
111 
112 		if (!flags && fs3d(FS3D_TEST) && (c = mount(path, tmp, FS3D_GET|FS3D_ALL|FS3D_SIZE(PATH_MAX), NiL)) > 1 && c < PATH_MAX)
113 			path = tmp;
114 
115 		/*
116 		 * preroot
117 		 */
118 
119 		if (attr)
120 			attr = strcopy(attr, "PREROOT='");
121 #if FS_PREROOT
122 		if (k = getenv(PR_BASE))
123 		{
124 			if (s = strrchr(k, '/'))
125 				k = s + 1;
126 			n = memsum(k, strlen(k), n);
127 		}
128 		if (attr && (getpreroot(attr, path) || getpreroot(attr, NiL)))
129 			attr += strlen(attr);
130 #else
131 		if ((k = getenv("VIRTUAL_ROOT")) && *k == '/')
132 		{
133 			n = memsum(k, strlen(k), n);
134 			if (attr)
135 				attr = strcopy(attr, k);
136 		}
137 #endif
138 #if _UWIN
139 		if (!stat("/", &st) && st.st_ino == 64)
140 		{
141 			k = "/64";
142 			n = memsum(k, strlen(k), n);
143 			if (attr)
144 				attr = strcopy(attr, k);
145 		}
146 #endif
147 
148 		/*
149 		 * universe
150 		 */
151 
152 		if (attr)
153 			attr = strcopy(attr, "' UNIVERSE='");
154 		if (k = astconf("UNIVERSE", NiL, NiL))
155 		{
156 			n = memsum(k, strlen(k), n);
157 			if (attr)
158 				attr = strcopy(attr, k);
159 		}
160 
161 		/*
162 		 * environment
163 		 *
164 		 *	${PROBE_ATTRIBUTES} || ${VERSION_ENVIRONMENT} : list of alternate env vars
165 		 *	${VERSION_ENVIRONMENT}	: list of alternate env vars
166 		 *	${VERSION_<lang>}
167 		 *	${VERSION_<base(path)>}
168 		 *	${<toupper(base(path))>VER}
169 		 *	${OBJTYPE}
170 		 */
171 
172 		if (attr)
173 			*attr++ = '\'';
174 		c = 0;
175 		usr[c++] = "OBJTYPE";
176 		if (!(k = getenv("PROBE_ATTRIBUTES")))
177 			k = getenv("VERSION_ENVIRONMENT");
178 		if (k)
179 			while (c < (elementsof(usr) - 1))
180 			{
181 				while (*k && (*k == ':' || *k == ' '))
182 					k++;
183 				if (!*k)
184 					break;
185 				usr[c++] = k;
186 				while (*k && *k != ':' && *k != ' ')
187 					k++;
188 			}
189 		usr[c] = 0;
190 		ver[0] = (char*)lang;
191 		ver[1] = k = (s = strrchr(path, '/')) ? s + 1 : path;
192 		s = buf;
193 		if (isdigit(*k))
194 		{
195 			if (*k == '3' && *(k + 1) == 'b')
196 			{
197 				/*
198 				 * cuteness never pays
199 				 */
200 
201 				k += 2;
202 				*s++ = 'B';
203 				*s++ = 'B';
204 				*s++ = 'B';
205 			}
206 			else
207 				*s++ = 'U';
208 		}
209 		for (; (c = *k) && s < &buf[sizeof(buf) - 1]; k++)
210 		{
211 			if (!isalnum(c))
212 				c = '_';
213 			else if (islower(c))
214 				c = toupper(c);
215 			*s++ = c;
216 		}
217 		*s = 0;
218 		for (p = environ; *p; p++)
219 		{
220 			s = "VERSION_";
221 			for (k = *p; *k && *k == *s; k++, s++);
222 			if (*k && !*s)
223 			{
224 				for (c = 0; c < elementsof(ver); c++)
225 					if (!env[c] && (s = ver[c]))
226 					{
227 						for (t = k; *t && *t != '=' && *t++ == *s; s++);
228 						if (*t == '=' && (!*s || (s - ver[c]) > 1))
229 						{
230 							env[c] = *p;
231 							goto found;
232 						}
233 					}
234 			}
235 			if (!env[2])
236 			{
237 				s = buf;
238 				for (k = *p; *k && *s++ == *k; k++);
239 				if ((s - buf) > 2 && k[0] == 'V' && k[1] == 'E' && k[2] == 'R' && k[3] == '=')
240 				{
241 					env[2] = *p;
242 					goto found;
243 				}
244 			}
245 			for (c = 0; c < elementsof(usr) && (s = usr[c]); c++)
246 				if (!env[c + elementsof(env) - elementsof(usr)])
247 				{
248 					for (k = *p; *k && *k == *s; k++, s++);
249 					if (*k == '=' && (!*s || *s == ':' || *s == ' '))
250 					{
251 						env[c + elementsof(env) - elementsof(usr)] = *p;
252 						goto found;
253 					}
254 				}
255 		found:	;
256 		}
257 		for (c = 0; c < elementsof(env); c++)
258 			if (k = env[c])
259 			{
260 				if (attr)
261 				{
262 					*attr++ = ' ';
263 					while ((*attr++ = *k++) != '=');
264 					*attr++ = '\'';
265 					attr = strcopy(attr, k);
266 					*attr++ = '\'';
267 				}
268 				else
269 					while (*k && *k++ != '=');
270 				n = memsum(k, strlen(k), n);
271 			}
272 		if (attr)
273 		{
274 			attr = strcopy(attr, " ATTRIBUTES='PREROOT UNIVERSE");
275 			for (c = 0; c < elementsof(env); c++)
276 				if (k = env[c])
277 				{
278 					*attr++ = ' ';
279 					while ((*attr = *k++) != '=')
280 						attr++;
281 				}
282 			*attr++ = '\'';
283 			*attr = 0;
284 		}
285 
286 		/*
287 		 * now the normal stuff
288 		 */
289 
290 		if (flags)
291 			*flags = ' ';
292 		s = path + strlen(path);
293 		sfsprintf(key, 15, "%08lX", memsum(path, s - path, n));
294 		k = key + 14;
295 		*k = 0;
296 		if (!flags)
297 			t = path;
298 		else if ((t = s - 4) < flags)
299 			t = flags + 1;
300 		for (;;)
301 		{
302 			if (--s < t)
303 			{
304 				if (t == path)
305 					break;
306 				s = flags - 2;
307 				t = path;
308 			}
309 			if (*s != '/' && *s != ' ')
310 			{
311 				*--k = *s;
312 				if (k <= key + 8)
313 					break;
314 			}
315 		}
316 		while (k > key + 8)
317 			*--k = '.';
318 	}
319 	return key == buf ? strdup(key) : key;
320 }
321