xref: /netbsd-src/usr.bin/rump_allserver/rump_allserver.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
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