1 1.1 christos /* $NetBSD: am_ops.c,v 1.1.1.3 2015/01/17 16:34:15 christos Exp $ */ 2 1.1 christos 3 1.1 christos /* 4 1.1.1.3 christos * Copyright (c) 1997-2014 Erez Zadok 5 1.1 christos * Copyright (c) 1989 Jan-Simon Pendry 6 1.1 christos * Copyright (c) 1989 Imperial College of Science, Technology & Medicine 7 1.1 christos * Copyright (c) 1989 The Regents of the University of California. 8 1.1 christos * All rights reserved. 9 1.1 christos * 10 1.1 christos * This code is derived from software contributed to Berkeley by 11 1.1 christos * Jan-Simon Pendry at Imperial College, London. 12 1.1 christos * 13 1.1 christos * Redistribution and use in source and binary forms, with or without 14 1.1 christos * modification, are permitted provided that the following conditions 15 1.1 christos * are met: 16 1.1 christos * 1. Redistributions of source code must retain the above copyright 17 1.1 christos * notice, this list of conditions and the following disclaimer. 18 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright 19 1.1 christos * notice, this list of conditions and the following disclaimer in the 20 1.1 christos * documentation and/or other materials provided with the distribution. 21 1.1.1.3 christos * 3. Neither the name of the University nor the names of its contributors 22 1.1 christos * may be used to endorse or promote products derived from this software 23 1.1 christos * without specific prior written permission. 24 1.1 christos * 25 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 1.1 christos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 1.1 christos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 1.1 christos * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 1.1 christos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 1.1 christos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 1.1 christos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 1.1 christos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 1.1 christos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 1.1 christos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 1.1 christos * SUCH DAMAGE. 36 1.1 christos * 37 1.1 christos * 38 1.1 christos * File: am-utils/amd/am_ops.c 39 1.1 christos * 40 1.1 christos */ 41 1.1 christos 42 1.1 christos #ifdef HAVE_CONFIG_H 43 1.1 christos # include <config.h> 44 1.1 christos #endif /* HAVE_CONFIG_H */ 45 1.1 christos #include <am_defs.h> 46 1.1 christos #include <amd.h> 47 1.1 christos 48 1.1 christos 49 1.1 christos /* 50 1.1 christos * The order of these entries matters, since lookups in this table are done 51 1.1 christos * on a first-match basis. The entries below are a mixture of native 52 1.1 christos * filesystems supported by the OS (HAVE_FS_FOO), and some meta-filesystems 53 1.1 christos * supported by amd (HAVE_AMU_FS_FOO). The order is set here in expected 54 1.1 christos * match-hit such that more popular filesystems are listed first (nfs is the 55 1.1 christos * most popular, followed by a symlink F/S) 56 1.1 christos */ 57 1.1 christos static am_ops *vops[] = 58 1.1 christos { 59 1.1 christos #ifdef HAVE_FS_NFS 60 1.1 christos &nfs_ops, /* network F/S (version 2) */ 61 1.1 christos #endif /* HAVE_FS_NFS */ 62 1.1 christos #ifdef HAVE_AMU_FS_LINK 63 1.1 christos &amfs_link_ops, /* symlink F/S */ 64 1.1 christos #endif /* HAVE_AMU_FS_LINK */ 65 1.1 christos 66 1.1 christos /* 67 1.1 christos * Other amd-supported meta-filesystems. 68 1.1 christos */ 69 1.1 christos #ifdef HAVE_AMU_FS_NFSX 70 1.1 christos &amfs_nfsx_ops, /* multiple-nfs F/S */ 71 1.1 christos #endif /* HAVE_AMU_FS_NFSX */ 72 1.1 christos #ifdef HAVE_AMU_FS_NFSL 73 1.1 christos &amfs_nfsl_ops, /* NFS with local link existence check */ 74 1.1 christos #endif /* HAVE_AMU_FS_NFSL */ 75 1.1 christos #ifdef HAVE_AMU_FS_HOST 76 1.1 christos &amfs_host_ops, /* multiple exported nfs F/S */ 77 1.1 christos #endif /* HAVE_AMU_FS_HOST */ 78 1.1 christos #ifdef HAVE_AMU_FS_LINKX 79 1.1 christos &amfs_linkx_ops, /* symlink F/S with link target verify */ 80 1.1 christos #endif /* HAVE_AMU_FS_LINKX */ 81 1.1 christos #ifdef HAVE_AMU_FS_PROGRAM 82 1.1 christos &amfs_program_ops, /* program F/S */ 83 1.1 christos #endif /* HAVE_AMU_FS_PROGRAM */ 84 1.1 christos #ifdef HAVE_AMU_FS_UNION 85 1.1 christos &amfs_union_ops, /* union F/S */ 86 1.1 christos #endif /* HAVE_AMU_FS_UNION */ 87 1.1 christos 88 1.1 christos /* 89 1.1 christos * A few more native filesystems. 90 1.1 christos */ 91 1.1 christos #ifdef HAVE_FS_UFS 92 1.1 christos &ufs_ops, /* Unix F/S */ 93 1.1 christos #endif /* HAVE_FS_UFS */ 94 1.1 christos #ifdef HAVE_FS_XFS 95 1.1 christos &xfs_ops, /* Unix (irix) F/S */ 96 1.1 christos #endif /* HAVE_FS_XFS */ 97 1.1.1.3 christos #ifdef HAVE_FS_EXT 98 1.1.1.3 christos &ext2_ops, /* Unix (linux) F/S */ 99 1.1.1.3 christos &ext3_ops, /* Unix (linux) F/S */ 100 1.1.1.3 christos &ext4_ops, /* Unix (linux) F/S */ 101 1.1.1.3 christos #endif /* HAVE_FS_EXT */ 102 1.1 christos #ifdef HAVE_FS_EFS 103 1.1 christos &efs_ops, /* Unix (irix) F/S */ 104 1.1 christos #endif /* HAVE_FS_EFS */ 105 1.1 christos #ifdef HAVE_FS_LOFS 106 1.1 christos &lofs_ops, /* loopback F/S */ 107 1.1 christos #endif /* HAVE_FS_LOFS */ 108 1.1 christos #ifdef HAVE_FS_CDFS 109 1.1 christos &cdfs_ops, /* CDROM/HSFS/ISO9960 F/S */ 110 1.1 christos #endif /* HAVE_FS_CDFS */ 111 1.1 christos #ifdef HAVE_FS_PCFS 112 1.1 christos &pcfs_ops, /* Floppy/MSDOS F/S */ 113 1.1 christos #endif /* HAVE_FS_PCFS */ 114 1.1 christos #ifdef HAVE_FS_CACHEFS 115 1.1 christos &cachefs_ops, /* caching F/S */ 116 1.1 christos #endif /* HAVE_FS_CACHEFS */ 117 1.1 christos #ifdef HAVE_FS_TMPFS 118 1.1 christos &tmpfs_ops, /* /tmp (in memory) F/S */ 119 1.1 christos #endif /* HAVE_FS_TMPFS */ 120 1.1 christos #ifdef HAVE_FS_NULLFS 121 1.1 christos /* FILL IN */ /* null (loopback) F/S */ 122 1.1 christos #endif /* HAVE_FS_NULLFS */ 123 1.1 christos #ifdef HAVE_FS_UNIONFS 124 1.1 christos /* FILL IN */ /* union (bsd44) F/S */ 125 1.1 christos #endif /* HAVE_FS_UNIONFS */ 126 1.1 christos #ifdef HAVE_FS_UMAPFS 127 1.1 christos /* FILL IN */ /* uid/gid mapping F/S */ 128 1.1 christos #endif /* HAVE_FS_UMAPFS */ 129 1.1.1.2 christos #ifdef HAVE_FS_UDF 130 1.1.1.2 christos &udf_ops, /* UDF F/S */ 131 1.1.1.2 christos #endif /* HAVE_FS_UDF */ 132 1.1.1.3 christos #ifdef HAVE_FS_LUSTRE 133 1.1.1.3 christos &lustre_ops, /* Lustre */ 134 1.1.1.3 christos #endif /* HAVE_FS_LUSTRE */ 135 1.1 christos 136 1.1 christos /* 137 1.1 christos * These 4 should be last, in the order: 138 1.1 christos * (1) amfs_auto 139 1.1 christos * (2) amfs_direct 140 1.1 christos * (3) amfs_toplvl 141 1.1 christos * (4) amfs_error 142 1.1 christos */ 143 1.1 christos #ifdef HAVE_AMU_FS_AUTO 144 1.1 christos &amfs_auto_ops, /* Automounter F/S */ 145 1.1 christos #endif /* HAVE_AMU_FS_AUTO */ 146 1.1 christos #ifdef HAVE_AMU_FS_DIRECT 147 1.1 christos &amfs_direct_ops, /* direct-mount F/S */ 148 1.1 christos #endif /* HAVE_AMU_FS_DIRECT */ 149 1.1 christos #ifdef HAVE_AMU_FS_TOPLVL 150 1.1 christos &amfs_toplvl_ops, /* top-level mount F/S */ 151 1.1 christos #endif /* HAVE_AMU_FS_TOPLVL */ 152 1.1 christos #ifdef HAVE_AMU_FS_ERROR 153 1.1 christos &amfs_error_ops, /* error F/S */ 154 1.1 christos #endif /* HAVE_AMU_FS_ERROR */ 155 1.1 christos 0 156 1.1 christos }; 157 1.1 christos 158 1.1 christos 159 1.1 christos void 160 1.1 christos ops_showamfstypes(char *buf, size_t l) 161 1.1 christos { 162 1.1 christos struct am_ops **ap; 163 1.1 christos int linesize = 0; 164 1.1 christos 165 1.1 christos buf[0] = '\0'; 166 1.1 christos for (ap = vops; *ap; ap++) { 167 1.1 christos xstrlcat(buf, (*ap)->fs_type, l); 168 1.1 christos if (ap[1]) 169 1.1 christos xstrlcat(buf, ", ", l); 170 1.1 christos linesize += strlen((*ap)->fs_type) + 2; 171 1.1 christos if (linesize > 62) { 172 1.1 christos linesize = 0; 173 1.1 christos xstrlcat(buf, "\n ", l); 174 1.1 christos } 175 1.1 christos } 176 1.1 christos } 177 1.1 christos 178 1.1 christos 179 1.1 christos static void 180 1.1 christos ops_show1(char *buf, size_t l, int *linesizep, const char *name) 181 1.1 christos { 182 1.1 christos xstrlcat(buf, name, l); 183 1.1 christos xstrlcat(buf, ", ", l); 184 1.1 christos *linesizep += strlen(name) + 2; 185 1.1 christos if (*linesizep > 60) { 186 1.1 christos xstrlcat(buf, "\t\n", l); 187 1.1 christos *linesizep = 0; 188 1.1 christos } 189 1.1 christos } 190 1.1 christos 191 1.1 christos 192 1.1 christos void 193 1.1 christos ops_showfstypes(char *buf, size_t l) 194 1.1 christos { 195 1.1 christos int linesize = 0; 196 1.1 christos 197 1.1 christos buf[0] = '\0'; 198 1.1 christos 199 1.1 christos #ifdef MNTTAB_TYPE_AUTOFS 200 1.1 christos ops_show1(buf, l, &linesize, MNTTAB_TYPE_AUTOFS); 201 1.1 christos #endif /* MNTTAB_TYPE_AUTOFS */ 202 1.1 christos 203 1.1 christos #ifdef MNTTAB_TYPE_CACHEFS 204 1.1 christos ops_show1(buf, l, &linesize, MNTTAB_TYPE_CACHEFS); 205 1.1 christos #endif /* MNTTAB_TYPE_CACHEFS */ 206 1.1 christos 207 1.1 christos #ifdef MNTTAB_TYPE_CDFS 208 1.1 christos ops_show1(buf, l, &linesize, MNTTAB_TYPE_CDFS); 209 1.1 christos #endif /* MNTTAB_TYPE_CDFS */ 210 1.1 christos 211 1.1 christos #ifdef MNTTAB_TYPE_CFS 212 1.1 christos ops_show1(buf, l, &linesize, MNTTAB_TYPE_CFS); 213 1.1 christos #endif /* MNTTAB_TYPE_CFS */ 214 1.1 christos 215 1.1 christos #ifdef MNTTAB_TYPE_LOFS 216 1.1 christos ops_show1(buf, l, &linesize, MNTTAB_TYPE_LOFS); 217 1.1 christos #endif /* MNTTAB_TYPE_LOFS */ 218 1.1 christos 219 1.1 christos #ifdef MNTTAB_TYPE_EFS 220 1.1 christos ops_show1(buf, l, &linesize, MNTTAB_TYPE_EFS); 221 1.1 christos #endif /* MNTTAB_TYPE_EFS */ 222 1.1 christos 223 1.1 christos #ifdef MNTTAB_TYPE_MFS 224 1.1 christos ops_show1(buf, l, &linesize, MNTTAB_TYPE_MFS); 225 1.1 christos #endif /* MNTTAB_TYPE_MFS */ 226 1.1 christos 227 1.1 christos #ifdef MNTTAB_TYPE_NFS 228 1.1 christos ops_show1(buf, l, &linesize, MNTTAB_TYPE_NFS); 229 1.1 christos #endif /* MNTTAB_TYPE_NFS */ 230 1.1 christos 231 1.1 christos #ifdef MNTTAB_TYPE_NFS3 232 1.1 christos ops_show1(buf, l, &linesize, "nfs3"); /* always hard-code as nfs3 */ 233 1.1 christos #endif /* MNTTAB_TYPE_NFS3 */ 234 1.1 christos 235 1.1 christos #ifdef MNTTAB_TYPE_NULLFS 236 1.1 christos ops_show1(buf, l, &linesize, MNTTAB_TYPE_NULLFS); 237 1.1 christos #endif /* MNTTAB_TYPE_NULLFS */ 238 1.1 christos 239 1.1 christos #ifdef MNTTAB_TYPE_PCFS 240 1.1 christos ops_show1(buf, l, &linesize, MNTTAB_TYPE_PCFS); 241 1.1 christos #endif /* MNTTAB_TYPE_PCFS */ 242 1.1 christos 243 1.1 christos #ifdef MNTTAB_TYPE_TFS 244 1.1 christos ops_show1(buf, l, &linesize, MNTTAB_TYPE_TFS); 245 1.1 christos #endif /* MNTTAB_TYPE_TFS */ 246 1.1 christos 247 1.1 christos #ifdef MNTTAB_TYPE_TMPFS 248 1.1 christos ops_show1(buf, l, &linesize, MNTTAB_TYPE_TMPFS); 249 1.1 christos #endif /* MNTTAB_TYPE_TMPFS */ 250 1.1 christos 251 1.1 christos #ifdef MNTTAB_TYPE_UFS 252 1.1 christos ops_show1(buf, l, &linesize, MNTTAB_TYPE_UFS); 253 1.1 christos #endif /* MNTTAB_TYPE_UFS */ 254 1.1 christos 255 1.1 christos #ifdef MNTTAB_TYPE_UMAPFS 256 1.1 christos ops_show1(buf, l, &linesize, MNTTAB_TYPE_UMAPFS); 257 1.1 christos #endif /* MNTTAB_TYPE_UMAPFS */ 258 1.1 christos 259 1.1 christos #ifdef MNTTAB_TYPE_UNIONFS 260 1.1 christos ops_show1(buf, l, &linesize, MNTTAB_TYPE_UNIONFS); 261 1.1 christos #endif /* MNTTAB_TYPE_UNIONFS */ 262 1.1 christos 263 1.1 christos #ifdef MNTTAB_TYPE_XFS 264 1.1 christos ops_show1(buf, l, &linesize, MNTTAB_TYPE_XFS); 265 1.1 christos #endif /* MNTTAB_TYPE_XFS */ 266 1.1 christos 267 1.1 christos /* terminate with a period, newline, and NULL */ 268 1.1 christos if (buf[strlen(buf)-1] == '\n') 269 1.1 christos buf[strlen(buf) - 4] = '\0'; 270 1.1 christos else 271 1.1 christos buf[strlen(buf) - 2] = '\0'; 272 1.1 christos xstrlcat(buf, ".\n", l); 273 1.1 christos } 274 1.1 christos 275 1.1 christos 276 1.1 christos /* 277 1.1 christos * return string option which is the reverse of opt. 278 1.1 christos * nosuid -> suid 279 1.1 christos * quota -> noquota 280 1.1 christos * ro -> rw 281 1.1 christos * etc. 282 1.1 christos * may return pointer to static buffer or subpointer within opt. 283 1.1 christos */ 284 1.1 christos static char * 285 1.1 christos reverse_option(const char *opt) 286 1.1 christos { 287 1.1 christos static char buf[80]; 288 1.1 christos 289 1.1 christos /* sanity check */ 290 1.1 christos if (!opt) 291 1.1 christos return NULL; 292 1.1 christos 293 1.1 christos /* check special cases */ 294 1.1 christos /* XXX: if this gets too long, rewrite the code more flexibly */ 295 1.1 christos if (STREQ(opt, "ro")) return "rw"; 296 1.1 christos if (STREQ(opt, "rw")) return "ro"; 297 1.1 christos if (STREQ(opt, "bg")) return "fg"; 298 1.1 christos if (STREQ(opt, "fg")) return "bg"; 299 1.1 christos if (STREQ(opt, "soft")) return "hard"; 300 1.1 christos if (STREQ(opt, "hard")) return "soft"; 301 1.1 christos 302 1.1 christos /* check if string starts with 'no' and chop it */ 303 1.1 christos if (NSTREQ(opt, "no", 2)) { 304 1.1 christos xstrlcpy(buf, &opt[2], sizeof(buf)); 305 1.1 christos } else { 306 1.1 christos /* finally return a string prepended with 'no' */ 307 1.1 christos xstrlcpy(buf, "no", sizeof(buf)); 308 1.1 christos xstrlcat(buf, opt, sizeof(buf)); 309 1.1 christos } 310 1.1 christos return buf; 311 1.1 christos } 312 1.1 christos 313 1.1 christos 314 1.1 christos /* 315 1.1 christos * start with an empty string. for each opts1 option that is not 316 1.1 christos * in opts2, add it to the string (make sure the reverse of it 317 1.1 christos * isn't in either). finally add opts2. return new string. 318 1.1 christos * Both opts1 and opts2 must not be null! 319 1.1 christos * Caller must eventually free the string being returned. 320 1.1 christos */ 321 1.1 christos static char * 322 1.1 christos merge_opts(const char *opts1, const char *opts2) 323 1.1 christos { 324 1.1 christos mntent_t mnt2; /* place holder for opts2 */ 325 1.1 christos char *newstr; /* new string to return (malloc'ed) */ 326 1.1 christos char *tmpstr; /* temp */ 327 1.1 christos char *eq; /* pointer to whatever follows '=' within temp */ 328 1.1 christos char oneopt[80]; /* one option w/o value if any */ 329 1.1 christos char *revoneopt; /* reverse of oneopt */ 330 1.1 christos size_t len = strlen(opts1) + strlen(opts2) + 2; /* space for "," and NULL */ 331 1.1.1.3 christos char *s1 = xstrdup(opts1); /* copy of opts1 to munge */ 332 1.1 christos 333 1.1 christos /* initialization */ 334 1.1 christos mnt2.mnt_opts = (char *) opts2; 335 1.1 christos newstr = xmalloc(len); 336 1.1 christos newstr[0] = '\0'; 337 1.1 christos 338 1.1 christos for (tmpstr = strtok(s1, ","); 339 1.1 christos tmpstr; 340 1.1 christos tmpstr = strtok(NULL, ",")) { 341 1.1 christos /* copy option to temp buffer */ 342 1.1 christos xstrlcpy(oneopt, tmpstr, sizeof(oneopt)); 343 1.1 christos /* if option has a value such as rsize=1024, chop the value part */ 344 1.1.1.3 christos if ((eq = strchr(oneopt, '='))) 345 1.1 christos *eq = '\0'; 346 1.1 christos /* find reverse option of oneopt */ 347 1.1 christos revoneopt = reverse_option(oneopt); 348 1.1.1.3 christos /* if option or its reverse exist in opts2, ignore it */ 349 1.1 christos if (amu_hasmntopt(&mnt2, oneopt) || amu_hasmntopt(&mnt2, revoneopt)) 350 1.1 christos continue; 351 1.1 christos /* add option to returned string */ 352 1.1 christos if (newstr[0]) { 353 1.1 christos xstrlcat(newstr, ",", len); 354 1.1 christos xstrlcat(newstr, tmpstr, len); 355 1.1 christos } else { 356 1.1 christos xstrlcpy(newstr, tmpstr, len); 357 1.1 christos } 358 1.1 christos } 359 1.1 christos 360 1.1 christos /* finally, append opts2 itself */ 361 1.1 christos if (newstr[0]) { 362 1.1 christos xstrlcat(newstr, ",", len); 363 1.1 christos xstrlcat(newstr, opts2, len); 364 1.1 christos } else { 365 1.1 christos xstrlcpy(newstr, opts2, len); 366 1.1 christos } 367 1.1 christos 368 1.1 christos XFREE(s1); 369 1.1 christos return newstr; 370 1.1 christos } 371 1.1 christos 372 1.1 christos 373 1.1 christos am_ops * 374 1.1 christos ops_search(char *type) 375 1.1 christos { 376 1.1 christos am_ops **vp; 377 1.1 christos am_ops *rop = NULL; 378 1.1 christos for (vp = vops; (rop = *vp); vp++) 379 1.1 christos if (STREQ(rop->fs_type, type)) 380 1.1 christos break; 381 1.1 christos return rop; 382 1.1 christos } 383 1.1 christos 384 1.1 christos 385 1.1 christos am_ops * 386 1.1 christos ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map) 387 1.1 christos { 388 1.1 christos am_ops *rop = NULL; 389 1.1 christos char *link_dir; 390 1.1 christos 391 1.1 christos /* 392 1.1 christos * First crack the global opts and the local opts 393 1.1 christos */ 394 1.1 christos if (!eval_fs_opts(fo, key, g_key, path, keym, map)) { 395 1.1 christos rop = &amfs_error_ops; 396 1.1 christos } else if (fo->opt_type == 0) { 397 1.1 christos plog(XLOG_USER, "No fs type specified (key = \"%s\", map = \"%s\")", keym, map); 398 1.1 christos rop = &amfs_error_ops; 399 1.1 christos } else { 400 1.1 christos /* 401 1.1 christos * Next find the correct filesystem type 402 1.1 christos */ 403 1.1 christos rop = ops_search(fo->opt_type); 404 1.1 christos if (!rop) { 405 1.1 christos plog(XLOG_USER, "fs type \"%s\" not recognized", fo->opt_type); 406 1.1 christos rop = &amfs_error_ops; 407 1.1 christos } 408 1.1 christos } 409 1.1 christos 410 1.1 christos /* 411 1.1 christos * Make sure we have a default mount option. 412 1.1 christos * Otherwise skip past any leading '-'. 413 1.1 christos */ 414 1.1 christos if (fo->opt_opts == 0) 415 1.1.1.3 christos fo->opt_opts = xstrdup("rw,defaults"); 416 1.1 christos else if (*fo->opt_opts == '-') { 417 1.1 christos /* 418 1.1 christos * We cannot simply do fo->opt_opts++ here since the opts 419 1.1 christos * module will try to free the pointer fo->opt_opts later. 420 1.1 christos * So just reallocate the thing -- stolcke 11/11/94 421 1.1 christos */ 422 1.1 christos char *old = fo->opt_opts; 423 1.1.1.3 christos fo->opt_opts = xstrdup(old + 1); 424 1.1 christos XFREE(old); 425 1.1 christos } 426 1.1 christos 427 1.1 christos /* 428 1.1 christos * If addopts option was used, then append it to the 429 1.1 christos * current options and remote mount options. 430 1.1 christos */ 431 1.1 christos if (fo->opt_addopts) { 432 1.1 christos if (STREQ(fo->opt_opts, fo->opt_remopts)) { 433 1.1 christos /* optimize things for the common case where opts==remopts */ 434 1.1 christos char *mergedstr; 435 1.1 christos mergedstr = merge_opts(fo->opt_opts, fo->opt_addopts); 436 1.1 christos plog(XLOG_INFO, "merge rem/opts \"%s\" add \"%s\" => \"%s\"", 437 1.1 christos fo->opt_opts, fo->opt_addopts, mergedstr); 438 1.1 christos XFREE(fo->opt_opts); 439 1.1 christos XFREE(fo->opt_remopts); 440 1.1 christos fo->opt_opts = mergedstr; 441 1.1.1.3 christos fo->opt_remopts = xstrdup(mergedstr); 442 1.1 christos } else { 443 1.1 christos char *mergedstr, *remmergedstr; 444 1.1 christos mergedstr = merge_opts(fo->opt_opts, fo->opt_addopts); 445 1.1 christos plog(XLOG_INFO, "merge opts \"%s\" add \"%s\" => \"%s\"", 446 1.1 christos fo->opt_opts, fo->opt_addopts, mergedstr); 447 1.1 christos XFREE(fo->opt_opts); 448 1.1 christos fo->opt_opts = mergedstr; 449 1.1 christos remmergedstr = merge_opts(fo->opt_remopts, fo->opt_addopts); 450 1.1 christos plog(XLOG_INFO, "merge remopts \"%s\" add \"%s\" => \"%s\"", 451 1.1 christos fo->opt_remopts, fo->opt_addopts, remmergedstr); 452 1.1 christos XFREE(fo->opt_remopts); 453 1.1 christos fo->opt_remopts = remmergedstr; 454 1.1 christos } 455 1.1 christos } 456 1.1 christos 457 1.1 christos /* 458 1.1 christos * Initialize opt_mount_type to "nfs", if it's not initialized already 459 1.1 christos */ 460 1.1 christos if (!fo->opt_mount_type) 461 1.1 christos fo->opt_mount_type = "nfs"; 462 1.1 christos 463 1.1 christos /* Normalize the sublink and make it absolute */ 464 1.1 christos link_dir = fo->opt_sublink; 465 1.1 christos if (link_dir && link_dir[0] && link_dir[0] != '/') { 466 1.1 christos link_dir = str3cat((char *) NULL, fo->opt_fs, "/", link_dir); 467 1.1 christos normalize_slash(link_dir); 468 1.1 christos XFREE(fo->opt_sublink); 469 1.1 christos fo->opt_sublink = link_dir; 470 1.1 christos } 471 1.1 christos 472 1.1 christos /* 473 1.1 christos * Check the filesystem is happy 474 1.1 christos */ 475 1.1.1.3 christos XFREE(fo->fs_mtab); 476 1.1 christos 477 1.1 christos fo->fs_mtab = rop->fs_match(fo); 478 1.1 christos if (fo->fs_mtab) 479 1.1 christos return rop; 480 1.1 christos 481 1.1 christos /* 482 1.1 christos * Return error file system 483 1.1 christos */ 484 1.1 christos fo->fs_mtab = amfs_error_ops.fs_match(fo); 485 1.1 christos return &amfs_error_ops; 486 1.1 christos } 487