xref: /netbsd-src/external/bsd/am-utils/dist/amd/sun_map.c (revision 8bae5d409deb915cf7c8f0539fae22ff2cb8a313)
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