1 /* $NetBSD: rump_allserver.c,v 1.32 2013/12/18 20:56:32 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.32 2013/12/18 20:56:32 pooka Exp $"); 32 #endif /* !lint */ 33 34 #include <sys/types.h> 35 #include <sys/signal.h> 36 #include <sys/stat.h> 37 38 #include <dlfcn.h> 39 #include <errno.h> 40 #include <fcntl.h> 41 #include <semaphore.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 int 140 main(int argc, char *argv[]) 141 { 142 const char *serverurl; 143 struct etfsreg *etfs = NULL; 144 unsigned netfs = 0, curetfs = 0; 145 int error; 146 int ch, sflag; 147 unsigned i; 148 char **modarray = NULL; 149 unsigned nmods = 0, curmod = 0; 150 151 #ifdef PLATFORM_HAS_SETGETPROGNAME 152 setprogname(argv[0]); 153 #endif 154 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 PLATFORM_HAS_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 PLATFORM_HAS_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 && partition == 0)) { 288 fprintf(stderr, "incomplete drivespec\n"); 289 usage(); 290 } 291 if (ftype == -1) 292 ftype = RUMP_ETFS_BLK; 293 294 if (netfs - curetfs == 0) { 295 etfs = realloc(etfs, (netfs+16)*sizeof(*etfs)); 296 if (etfs == NULL) 297 die(1, errno, "realloc etfs"); 298 netfs += 16; 299 } 300 301 etfs[curetfs].key = key; 302 etfs[curetfs].hostpath = hostpath; 303 etfs[curetfs].flen = flen; 304 etfs[curetfs].foffset = foffset; 305 etfs[curetfs].partition = partition; 306 etfs[curetfs].type = ftype; 307 curetfs++; 308 309 break; 310 } 311 case 'l': 312 if (dlopen(optarg, RTLD_LAZY|RTLD_GLOBAL) == NULL) { 313 char pb[MAXPATHLEN]; 314 /* try to mimic linker -l syntax */ 315 316 snprintf(pb, sizeof(pb), "lib%s.so", optarg); 317 if (dlopen(pb, RTLD_LAZY|RTLD_GLOBAL) == NULL) { 318 fprintf(stderr, "dlopen: %s", dlerror()); 319 die(1, 0, NULL); 320 } 321 } 322 break; 323 case 'm': { 324 325 if (nmods - curmod == 0) { 326 modarray = realloc(modarray, 327 (nmods+16) * sizeof(char *)); 328 if (modarray == NULL) 329 die(1, errno, "realloc"); 330 nmods += 16; 331 } 332 modarray[curmod++] = optarg; 333 break; } 334 case 'r': 335 setenv("RUMP_MEMLIMIT", optarg, 1); 336 break; 337 case 's': 338 sflag = 1; 339 break; 340 case 'v': 341 setenv("RUMP_VERBOSE", "1", 1); 342 break; 343 default: 344 usage(); 345 /*NOTREACHED*/ 346 } 347 } 348 349 argc -= optind; 350 argv += optind; 351 352 if (argc != 1) 353 usage(); 354 355 serverurl = argv[0]; 356 357 if (!sflag) { 358 error = rump_daemonize_begin(); 359 if (error) 360 die_rumperr(1, error, "rump daemonize"); 361 } 362 363 error = rump_init(); 364 if (error) 365 die_rumperr(sflag, error, "rump init failed"); 366 367 /* load modules */ 368 for (i = 0; i < curmod; i++) { 369 struct rump_modctl_load ml; 370 371 #define ETFSKEY "/module.mod" 372 if ((error = rump_pub_etfs_register(ETFSKEY, 373 modarray[0], RUMP_ETFS_REG)) != 0) 374 die_rumperr(sflag, 375 error, "module etfs register failed"); 376 memset(&ml, 0, sizeof(ml)); 377 ml.ml_filename = ETFSKEY; 378 /* 379 * XXX: since this is a syscall, error namespace depends 380 * on loaded emulations. revisit and fix. 381 */ 382 if (rump_sys_modctl(RUMP_MODCTL_LOAD, &ml) == -1) 383 die(sflag, errno, "module load failed"); 384 rump_pub_etfs_remove(ETFSKEY); 385 #undef ETFSKEY 386 } 387 388 /* register host drives */ 389 for (i = 0; i < curetfs; i++) { 390 struct stat sb; 391 off_t foffset, flen, fendoff; 392 int fd, oflags; 393 394 oflags = etfs[i].flen == DSIZE_E ? 0 : O_CREAT; 395 fd = open(etfs[i].hostpath, O_RDWR | oflags, 0644); 396 if (fd == -1) 397 die(sflag, errno, "etfs hostpath open"); 398 399 if (etfs[i].partition) { 400 processlabel(sflag, fd, etfs[i].partition - 'a', 401 &foffset, &flen); 402 } else { 403 foffset = etfs[i].foffset; 404 flen = etfs[i].flen; 405 } 406 407 if (fstat(fd, &sb) == -1) 408 die(sflag, errno, "fstat etfs hostpath"); 409 if (flen == DSIZE_E) { 410 if (sb.st_size == 0) 411 die(sflag, EINVAL, "size=host, but cannot " 412 "query non-zero size"); 413 flen = sb.st_size; 414 } 415 fendoff = foffset + flen; 416 if (S_ISREG(sb.st_mode) && sb.st_size < fendoff) { 417 if (ftruncate(fd, fendoff) == -1) 418 die(sflag, errno, "truncate"); 419 } 420 close(fd); 421 422 if ((error = rump_pub_etfs_register_withsize(etfs[i].key, 423 etfs[i].hostpath, etfs[i].type, foffset, flen)) != 0) 424 die_rumperr(sflag, error, "etfs register"); 425 } 426 427 error = rump_init_server(serverurl); 428 if (error) 429 die_rumperr(sflag, error, "rump server init failed"); 430 431 if (!sflag) 432 rump_daemonize_done(RUMP_DAEMONIZE_SUCCESS); 433 434 sem_init(&sigsem, 0, 0); 435 signal(SIGTERM, sigreboot); 436 signal(SIGINT, sigreboot); 437 sem_wait(&sigsem); 438 439 rump_sys_reboot(0, NULL); 440 /*NOTREACHED*/ 441 442 return 0; 443 } 444 445 /* 446 * Copyright (c) 1987, 1988, 1993 447 * The Regents of the University of California. All rights reserved. 448 * 449 * Redistribution and use in source and binary forms, with or without 450 * modification, are permitted provided that the following conditions 451 * are met: 452 * 1. Redistributions of source code must retain the above copyright 453 * notice, this list of conditions and the following disclaimer. 454 * 2. Redistributions in binary form must reproduce the above copyright 455 * notice, this list of conditions and the following disclaimer in the 456 * documentation and/or other materials provided with the distribution. 457 * 3. Neither the name of the University nor the names of its contributors 458 * may be used to endorse or promote products derived from this software 459 * without specific prior written permission. 460 * 461 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 462 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 463 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 464 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 465 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 466 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 467 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 468 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 469 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 470 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 471 * SUCH DAMAGE. 472 * 473 * @(#)disklabel.h 8.2 (Berkeley) 7/10/94 474 */ 475 476 #define RUMPSERVER_MAXPARTITIONS 22 477 #define RUMPSERVER_DISKMAGIC ((uint32_t)0x82564557) /* magic */ 478 #define RUMPSERVER_DEVSHIFT 9 479 480 struct rumpserver_disklabel { 481 uint32_t d_magic; /* the magic number */ 482 uint16_t d_type; /* drive type */ 483 uint16_t d_subtype; /* controller/d_type specific */ 484 char d_typename[16]; /* type name, e.g. "eagle" */ 485 486 /* 487 * d_packname contains the pack identifier and is returned when 488 * the disklabel is read off the disk or in-core copy. 489 * d_boot0 and d_boot1 are the (optional) names of the 490 * primary (block 0) and secondary (block 1-15) bootstraps 491 * as found in /usr/mdec. These are returned when using 492 * getdiskbyname(3) to retrieve the values from /etc/disktab. 493 */ 494 union { 495 char un_d_packname[16]; /* pack identifier */ 496 struct { 497 char *un_d_boot0; /* primary bootstrap name */ 498 char *un_d_boot1; /* secondary bootstrap name */ 499 } un_b; 500 } d_un; 501 #define d_packname d_un.un_d_packname 502 #define d_boot0 d_un.un_b.un_d_boot0 503 #define d_boot1 d_un.un_b.un_d_boot1 504 505 /* disk geometry: */ 506 uint32_t d_secsize; /* # of bytes per sector */ 507 uint32_t d_nsectors; /* # of data sectors per track */ 508 uint32_t d_ntracks; /* # of tracks per cylinder */ 509 uint32_t d_ncylinders; /* # of data cylinders per unit */ 510 uint32_t d_secpercyl; /* # of data sectors per cylinder */ 511 uint32_t d_secperunit; /* # of data sectors per unit */ 512 513 /* 514 * Spares (bad sector replacements) below are not counted in 515 * d_nsectors or d_secpercyl. Spare sectors are assumed to 516 * be physical sectors which occupy space at the end of each 517 * track and/or cylinder. 518 */ 519 uint16_t d_sparespertrack; /* # of spare sectors per track */ 520 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */ 521 /* 522 * Alternative cylinders include maintenance, replacement, 523 * configuration description areas, etc. 524 */ 525 uint32_t d_acylinders; /* # of alt. cylinders per unit */ 526 527 /* hardware characteristics: */ 528 /* 529 * d_interleave, d_trackskew and d_cylskew describe perturbations 530 * in the media format used to compensate for a slow controller. 531 * Interleave is physical sector interleave, set up by the 532 * formatter or controller when formatting. When interleaving is 533 * in use, logically adjacent sectors are not physically 534 * contiguous, but instead are separated by some number of 535 * sectors. It is specified as the ratio of physical sectors 536 * traversed per logical sector. Thus an interleave of 1:1 537 * implies contiguous layout, while 2:1 implies that logical 538 * sector 0 is separated by one sector from logical sector 1. 539 * d_trackskew is the offset of sector 0 on track N relative to 540 * sector 0 on track N-1 on the same cylinder. Finally, d_cylskew 541 * is the offset of sector 0 on cylinder N relative to sector 0 542 * on cylinder N-1. 543 */ 544 uint16_t d_rpm; /* rotational speed */ 545 uint16_t d_interleave; /* hardware sector interleave */ 546 uint16_t d_trackskew; /* sector 0 skew, per track */ 547 uint16_t d_cylskew; /* sector 0 skew, per cylinder */ 548 uint32_t d_headswitch; /* head switch time, usec */ 549 uint32_t d_trkseek; /* track-to-track seek, usec */ 550 uint32_t d_flags; /* generic flags */ 551 #define NDDATA 5 552 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */ 553 #define NSPARE 5 554 uint32_t d_spare[NSPARE]; /* reserved for future use */ 555 uint32_t d_magic2; /* the magic number (again) */ 556 uint16_t d_checksum; /* xor of data incl. partitions */ 557 558 /* filesystem and partition information: */ 559 uint16_t d_npartitions; /* number of partitions in following */ 560 uint32_t d_bbsize; /* size of boot area at sn0, bytes */ 561 uint32_t d_sbsize; /* max size of fs superblock, bytes */ 562 struct rumpserver_partition { /* the partition table */ 563 uint32_t p_size; /* number of sectors in partition */ 564 uint32_t p_offset; /* starting sector */ 565 union { 566 uint32_t fsize; /* FFS, ADOS: 567 filesystem basic fragment size */ 568 uint32_t cdsession; /* ISO9660: session offset */ 569 } __partition_u2; 570 #define p_fsize __partition_u2.fsize 571 #define p_cdsession __partition_u2.cdsession 572 uint8_t p_fstype; /* filesystem type, see below */ 573 uint8_t p_frag; /* filesystem fragments per block */ 574 union { 575 uint16_t cpg; /* UFS: FS cylinders per group */ 576 uint16_t sgs; /* LFS: FS segment shift */ 577 } __partition_u1; 578 #define p_cpg __partition_u1.cpg 579 #define p_sgs __partition_u1.sgs 580 } d_partitions[RUMPSERVER_MAXPARTITIONS]; /* actually may be more */ 581 }; 582 583 584 /* for swapping disklabel, so don't care about perf, just portability */ 585 #define bs32(x) \ 586 ((((x) & 0xff000000) >> 24)| \ 587 (((x) & 0x00ff0000) >> 8) | \ 588 (((x) & 0x0000ff00) << 8) | \ 589 (((x) & 0x000000ff) << 24)) 590 #define bs16(x) ((((x) & 0xff00) >> 8) | (((x) & 0x00ff) << 8)) 591 592 /* 593 * From: 594 * $NetBSD: disklabel_dkcksum.c,v 1.4 2005/05/15 21:01:34 thorpej Exp 595 */ 596 597 /*- 598 * Copyright (c) 1991, 1993 599 * The Regents of the University of California. All rights reserved. 600 * 601 * Redistribution and use in source and binary forms, with or without 602 * modification, are permitted provided that the following conditions 603 * are met: 604 * 1. Redistributions of source code must retain the above copyright 605 * notice, this list of conditions and the following disclaimer. 606 * 2. Redistributions in binary form must reproduce the above copyright 607 * notice, this list of conditions and the following disclaimer in the 608 * documentation and/or other materials provided with the distribution. 609 * 3. Neither the name of the University nor the names of its contributors 610 * may be used to endorse or promote products derived from this software 611 * without specific prior written permission. 612 * 613 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 614 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 615 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 616 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 617 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 618 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 619 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 620 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 621 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 622 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 623 * SUCH DAMAGE. 624 */ 625 626 static uint16_t 627 rs_dl_dkcksum(struct rumpserver_disklabel *lp, int imswapped) 628 { 629 uint16_t *start, *end; 630 uint16_t sum; 631 uint16_t npart; 632 633 if (imswapped) 634 npart = bs16(lp->d_npartitions); 635 else 636 npart = lp->d_npartitions; 637 638 sum = 0; 639 start = (uint16_t *)(void *)lp; 640 end = (uint16_t *)(void *)&lp->d_partitions[npart]; 641 while (start < end) { 642 if (imswapped) 643 sum ^= bs16(*start); 644 else 645 sum ^= *start; 646 start++; 647 } 648 return (sum); 649 } 650 651 /* 652 * From: 653 * NetBSD: disklabel_scan.c,v 1.3 2009/01/18 12:13:03 lukem Exp 654 */ 655 656 /*- 657 * Copyright (c) 2002 The NetBSD Foundation, Inc. 658 * All rights reserved. 659 * 660 * This code is derived from software contributed to The NetBSD Foundation 661 * by Roland C. Dowdeswell. 662 * 663 * Redistribution and use in source and binary forms, with or without 664 * modification, are permitted provided that the following conditions 665 * are met: 666 * 1. Redistributions of source code must retain the above copyright 667 * notice, this list of conditions and the following disclaimer. 668 * 2. Redistributions in binary form must reproduce the above copyright 669 * notice, this list of conditions and the following disclaimer in the 670 * documentation and/or other materials provided with the distribution. 671 * 672 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 673 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 674 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 675 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 676 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 677 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 678 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 679 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 680 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 681 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 682 * POSSIBILITY OF SUCH DAMAGE. 683 */ 684 685 static int 686 rs_dl_scan(struct rumpserver_disklabel *lp, int *isswapped, 687 char *buf, size_t buflen) 688 { 689 size_t i; 690 int imswapped; 691 uint16_t npart; 692 693 /* scan for the correct magic numbers. */ 694 695 for (i=0; i <= buflen - sizeof(*lp); i += 4) { 696 memcpy(lp, buf + i, sizeof(*lp)); 697 if (lp->d_magic == RUMPSERVER_DISKMAGIC && 698 lp->d_magic2 == RUMPSERVER_DISKMAGIC) { 699 imswapped = 0; 700 goto sanity; 701 } 702 if (lp->d_magic == bs32(RUMPSERVER_DISKMAGIC) && 703 lp->d_magic2 == bs32(RUMPSERVER_DISKMAGIC)) { 704 imswapped = 1; 705 goto sanity; 706 } 707 } 708 709 return 1; 710 711 sanity: 712 if (imswapped) 713 npart = bs16(lp->d_npartitions); 714 else 715 npart = lp->d_npartitions; 716 /* we've found something, let's sanity check it */ 717 if (npart > RUMPSERVER_MAXPARTITIONS 718 || rs_dl_dkcksum(lp, imswapped)) 719 return 1; 720 721 *isswapped = imswapped; 722 return 0; 723 } 724 725 static void 726 processlabel(int sflag, int fd, int partition, off_t *foffp, off_t *flenp) 727 { 728 struct rumpserver_disklabel dl; 729 char buf[1<<16]; 730 uint32_t foffset, flen; 731 int imswapped; 732 733 if (pread(fd, buf, sizeof(buf), 0) == -1) 734 die(sflag, errno, "could not read disk device"); 735 if (rs_dl_scan(&dl, &imswapped, buf, sizeof(buf))) 736 die(sflag, ENOENT, "disklabel not found"); 737 738 if (partition >= dl.d_npartitions) 739 die(sflag, ENOENT, "partition not available"); 740 741 foffset = dl.d_partitions[partition].p_offset << RUMPSERVER_DEVSHIFT; 742 flen = dl.d_partitions[partition].p_size << RUMPSERVER_DEVSHIFT; 743 if (imswapped) { 744 foffset = bs32(foffset); 745 flen = bs32(flen); 746 } 747 748 *foffp = (off_t)foffset; 749 *flenp = (off_t)flen; 750 } 751