1/* $NetBSD$ */ 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 */ 55void 56sun_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 */ 127static char * 128sun_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 */ 193static char * 194sun_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 */ 276static void 277sun_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 */ 331static void 332sun_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 */ 362static void 363sun_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 */ 422static void 423sun_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 */ 446static void 447sun_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 */ 468static void 469sun_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 */ 506char * 507sun_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