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