1%{ 2/*- 3 * Copyright (c) 2009-2010 The FreeBSD Foundation 4 * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net> 5 * All rights reserved. 6 * 7 * This software was developed by Pawel Jakub Dawidek under sponsorship from 8 * the FreeBSD Foundation. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 *
|
31 * $FreeBSD: head/sbin/hastd/parse.y 225784 2011-09-27 08:04:01Z pjd $
|
31 * $FreeBSD: head/sbin/hastd/parse.y 225830 2011-09-28 13:08:51Z pjd $ |
32 */ 33 34#include <sys/param.h> /* MAXHOSTNAMELEN */ 35#include <sys/queue.h> 36#include <sys/socket.h> 37#include <sys/sysctl.h> 38 39#include <arpa/inet.h> 40 41#include <err.h> 42#include <errno.h> 43#include <stdio.h> 44#include <string.h> 45#include <sysexits.h> 46#include <unistd.h> 47 48#include <pjdlog.h> 49 50#include "hast.h" 51 52extern int depth; 53extern int lineno; 54 55extern FILE *yyin; 56extern char *yytext; 57 58static struct hastd_config *lconfig; 59static struct hast_resource *curres; 60static bool mynode, hadmynode; 61 62static char depth0_control[HAST_ADDRSIZE]; 63static char depth0_listen_tcp4[HAST_ADDRSIZE]; 64static char depth0_listen_tcp6[HAST_ADDRSIZE]; 65static TAILQ_HEAD(, hastd_listen) depth0_listen; 66static int depth0_replication; 67static int depth0_checksum; 68static int depth0_compression; 69static int depth0_timeout; 70static char depth0_exec[PATH_MAX];
|
71static int depth0_metaflush; |
72 73static char depth1_provname[PATH_MAX]; 74static char depth1_localpath[PATH_MAX];
|
75static int depth1_metaflush; |
76 77extern void yyrestart(FILE *); 78 79static int 80isitme(const char *name) 81{ 82 char buf[MAXHOSTNAMELEN]; 83 char *pos; 84 size_t bufsize; 85 86 /* 87 * First check if the give name matches our full hostname. 88 */ 89 if (gethostname(buf, sizeof(buf)) < 0) { 90 pjdlog_errno(LOG_ERR, "gethostname() failed"); 91 return (-1); 92 } 93 if (strcmp(buf, name) == 0) 94 return (1); 95 96 /* 97 * Now check if it matches first part of the host name. 98 */ 99 pos = strchr(buf, '.'); 100 if (pos != NULL && (size_t)(pos - buf) == strlen(name) && 101 strncmp(buf, name, pos - buf) == 0) { 102 return (1); 103 } 104 105 /* 106 * At the end check if name is equal to our host's UUID. 107 */ 108 bufsize = sizeof(buf); 109 if (sysctlbyname("kern.hostuuid", buf, &bufsize, NULL, 0) < 0) { 110 pjdlog_errno(LOG_ERR, "sysctlbyname(kern.hostuuid) failed"); 111 return (-1); 112 } 113 if (strcasecmp(buf, name) == 0) 114 return (1); 115 116 /* 117 * Looks like this isn't about us. 118 */ 119 return (0); 120} 121 122static bool 123family_supported(int family) 124{ 125 int sock; 126 127 sock = socket(family, SOCK_STREAM, 0); 128 if (sock == -1 && errno == EPROTONOSUPPORT) 129 return (false); 130 if (sock >= 0) 131 (void)close(sock); 132 return (true); 133} 134 135static int 136node_names(char **namesp) 137{ 138 static char names[MAXHOSTNAMELEN * 3]; 139 char buf[MAXHOSTNAMELEN]; 140 char *pos; 141 size_t bufsize; 142 143 if (gethostname(buf, sizeof(buf)) < 0) { 144 pjdlog_errno(LOG_ERR, "gethostname() failed"); 145 return (-1); 146 } 147 148 /* First component of the host name. */ 149 pos = strchr(buf, '.'); 150 if (pos != NULL && pos != buf) { 151 (void)strlcpy(names, buf, MIN((size_t)(pos - buf + 1), 152 sizeof(names))); 153 (void)strlcat(names, ", ", sizeof(names)); 154 } 155 156 /* Full host name. */ 157 (void)strlcat(names, buf, sizeof(names)); 158 (void)strlcat(names, ", ", sizeof(names)); 159 160 /* Host UUID. */ 161 bufsize = sizeof(buf); 162 if (sysctlbyname("kern.hostuuid", buf, &bufsize, NULL, 0) < 0) { 163 pjdlog_errno(LOG_ERR, "sysctlbyname(kern.hostuuid) failed"); 164 return (-1); 165 } 166 (void)strlcat(names, buf, sizeof(names)); 167 168 *namesp = names; 169 170 return (0); 171} 172 173void 174yyerror(const char *str) 175{ 176 177 pjdlog_error("Unable to parse configuration file at line %d near '%s': %s", 178 lineno, yytext, str); 179} 180 181struct hastd_config * 182yy_config_parse(const char *config, bool exitonerror) 183{ 184 int ret; 185 186 curres = NULL; 187 mynode = false; 188 depth = 0; 189 lineno = 0; 190 191 depth0_timeout = HAST_TIMEOUT; 192 depth0_replication = HAST_REPLICATION_FULLSYNC; 193 depth0_checksum = HAST_CHECKSUM_NONE; 194 depth0_compression = HAST_COMPRESSION_HOLE; 195 strlcpy(depth0_control, HAST_CONTROL, sizeof(depth0_control)); 196 TAILQ_INIT(&depth0_listen); 197 strlcpy(depth0_listen_tcp4, HASTD_LISTEN_TCP4, 198 sizeof(depth0_listen_tcp4)); 199 strlcpy(depth0_listen_tcp6, HASTD_LISTEN_TCP6, 200 sizeof(depth0_listen_tcp6)); 201 depth0_exec[0] = '\0';
|
202 depth0_metaflush = 1; |
203 204 lconfig = calloc(1, sizeof(*lconfig)); 205 if (lconfig == NULL) { 206 pjdlog_error("Unable to allocate memory for configuration."); 207 if (exitonerror) 208 exit(EX_TEMPFAIL); 209 return (NULL); 210 } 211 212 TAILQ_INIT(&lconfig->hc_listen); 213 TAILQ_INIT(&lconfig->hc_resources); 214 215 yyin = fopen(config, "r"); 216 if (yyin == NULL) { 217 pjdlog_errno(LOG_ERR, "Unable to open configuration file %s", 218 config); 219 yy_config_free(lconfig); 220 if (exitonerror) 221 exit(EX_OSFILE); 222 return (NULL); 223 } 224 yyrestart(yyin); 225 ret = yyparse(); 226 fclose(yyin); 227 if (ret != 0) { 228 yy_config_free(lconfig); 229 if (exitonerror) 230 exit(EX_CONFIG); 231 return (NULL); 232 } 233 234 /* 235 * Let's see if everything is set up. 236 */ 237 if (lconfig->hc_controladdr[0] == '\0') { 238 strlcpy(lconfig->hc_controladdr, depth0_control, 239 sizeof(lconfig->hc_controladdr)); 240 } 241 if (!TAILQ_EMPTY(&depth0_listen)) 242 TAILQ_CONCAT(&lconfig->hc_listen, &depth0_listen, hl_next); 243 if (TAILQ_EMPTY(&lconfig->hc_listen)) { 244 struct hastd_listen *lst; 245 246 if (family_supported(AF_INET)) { 247 lst = calloc(1, sizeof(*lst)); 248 if (lst == NULL) { 249 pjdlog_error("Unable to allocate memory for listen address."); 250 yy_config_free(lconfig); 251 if (exitonerror) 252 exit(EX_TEMPFAIL); 253 return (NULL); 254 } 255 (void)strlcpy(lst->hl_addr, depth0_listen_tcp4, 256 sizeof(lst->hl_addr)); 257 TAILQ_INSERT_TAIL(&lconfig->hc_listen, lst, hl_next); 258 } else { 259 pjdlog_debug(1, 260 "No IPv4 support in the kernel, not listening on IPv4 address."); 261 } 262 if (family_supported(AF_INET6)) { 263 lst = calloc(1, sizeof(*lst)); 264 if (lst == NULL) { 265 pjdlog_error("Unable to allocate memory for listen address."); 266 yy_config_free(lconfig); 267 if (exitonerror) 268 exit(EX_TEMPFAIL); 269 return (NULL); 270 } 271 (void)strlcpy(lst->hl_addr, depth0_listen_tcp6, 272 sizeof(lst->hl_addr)); 273 TAILQ_INSERT_TAIL(&lconfig->hc_listen, lst, hl_next); 274 } else { 275 pjdlog_debug(1, 276 "No IPv6 support in the kernel, not listening on IPv6 address."); 277 } 278 if (TAILQ_EMPTY(&lconfig->hc_listen)) { 279 pjdlog_error("No address to listen on."); 280 yy_config_free(lconfig); 281 if (exitonerror) 282 exit(EX_TEMPFAIL); 283 return (NULL); 284 } 285 } 286 TAILQ_FOREACH(curres, &lconfig->hc_resources, hr_next) { 287 PJDLOG_ASSERT(curres->hr_provname[0] != '\0'); 288 PJDLOG_ASSERT(curres->hr_localpath[0] != '\0'); 289 PJDLOG_ASSERT(curres->hr_remoteaddr[0] != '\0'); 290 291 if (curres->hr_replication == -1) { 292 /* 293 * Replication is not set at resource-level. 294 * Use global or default setting. 295 */ 296 curres->hr_replication = depth0_replication; 297 } 298 if (curres->hr_replication == HAST_REPLICATION_MEMSYNC || 299 curres->hr_replication == HAST_REPLICATION_ASYNC) { 300 pjdlog_warning("Replication mode \"%s\" is not implemented, falling back to \"%s\".", 301 curres->hr_replication == HAST_REPLICATION_MEMSYNC ? 302 "memsync" : "async", "fullsync"); 303 curres->hr_replication = HAST_REPLICATION_FULLSYNC; 304 } 305 if (curres->hr_checksum == -1) { 306 /* 307 * Checksum is not set at resource-level. 308 * Use global or default setting. 309 */ 310 curres->hr_checksum = depth0_checksum; 311 } 312 if (curres->hr_compression == -1) { 313 /* 314 * Compression is not set at resource-level. 315 * Use global or default setting. 316 */ 317 curres->hr_compression = depth0_compression; 318 } 319 if (curres->hr_timeout == -1) { 320 /* 321 * Timeout is not set at resource-level. 322 * Use global or default setting. 323 */ 324 curres->hr_timeout = depth0_timeout; 325 } 326 if (curres->hr_exec[0] == '\0') { 327 /* 328 * Exec is not set at resource-level. 329 * Use global or default setting. 330 */ 331 strlcpy(curres->hr_exec, depth0_exec, 332 sizeof(curres->hr_exec)); 333 }
|
334 if (curres->hr_metaflush == -1) { 335 /* 336 * Metaflush is not set at resource-level. 337 * Use global or default setting. 338 */ 339 curres->hr_metaflush = depth0_metaflush; 340 } |
341 } 342 343 return (lconfig); 344} 345 346void 347yy_config_free(struct hastd_config *config) 348{ 349 struct hastd_listen *lst; 350 struct hast_resource *res; 351 352 while ((lst = TAILQ_FIRST(&depth0_listen)) != NULL) { 353 TAILQ_REMOVE(&depth0_listen, lst, hl_next); 354 free(lst); 355 } 356 while ((lst = TAILQ_FIRST(&config->hc_listen)) != NULL) { 357 TAILQ_REMOVE(&config->hc_listen, lst, hl_next); 358 free(lst); 359 } 360 while ((res = TAILQ_FIRST(&config->hc_resources)) != NULL) { 361 TAILQ_REMOVE(&config->hc_resources, res, hr_next); 362 free(res); 363 } 364 free(config); 365} 366%} 367
|
358%token CONTROL LISTEN PORT REPLICATION CHECKSUM COMPRESSION
359%token TIMEOUT EXEC EXTENTSIZE RESOURCE NAME LOCAL REMOTE SOURCE ON
|
368%token CONTROL LISTEN PORT REPLICATION CHECKSUM COMPRESSION METAFLUSH 369%token TIMEOUT EXEC EXTENTSIZE RESOURCE NAME LOCAL REMOTE SOURCE ON OFF |
370%token FULLSYNC MEMSYNC ASYNC NONE CRC32 SHA256 HOLE LZF 371%token NUM STR OB CB 372 373%type <str> remote_str 374%type <num> replication_type 375%type <num> checksum_type 376%type <num> compression_type
|
377%type <num> boolean |
378 379%union 380{ 381 int num; 382 char *str; 383} 384 385%token <num> NUM 386%token <str> STR 387 388%% 389 390statements: 391 | 392 statements statement 393 ; 394 395statement: 396 control_statement 397 | 398 listen_statement 399 | 400 replication_statement 401 | 402 checksum_statement 403 | 404 compression_statement 405 | 406 timeout_statement 407 | 408 exec_statement 409 |
|
410 metaflush_statement 411 | |
412 node_statement 413 | 414 resource_statement 415 ; 416 417control_statement: CONTROL STR 418 { 419 switch (depth) { 420 case 0: 421 if (strlcpy(depth0_control, $2, 422 sizeof(depth0_control)) >= 423 sizeof(depth0_control)) { 424 pjdlog_error("control argument is too long."); 425 free($2); 426 return (1); 427 } 428 break; 429 case 1: 430 if (!mynode) 431 break; 432 if (strlcpy(lconfig->hc_controladdr, $2, 433 sizeof(lconfig->hc_controladdr)) >= 434 sizeof(lconfig->hc_controladdr)) { 435 pjdlog_error("control argument is too long."); 436 free($2); 437 return (1); 438 } 439 break; 440 default: 441 PJDLOG_ABORT("control at wrong depth level"); 442 } 443 free($2); 444 } 445 ; 446 447listen_statement: LISTEN STR 448 { 449 struct hastd_listen *lst; 450 451 lst = calloc(1, sizeof(*lst)); 452 if (lst == NULL) { 453 pjdlog_error("Unable to allocate memory for listen address."); 454 free($2); 455 return (1); 456 } 457 if (strlcpy(lst->hl_addr, $2, sizeof(lst->hl_addr)) >= 458 sizeof(lst->hl_addr)) { 459 pjdlog_error("listen argument is too long."); 460 free($2); 461 free(lst); 462 return (1); 463 } 464 switch (depth) { 465 case 0: 466 TAILQ_INSERT_TAIL(&depth0_listen, lst, hl_next); 467 break; 468 case 1: 469 if (mynode) 470 TAILQ_INSERT_TAIL(&depth0_listen, lst, hl_next); 471 else 472 free(lst); 473 break; 474 default: 475 PJDLOG_ABORT("listen at wrong depth level"); 476 } 477 free($2); 478 } 479 ; 480 481replication_statement: REPLICATION replication_type 482 { 483 switch (depth) { 484 case 0: 485 depth0_replication = $2; 486 break; 487 case 1: 488 PJDLOG_ASSERT(curres != NULL); 489 curres->hr_replication = $2; 490 break; 491 default: 492 PJDLOG_ABORT("replication at wrong depth level"); 493 } 494 } 495 ; 496 497replication_type: 498 FULLSYNC { $$ = HAST_REPLICATION_FULLSYNC; } 499 | 500 MEMSYNC { $$ = HAST_REPLICATION_MEMSYNC; } 501 | 502 ASYNC { $$ = HAST_REPLICATION_ASYNC; } 503 ; 504 505checksum_statement: CHECKSUM checksum_type 506 { 507 switch (depth) { 508 case 0: 509 depth0_checksum = $2; 510 break; 511 case 1: 512 PJDLOG_ASSERT(curres != NULL); 513 curres->hr_checksum = $2; 514 break; 515 default: 516 PJDLOG_ABORT("checksum at wrong depth level"); 517 } 518 } 519 ; 520 521checksum_type: 522 NONE { $$ = HAST_CHECKSUM_NONE; } 523 | 524 CRC32 { $$ = HAST_CHECKSUM_CRC32; } 525 | 526 SHA256 { $$ = HAST_CHECKSUM_SHA256; } 527 ; 528 529compression_statement: COMPRESSION compression_type 530 { 531 switch (depth) { 532 case 0: 533 depth0_compression = $2; 534 break; 535 case 1: 536 PJDLOG_ASSERT(curres != NULL); 537 curres->hr_compression = $2; 538 break; 539 default: 540 PJDLOG_ABORT("compression at wrong depth level"); 541 } 542 } 543 ; 544 545compression_type: 546 NONE { $$ = HAST_COMPRESSION_NONE; } 547 | 548 HOLE { $$ = HAST_COMPRESSION_HOLE; } 549 | 550 LZF { $$ = HAST_COMPRESSION_LZF; } 551 ; 552 553timeout_statement: TIMEOUT NUM 554 { 555 if ($2 <= 0) { 556 pjdlog_error("Negative or zero timeout."); 557 return (1); 558 } 559 switch (depth) { 560 case 0: 561 depth0_timeout = $2; 562 break; 563 case 1: 564 PJDLOG_ASSERT(curres != NULL); 565 curres->hr_timeout = $2; 566 break; 567 default: 568 PJDLOG_ABORT("timeout at wrong depth level"); 569 } 570 } 571 ; 572 573exec_statement: EXEC STR 574 { 575 switch (depth) { 576 case 0: 577 if (strlcpy(depth0_exec, $2, sizeof(depth0_exec)) >= 578 sizeof(depth0_exec)) { 579 pjdlog_error("Exec path is too long."); 580 free($2); 581 return (1); 582 } 583 break; 584 case 1: 585 PJDLOG_ASSERT(curres != NULL); 586 if (strlcpy(curres->hr_exec, $2, 587 sizeof(curres->hr_exec)) >= 588 sizeof(curres->hr_exec)) { 589 pjdlog_error("Exec path is too long."); 590 free($2); 591 return (1); 592 } 593 break; 594 default: 595 PJDLOG_ABORT("exec at wrong depth level"); 596 } 597 free($2); 598 } 599 ; 600
|
601metaflush_statement: METAFLUSH boolean 602 { 603 switch (depth) { 604 case 0: 605 depth0_metaflush = $2; 606 break; 607 case 1: 608 PJDLOG_ASSERT(curres != NULL); 609 depth1_metaflush = $2; 610 break; 611 case 2: 612 if (!mynode) 613 break; 614 PJDLOG_ASSERT(curres != NULL); 615 curres->hr_metaflush = $2; 616 break; 617 default: 618 PJDLOG_ABORT("metaflush at wrong depth level"); 619 } 620 } 621 ; 622 623boolean: 624 ON { $$ = 1; } 625 | 626 OFF { $$ = 0; } 627 ; 628 |
629node_statement: ON node_start OB node_entries CB 630 { 631 mynode = false; 632 } 633 ; 634 635node_start: STR 636 { 637 switch (isitme($1)) { 638 case -1: 639 free($1); 640 return (1); 641 case 0: 642 break; 643 case 1: 644 mynode = true; 645 break; 646 default: 647 PJDLOG_ABORT("invalid isitme() return value"); 648 } 649 free($1); 650 } 651 ; 652 653node_entries: 654 | 655 node_entries node_entry 656 ; 657 658node_entry: 659 control_statement 660 | 661 listen_statement 662 ; 663 664resource_statement: RESOURCE resource_start OB resource_entries CB 665 { 666 if (curres != NULL) { 667 /* 668 * There must be section for this node, at least with 669 * remote address configuration. 670 */ 671 if (!hadmynode) { 672 char *names; 673 674 if (node_names(&names) != 0) 675 return (1); 676 pjdlog_error("No resource %s configuration for this node (acceptable node names: %s).", 677 curres->hr_name, names); 678 return (1); 679 } 680 681 /* 682 * Let's see if there are some resource-level settings 683 * that we can use for node-level settings. 684 */ 685 if (curres->hr_provname[0] == '\0' && 686 depth1_provname[0] != '\0') { 687 /* 688 * Provider name is not set at node-level, 689 * but is set at resource-level, use it. 690 */ 691 strlcpy(curres->hr_provname, depth1_provname, 692 sizeof(curres->hr_provname)); 693 } 694 if (curres->hr_localpath[0] == '\0' && 695 depth1_localpath[0] != '\0') { 696 /* 697 * Path to local provider is not set at 698 * node-level, but is set at resource-level, 699 * use it. 700 */ 701 strlcpy(curres->hr_localpath, depth1_localpath, 702 sizeof(curres->hr_localpath)); 703 }
|
704 if (curres->hr_metaflush == -1 && depth1_metaflush != -1) { 705 /* 706 * Metaflush is not set at node-level, 707 * but is set at resource-level, use it. 708 */ 709 curres->hr_metaflush = depth1_metaflush; 710 } |
711 712 /* 713 * If provider name is not given, use resource name 714 * as provider name. 715 */ 716 if (curres->hr_provname[0] == '\0') { 717 strlcpy(curres->hr_provname, curres->hr_name, 718 sizeof(curres->hr_provname)); 719 } 720 721 /* 722 * Remote address has to be configured at this point. 723 */ 724 if (curres->hr_remoteaddr[0] == '\0') { 725 pjdlog_error("Remote address not configured for resource %s.", 726 curres->hr_name); 727 return (1); 728 } 729 /* 730 * Path to local provider has to be configured at this 731 * point. 732 */ 733 if (curres->hr_localpath[0] == '\0') { 734 pjdlog_error("Path to local component not configured for resource %s.", 735 curres->hr_name); 736 return (1); 737 } 738 739 /* Put it onto resource list. */ 740 TAILQ_INSERT_TAIL(&lconfig->hc_resources, curres, hr_next); 741 curres = NULL; 742 } 743 } 744 ; 745 746resource_start: STR 747 { 748 /* Check if there is no duplicate entry. */ 749 TAILQ_FOREACH(curres, &lconfig->hc_resources, hr_next) { 750 if (strcmp(curres->hr_name, $1) == 0) { 751 pjdlog_error("Resource %s configured more than once.", 752 curres->hr_name); 753 free($1); 754 return (1); 755 } 756 } 757 758 /* 759 * Clear those, so we can tell if they were set at 760 * resource-level or not. 761 */ 762 depth1_provname[0] = '\0'; 763 depth1_localpath[0] = '\0';
|
764 depth1_metaflush = -1; |
765 hadmynode = false; 766 767 curres = calloc(1, sizeof(*curres)); 768 if (curres == NULL) { 769 pjdlog_error("Unable to allocate memory for resource."); 770 free($1); 771 return (1); 772 } 773 if (strlcpy(curres->hr_name, $1, 774 sizeof(curres->hr_name)) >= 775 sizeof(curres->hr_name)) { 776 pjdlog_error("Resource name is too long."); 777 free($1); 778 return (1); 779 } 780 free($1); 781 curres->hr_role = HAST_ROLE_INIT; 782 curres->hr_previous_role = HAST_ROLE_INIT; 783 curres->hr_replication = -1; 784 curres->hr_checksum = -1; 785 curres->hr_compression = -1; 786 curres->hr_timeout = -1; 787 curres->hr_exec[0] = '\0'; 788 curres->hr_provname[0] = '\0'; 789 curres->hr_localpath[0] = '\0'; 790 curres->hr_localfd = -1;
|
791 curres->hr_metaflush = -1; |
792 curres->hr_remoteaddr[0] = '\0'; 793 curres->hr_sourceaddr[0] = '\0'; 794 curres->hr_ggateunit = -1; 795 } 796 ; 797 798resource_entries: 799 | 800 resource_entries resource_entry 801 ; 802 803resource_entry: 804 replication_statement 805 | 806 checksum_statement 807 | 808 compression_statement 809 | 810 timeout_statement 811 | 812 exec_statement 813 |
|
814 metaflush_statement 815 | |
816 name_statement 817 | 818 local_statement 819 | 820 resource_node_statement 821 ; 822 823name_statement: NAME STR 824 { 825 switch (depth) { 826 case 1: 827 if (strlcpy(depth1_provname, $2, 828 sizeof(depth1_provname)) >= 829 sizeof(depth1_provname)) { 830 pjdlog_error("name argument is too long."); 831 free($2); 832 return (1); 833 } 834 break; 835 case 2: 836 if (!mynode) 837 break; 838 PJDLOG_ASSERT(curres != NULL); 839 if (strlcpy(curres->hr_provname, $2, 840 sizeof(curres->hr_provname)) >= 841 sizeof(curres->hr_provname)) { 842 pjdlog_error("name argument is too long."); 843 free($2); 844 return (1); 845 } 846 break; 847 default: 848 PJDLOG_ABORT("name at wrong depth level"); 849 } 850 free($2); 851 } 852 ; 853 854local_statement: LOCAL STR 855 { 856 switch (depth) { 857 case 1: 858 if (strlcpy(depth1_localpath, $2, 859 sizeof(depth1_localpath)) >= 860 sizeof(depth1_localpath)) { 861 pjdlog_error("local argument is too long."); 862 free($2); 863 return (1); 864 } 865 break; 866 case 2: 867 if (!mynode) 868 break; 869 PJDLOG_ASSERT(curres != NULL); 870 if (strlcpy(curres->hr_localpath, $2, 871 sizeof(curres->hr_localpath)) >= 872 sizeof(curres->hr_localpath)) { 873 pjdlog_error("local argument is too long."); 874 free($2); 875 return (1); 876 } 877 break; 878 default: 879 PJDLOG_ABORT("local at wrong depth level"); 880 } 881 free($2); 882 } 883 ; 884 885resource_node_statement:ON resource_node_start OB resource_node_entries CB 886 { 887 mynode = false; 888 } 889 ; 890 891resource_node_start: STR 892 { 893 if (curres != NULL) { 894 switch (isitme($1)) { 895 case -1: 896 free($1); 897 return (1); 898 case 0: 899 break; 900 case 1: 901 mynode = hadmynode = true; 902 break; 903 default: 904 PJDLOG_ABORT("invalid isitme() return value"); 905 } 906 } 907 free($1); 908 } 909 ; 910 911resource_node_entries: 912 | 913 resource_node_entries resource_node_entry 914 ; 915 916resource_node_entry: 917 name_statement 918 | 919 local_statement 920 | 921 remote_statement 922 | 923 source_statement
|
924 | 925 metaflush_statement |
926 ; 927 928remote_statement: REMOTE remote_str 929 { 930 PJDLOG_ASSERT(depth == 2); 931 if (mynode) { 932 PJDLOG_ASSERT(curres != NULL); 933 if (strlcpy(curres->hr_remoteaddr, $2, 934 sizeof(curres->hr_remoteaddr)) >= 935 sizeof(curres->hr_remoteaddr)) { 936 pjdlog_error("remote argument is too long."); 937 free($2); 938 return (1); 939 } 940 } 941 free($2); 942 } 943 ; 944 945remote_str: 946 NONE { $$ = strdup("none"); } 947 | 948 STR { } 949 ; 950 951source_statement: SOURCE STR 952 { 953 PJDLOG_ASSERT(depth == 2); 954 if (mynode) { 955 PJDLOG_ASSERT(curres != NULL); 956 if (strlcpy(curres->hr_sourceaddr, $2, 957 sizeof(curres->hr_sourceaddr)) >= 958 sizeof(curres->hr_sourceaddr)) { 959 pjdlog_error("source argument is too long."); 960 free($2); 961 return (1); 962 } 963 } 964 free($2); 965 } 966 ;
|