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