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