1 /* $NetBSD: rump_allserver.c,v 1.37 2014/04/27 15:26:05 pooka Exp $ */ 2 3 /*- 4 * Copyright (c) 2010, 2011 Antti Kantee. All Rights Reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <rump/rumpuser_port.h> 29 30 #ifndef lint 31 __RCSID("$NetBSD: rump_allserver.c,v 1.37 2014/04/27 15:26:05 pooka Exp $"); 32 #endif /* !lint */ 33 34 #include <sys/types.h> 35 #include <sys/stat.h> 36 37 #include <dlfcn.h> 38 #include <errno.h> 39 #include <fcntl.h> 40 #include <semaphore.h> 41 #include <signal.h> 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <stdint.h> 45 #include <string.h> 46 #include <unistd.h> 47 48 #include <rump/rump.h> 49 #include <rump/rump_syscalls.h> 50 #include <rump/rumpdefs.h> 51 #include <rump/rumperr.h> 52 53 __dead static void 54 usage(void) 55 { 56 57 #ifndef PLATFORM_HAS_SETGETPROGNAME 58 #define getprogname() "rump_server" 59 #endif 60 fprintf(stderr, "usage: %s [-s] [-c ncpu] [-d drivespec] [-l libs] " 61 "[-m modules] bindurl\n", getprogname()); 62 exit(1); 63 } 64 65 __dead static void 66 diedie(int sflag, const char *reason, int error, const char *errstr) 67 { 68 69 if (reason != NULL) 70 fputs(reason, stderr); 71 if (errstr) { 72 fprintf(stderr, ": %s", errstr); 73 } 74 fputc('\n', stderr); 75 if (!sflag) 76 rump_daemonize_done(error); 77 exit(1); 78 } 79 80 __dead static void 81 die(int sflag, int error, const char *reason) 82 { 83 84 diedie(sflag, reason, error, error == 0 ? NULL : strerror(error)); 85 } 86 87 __dead static void 88 die_rumperr(int sflag, int error, const char *reason) 89 { 90 91 diedie(sflag, reason, error, error == 0 ? NULL : rump_strerror(error)); 92 } 93 94 static sem_t sigsem; 95 static void 96 sigreboot(int sig) 97 { 98 99 sem_post(&sigsem); 100 } 101 102 static const char *const disktokens[] = { 103 #define DKEY 0 104 "key", 105 #define DFILE 1 106 "hostpath", 107 #define DSIZE 2 108 #define DSIZE_E -1 109 "size", 110 #define DOFFSET 3 111 "offset", 112 #define DLABEL 4 113 "disklabel", 114 #define DTYPE 5 115 "type", 116 NULL 117 }; 118 119 struct etfsreg { 120 const char *key; 121 const char *hostpath; 122 off_t flen; 123 off_t foffset; 124 char partition; 125 enum rump_etfs_type type; 126 }; 127 128 struct etfstype { 129 const char *name; 130 enum rump_etfs_type type; 131 } etfstypes[] = { 132 { "blk", RUMP_ETFS_BLK }, 133 { "chr", RUMP_ETFS_CHR }, 134 { "reg", RUMP_ETFS_REG }, 135 }; 136 137 static void processlabel(int, int, int, off_t *, off_t *); 138 139 #define ALLOCCHUNK 32 140 141 int 142 main(int argc, char *argv[]) 143 { 144 const char *serverurl; 145 struct etfsreg *etfs = NULL; 146 unsigned netfs = 0, curetfs = 0; 147 int error; 148 int ch, sflag, onthepath; 149 unsigned i; 150 char **modarray = NULL, **libarray = NULL; 151 unsigned nmods = 0, curmod = 0, nlibs = 0, curlib = 0, libidx; 152 unsigned liblast = -1; /* XXXgcc */ 153 154 #ifdef PLATFORM_HAS_SETGETPROGNAME 155 setprogname(argv[0]); 156 #endif 157 158 sflag = 0; 159 while ((ch = getopt(argc, argv, "c:d:l:m:r:sv")) != -1) { 160 switch (ch) { 161 case 'c': 162 setenv("RUMP_NCPU", optarg, 1); 163 break; 164 case 'd': { 165 char *options, *value; 166 char *key, *hostpath; 167 long long flen, foffset; 168 char partition; 169 int ftype; 170 171 flen = foffset = 0; 172 partition = 0; 173 key = hostpath = NULL; 174 ftype = -1; 175 options = optarg; 176 while (*options) { 177 switch (getsubopt(&options, 178 __UNCONST(disktokens), &value)) { 179 case DKEY: 180 if (key != NULL) { 181 fprintf(stderr, 182 "key already given\n"); 183 usage(); 184 } 185 key = value; 186 break; 187 188 case DFILE: 189 if (hostpath != NULL) { 190 fprintf(stderr, 191 "hostpath already given\n"); 192 usage(); 193 } 194 hostpath = value; 195 break; 196 197 case DSIZE: 198 if (flen != 0) { 199 fprintf(stderr, 200 "size already given\n"); 201 usage(); 202 } 203 if (strcmp(value, "host") == 0) { 204 if (foffset != 0) { 205 fprintf(stderr, 206 "cannot specify " 207 "offset with " 208 "size=host\n"); 209 usage(); 210 } 211 flen = DSIZE_E; 212 } else { 213 #ifdef PLATFORM_HAS_STRSUFTOLL 214 /* XXX: off_t max? */ 215 flen = strsuftoll("-d size", 216 value, 0, LLONG_MAX); 217 #else 218 flen = strtoull(value, 219 NULL, 10); 220 #endif 221 } 222 break; 223 case DOFFSET: 224 if (foffset != 0) { 225 fprintf(stderr, 226 "offset already given\n"); 227 usage(); 228 } 229 if (flen == DSIZE_E) { 230 fprintf(stderr, "cannot " 231 "specify offset with " 232 "size=host\n"); 233 usage(); 234 } 235 #ifdef PLATFORM_HAS_STRSUFTOLL 236 /* XXX: off_t max? */ 237 foffset = strsuftoll("-d offset", value, 238 0, LLONG_MAX); 239 #else 240 foffset = strtoull(value, NULL, 10); 241 #endif 242 break; 243 244 case DLABEL: 245 if (foffset != 0 || flen != 0) { 246 fprintf(stderr, 247 "disklabel needs to be " 248 "used alone\n"); 249 usage(); 250 } 251 if (strlen(value) != 1 || 252 *value < 'a' || *value > 'z') { 253 fprintf(stderr, 254 "invalid label part\n"); 255 usage(); 256 } 257 partition = *value; 258 break; 259 260 case DTYPE: 261 if (ftype != -1) { 262 fprintf(stderr, 263 "type already specified\n"); 264 usage(); 265 } 266 267 for (i = 0; 268 i < __arraycount(etfstypes); 269 i++) { 270 if (strcmp(etfstypes[i].name, 271 value) == 0) 272 break; 273 } 274 if (i == __arraycount(etfstypes)) { 275 fprintf(stderr, 276 "invalid type %s\n", value); 277 usage(); 278 } 279 ftype = etfstypes[i].type; 280 break; 281 282 default: 283 fprintf(stderr, "invalid dtoken\n"); 284 usage(); 285 break; 286 } 287 } 288 289 if (key == NULL || hostpath == NULL || 290 (flen == 0 && partition == 0)) { 291 fprintf(stderr, "incomplete drivespec\n"); 292 usage(); 293 } 294 if (ftype == -1) 295 ftype = RUMP_ETFS_BLK; 296 297 if (netfs - curetfs == 0) { 298 etfs = realloc(etfs, 299 (netfs+ALLOCCHUNK)*sizeof(*etfs)); 300 if (etfs == NULL) 301 die(1, errno, "realloc etfs"); 302 netfs += ALLOCCHUNK; 303 } 304 305 etfs[curetfs].key = key; 306 etfs[curetfs].hostpath = hostpath; 307 etfs[curetfs].flen = flen; 308 etfs[curetfs].foffset = foffset; 309 etfs[curetfs].partition = partition; 310 etfs[curetfs].type = ftype; 311 curetfs++; 312 313 break; 314 } 315 case 'l': 316 if (nlibs - curlib == 0) { 317 libarray = realloc(libarray, 318 (nlibs+ALLOCCHUNK) * sizeof(char *)); 319 if (libarray == NULL) 320 die(1, errno, "realloc"); 321 nlibs += ALLOCCHUNK; 322 } 323 libarray[curlib++] = optarg; 324 break; 325 case 'm': 326 if (nmods - curmod == 0) { 327 modarray = realloc(modarray, 328 (nmods+ALLOCCHUNK) * sizeof(char *)); 329 if (modarray == NULL) 330 die(1, errno, "realloc"); 331 nmods += ALLOCCHUNK; 332 } 333 modarray[curmod++] = optarg; 334 break; 335 case 'r': 336 setenv("RUMP_MEMLIMIT", optarg, 1); 337 break; 338 case 's': 339 sflag = 1; 340 break; 341 case 'v': 342 setenv("RUMP_VERBOSE", "1", 1); 343 break; 344 default: 345 usage(); 346 /*NOTREACHED*/ 347 } 348 } 349 350 argc -= optind; 351 argv += optind; 352 353 if (argc != 1) 354 usage(); 355 356 /* 357 * Automatically "resolve" component dependencies, i.e. 358 * try to load libs in a loop until all are loaded or a 359 * full loop completes with no loads (latter case is an error). 360 */ 361 for (onthepath = 1, nlibs = curlib; onthepath && nlibs > 0;) { 362 onthepath = 0; 363 for (libidx = 0; libidx < curlib; libidx++) { 364 /* loaded already? */ 365 if (libarray[libidx] == NULL) 366 continue; 367 368 /* try to load */ 369 liblast = libidx; 370 if (dlopen(libarray[libidx], 371 RTLD_LAZY|RTLD_GLOBAL) == NULL) { 372 char pb[MAXPATHLEN]; 373 /* try to mimic linker -l syntax */ 374 snprintf(pb, sizeof(pb), 375 "lib%s.so", libarray[libidx]); 376 if (dlopen(pb, RTLD_LAZY|RTLD_GLOBAL) == NULL) 377 continue; 378 } 379 380 /* managed to load that one */ 381 libarray[libidx] = NULL; 382 nlibs--; 383 onthepath = 1; 384 } 385 } 386 if (nlibs > 0) { 387 fprintf(stderr, 388 "failed to load -libraries, last error from \"%s\":\n", 389 libarray[liblast]); 390 fprintf(stderr, " %s", dlerror()); 391 die(1, 0, NULL); 392 } 393 free(libarray); 394 395 serverurl = argv[0]; 396 397 if (!sflag) { 398 error = rump_daemonize_begin(); 399 if (error) 400 die_rumperr(1, error, "rump daemonize"); 401 } 402 403 error = rump_init(); 404 if (error) 405 die_rumperr(sflag, error, "rump init failed"); 406 407 /* load modules */ 408 for (i = 0; i < curmod; i++) { 409 struct rump_modctl_load ml; 410 411 #define ETFSKEY "/module.mod" 412 if ((error = rump_pub_etfs_register(ETFSKEY, 413 modarray[0], RUMP_ETFS_REG)) != 0) 414 die_rumperr(sflag, 415 error, "module etfs register failed"); 416 memset(&ml, 0, sizeof(ml)); 417 ml.ml_filename = ETFSKEY; 418 /* 419 * XXX: since this is a syscall, error namespace depends 420 * on loaded emulations. revisit and fix. 421 */ 422 if (rump_sys_modctl(RUMP_MODCTL_LOAD, &ml) == -1) 423 die(sflag, errno, "module load failed"); 424 rump_pub_etfs_remove(ETFSKEY); 425 #undef ETFSKEY 426 } 427 free(modarray); 428 429 /* register host drives */ 430 for (i = 0; i < curetfs; i++) { 431 struct stat sb; 432 off_t foffset, flen, fendoff; 433 int fd, oflags; 434 435 oflags = etfs[i].flen == DSIZE_E ? 0 : O_CREAT; 436 fd = open(etfs[i].hostpath, O_RDWR | oflags, 0644); 437 if (fd == -1) 438 die(sflag, errno, "etfs hostpath open"); 439 440 if (etfs[i].partition) { 441 processlabel(sflag, fd, etfs[i].partition - 'a', 442 &foffset, &flen); 443 } else { 444 foffset = etfs[i].foffset; 445 flen = etfs[i].flen; 446 } 447 448 if (fstat(fd, &sb) == -1) 449 die(sflag, errno, "fstat etfs hostpath"); 450 if (flen == DSIZE_E) { 451 if (sb.st_size == 0) 452 die(sflag, EINVAL, "size=host, but cannot " 453 "query non-zero size"); 454 flen = sb.st_size; 455 } 456 fendoff = foffset + flen; 457 if (S_ISREG(sb.st_mode) && sb.st_size < fendoff) { 458 if (ftruncate(fd, fendoff) == -1) 459 die(sflag, errno, "truncate"); 460 } 461 close(fd); 462 463 if ((error = rump_pub_etfs_register_withsize(etfs[i].key, 464 etfs[i].hostpath, etfs[i].type, foffset, flen)) != 0) 465 die_rumperr(sflag, error, "etfs register"); 466 } 467 468 error = rump_init_server(serverurl); 469 if (error) 470 die_rumperr(sflag, error, "rump server init failed"); 471 472 if (!sflag) 473 rump_daemonize_done(RUMP_DAEMONIZE_SUCCESS); 474 475 sem_init(&sigsem, 0, 0); 476 signal(SIGTERM, sigreboot); 477 signal(SIGINT, sigreboot); 478 sem_wait(&sigsem); 479 480 rump_sys_reboot(0, NULL); 481 /*NOTREACHED*/ 482 483 return 0; 484 } 485 486 /* 487 * Copyright (c) 1987, 1988, 1993 488 * The Regents of the University of California. All rights reserved. 489 * 490 * Redistribution and use in source and binary forms, with or without 491 * modification, are permitted provided that the following conditions 492 * are met: 493 * 1. Redistributions of source code must retain the above copyright 494 * notice, this list of conditions and the following disclaimer. 495 * 2. Redistributions in binary form must reproduce the above copyright 496 * notice, this list of conditions and the following disclaimer in the 497 * documentation and/or other materials provided with the distribution. 498 * 3. Neither the name of the University nor the names of its contributors 499 * may be used to endorse or promote products derived from this software 500 * without specific prior written permission. 501 * 502 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 503 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 504 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 505 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 506 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 507 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 508 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 509 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 510 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 511 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 512 * SUCH DAMAGE. 513 * 514 * @(#)disklabel.h 8.2 (Berkeley) 7/10/94 515 */ 516 517 #define RUMPSERVER_MAXPARTITIONS 22 518 #define RUMPSERVER_DISKMAGIC ((uint32_t)0x82564557) /* magic */ 519 #define RUMPSERVER_DEVSHIFT 9 520 521 struct rumpserver_disklabel { 522 uint32_t d_magic; /* the magic number */ 523 uint16_t d_type; /* drive type */ 524 uint16_t d_subtype; /* controller/d_type specific */ 525 char d_typename[16]; /* type name, e.g. "eagle" */ 526 527 /* 528 * d_packname contains the pack identifier and is returned when 529 * the disklabel is read off the disk or in-core copy. 530 * d_boot0 and d_boot1 are the (optional) names of the 531 * primary (block 0) and secondary (block 1-15) bootstraps 532 * as found in /usr/mdec. These are returned when using 533 * getdiskbyname(3) to retrieve the values from /etc/disktab. 534 */ 535 union { 536 char un_d_packname[16]; /* pack identifier */ 537 struct { 538 char *un_d_boot0; /* primary bootstrap name */ 539 char *un_d_boot1; /* secondary bootstrap name */ 540 } un_b; 541 } d_un; 542 #define d_packname d_un.un_d_packname 543 #define d_boot0 d_un.un_b.un_d_boot0 544 #define d_boot1 d_un.un_b.un_d_boot1 545 546 /* disk geometry: */ 547 uint32_t d_secsize; /* # of bytes per sector */ 548 uint32_t d_nsectors; /* # of data sectors per track */ 549 uint32_t d_ntracks; /* # of tracks per cylinder */ 550 uint32_t d_ncylinders; /* # of data cylinders per unit */ 551 uint32_t d_secpercyl; /* # of data sectors per cylinder */ 552 uint32_t d_secperunit; /* # of data sectors per unit */ 553 554 /* 555 * Spares (bad sector replacements) below are not counted in 556 * d_nsectors or d_secpercyl. Spare sectors are assumed to 557 * be physical sectors which occupy space at the end of each 558 * track and/or cylinder. 559 */ 560 uint16_t d_sparespertrack; /* # of spare sectors per track */ 561 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */ 562 /* 563 * Alternative cylinders include maintenance, replacement, 564 * configuration description areas, etc. 565 */ 566 uint32_t d_acylinders; /* # of alt. cylinders per unit */ 567 568 /* hardware characteristics: */ 569 /* 570 * d_interleave, d_trackskew and d_cylskew describe perturbations 571 * in the media format used to compensate for a slow controller. 572 * Interleave is physical sector interleave, set up by the 573 * formatter or controller when formatting. When interleaving is 574 * in use, logically adjacent sectors are not physically 575 * contiguous, but instead are separated by some number of 576 * sectors. It is specified as the ratio of physical sectors 577 * traversed per logical sector. Thus an interleave of 1:1 578 * implies contiguous layout, while 2:1 implies that logical 579 * sector 0 is separated by one sector from logical sector 1. 580 * d_trackskew is the offset of sector 0 on track N relative to 581 * sector 0 on track N-1 on the same cylinder. Finally, d_cylskew 582 * is the offset of sector 0 on cylinder N relative to sector 0 583 * on cylinder N-1. 584 */ 585 uint16_t d_rpm; /* rotational speed */ 586 uint16_t d_interleave; /* hardware sector interleave */ 587 uint16_t d_trackskew; /* sector 0 skew, per track */ 588 uint16_t d_cylskew; /* sector 0 skew, per cylinder */ 589 uint32_t d_headswitch; /* head switch time, usec */ 590 uint32_t d_trkseek; /* track-to-track seek, usec */ 591 uint32_t d_flags; /* generic flags */ 592 #define NDDATA 5 593 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */ 594 #define NSPARE 5 595 uint32_t d_spare[NSPARE]; /* reserved for future use */ 596 uint32_t d_magic2; /* the magic number (again) */ 597 uint16_t d_checksum; /* xor of data incl. partitions */ 598 599 /* filesystem and partition information: */ 600 uint16_t d_npartitions; /* number of partitions in following */ 601 uint32_t d_bbsize; /* size of boot area at sn0, bytes */ 602 uint32_t d_sbsize; /* max size of fs superblock, bytes */ 603 struct rumpserver_partition { /* the partition table */ 604 uint32_t p_size; /* number of sectors in partition */ 605 uint32_t p_offset; /* starting sector */ 606 union { 607 uint32_t fsize; /* FFS, ADOS: 608 filesystem basic fragment size */ 609 uint32_t cdsession; /* ISO9660: session offset */ 610 } __partition_u2; 611 #define p_fsize __partition_u2.fsize 612 #define p_cdsession __partition_u2.cdsession 613 uint8_t p_fstype; /* filesystem type, see below */ 614 uint8_t p_frag; /* filesystem fragments per block */ 615 union { 616 uint16_t cpg; /* UFS: FS cylinders per group */ 617 uint16_t sgs; /* LFS: FS segment shift */ 618 } __partition_u1; 619 #define p_cpg __partition_u1.cpg 620 #define p_sgs __partition_u1.sgs 621 } d_partitions[RUMPSERVER_MAXPARTITIONS]; /* actually may be more */ 622 }; 623 624 625 /* for swapping disklabel, so don't care about perf, just portability */ 626 #define bs32(x) \ 627 ((((x) & 0xff000000) >> 24)| \ 628 (((x) & 0x00ff0000) >> 8) | \ 629 (((x) & 0x0000ff00) << 8) | \ 630 (((x) & 0x000000ff) << 24)) 631 #define bs16(x) ((((x) & 0xff00) >> 8) | (((x) & 0x00ff) << 8)) 632 633 /* 634 * From: 635 * $NetBSD: disklabel_dkcksum.c,v 1.4 2005/05/15 21:01:34 thorpej Exp 636 */ 637 638 /*- 639 * Copyright (c) 1991, 1993 640 * The Regents of the University of California. All rights reserved. 641 * 642 * Redistribution and use in source and binary forms, with or without 643 * modification, are permitted provided that the following conditions 644 * are met: 645 * 1. Redistributions of source code must retain the above copyright 646 * notice, this list of conditions and the following disclaimer. 647 * 2. Redistributions in binary form must reproduce the above copyright 648 * notice, this list of conditions and the following disclaimer in the 649 * documentation and/or other materials provided with the distribution. 650 * 3. Neither the name of the University nor the names of its contributors 651 * may be used to endorse or promote products derived from this software 652 * without specific prior written permission. 653 * 654 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 655 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 656 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 657 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 658 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 659 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 660 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 661 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 662 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 663 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 664 * SUCH DAMAGE. 665 */ 666 667 static uint16_t 668 rs_dl_dkcksum(struct rumpserver_disklabel *lp, int imswapped) 669 { 670 uint16_t *start, *end; 671 uint16_t sum; 672 uint16_t npart; 673 674 if (imswapped) 675 npart = bs16(lp->d_npartitions); 676 else 677 npart = lp->d_npartitions; 678 679 sum = 0; 680 start = (uint16_t *)(void *)lp; 681 end = (uint16_t *)(void *)&lp->d_partitions[npart]; 682 while (start < end) { 683 if (imswapped) 684 sum ^= bs16(*start); 685 else 686 sum ^= *start; 687 start++; 688 } 689 return (sum); 690 } 691 692 /* 693 * From: 694 * NetBSD: disklabel_scan.c,v 1.3 2009/01/18 12:13:03 lukem Exp 695 */ 696 697 /*- 698 * Copyright (c) 2002 The NetBSD Foundation, Inc. 699 * All rights reserved. 700 * 701 * This code is derived from software contributed to The NetBSD Foundation 702 * by Roland C. Dowdeswell. 703 * 704 * Redistribution and use in source and binary forms, with or without 705 * modification, are permitted provided that the following conditions 706 * are met: 707 * 1. Redistributions of source code must retain the above copyright 708 * notice, this list of conditions and the following disclaimer. 709 * 2. Redistributions in binary form must reproduce the above copyright 710 * notice, this list of conditions and the following disclaimer in the 711 * documentation and/or other materials provided with the distribution. 712 * 713 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 714 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 715 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 716 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 717 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 718 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 719 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 720 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 721 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 722 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 723 * POSSIBILITY OF SUCH DAMAGE. 724 */ 725 726 static int 727 rs_dl_scan(struct rumpserver_disklabel *lp, int *isswapped, 728 char *buf, size_t buflen) 729 { 730 size_t i; 731 int imswapped; 732 uint16_t npart; 733 734 /* scan for the correct magic numbers. */ 735 736 for (i=0; i <= buflen - sizeof(*lp); i += 4) { 737 memcpy(lp, buf + i, sizeof(*lp)); 738 if (lp->d_magic == RUMPSERVER_DISKMAGIC && 739 lp->d_magic2 == RUMPSERVER_DISKMAGIC) { 740 imswapped = 0; 741 goto sanity; 742 } 743 if (lp->d_magic == bs32(RUMPSERVER_DISKMAGIC) && 744 lp->d_magic2 == bs32(RUMPSERVER_DISKMAGIC)) { 745 imswapped = 1; 746 goto sanity; 747 } 748 } 749 750 return 1; 751 752 sanity: 753 if (imswapped) 754 npart = bs16(lp->d_npartitions); 755 else 756 npart = lp->d_npartitions; 757 /* we've found something, let's sanity check it */ 758 if (npart > RUMPSERVER_MAXPARTITIONS 759 || rs_dl_dkcksum(lp, imswapped)) 760 return 1; 761 762 *isswapped = imswapped; 763 return 0; 764 } 765 766 static void 767 processlabel(int sflag, int fd, int partition, off_t *foffp, off_t *flenp) 768 { 769 struct rumpserver_disklabel dl; 770 char buf[1<<16]; 771 uint32_t foffset, flen; 772 int imswapped; 773 774 if (pread(fd, buf, sizeof(buf), 0) == -1) 775 die(sflag, errno, "could not read disk device"); 776 if (rs_dl_scan(&dl, &imswapped, buf, sizeof(buf))) 777 die(sflag, ENOENT, "disklabel not found"); 778 779 if (partition >= dl.d_npartitions) 780 die(sflag, ENOENT, "partition not available"); 781 782 foffset = dl.d_partitions[partition].p_offset << RUMPSERVER_DEVSHIFT; 783 flen = dl.d_partitions[partition].p_size << RUMPSERVER_DEVSHIFT; 784 if (imswapped) { 785 foffset = bs32(foffset); 786 flen = bs32(flen); 787 } 788 789 *foffp = (off_t)foffset; 790 *flenp = (off_t)flen; 791 } 792