]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/amd/amd/sun_map.c
MFC r308493, r308619: Update amd from am-utils 6.1.5 to 6.2.
[FreeBSD/stable/10.git] / contrib / amd / amd / sun_map.c
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
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 *
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 *
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
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
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
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
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
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
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 *
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 }