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 */ 53void 54sun_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 */ 125static char * 126sun_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 */ 191static char * 192sun_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 */ 274static void 275sun_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 */ 329static void 330sun_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 */ 360static void 361sun_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 */ 420static void 421sun_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 */ 444static void 445sun_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 */ 466static void 467sun_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 */ 504char * 505sun_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} 596