1 /*
2 * Copyright (c) 1997-2014 Erez Zadok
3 * Copyright (c) 2005 Daniel P. Ottavio
4 * Copyright (c) 1990 Jan-Simon Pendry
5 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
6 * Copyright (c) 1990 The Regents of the University of California.
7 * All rights reserved.
8 *
9 * This code is derived from software contributed to Berkeley by
10 * Jan-Simon Pendry at Imperial College, London.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 *
37 * File: am-utils/amd/sun_map.c
38 *
39 */
40
41 #ifdef HAVE_CONFIG_H
42 # include <config.h>
43 #endif /* HAVE_CONFIG_H */
44 #include <am_defs.h>
45 #include <amd.h>
46 #include <sun_map.h>
47
48
49
50 /*
51 * Add a data pointer to the end of the list.
52 */
53 void
sun_list_add(struct sun_list * list,qelem * item)54 sun_list_add(struct sun_list *list, qelem *item)
55 {
56 if (list->last == NULL) {
57 list->last = item;
58 list->first = item;
59 item->q_back = NULL;
60 }
61 else {
62 list->last->q_forw = item;
63 item->q_back = list->last;
64 list->last = item;
65 }
66
67 item->q_forw = NULL;
68 }
69
70
71 /*
72 * Sun2Amd conversion routines
73 */
74
75 /*
76 * AMD entry keywords
77 */
78 #define AMD_OPTS_KW "addopts:=" /* add entry options */
79 #define AMD_RHOST_KW "rhost:=" /* remote host */
80 #define AMD_RFS_KW "rfs:=" /* remote file system */
81 #define AMD_FS_KW "fs:=" /* local file system */
82 #define AMD_DEV_KW "dev:=" /* device */
83 #define AMD_TYPE_NFS_KW "type:=nfs;" /* fs type nfs */
84 #define AMD_TYPE_AUTO_KW "type:=auto;" /* fs type auto */
85 #define AMD_TYPE_CDFS_KW "type:=cdfs;" /* fs type cd */
86 #define AMD_MAP_FS_KW "fs:=${map};" /* set the mount map as current map */
87 #define AMD_MAP_PREF_KW "pref:=${key}/" /* set the mount map as current map */
88
89 /*
90 * A set of string Sun fstypes.
91 */
92 #define SUN_NFS_TYPE "nfs"
93 #define SUN_HSFS_TYPE "hsfs" /* CD fs */
94 #define SUN_AUTOFS_TYPE "autofs"
95 #define SUN_CACHEFS_TYPE "cachefs"
96
97 #define SUN_KEY_SUB "&" /* Sun key substitution */
98
99 /* a set a Sun variable substitutions for map entries */
100 #define SUN_ARCH "$ARCH" /* host architecture */
101 #define SUN_CPU "$CPU" /* processor type */
102 #define SUN_HOST "$HOST" /* host name */
103 #define SUN_OSNAME "$OSNAME" /* OS name */
104 #define SUN_OSREL "$OSREL" /* OS release */
105 #define SUN_OSVERS "$OSVERS" /* OS version */
106 #define SUN_NATISA "$NATISA" /* native instruction set */
107
108 /* a set of Amd variable substitutions */
109 #define AMD_ARCH "${arch}" /* host architecture */
110 #define AMD_HOST "${host}" /* host name */
111 #define AMD_OSNAME "${os}" /* OS name */
112 #define AMD_OSVER "${osver}" /* OS version */
113
114
115 /*
116 * Return a copy of src that has all occurrences of 'str' replaced
117 * with sub.
118 *
119 * param src - the original string
120 * param str - string that is the replaced with str
121 * param sub - string that replaces an occurrences of 'delim'
122 *
123 * return - new string with str substitutions, NULL on error
124 */
125 static char *
sun_strsub(const char * src,const char * str,const char * sub)126 sun_strsub(const char *src, const char *str, const char *sub)
127 {
128
129 char *retval = NULL, *str_start, *str_end, *src_end;
130 size_t total_size, first_half, second_half, sub_size;
131
132 /* assign pointers to the start and end of str */
133 if ((str_start = strstr(src, str)) == NULL) {
134 return retval;
135 }
136 str_end = (strlen(str) - 1) + str_start;
137
138 /* assign to the end of the src. */
139 src_end = (strlen(src) - 1) + (char*)src;
140
141 /* size from the beginning of src to the start of str */
142 first_half = (size_t)(str_start - src);
143
144 /* size from the end of str to the end of src */
145 second_half = (size_t)(src_end - str_end);
146
147 sub_size = strlen(sub);
148
149 total_size = (first_half + sub_size + second_half + 1);
150
151 retval = (char*)xmalloc(total_size);
152 memset(retval, 0, total_size);
153
154 /*
155 * Put together the string such that the first half is copied
156 * followed the sub and second half.
157 *
158 * We use strncpy instead of xstrlcpy because we are intentionally
159 * causing truncation and we don't want this to cause errors in the
160 * log.
161 */
162 (void)strncpy(retval, src, first_half);
163 (void)strncat(retval, sub, sub_size);
164 (void)strncat(retval, str_end + 1, second_half);
165
166 if (strstr(retval, str) != NULL) {
167 /*
168 * If there is another occurrences of str call this function
169 * recursively.
170 */
171 char* tmp;
172 if ((tmp = sun_strsub(retval, str, sub)) != NULL) {
173 XFREE(retval);
174 retval = tmp;
175 }
176 }
177 return retval;
178 }
179
180
181 /*
182 * Return a new string that is a copy of str, all occurrences of a Sun
183 * variable substitutions are replaced by there equivalent Amd
184 * substitutions.
185 *
186 * param str - source string
187 *
188 * return - A new string with the expansions, NULL if str does not
189 * exist in src or error.
190 */
191 static char *
sun_expand2amd(const char * str)192 sun_expand2amd(const char *str)
193 {
194
195 char *retval = NULL, *tmp = NULL, *tmp2 = NULL;
196 const char *pos;
197
198 /*
199 * Iterator through the string looking for '$' chars. For each '$'
200 * found try to replace it with Sun variable substitutions. If we
201 * find a '$' that is not a substation each of the i.e $blah than
202 * each of the replace attempt will fail and we'll move on to the
203 * next char.
204 */
205 tmp = xstrdup(str);
206 for (pos = str; *pos != '\0'; pos++) {
207 if (*pos != '$') {
208 continue;
209 }
210 if (tmp2 != NULL) {
211 XFREE(tmp);
212 tmp = tmp2;
213 }
214
215 /*
216 * If a 'replace' does not return NULL than a variable was
217 * successfully substituted.
218 */
219
220 /* architecture */
221 if ((tmp2 = sun_strsub(tmp, SUN_ARCH, AMD_ARCH)) != NULL) {
222 continue;
223 }
224 /* cpu - there is not POSIX uname for cpu so just use machine */
225 if ((tmp2 = sun_strsub(tmp, SUN_CPU, AMD_ARCH)) != NULL) {
226 continue;
227 }
228 /* hostname */
229 if ((tmp2 = sun_strsub(tmp, SUN_HOST, AMD_HOST)) != NULL) {
230 continue;
231 }
232 /* os name */
233 if ((tmp2 = sun_strsub(tmp, SUN_OSNAME, AMD_OSNAME)) != NULL) {
234 continue;
235 }
236 /*
237 * os release - Amd doesn't hava a OS release var just usr os
238 * version or now.
239 */
240 if ((tmp2 = sun_strsub(tmp, SUN_OSREL, AMD_OSVER)) != NULL) {
241 continue;
242 }
243 /* os version */
244 if ((tmp2 = sun_strsub(tmp, SUN_OSVERS, AMD_OSVER)) != NULL) {
245 continue;
246 }
247 /* native instruction set - there is no POSIX natisa so just use system */
248 if ((tmp2 = sun_strsub(tmp, SUN_NATISA, AMD_ARCH)) != NULL) {
249 continue;
250 }
251 }
252 if (tmp2 == NULL) {
253 retval = tmp;
254 }
255 else {
256 retval = tmp2;
257 XFREE(tmp);
258 }
259
260 return retval;
261 }
262
263
264 /*
265 * This is a wrapper function for appending Amd entry information to a
266 * buffer. Any Sun variable substitutions will be converted into Amd
267 * equivalents.
268 *
269 * param dest - destination buffer
270 * param deslen - destination buffer length
271 * param key - entry key, this might be needed for key substitutions
272 * param str - string to append
273 */
274 static void
sun_append_str(char * dest,size_t destlen,const char * key,const char * str)275 sun_append_str(char *dest,
276 size_t destlen,
277 const char *key,
278 const char *str)
279 {
280 char *sub = NULL, *sub2 = NULL, *out = NULL;
281
282 /* By default we are going to just write the original string. */
283 out = (char*)str;
284
285 /*
286 * Resolve variable substitutions in two steps; 1) replace any key
287 * map substitutions with the entry key 2) expand any variable
288 * substitutions i.e $HOST.
289 *
290 * Try to replace the key substitution '&'. If this function returns
291 * with a new string, one or more key subs. where replaced with the
292 * entry key.
293 */
294 if ((sub = sun_strsub(str, SUN_KEY_SUB, "${key}")) != NULL) {
295 out = sub;
296 /*
297 * Try to convert any variable substitutions. If this function
298 * returns a new string one or more var subs where expanded.
299 */
300 if ((sub2 = sun_expand2amd(sub)) != NULL) {
301 out = sub2;
302 }
303 }
304 /*
305 * Try to convert any variable substitutions. If this function
306 * returns a new string one or more var subs where expanded.
307 */
308 else if (out != NULL && (sub = sun_expand2amd(out)) != NULL) {
309 out = sub;
310 }
311
312 if (out != NULL) {
313 xstrlcat(dest, out, destlen);
314 }
315 XFREE(sub);
316 XFREE(sub2);
317 }
318
319
320 /*
321 * Convert the list of Sun mount options to Amd mount options. The
322 * result is concatenated to dest.
323 *
324 * param dest - destination buffer
325 * param destlen - destination buffer length
326 * param key - automount key
327 * param opt_list - list of Sun mount options
328 */
329 static void
sun_opts2amd(char * dest,size_t destlen,const char * key,const struct sun_opt * opt_list)330 sun_opts2amd(char *dest,
331 size_t destlen,
332 const char *key,
333 const struct sun_opt *opt_list)
334 {
335 const struct sun_opt *opt;
336
337 xstrlcat(dest, AMD_OPTS_KW, destlen);
338
339 /* Iterate through each option and append it to the buffer. */
340 for(opt = opt_list; opt != NULL; opt = NEXT(struct sun_opt, opt)) {
341 sun_append_str(dest, destlen, key, opt->str);
342 /* If there are more options add some commas. */
343 if (NEXT(struct sun_opt, opt) != NULL) {
344 xstrlcat(dest, ",", destlen);
345 }
346 }
347 xstrlcat(dest, ";", destlen);
348 }
349
350
351 /*
352 * Convert the list of Sun mount locations to a list of Amd mount
353 * locations. The result is concatenated to dest.
354 *
355 * param dest - destination buffer
356 * param destlen - destination buffer length
357 * param key - automount key
358 * param local_list - list of Sun mount locations
359 */
360 static void
sun_locations2amd(char * dest,size_t destlen,const char * key,const struct sun_location * local_list)361 sun_locations2amd(char *dest,
362 size_t destlen,
363 const char *key,
364 const struct sun_location *local_list)
365 {
366 const struct sun_location *local;
367 const struct sun_host *host;
368
369 for (local = local_list;
370 local != NULL;
371 local = NEXT(struct sun_location,local)) {
372 /*
373 * Check to see if the list of hosts is empty. Some mount types
374 * i.e cd-rom may have mount location with no host.
375 */
376 if (local->host_list != NULL) {
377 /* Write each host that belongs to this location. */
378 for (host = local->host_list;
379 host != NULL;
380 host = NEXT(struct sun_host, host)) {
381 /* set fstype NFS */
382 xstrlcat(dest, AMD_TYPE_NFS_KW, destlen);
383 /* add rhost key word */
384 xstrlcat(dest, AMD_RHOST_KW, destlen);
385 /* add host name */
386 sun_append_str(dest, destlen, key, host->name);
387 xstrlcat(dest, ";", destlen);
388 /* add remote fs key word */
389 xstrlcat(dest, AMD_RFS_KW, destlen);
390 /* add local path */
391 sun_append_str(dest, destlen, key, local->path);
392 if (NEXT(struct sun_host, host) != NULL) {
393 xstrlcat(dest, ";", destlen);
394 xstrlcat(dest, " ", destlen);
395 }
396 }
397 }
398 else {
399 /* no host location */
400 xstrlcat(dest, AMD_FS_KW, destlen);
401 sun_append_str(dest, destlen, key, local->path);
402 }
403 if (NEXT(struct sun_location, local) != NULL) {
404 /* add a space to separate each location */
405 xstrlcat(dest, " ", destlen);
406 }
407 }
408 }
409
410
411 /*
412 * Convert a Sun HSFS mount point to an Amd. The result is
413 * concatenated intp dest.
414 *
415 * param dest - destination buffer
416 * param destlen - destination buffer length
417 * param key - automount key
418 * param s_entry - Sun entry
419 */
420 static void
sun_hsfs2amd(char * dest,size_t destlen,const char * key,const struct sun_entry * s_entry)421 sun_hsfs2amd(char *dest,
422 size_t destlen,
423 const char *key,
424 const struct sun_entry *s_entry)
425 {
426 /* set fstype CDFS */
427 xstrlcat(dest, AMD_TYPE_CDFS_KW, destlen);
428 /* set the cdrom device */
429 xstrlcat(dest, AMD_DEV_KW, destlen);
430 /* XXX: For now just assume that there is only one device. */
431 xstrlcat(dest, s_entry->location_list->path, destlen);
432 }
433
434
435 /*
436 * Convert a Sun NFS automount entry to an Amd. The result is concatenated
437 * into dest.
438 *
439 * param dest - destination buffer
440 * param destlen - destination buffer length
441 * param key - automount key
442 * param s_entry - Sun entry
443 */
444 static void
sun_nfs2amd(char * dest,size_t destlen,const char * key,const struct sun_entry * s_entry)445 sun_nfs2amd(char *dest,
446 size_t destlen,
447 const char *key,
448 const struct sun_entry *s_entry)
449 {
450 if (s_entry->location_list != NULL) {
451 /* write out the list of mountpoint locations */
452 sun_locations2amd(dest, destlen, key, s_entry->location_list);
453 }
454 }
455
456
457 /*
458 * Convert a Sun multi-mount point entry to an Amd. This is done
459 * using the Amd type auto. Each auto entry is separated with a \n.
460 *
461 * param dest - destination buffer
462 * param destlen - destination buffer length
463 * param key - automount key
464 * param s_entry - Sun entry
465 */
466 static void
sun_multi2amd(char * dest,size_t destlen,const char * key,const struct sun_entry * s_entry)467 sun_multi2amd(char *dest,
468 size_t destlen,
469 const char *key,
470 const struct sun_entry *s_entry)
471 {
472 const struct sun_mountpt *mountpt;
473
474 /* We need to setup a auto fs Amd automount point. */
475 xstrlcat(dest, AMD_TYPE_AUTO_KW, destlen);
476 xstrlcat(dest, AMD_MAP_FS_KW, destlen);
477 xstrlcat(dest, AMD_MAP_PREF_KW, destlen);
478
479 /* write the mountpts to dest */
480 for (mountpt = s_entry->mountpt_list;
481 mountpt != NULL;
482 mountpt = NEXT(struct sun_mountpt, mountpt)) {
483 xstrlcat(dest, "\n", destlen);
484 /* write the key */
485 xstrlcat(dest, key, destlen);
486 /* write the mount path */
487 sun_append_str(dest, destlen, key, mountpt->path);
488 /* space */
489 xstrlcat(dest, " ", destlen);
490 /* Write all the host locations for this mount point. */
491 sun_locations2amd(dest, destlen, key, mountpt->location_list);
492 }
493 }
494
495
496 /*
497 * Convert the sun_entry into an Amd equivalent string.
498 *
499 * param key - automount key
500 * param s_entry - Sun style automap entry
501 *
502 * return - Amd entry on succes, NULL on error
503 */
504 char *
sun_entry2amd(const char * key,const char * s_entry_str)505 sun_entry2amd(const char *key, const char *s_entry_str)
506 {
507 char *retval = NULL;
508 char line_buff[INFO_MAX_LINE_LEN];
509 int ws;
510 struct sun_entry *s_entry = NULL;
511
512 /* The key should not be NULL. */
513 if (key == NULL) {
514 plog(XLOG_ERROR,"Sun key value was null");
515 goto err;
516 }
517 /* The Sun entry string should never be NULL. */
518 if (s_entry_str == NULL) {
519 plog(XLOG_ERROR,"Sun entry value was null");
520 goto err;
521 }
522
523 /* Make sure there are no trailing white spaces or '\n'. */
524 xstrlcpy(line_buff, s_entry_str, sizeof(line_buff));
525 ws = strlen(line_buff) - 1;
526 while (ws >= 0 && (isspace((unsigned char)line_buff[ws]) || line_buff[ws] == '\n')) {
527 line_buff[ws--] = '\0';
528 }
529
530 /* Parse the sun entry line. */
531 s_entry = sun_map_parse_read(line_buff);
532 if (s_entry == NULL) {
533 plog(XLOG_ERROR,"could not parse Sun style map");
534 goto err;
535 }
536
537 memset(line_buff, 0, sizeof(line_buff));
538
539 if (s_entry->opt_list != NULL) {
540 /* write the mount options to the buffer */
541 sun_opts2amd(line_buff, sizeof(line_buff), key, s_entry->opt_list);
542 }
543
544 /* Check if this is a multi-mount entry. */
545 if (s_entry->mountpt_list != NULL) {
546 /* multi-mount point */
547 sun_multi2amd(line_buff, sizeof(line_buff), key, s_entry);
548 retval = xstrdup(line_buff);
549 }
550 else {
551 /* single mount point */
552 if (s_entry->fstype != NULL) {
553 if (NSTREQ(s_entry->fstype, SUN_NFS_TYPE, strlen(SUN_NFS_TYPE))) {
554 /* NFS Type */
555 sun_nfs2amd(line_buff, sizeof(line_buff), key, s_entry);
556 retval = xstrdup(line_buff);
557 }
558 else if (NSTREQ(s_entry->fstype, SUN_HSFS_TYPE, strlen(SUN_HSFS_TYPE))) {
559 /* HSFS Type (CD fs) */
560 sun_hsfs2amd(line_buff, sizeof(line_buff), key, s_entry);
561 retval = xstrdup(line_buff);
562 }
563 /*
564 * XXX: The following fstypes are not yet supported.
565 */
566 else if (NSTREQ(s_entry->fstype, SUN_AUTOFS_TYPE, strlen(SUN_AUTOFS_TYPE))) {
567 /* AutoFS Type */
568 plog(XLOG_ERROR, "Sun fstype %s is currently not supported by Amd.",
569 s_entry->fstype);
570 goto err;
571
572 }
573 else if (NSTREQ(s_entry->fstype, SUN_CACHEFS_TYPE, strlen(SUN_CACHEFS_TYPE))) {
574 /* CacheFS Type */
575 plog(XLOG_ERROR, "Sun fstype %s is currently not supported by Amd.",
576 s_entry->fstype);
577 goto err;
578 }
579 else {
580 plog(XLOG_ERROR, "Sun fstype %s is currently not supported by Amd.",
581 s_entry->fstype);
582 goto err;
583 }
584 }
585 else {
586 plog(XLOG_INFO, "No SUN fstype specified defaulting to NFS.");
587 sun_nfs2amd(line_buff, sizeof(line_buff), key, s_entry);
588 retval = xstrdup(line_buff);
589 }
590 }
591
592 err:
593 XFREE(s_entry);
594 return retval;
595 }
596