1305100Scy/*
2305100Scy * Copyright (c) 1997-2014 Erez Zadok
3305100Scy * Copyright (c) 2005 Daniel P. Ottavio
4305100Scy * Copyright (c) 1990 Jan-Simon Pendry
5305100Scy * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
6305100Scy * Copyright (c) 1990 The Regents of the University of California.
7305100Scy * All rights reserved.
8305100Scy *
9305100Scy * This code is derived from software contributed to Berkeley by
10305100Scy * Jan-Simon Pendry at Imperial College, London.
11305100Scy *
12305100Scy * Redistribution and use in source and binary forms, with or without
13305100Scy * modification, are permitted provided that the following conditions
14305100Scy * are met:
15305100Scy * 1. Redistributions of source code must retain the above copyright
16305100Scy *    notice, this list of conditions and the following disclaimer.
17305100Scy * 2. Redistributions in binary form must reproduce the above copyright
18305100Scy *    notice, this list of conditions and the following disclaimer in the
19305100Scy *    documentation and/or other materials provided with the distribution.
20305100Scy * 3. Neither the name of the University nor the names of its contributors
21305100Scy *    may be used to endorse or promote products derived from this software
22305100Scy *    without specific prior written permission.
23305100Scy *
24305100Scy * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25305100Scy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26305100Scy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27305100Scy * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28305100Scy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29305100Scy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30305100Scy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31305100Scy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32305100Scy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33305100Scy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34305100Scy * SUCH DAMAGE.
35305100Scy *
36305100Scy *
37305100Scy * File: am-utils/amd/sun_map.c
38305100Scy *
39305100Scy */
40305100Scy
41305100Scy#ifdef HAVE_CONFIG_H
42305100Scy# include <config.h>
43305100Scy#endif /* HAVE_CONFIG_H */
44305100Scy#include <am_defs.h>
45305100Scy#include <amd.h>
46305100Scy#include <sun_map.h>
47305100Scy
48305100Scy
49305100Scy
50305100Scy/*
51305100Scy * Add a data pointer to the end of the list.
52305100Scy */
53305100Scyvoid
54305100Scysun_list_add(struct sun_list *list, qelem *item)
55305100Scy{
56305100Scy  if (list->last == NULL) {
57305100Scy    list->last = item;
58305100Scy    list->first = item;
59305100Scy    item->q_back = NULL;
60305100Scy  }
61305100Scy  else {
62305100Scy    list->last->q_forw = item;
63305100Scy    item->q_back = list->last;
64305100Scy    list->last = item;
65305100Scy  }
66305100Scy
67305100Scy  item->q_forw = NULL;
68305100Scy}
69305100Scy
70305100Scy
71305100Scy/*
72305100Scy * Sun2Amd conversion routines
73305100Scy */
74305100Scy
75305100Scy/*
76305100Scy * AMD entry keywords
77305100Scy */
78305100Scy#define AMD_OPTS_KW      "addopts:="     /* add entry options */
79305100Scy#define AMD_RHOST_KW     "rhost:="       /* remote host */
80305100Scy#define AMD_RFS_KW       "rfs:="         /* remote file system */
81305100Scy#define AMD_FS_KW        "fs:="          /* local file system */
82305100Scy#define AMD_DEV_KW       "dev:="         /* device */
83305100Scy#define AMD_TYPE_NFS_KW  "type:=nfs;"    /* fs type nfs */
84305100Scy#define AMD_TYPE_AUTO_KW "type:=auto;"   /* fs type auto */
85305100Scy#define AMD_TYPE_CDFS_KW "type:=cdfs;"   /* fs type cd */
86305100Scy#define AMD_MAP_FS_KW    "fs:=${map};"   /* set the mount map as current map */
87305100Scy#define AMD_MAP_PREF_KW  "pref:=${key}/" /* set the mount map as current map */
88305100Scy
89305100Scy/*
90305100Scy * A set of string Sun fstypes.
91305100Scy */
92305100Scy#define SUN_NFS_TYPE     "nfs"
93305100Scy#define SUN_HSFS_TYPE    "hsfs" /* CD fs */
94305100Scy#define SUN_AUTOFS_TYPE  "autofs"
95305100Scy#define SUN_CACHEFS_TYPE "cachefs"
96305100Scy
97305100Scy#define SUN_KEY_SUB      "&"         /* Sun key substitution */
98305100Scy
99305100Scy/* a set a Sun variable substitutions for map entries */
100305100Scy#define SUN_ARCH         "$ARCH"     /* host architecture */
101305100Scy#define SUN_CPU          "$CPU"      /* processor type */
102305100Scy#define SUN_HOST         "$HOST"     /* host name */
103305100Scy#define SUN_OSNAME       "$OSNAME"   /* OS name */
104305100Scy#define SUN_OSREL        "$OSREL"    /* OS release */
105305100Scy#define SUN_OSVERS       "$OSVERS"   /* OS version */
106305100Scy#define SUN_NATISA       "$NATISA"   /* native instruction set */
107305100Scy
108305100Scy/* a set of Amd variable substitutions */
109305100Scy#define AMD_ARCH         "${arch}"   /* host architecture */
110305100Scy#define AMD_HOST         "${host}"   /* host name */
111305100Scy#define AMD_OSNAME       "${os}"     /* OS name */
112305100Scy#define AMD_OSVER        "${osver}"  /* OS version */
113305100Scy
114305100Scy
115305100Scy/*
116305100Scy * Return a copy of src that has all occurrences of 'str' replaced
117305100Scy * with sub.
118305100Scy *
119305100Scy * param src - the original string
120305100Scy * param str - string that is the replaced with str
121305100Scy * param sub - string that replaces an occurrences of 'delim'
122305100Scy *
123305100Scy * return - new string with str substitutions, NULL on error
124305100Scy */
125305100Scystatic char *
126305100Scysun_strsub(const char *src, const char *str, const char *sub)
127305100Scy{
128305100Scy
129305100Scy  char *retval = NULL, *str_start, *str_end, *src_end;
130305100Scy  size_t total_size, first_half, second_half, sub_size;
131305100Scy
132305100Scy  /* assign pointers to the start and end of str */
133305100Scy  if ((str_start = strstr(src, str)) == NULL) {
134305100Scy    return retval;
135305100Scy  }
136305100Scy  str_end = (strlen(str) - 1) + str_start;
137305100Scy
138305100Scy  /* assign to the end of the src. */
139305100Scy  src_end = (strlen(src) - 1) + (char*)src;
140305100Scy
141305100Scy  /* size from the beginning of src to the start of str */
142305100Scy  first_half = (size_t)(str_start - src);
143305100Scy
144305100Scy  /* size from the end of str to the end of src */
145305100Scy  second_half = (size_t)(src_end - str_end);
146305100Scy
147305100Scy  sub_size = strlen(sub);
148305100Scy
149305100Scy  total_size = (first_half + sub_size + second_half + 1);
150305100Scy
151305100Scy  retval = (char*)xmalloc(total_size);
152305100Scy  memset(retval, 0, total_size);
153305100Scy
154305100Scy  /*
155305100Scy   * Put together the string such that the first half is copied
156305100Scy   * followed the sub and second half.
157305100Scy   *
158305100Scy   * We use strncpy instead of xstrlcpy because we are intentionally
159305100Scy   * causing truncation and we don't want this to cause errors in the
160305100Scy   * log.
161305100Scy   */
162305100Scy  (void)strncpy(retval, src, first_half);
163305100Scy  (void)strncat(retval, sub, sub_size);
164305100Scy  (void)strncat(retval, str_end + 1, second_half);
165305100Scy
166305100Scy  if (strstr(retval, str) != NULL) {
167305100Scy    /*
168305100Scy     * If there is another occurrences of str call this function
169305100Scy     * recursively.
170305100Scy     */
171305100Scy    char* tmp;
172305100Scy    if ((tmp = sun_strsub(retval, str, sub)) != NULL) {
173305100Scy      XFREE(retval);
174305100Scy      retval = tmp;
175305100Scy    }
176305100Scy  }
177305100Scy  return retval;
178305100Scy}
179305100Scy
180305100Scy
181305100Scy/*
182305100Scy * Return a new string that is a copy of str, all occurrences of a Sun
183305100Scy * variable substitutions are replaced by there equivalent Amd
184305100Scy * substitutions.
185305100Scy *
186305100Scy * param str - source string
187305100Scy *
188305100Scy * return - A new string with the expansions, NULL if str does not
189305100Scy * exist in src or error.
190305100Scy */
191305100Scystatic char *
192305100Scysun_expand2amd(const char *str)
193305100Scy{
194305100Scy
195305100Scy  char *retval = NULL, *tmp = NULL, *tmp2 = NULL;
196305100Scy  const char *pos;
197305100Scy
198305100Scy  /*
199305100Scy   * Iterator through the string looking for '$' chars.  For each '$'
200305100Scy   * found try to replace it with Sun variable substitutions.  If we
201305100Scy   * find a '$' that is not a substation each of the i.e $blah than
202305100Scy   * each of the replace attempt will fail and we'll move on to the
203305100Scy   * next char.
204305100Scy   */
205305100Scy  tmp = xstrdup(str);
206305100Scy  for (pos = str; *pos != '\0'; pos++) {
207305100Scy    if (*pos != '$') {
208305100Scy      continue;
209305100Scy    }
210305100Scy    if (tmp2 != NULL) {
211305100Scy      XFREE(tmp);
212305100Scy      tmp = tmp2;
213305100Scy    }
214305100Scy
215305100Scy    /*
216305100Scy     * If a 'replace' does not return NULL than a variable was
217305100Scy     * successfully substituted.
218305100Scy     */
219305100Scy
220305100Scy    /* architecture */
221305100Scy    if ((tmp2 = sun_strsub(tmp, SUN_ARCH, AMD_ARCH)) != NULL) {
222305100Scy      continue;
223305100Scy    }
224305100Scy    /* cpu - there is not POSIX uname for cpu so just use machine */
225305100Scy    if ((tmp2 = sun_strsub(tmp, SUN_CPU, AMD_ARCH)) != NULL) {
226305100Scy      continue;
227305100Scy    }
228305100Scy    /* hostname */
229305100Scy    if ((tmp2 = sun_strsub(tmp, SUN_HOST, AMD_HOST)) != NULL) {
230305100Scy      continue;
231305100Scy    }
232305100Scy    /* os name */
233305100Scy    if ((tmp2 = sun_strsub(tmp, SUN_OSNAME, AMD_OSNAME)) != NULL) {
234305100Scy      continue;
235305100Scy    }
236305100Scy    /*
237305100Scy     * os release - Amd doesn't hava a OS release var just usr os
238305100Scy     * version or now.
239305100Scy     */
240305100Scy    if ((tmp2 = sun_strsub(tmp, SUN_OSREL, AMD_OSVER)) != NULL) {
241305100Scy      continue;
242305100Scy    }
243305100Scy    /* os version */
244305100Scy    if ((tmp2 = sun_strsub(tmp, SUN_OSVERS, AMD_OSVER)) != NULL) {
245305100Scy      continue;
246305100Scy    }
247305100Scy    /* native instruction set - there is no POSIX natisa so just use system */
248305100Scy    if ((tmp2 = sun_strsub(tmp, SUN_NATISA, AMD_ARCH)) != NULL) {
249305100Scy      continue;
250305100Scy    }
251305100Scy  }
252305100Scy  if (tmp2 == NULL) {
253305100Scy    retval = tmp;
254305100Scy  }
255305100Scy  else {
256305100Scy    retval = tmp2;
257305100Scy    XFREE(tmp);
258305100Scy  }
259305100Scy
260305100Scy  return retval;
261305100Scy}
262305100Scy
263305100Scy
264305100Scy/*
265305100Scy * This is a wrapper function for appending Amd entry information to a
266305100Scy * buffer.  Any Sun variable substitutions will be converted into Amd
267305100Scy * equivalents.
268305100Scy *
269305100Scy * param dest   - destination buffer
270305100Scy * param deslen - destination buffer length
271305100Scy * param key    - entry key, this might be needed for key substitutions
272305100Scy * param str    - string to append
273305100Scy */
274305100Scystatic void
275305100Scysun_append_str(char *dest,
276305100Scy	       size_t destlen,
277305100Scy	       const char *key,
278305100Scy	       const char *str)
279305100Scy{
280305100Scy  char *sub = NULL, *sub2 = NULL, *out = NULL;
281305100Scy
282305100Scy  /* By default we are going to just write the original string. */
283305100Scy  out = (char*)str;
284305100Scy
285305100Scy  /*
286305100Scy   * Resolve variable substitutions in two steps; 1) replace any key
287305100Scy   * map substitutions with the entry key 2) expand any variable
288305100Scy   * substitutions i.e $HOST.
289305100Scy   *
290305100Scy   * Try to replace the key substitution '&'. If this function returns
291305100Scy   * with a new string, one or more key subs. where replaced with the
292305100Scy   * entry key.
293305100Scy   */
294305100Scy  if ((sub = sun_strsub(str, SUN_KEY_SUB, "${key}")) != NULL) {
295305100Scy    out = sub;
296305100Scy    /*
297305100Scy     * Try to convert any variable substitutions. If this function
298305100Scy     * returns a new string one or more var subs where expanded.
299305100Scy     */
300305100Scy    if ((sub2 = sun_expand2amd(sub)) != NULL) {
301305100Scy      out = sub2;
302305100Scy    }
303305100Scy  }
304305100Scy  /*
305305100Scy   * Try to convert any variable substitutions. If this function
306305100Scy   * returns a new string one or more var subs where expanded.
307305100Scy   */
308305100Scy  else if (out != NULL && (sub = sun_expand2amd(out)) != NULL) {
309305100Scy    out = sub;
310305100Scy  }
311305100Scy
312305100Scy  if (out != NULL) {
313305100Scy    xstrlcat(dest, out, destlen);
314305100Scy  }
315305100Scy  XFREE(sub);
316305100Scy  XFREE(sub2);
317305100Scy}
318305100Scy
319305100Scy
320305100Scy/*
321305100Scy * Convert the list of Sun mount options to Amd mount options.  The
322305100Scy * result is concatenated to dest.
323305100Scy *
324305100Scy * param dest     - destination buffer
325305100Scy * param destlen  - destination buffer length
326305100Scy * param key      - automount key
327305100Scy * param opt_list - list of Sun mount options
328305100Scy */
329305100Scystatic void
330305100Scysun_opts2amd(char *dest,
331305100Scy	     size_t destlen,
332305100Scy	     const char *key,
333305100Scy	     const struct sun_opt *opt_list)
334305100Scy{
335305100Scy  const struct sun_opt *opt;
336305100Scy
337305100Scy  xstrlcat(dest, AMD_OPTS_KW, destlen);
338305100Scy
339305100Scy  /* Iterate through each option and append it to the buffer. */
340305100Scy  for(opt = opt_list; opt != NULL; opt = NEXT(struct sun_opt, opt)) {
341305100Scy    sun_append_str(dest, destlen, key, opt->str);
342305100Scy    /* If there are more options add some commas. */
343305100Scy    if (NEXT(struct sun_opt, opt) != NULL) {
344305100Scy      xstrlcat(dest, ",", destlen);
345305100Scy    }
346305100Scy  }
347305100Scy  xstrlcat(dest, ";", destlen);
348305100Scy}
349305100Scy
350305100Scy
351305100Scy/*
352305100Scy * Convert the list of Sun mount locations to a list of Amd mount
353305100Scy * locations.  The result is concatenated to dest.
354305100Scy *
355305100Scy * param dest       - destination buffer
356305100Scy * param destlen    - destination buffer length
357305100Scy * param key        - automount key
358305100Scy * param local_list - list of Sun mount locations
359305100Scy */
360305100Scystatic void
361305100Scysun_locations2amd(char *dest,
362305100Scy		  size_t destlen,
363305100Scy		  const char *key,
364305100Scy		  const struct sun_location *local_list)
365305100Scy{
366305100Scy  const struct sun_location *local;
367305100Scy  const struct sun_host *host;
368305100Scy
369305100Scy  for (local = local_list;
370305100Scy       local != NULL;
371305100Scy       local = NEXT(struct sun_location,local)) {
372305100Scy    /*
373305100Scy     * Check to see if the list of hosts is empty.  Some mount types
374305100Scy     * i.e cd-rom may have mount location with no host.
375305100Scy     */
376305100Scy    if (local->host_list != NULL) {
377305100Scy      /* Write each host that belongs to this location. */
378305100Scy      for (host = local->host_list;
379305100Scy	   host != NULL;
380305100Scy	   host = NEXT(struct sun_host, host)) {
381305100Scy	/* set fstype NFS */
382305100Scy	xstrlcat(dest, AMD_TYPE_NFS_KW, destlen);
383305100Scy	/* add rhost key word */
384305100Scy	xstrlcat(dest, AMD_RHOST_KW, destlen);
385305100Scy	/* add host name */
386305100Scy	sun_append_str(dest, destlen, key, host->name);
387305100Scy	xstrlcat(dest, ";", destlen);
388305100Scy	/* add remote fs key word */
389305100Scy	xstrlcat(dest, AMD_RFS_KW, destlen);
390305100Scy	/* add local path */
391305100Scy	sun_append_str(dest, destlen, key, local->path);
392305100Scy	if (NEXT(struct sun_host, host) != NULL) {
393305100Scy	  xstrlcat(dest, ";", destlen);
394305100Scy	  xstrlcat(dest, " ", destlen);
395305100Scy	}
396305100Scy      }
397305100Scy    }
398305100Scy    else {
399305100Scy      /* no host location */
400305100Scy      xstrlcat(dest, AMD_FS_KW, destlen);
401305100Scy      sun_append_str(dest, destlen, key, local->path);
402305100Scy    }
403305100Scy    if (NEXT(struct sun_location, local) != NULL) {
404305100Scy      /* add a space to separate each location */
405305100Scy      xstrlcat(dest, " ", destlen);
406305100Scy    }
407305100Scy  }
408305100Scy}
409305100Scy
410305100Scy
411305100Scy/*
412305100Scy * Convert a Sun HSFS mount point to an Amd.  The result is
413305100Scy * concatenated intp dest.
414305100Scy *
415305100Scy * param dest    - destination buffer
416305100Scy * param destlen - destination buffer length
417305100Scy * param key     - automount key
418305100Scy * param s_entry - Sun entry
419305100Scy */
420305100Scystatic void
421305100Scysun_hsfs2amd(char *dest,
422305100Scy	     size_t destlen,
423305100Scy	     const char *key,
424305100Scy	     const struct sun_entry *s_entry)
425305100Scy{
426305100Scy  /* set fstype CDFS */
427305100Scy  xstrlcat(dest, AMD_TYPE_CDFS_KW, destlen);
428305100Scy  /* set the cdrom device */
429305100Scy  xstrlcat(dest, AMD_DEV_KW, destlen);
430305100Scy  /* XXX: For now just assume that there is only one device. */
431305100Scy  xstrlcat(dest, s_entry->location_list->path, destlen);
432305100Scy}
433305100Scy
434305100Scy
435305100Scy/*
436305100Scy * Convert a Sun NFS automount entry to an Amd.  The result is concatenated
437305100Scy * into dest.
438305100Scy *
439305100Scy * param dest    - destination buffer
440305100Scy * param destlen - destination buffer length
441305100Scy * param key     - automount key
442305100Scy * param s_entry - Sun entry
443305100Scy */
444305100Scystatic void
445305100Scysun_nfs2amd(char *dest,
446305100Scy	    size_t destlen,
447305100Scy	    const char *key,
448305100Scy	    const struct sun_entry *s_entry)
449305100Scy{
450305100Scy  if (s_entry->location_list != NULL) {
451305100Scy    /* write out the list of mountpoint locations */
452305100Scy    sun_locations2amd(dest, destlen, key, s_entry->location_list);
453305100Scy  }
454305100Scy}
455305100Scy
456305100Scy
457305100Scy/*
458305100Scy * Convert a Sun multi-mount point entry to an Amd.  This is done
459305100Scy * using the Amd type auto.  Each auto entry is separated with a \n.
460305100Scy *
461305100Scy * param dest    - destination buffer
462305100Scy * param destlen - destination buffer length
463305100Scy * param key     - automount key
464305100Scy * param s_entry - Sun entry
465305100Scy */
466305100Scystatic void
467305100Scysun_multi2amd(char *dest,
468305100Scy	      size_t destlen,
469305100Scy	      const char *key,
470305100Scy	      const struct sun_entry *s_entry)
471305100Scy{
472305100Scy  const struct sun_mountpt *mountpt;
473305100Scy
474305100Scy  /* We need to setup a auto fs Amd automount point. */
475305100Scy  xstrlcat(dest, AMD_TYPE_AUTO_KW, destlen);
476305100Scy  xstrlcat(dest, AMD_MAP_FS_KW, destlen);
477305100Scy  xstrlcat(dest, AMD_MAP_PREF_KW, destlen);
478305100Scy
479305100Scy  /* write the mountpts to dest */
480305100Scy  for (mountpt = s_entry->mountpt_list;
481305100Scy       mountpt != NULL;
482305100Scy       mountpt = NEXT(struct sun_mountpt, mountpt)) {
483305100Scy    xstrlcat(dest, "\n", destlen);
484305100Scy    /* write the key */
485305100Scy    xstrlcat(dest, key, destlen);
486305100Scy    /* write the mount path */
487305100Scy    sun_append_str(dest, destlen, key, mountpt->path);
488305100Scy    /* space */
489305100Scy    xstrlcat(dest, " ", destlen);
490305100Scy    /* Write all the host locations for this mount point. */
491305100Scy    sun_locations2amd(dest, destlen, key, mountpt->location_list);
492305100Scy  }
493305100Scy}
494305100Scy
495305100Scy
496305100Scy/*
497305100Scy * Convert the sun_entry into an Amd equivalent string.
498305100Scy *
499305100Scy * param key     - automount key
500305100Scy * param s_entry - Sun style automap entry
501305100Scy *
502305100Scy * return - Amd entry on succes, NULL on error
503305100Scy */
504305100Scychar *
505305100Scysun_entry2amd(const char *key, const char *s_entry_str)
506305100Scy{
507305100Scy  char *retval = NULL;
508305100Scy  char line_buff[INFO_MAX_LINE_LEN];
509305100Scy  int ws;
510305100Scy  struct sun_entry *s_entry = NULL;
511305100Scy
512305100Scy  /* The key should not be NULL. */
513305100Scy  if (key == NULL) {
514305100Scy    plog(XLOG_ERROR,"Sun key value was null");
515305100Scy    goto err;
516305100Scy  }
517305100Scy  /* The Sun entry string should never be NULL. */
518305100Scy  if (s_entry_str == NULL) {
519305100Scy    plog(XLOG_ERROR,"Sun entry value was null");
520305100Scy    goto err;
521305100Scy  }
522305100Scy
523305100Scy  /* Make sure there are no trailing white spaces or '\n'. */
524305100Scy  xstrlcpy(line_buff, s_entry_str, sizeof(line_buff));
525305100Scy  ws = strlen(line_buff) - 1;
526305100Scy  while (ws >= 0 && (isspace((unsigned char)line_buff[ws]) || line_buff[ws] == '\n')) {
527305100Scy    line_buff[ws--] = '\0';
528305100Scy  }
529305100Scy
530305100Scy  /* Parse the sun entry line. */
531305100Scy  s_entry = sun_map_parse_read(line_buff);
532305100Scy  if (s_entry == NULL) {
533305100Scy    plog(XLOG_ERROR,"could not parse Sun style map");
534305100Scy    goto err;
535305100Scy  }
536305100Scy
537305100Scy  memset(line_buff, 0, sizeof(line_buff));
538305100Scy
539305100Scy  if (s_entry->opt_list != NULL) {
540305100Scy    /* write the mount options to the buffer  */
541305100Scy    sun_opts2amd(line_buff, sizeof(line_buff), key, s_entry->opt_list);
542305100Scy  }
543305100Scy
544305100Scy  /* Check if this is a multi-mount entry. */
545305100Scy  if (s_entry->mountpt_list != NULL) {
546305100Scy    /* multi-mount point */
547305100Scy    sun_multi2amd(line_buff, sizeof(line_buff), key, s_entry);
548305100Scy    retval = xstrdup(line_buff);
549305100Scy  }
550305100Scy  else {
551305100Scy    /* single mount point */
552305100Scy    if (s_entry->fstype != NULL) {
553305100Scy      if (NSTREQ(s_entry->fstype, SUN_NFS_TYPE, strlen(SUN_NFS_TYPE))) {
554305100Scy	/* NFS Type */
555305100Scy	sun_nfs2amd(line_buff, sizeof(line_buff), key, s_entry);
556305100Scy	retval = xstrdup(line_buff);
557305100Scy      }
558305100Scy      else if (NSTREQ(s_entry->fstype, SUN_HSFS_TYPE, strlen(SUN_HSFS_TYPE))) {
559305100Scy	/* HSFS Type (CD fs) */
560305100Scy	sun_hsfs2amd(line_buff, sizeof(line_buff), key, s_entry);
561305100Scy	retval = xstrdup(line_buff);
562305100Scy      }
563305100Scy      /*
564305100Scy       * XXX: The following fstypes are not yet supported.
565305100Scy       */
566305100Scy      else if (NSTREQ(s_entry->fstype, SUN_AUTOFS_TYPE, strlen(SUN_AUTOFS_TYPE))) {
567305100Scy	/* AutoFS Type */
568305100Scy	plog(XLOG_ERROR, "Sun fstype %s is currently not supported by Amd.",
569305100Scy	     s_entry->fstype);
570305100Scy	goto err;
571305100Scy
572305100Scy      }
573305100Scy      else if (NSTREQ(s_entry->fstype, SUN_CACHEFS_TYPE, strlen(SUN_CACHEFS_TYPE))) {
574305100Scy	/* CacheFS Type */
575305100Scy	plog(XLOG_ERROR, "Sun fstype %s is currently not supported by Amd.",
576305100Scy	     s_entry->fstype);
577305100Scy	goto err;
578305100Scy      }
579305100Scy      else {
580305100Scy	plog(XLOG_ERROR, "Sun fstype %s is currently not supported by Amd.",
581305100Scy	     s_entry->fstype);
582305100Scy	goto err;
583305100Scy      }
584305100Scy    }
585305100Scy    else {
586305100Scy      plog(XLOG_INFO, "No SUN fstype specified defaulting to NFS.");
587305100Scy      sun_nfs2amd(line_buff, sizeof(line_buff), key, s_entry);
588305100Scy      retval = xstrdup(line_buff);
589305100Scy    }
590305100Scy  }
591305100Scy
592305100Scy err:
593305100Scy  XFREE(s_entry);
594305100Scy  return retval;
595305100Scy}
596