1/* $NetBSD: sdread.c,v 1.5 2010/03/22 20:37:26 pooka Exp $ */ 2 3/* 4 * Copyright (c) 2009 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 <sys/types.h> 29#include <sys/dirent.h> 30#include <sys/mount.h> 31#include <sys/dkio.h> 32 33#include <ufs/ufs/ufsmount.h> 34#include <msdosfs/msdosfsmount.h> 35#include <isofs/cd9660/cd9660_mount.h> 36 37#include <rump/rump.h> 38#include <rump/rump_syscalls.h> 39 40#include <err.h> 41#include <errno.h> 42#include <fcntl.h> 43#include <stdio.h> 44#include <stdlib.h> 45#include <string.h> 46#include <unistd.h> 47 48/* 49 * Proof-of-concept program: 50 * 51 * Mount rump file system from device driver stack included in the 52 * rump kernel. Optionally copy a file out of the mounted file system. 53 */ 54 55/* recent -current, appease 5.0 etc. userland */ 56#ifndef DIOCTUR 57#define DIOCTUR _IOR('d', 128, int) 58#endif 59 60static void 61waitcd(void) 62{ 63 int fd, val = 0, rounds = 0; 64 65 fd = rump_sys_open("/dev/rcd0d", O_RDWR); 66 if (fd == -1) 67 return; 68 69 do { 70 if (rounds > 0) { 71 if (rounds == 1) { 72 printf("Waiting for CD device to settle "); 73 } else { 74 printf("."); 75 } 76 fflush(stdout); 77 sleep(1); 78 } 79 if (rump_sys_ioctl(fd, DIOCTUR, &val) == -1) 80 err(1, "DIOCTUR"); 81 rounds++; 82 } while (val == 0 || rounds >= 30); 83 84 if (!val) 85 printf(" giving up\n"); 86 else 87 printf(" done!\n"); 88 89 rump_sys_close(fd); 90} 91 92int 93main(int argc, char *argv[]) 94{ 95 char buf[2048]; 96 struct msdosfs_args args; 97 struct ufs_args uargs; 98 struct iso_args iargs; 99 struct dirent *dp; 100 const char *msg = NULL; 101 int fd, n, fd_h, sverrno; 102 int probeonly = 0; 103 104 if (argc > 1) { 105 if (argc == 2 && strcmp(argv[1], "probe") == 0) { 106 probeonly = 1; 107 } else if (argc != 3) { 108 fprintf(stderr, "usage: a.out [src hostdest]\n"); 109 exit(1); 110 } 111 } 112 113 memset(&args, 0, sizeof(args)); 114 args.fspec = strdup("/dev/sd0e"); 115 args.version = MSDOSFSMNT_VERSION; 116 117 memset(&uargs, 0, sizeof(uargs)); 118 uargs.fspec = strdup("/dev/sd0e"); 119 120 memset(&iargs, 0, sizeof(iargs)); 121 iargs.fspec = strdup("/dev/cd0a"); 122 123 if (probeonly) 124 rump_boot_sethowto(RUMP_AB_VERBOSE); 125 rump_init(); 126 if (probeonly) { 127 pause(); 128 exit(0); 129 } 130 131 if (rump_sys_mkdir("/mp", 0777) == -1) 132 err(1, "mkdir"); 133 if (rump_sys_mount(MOUNT_MSDOS, "/mp", MNT_RDONLY, 134 &args, sizeof(args)) == -1) { 135 if (rump_sys_mount(MOUNT_FFS, "/mp", MNT_RDONLY, 136 &uargs, sizeof(uargs)) == -1) { 137 /* 138 * Wait for CD media to settle. In the end, 139 * just try to do it anyway and see if we fail. 140 */ 141 waitcd(); 142 if (rump_sys_mount(MOUNT_CD9660, "/mp", MNT_RDONLY, 143 &iargs, sizeof(iargs)) == -1) { 144 err(1, "mount"); 145 } 146 } 147 } 148 149 fd = rump_sys_open("/mp", O_RDONLY, 0); 150 if (fd == -1) { 151 msg = "open dir"; 152 goto out; 153 } 154 155 while ((n = rump_sys_getdents(fd, buf, sizeof(buf))) > 0) { 156 for (dp = (struct dirent *)buf; 157 (char *)dp - buf < n; 158 dp = _DIRENT_NEXT(dp)) { 159 printf("%" PRIu64 ": %s\n", dp->d_fileno, dp->d_name); 160 } 161 } 162 rump_sys_close(fd); 163 if (argc == 1) 164 goto out; 165 166 rump_sys_chdir("/mp"); 167 fd = rump_sys_open(argv[1], O_RDONLY, 0); 168 if (fd == -1) { 169 msg = "open fs file"; 170 goto out; 171 } 172 173 fd_h = open(argv[2], O_RDWR | O_CREAT, 0777); 174 if (fd_h == -1) { 175 msg = "open host file"; 176 goto out; 177 } 178 179 while ((n = rump_sys_read(fd, buf, sizeof(buf))) == sizeof(buf)) { 180 if (write(fd_h, buf, sizeof(buf)) != sizeof(buf)) { 181 msg = "write host file"; 182 goto out; 183 } 184 } 185 if (n == -1) { 186 msg = "read fs file"; 187 goto out; 188 } 189 190 if (n > 0) { 191 if (write(fd_h, buf, n) == -1) 192 msg = "write tail"; 193 } 194 195 out: 196 sverrno = errno; 197 rump_sys_chdir("/"); 198 rump_sys_close(fd); 199 close(fd_h); 200 if (rump_sys_unmount("/mp", 0) == -1) 201 err(1, "unmount"); 202 203 if (msg) { 204 errno = sverrno; 205 err(1, "%s", msg); 206 } 207 208 return 0; 209} 210