1 /* $NetBSD: sun_map.c,v 1.1.1.2 2009/03/20 20:26:50 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1997-2009 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. All advertising materials mentioning features or use of this software 23 * must display the following acknowledgment: 24 * This product includes software developed by the University of 25 * California, Berkeley and its contributors. 26 * 4. Neither the name of the University nor the names of its contributors 27 * may be used to endorse or promote products derived from this software 28 * without specific prior written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 40 * SUCH DAMAGE. 41 * 42 * 43 * File: am-utils/amd/sun_map.c 44 * 45 */ 46 47 #ifdef HAVE_CONFIG_H 48 # include <config.h> 49 #endif /* HAVE_CONFIG_H */ 50 #include <am_defs.h> 51 #include <amd.h> 52 #include <sun_map.h> 53 54 55 56 /* 57 * Add a data pointer to the end of the list. 58 */ 59 void 60 sun_list_add(struct sun_list *list, qelem *item) 61 { 62 if (list->last == NULL) { 63 list->last = item; 64 list->first = item; 65 item->q_back = NULL; 66 } 67 else { 68 list->last->q_forw = item; 69 item->q_back = list->last; 70 list->last = item; 71 } 72 73 item->q_forw = NULL; 74 } 75 76 77 /* 78 * Sun2Amd conversion routines 79 */ 80 81 /* 82 * AMD entry keywords 83 */ 84 #define AMD_OPTS_KW "addopts:=" /* add entry options */ 85 #define AMD_RHOST_KW "rhost:=" /* remote host */ 86 #define AMD_RFS_KW "rfs:=" /* remote file system */ 87 #define AMD_FS_KW "fs:=" /* local file system */ 88 #define AMD_DEV_KW "dev:=" /* device */ 89 #define AMD_TYPE_NFS_KW "type:=nfs;" /* fs type nfs */ 90 #define AMD_TYPE_AUTO_KW "type:=auto;" /* fs type auto */ 91 #define AMD_TYPE_CDFS_KW "type:=cdfs;" /* fs type cd */ 92 #define AMD_MAP_FS_KW "fs:=${map};" /* set the mount map as current map */ 93 #define AMD_MAP_PREF_KW "pref:=${key}/" /* set the mount map as current map */ 94 95 /* 96 * A set of string Sun fstypes. 97 */ 98 #define SUN_NFS_TYPE "nfs" 99 #define SUN_HSFS_TYPE "hsfs" /* CD fs */ 100 #define SUN_AUTOFS_TYPE "autofs" 101 #define SUN_CACHEFS_TYPE "cachefs" 102 103 #define SUN_KEY_SUB "&" /* Sun key substitution */ 104 105 /* a set a Sun variable substitutions for map entries */ 106 #define SUN_ARCH "$ARCH" /* host architecture */ 107 #define SUN_CPU "$CPU" /* processor type */ 108 #define SUN_HOST "$HOST" /* host name */ 109 #define SUN_OSNAME "$OSNAME" /* OS name */ 110 #define SUN_OSREL "$OSREL" /* OS release */ 111 #define SUN_OSVERS "$OSVERS" /* OS version */ 112 #define SUN_NATISA "$NATISA" /* native instruction set */ 113 114 /* a set of Amd variable substitutions */ 115 #define AMD_ARCH "${arch}" /* host architecture */ 116 #define AMD_HOST "${host}" /* host name */ 117 #define AMD_OSNAME "${os}" /* OS name */ 118 #define AMD_OSVER "${osver}" /* OS version */ 119 120 121 /* 122 * Return a copy of src that has all occurrences of 'str' replaced 123 * with sub. 124 * 125 * param src - the original string 126 * param str - string that is the replaced with str 127 * param sub - string that replaces an occurrences of 'delim' 128 * 129 * return - new string with str substitutions, NULL on error 130 */ 131 static char * 132 sun_strsub(const char *src, const char *str, const char *sub) 133 { 134 135 char *retval = NULL, *str_start, *str_end, *src_end; 136 size_t total_size, first_half, second_half, sub_size; 137 138 /* assign pointers to the start and end of str */ 139 if ((str_start = strstr(src, str)) == NULL) { 140 return retval; 141 } 142 str_end = (strlen(str) - 1) + str_start; 143 144 /* assign to the end of the src. */ 145 src_end = (strlen(src) - 1) + (char*)src; 146 147 /* size from the beginning of src to the start of str */ 148 first_half = (size_t)(str_start - src); 149 150 /* size from the end of str to the end of src */ 151 second_half = (size_t)(src_end - str_end); 152 153 sub_size = strlen(sub); 154 155 total_size = (first_half + sub_size + second_half + 1); 156 157 retval = (char*)xmalloc(total_size); 158 memset(retval, 0, total_size); 159 160 /* 161 * Put together the string such that the first half is copied 162 * followed the sub and second half. 163 * 164 * We use strncpy instead of xstrlcpy because we are intentionally 165 * causing truncation and we don't want this to cause errors in the 166 * log. 167 */ 168 (void)strncpy(retval, src, first_half); 169 (void)strncat(retval, sub, sub_size); 170 (void)strncat(retval, str_end + 1, second_half); 171 172 if ((str_start = strstr(retval, str)) != NULL) { 173 /* 174 * If there is another occurrences of str call this function 175 * recursively. 176 */ 177 char* tmp; 178 if ((tmp = sun_strsub(retval, str, sub)) != NULL) { 179 XFREE(retval); 180 retval = tmp; 181 } 182 } 183 return retval; 184 } 185 186 187 /* 188 * Return a new string that is a copy of str, all occurrences of a Sun 189 * variable substitutions are replaced by there equivalent Amd 190 * substitutions. 191 * 192 * param str - source string 193 * 194 * return - A new string with the expansions, NULL if str does not 195 * exist in src or error. 196 */ 197 static char * 198 sun_expand2amd(const char *str) 199 { 200 201 char *retval = NULL, *tmp = NULL, *tmp2 = NULL; 202 const char *pos; 203 204 /* 205 * Iterator through the string looking for '$' chars. For each '$' 206 * found try to replace it with Sun variable substitutions. If we 207 * find a '$' that is not a substation each of the i.e $blah than 208 * each of the replace attempt will fail and we'll move on to the 209 * next char. 210 */ 211 tmp = strdup(str); 212 for (pos = str; *pos != '\0'; pos++) { 213 if (*pos != '$') { 214 continue; 215 } 216 if (tmp2 != NULL) { 217 XFREE(tmp); 218 tmp = tmp2; 219 } 220 221 /* 222 * If a 'replace' does not return NULL than a variable was 223 * successfully substituted. 224 */ 225 226 /* architecture */ 227 if ((tmp2 = sun_strsub(tmp, SUN_ARCH, AMD_ARCH)) != NULL) { 228 continue; 229 } 230 /* cpu - there is not POSIX uname for cpu so just use machine */ 231 if ((tmp2 = sun_strsub(tmp, SUN_CPU, AMD_ARCH)) != NULL) { 232 continue; 233 } 234 /* hostname */ 235 if ((tmp2 = sun_strsub(tmp, SUN_HOST, AMD_HOST)) != NULL) { 236 continue; 237 } 238 /* os name */ 239 if ((tmp2 = sun_strsub(tmp, SUN_OSNAME, AMD_OSNAME)) != NULL) { 240 continue; 241 } 242 /* 243 * os release - Amd doesn't hava a OS release var just usr os 244 * version or now. 245 */ 246 if ((tmp2 = sun_strsub(tmp, SUN_OSREL, AMD_OSVER)) != NULL) { 247 continue; 248 } 249 /* os version */ 250 if ((tmp2 = sun_strsub(tmp, SUN_OSVERS, AMD_OSVER)) != NULL) { 251 continue; 252 } 253 /* native instruction set - there is no POSIX natisa so just use system */ 254 if ((tmp2 = sun_strsub(tmp, SUN_NATISA, AMD_ARCH)) != NULL) { 255 continue; 256 } 257 } 258 if (tmp2 == NULL) { 259 retval = tmp; 260 } 261 else { 262 retval = tmp2; 263 if (tmp != NULL) { 264 XFREE(tmp); 265 } 266 } 267 268 return retval; 269 } 270 271 272 /* 273 * This is a wrapper function for appending Amd entry information to a 274 * buffer. Any Sun variable substitutions will be converted into Amd 275 * equivalents. 276 * 277 * param dest - destination buffer 278 * param deslen - destination buffer length 279 * param key - entry key, this might be needed for key substitutions 280 * param str - string to append 281 */ 282 static void 283 sun_append_str(char *dest, 284 size_t destlen, 285 const char *key, 286 const char *str) 287 { 288 char *sub = NULL, *sub2 = NULL, *out = NULL; 289 290 /* By default we are going to just write the original string. */ 291 out = (char*)str; 292 293 /* 294 * Resolve variable substitutions in two steps; 1) replace any key 295 * map substitutions with the entry key 2) expand any variable 296 * substitutions i.e $HOST. 297 * 298 * Try to replace the key substitution '&'. If this function returns 299 * with a new string, one or more key subs. where replaced with the 300 * entry key. 301 */ 302 if ((sub = sun_strsub(str, SUN_KEY_SUB, "${key}")) != NULL) { 303 out = sub; 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 if ((sub2 = sun_expand2amd(sub)) != NULL) { 309 out = sub2; 310 } 311 } 312 /* 313 * Try to convert any variable substitutions. If this function 314 * returns a new string one or more var subs where expanded. 315 */ 316 else if ((sub = sun_expand2amd(out)) != NULL) { 317 out = sub; 318 } 319 320 if (out != NULL) { 321 xstrlcat(dest, out, destlen); 322 } 323 if (sub != NULL) { 324 XFREE(sub); 325 } 326 if (sub2 != NULL) { 327 XFREE(sub2); 328 } 329 } 330 331 332 /* 333 * Convert the list of Sun mount options to Amd mount options. The 334 * result is concatenated to dest. 335 * 336 * param dest - destination buffer 337 * param destlen - destination buffer length 338 * param key - automount key 339 * param opt_list - list of Sun mount options 340 */ 341 static void 342 sun_opts2amd(char *dest, 343 size_t destlen, 344 const char *key, 345 const struct sun_opt *opt_list) 346 { 347 const struct sun_opt *opt; 348 349 xstrlcat(dest, AMD_OPTS_KW, destlen); 350 351 /* Iterate through each option and append it to the buffer. */ 352 for(opt = opt_list; opt != NULL; opt = NEXT(struct sun_opt, opt)) { 353 sun_append_str(dest, destlen, key, opt->str); 354 /* If there are more options add some commas. */ 355 if (NEXT(struct sun_opt, opt) != NULL) { 356 xstrlcat(dest, ",", destlen); 357 } 358 } 359 xstrlcat(dest, ";", destlen); 360 } 361 362 363 /* 364 * Convert the list of Sun mount locations to a list of Amd mount 365 * locations. The result is concatenated to dest. 366 * 367 * param dest - destination buffer 368 * param destlen - destination buffer length 369 * param key - automount key 370 * param local_list - list of Sun mount locations 371 */ 372 static void 373 sun_locations2amd(char *dest, 374 size_t destlen, 375 const char *key, 376 const struct sun_location *local_list) 377 { 378 const struct sun_location *local; 379 const struct sun_host *host; 380 381 for (local = local_list; 382 local != NULL; 383 local = NEXT(struct sun_location,local)) { 384 /* 385 * Check to see if the list of hosts is empty. Some mount types 386 * i.e cd-rom may have mount location with no host. 387 */ 388 if (local->host_list != NULL) { 389 /* Write each host that belongs to this location. */ 390 for (host = local->host_list; 391 host != NULL; 392 host = NEXT(struct sun_host, host)) { 393 /* set fstype NFS */ 394 xstrlcat(dest, AMD_TYPE_NFS_KW, destlen); 395 /* add rhost key word */ 396 xstrlcat(dest, AMD_RHOST_KW, destlen); 397 /* add host name */ 398 sun_append_str(dest, destlen, key, host->name); 399 xstrlcat(dest, ";", destlen); 400 /* add remote fs key word */ 401 xstrlcat(dest, AMD_RFS_KW, destlen); 402 /* add local path */ 403 sun_append_str(dest, destlen, key, local->path); 404 if (NEXT(struct sun_host, host) != NULL) { 405 xstrlcat(dest, ";", destlen); 406 xstrlcat(dest, " ", destlen); 407 } 408 } 409 } 410 else { 411 /* no host location */ 412 xstrlcat(dest, AMD_FS_KW, destlen); 413 sun_append_str(dest, destlen, key, local->path); 414 } 415 if (NEXT(struct sun_location, local) != NULL) { 416 /* add a space to separate each location */ 417 xstrlcat(dest, " ", destlen); 418 } 419 } 420 } 421 422 423 /* 424 * Convert a Sun HSFS mount point to an Amd. The result is 425 * concatenated intp dest. 426 * 427 * param dest - destination buffer 428 * param destlen - destination buffer length 429 * param key - automount key 430 * param s_entry - Sun entry 431 */ 432 static void 433 sun_hsfs2amd(char *dest, 434 size_t destlen, 435 const char *key, 436 const struct sun_entry *s_entry) 437 { 438 /* set fstype CDFS */ 439 xstrlcat(dest, AMD_TYPE_CDFS_KW, destlen); 440 /* set the cdrom device */ 441 xstrlcat(dest, AMD_DEV_KW, destlen); 442 /* XXX: For now just assume that there is only one device. */ 443 xstrlcat(dest, s_entry->location_list->path, destlen); 444 } 445 446 447 /* 448 * Convert a Sun NFS automount entry to an Amd. The result is concatenated 449 * into dest. 450 * 451 * param dest - destination buffer 452 * param destlen - destination buffer length 453 * param key - automount key 454 * param s_entry - Sun entry 455 */ 456 static void 457 sun_nfs2amd(char *dest, 458 size_t destlen, 459 const char *key, 460 const struct sun_entry *s_entry) 461 { 462 if (s_entry->location_list != NULL) { 463 /* write out the list of mountpoint locations */ 464 sun_locations2amd(dest, destlen, key, s_entry->location_list); 465 } 466 } 467 468 469 /* 470 * Convert a Sun multi-mount point entry to an Amd. This is done 471 * using the Amd type auto. Each auto entry is separated with a \n. 472 * 473 * param dest - destination buffer 474 * param destlen - destination buffer length 475 * param key - automount key 476 * param s_entry - Sun entry 477 */ 478 static void 479 sun_multi2amd(char *dest, 480 size_t destlen, 481 const char *key, 482 const struct sun_entry *s_entry) 483 { 484 const struct sun_mountpt *mountpt; 485 486 /* We need to setup a auto fs Amd automount point. */ 487 xstrlcat(dest, AMD_TYPE_AUTO_KW, destlen); 488 xstrlcat(dest, AMD_MAP_FS_KW, destlen); 489 xstrlcat(dest, AMD_MAP_PREF_KW, destlen); 490 491 /* write the mountpts to dest */ 492 for (mountpt = s_entry->mountpt_list; 493 mountpt != NULL; 494 mountpt = NEXT(struct sun_mountpt, mountpt)) { 495 xstrlcat(dest, "\n", destlen); 496 /* write the key */ 497 xstrlcat(dest, key, destlen); 498 /* write the mount path */ 499 sun_append_str(dest, destlen, key, mountpt->path); 500 /* space */ 501 xstrlcat(dest, " ", destlen); 502 /* Write all the host locations for this mount point. */ 503 sun_locations2amd(dest, destlen, key, mountpt->location_list); 504 } 505 } 506 507 508 /* 509 * Convert the sun_entry into an Amd equivalent string. 510 * 511 * param key - automount key 512 * param s_entry - Sun style automap entry 513 * 514 * return - Amd entry on succes, NULL on error 515 */ 516 char * 517 sun_entry2amd(const char *key, const char *s_entry_str) 518 { 519 char *retval = NULL; 520 char line_buff[INFO_MAX_LINE_LEN]; 521 int ws; 522 struct sun_entry *s_entry = NULL; 523 524 /* The key should not be NULL. */ 525 if (key == NULL) { 526 plog(XLOG_ERROR,"Sun key value was null"); 527 goto err; 528 } 529 /* The Sun entry string should never be NULL. */ 530 if (s_entry_str == NULL) { 531 plog(XLOG_ERROR,"Sun entry value was null"); 532 goto err; 533 } 534 535 /* Make sure there are no trailing white spaces or '\n'. */ 536 xstrlcpy(line_buff, s_entry_str, sizeof(line_buff)); 537 ws = strlen(line_buff) - 1; 538 while (ws >= 0 && (isspace((unsigned char)line_buff[ws]) || line_buff[ws] == '\n')) { 539 line_buff[ws--] = '\0'; 540 } 541 542 /* Parse the sun entry line. */ 543 s_entry = sun_map_parse_read(line_buff); 544 if (s_entry == NULL) { 545 plog(XLOG_ERROR,"could not parse Sun style map"); 546 goto err; 547 } 548 549 memset(line_buff, 0, sizeof(line_buff)); 550 551 if (s_entry->opt_list != NULL) { 552 /* write the mount options to the buffer */ 553 sun_opts2amd(line_buff, sizeof(line_buff), key, s_entry->opt_list); 554 } 555 556 /* Check if this is a multi-mount entry. */ 557 if (s_entry->mountpt_list != NULL) { 558 /* multi-mount point */ 559 sun_multi2amd(line_buff, sizeof(line_buff), key, s_entry); 560 retval = strdup(line_buff); 561 } 562 else { 563 /* single mount point */ 564 if (s_entry->fstype != NULL) { 565 if (NSTREQ(s_entry->fstype, SUN_NFS_TYPE, strlen(SUN_NFS_TYPE))) { 566 /* NFS Type */ 567 sun_nfs2amd(line_buff, sizeof(line_buff), key, s_entry); 568 retval = strdup(line_buff); 569 } 570 else if (NSTREQ(s_entry->fstype, SUN_HSFS_TYPE, strlen(SUN_HSFS_TYPE))) { 571 /* HSFS Type (CD fs) */ 572 sun_hsfs2amd(line_buff, sizeof(line_buff), key, s_entry); 573 retval = strdup(line_buff); 574 } 575 /* 576 * XXX: The following fstypes are not yet supported. 577 */ 578 else if (NSTREQ(s_entry->fstype, SUN_AUTOFS_TYPE, strlen(SUN_AUTOFS_TYPE))) { 579 /* AutoFS Type */ 580 plog(XLOG_ERROR, "Sun fstype %s is currently not supported by Amd.", 581 s_entry->fstype); 582 goto err; 583 584 } 585 else if (NSTREQ(s_entry->fstype, SUN_CACHEFS_TYPE, strlen(SUN_CACHEFS_TYPE))) { 586 /* CacheFS Type */ 587 plog(XLOG_ERROR, "Sun fstype %s is currently not supported by Amd.", 588 s_entry->fstype); 589 goto err; 590 } 591 else { 592 plog(XLOG_ERROR, "Sun fstype %s is currently not supported by Amd.", 593 s_entry->fstype); 594 goto err; 595 } 596 } 597 else { 598 plog(XLOG_INFO, "No SUN fstype specified defaulting to NFS."); 599 sun_nfs2amd(line_buff, sizeof(line_buff), key, s_entry); 600 retval = strdup(line_buff); 601 } 602 } 603 604 err: 605 if (s_entry != NULL) { 606 XFREE(s_entry); 607 } 608 return retval; 609 } 610