├── .gitignore ├── AUTHORS ├── COPYING ├── ChangeLog ├── INSTALL ├── Makefile.am ├── NEWS ├── README ├── TODO ├── autogen.sh ├── configure.ac ├── fetch_vbox_headers.sh ├── old ├── Makefile_old ├── macbuild.sh ├── vdautomount.py ├── vdbuild.sh └── vdbuild_new └── src └── vdfuse.c /.gitignore: -------------------------------------------------------------------------------- 1 | .svn 2 | Makefile.in 3 | /autom4te.cache 4 | /aclocal.m4 5 | /compile 6 | /configure 7 | /depcomp 8 | /install-sh 9 | /missing 10 | *.o 11 | .deps/ 12 | Makefile 13 | config.log 14 | src/config.h 15 | src/stamp-h1 16 | vdfuse -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | 2 | Copyright 2009-2011 3 | - Original author: h2o on forums.virtualbox.org: http://forums.virtualbox.org/viewtopic.php?p=59275 4 | - Reworked with Terry Ellison 5 | - Reworked by Gordon Miller 6 | 7 | Copyright 2011 8 | - Jonathan Xavier 9 | 10 | Copyright 2013 11 | - Chris Benninger -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 2 | 3 | v01 - 14 Feb 09 4 | * Initial release 5 | 6 | v02 - 15 Feb 09 7 | * Use the stat on the container file as the basis for any getattr on the partiton pseudo-files 8 | 9 | v03 - 16 Feb 09 10 | * Bug corrections from Gavin, plus EntireDisc/Partition interlock 11 | 12 | v04 - 23 Mar 09 13 | * Another Bug correction from Gavin, plus addition of printPartition. 14 | 15 | v05 - 09 May 09 16 | * Change sizes from size_t to uint64_t (size_t is 32-bit on 32-bit systems) 17 | * Fix _FILE_OFFSET_BITS 18 | * Option for older VBox 19 | 20 | v07 - 22 Feb 10 21 | * VBOX_SUCCESS macro was removed, replace with RT_SUCCESS 22 | 23 | v08 - 27 Jun 10 24 | * Support for snapshots through frontend (-s option) 25 | 26 | v09 - 29 May 13 27 | * Re-enable hidden -s option 28 | * Added autotools build scripts for Linux and OSX 29 | * Added script to pull down newer VBox Headers 30 | * Fixed minor compilation errors/warning associated with newer VBox API 31 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Installation Instructions 2 | ************************* 3 | 4 | Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation, 5 | Inc. 6 | 7 | Copying and distribution of this file, with or without modification, 8 | are permitted in any medium without royalty provided the copyright 9 | notice and this notice are preserved. This file is offered as-is, 10 | without warranty of any kind. 11 | 12 | Basic Installation 13 | ================== 14 | 15 | Briefly, the shell commands `./autogen.sh; ./configure; make; make install' should 16 | configure, build, and install this package. The following 17 | more-detailed instructions are generic; see the `README' file for 18 | instructions specific to this package. Some packages provide this 19 | `INSTALL' file but do not implement all of the features documented 20 | below. The lack of an optional feature in a given package is not 21 | necessarily a bug. More recommendations for GNU packages can be found 22 | in *note Makefile Conventions: (standards)Makefile Conventions. 23 | 24 | The `configure' shell script attempts to guess correct values for 25 | various system-dependent variables used during compilation. It uses 26 | those values to create a `Makefile' in each directory of the package. 27 | It may also create one or more `.h' files containing system-dependent 28 | definitions. Finally, it creates a shell script `config.status' that 29 | you can run in the future to recreate the current configuration, and a 30 | file `config.log' containing compiler output (useful mainly for 31 | debugging `configure'). 32 | 33 | It can also use an optional file (typically called `config.cache' 34 | and enabled with `--cache-file=config.cache' or simply `-C') that saves 35 | the results of its tests to speed up reconfiguring. Caching is 36 | disabled by default to prevent problems with accidental use of stale 37 | cache files. 38 | 39 | If you need to do unusual things to compile the package, please try 40 | to figure out how `configure' could check whether to do them, and mail 41 | diffs or instructions to the address given in the `README' so they can 42 | be considered for the next release. If you are using the cache, and at 43 | some point `config.cache' contains results you don't want to keep, you 44 | may remove or edit it. 45 | 46 | The file `configure.ac' (or `configure.in') is used to create 47 | `configure' by a program called `autoconf'. You need `configure.ac' if 48 | you want to change it or regenerate `configure' using a newer version 49 | of `autoconf'. 50 | 51 | The simplest way to compile this package is: 52 | 53 | 1. `cd' to the directory containing the package's source code and type 54 | `./configure' to configure the package for your system. 55 | 56 | Running `configure' might take a while. While running, it prints 57 | some messages telling which features it is checking for. 58 | 59 | 2. Type `make' to compile the package. 60 | 61 | 3. Optionally, type `make check' to run any self-tests that come with 62 | the package, generally using the just-built uninstalled binaries. 63 | 64 | 4. Type `make install' to install the programs and any data files and 65 | documentation. When installing into a prefix owned by root, it is 66 | recommended that the package be configured and built as a regular 67 | user, and only the `make install' phase executed with root 68 | privileges. 69 | 70 | 5. Optionally, type `make installcheck' to repeat any self-tests, but 71 | this time using the binaries in their final installed location. 72 | This target does not install anything. Running this target as a 73 | regular user, particularly if the prior `make install' required 74 | root privileges, verifies that the installation completed 75 | correctly. 76 | 77 | 6. You can remove the program binaries and object files from the 78 | source code directory by typing `make clean'. To also remove the 79 | files that `configure' created (so you can compile the package for 80 | a different kind of computer), type `make distclean'. There is 81 | also a `make maintainer-clean' target, but that is intended mainly 82 | for the package's developers. If you use it, you may have to get 83 | all sorts of other programs in order to regenerate files that came 84 | with the distribution. 85 | 86 | 7. Often, you can also type `make uninstall' to remove the installed 87 | files again. In practice, not all packages have tested that 88 | uninstallation works correctly, even though it is required by the 89 | GNU Coding Standards. 90 | 91 | 8. Some packages, particularly those that use Automake, provide `make 92 | distcheck', which can by used by developers to test that all other 93 | targets like `make install' and `make uninstall' work correctly. 94 | This target is generally not run by end users. 95 | 96 | Compilers and Options 97 | ===================== 98 | 99 | Some systems require unusual options for compilation or linking that 100 | the `configure' script does not know about. Run `./configure --help' 101 | for details on some of the pertinent environment variables. 102 | 103 | You can give `configure' initial values for configuration parameters 104 | by setting variables in the command line or in the environment. Here 105 | is an example: 106 | 107 | ./configure CC=c99 CFLAGS=-g LIBS=-lposix 108 | 109 | *Note Defining Variables::, for more details. 110 | 111 | Compiling For Multiple Architectures 112 | ==================================== 113 | 114 | You can compile the package for more than one kind of computer at the 115 | same time, by placing the object files for each architecture in their 116 | own directory. To do this, you can use GNU `make'. `cd' to the 117 | directory where you want the object files and executables to go and run 118 | the `configure' script. `configure' automatically checks for the 119 | source code in the directory that `configure' is in and in `..'. This 120 | is known as a "VPATH" build. 121 | 122 | With a non-GNU `make', it is safer to compile the package for one 123 | architecture at a time in the source code directory. After you have 124 | installed the package for one architecture, use `make distclean' before 125 | reconfiguring for another architecture. 126 | 127 | On MacOS X 10.5 and later systems, you can create libraries and 128 | executables that work on multiple system types--known as "fat" or 129 | "universal" binaries--by specifying multiple `-arch' options to the 130 | compiler but only a single `-arch' option to the preprocessor. Like 131 | this: 132 | 133 | ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ 134 | CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ 135 | CPP="gcc -E" CXXCPP="g++ -E" 136 | 137 | This is not guaranteed to produce working output in all cases, you 138 | may have to build one architecture at a time and combine the results 139 | using the `lipo' tool if you have problems. 140 | 141 | Installation Names 142 | ================== 143 | 144 | By default, `make install' installs the package's commands under 145 | `/usr/local/bin', include files under `/usr/local/include', etc. You 146 | can specify an installation prefix other than `/usr/local' by giving 147 | `configure' the option `--prefix=PREFIX', where PREFIX must be an 148 | absolute file name. 149 | 150 | You can specify separate installation prefixes for 151 | architecture-specific files and architecture-independent files. If you 152 | pass the option `--exec-prefix=PREFIX' to `configure', the package uses 153 | PREFIX as the prefix for installing programs and libraries. 154 | Documentation and other data files still use the regular prefix. 155 | 156 | In addition, if you use an unusual directory layout you can give 157 | options like `--bindir=DIR' to specify different values for particular 158 | kinds of files. Run `configure --help' for a list of the directories 159 | you can set and what kinds of files go in them. In general, the 160 | default for these options is expressed in terms of `${prefix}', so that 161 | specifying just `--prefix' will affect all of the other directory 162 | specifications that were not explicitly provided. 163 | 164 | The most portable way to affect installation locations is to pass the 165 | correct locations to `configure'; however, many packages provide one or 166 | both of the following shortcuts of passing variable assignments to the 167 | `make install' command line to change installation locations without 168 | having to reconfigure or recompile. 169 | 170 | The first method involves providing an override variable for each 171 | affected directory. For example, `make install 172 | prefix=/alternate/directory' will choose an alternate location for all 173 | directory configuration variables that were expressed in terms of 174 | `${prefix}'. Any directories that were specified during `configure', 175 | but not in terms of `${prefix}', must each be overridden at install 176 | time for the entire installation to be relocated. The approach of 177 | makefile variable overrides for each directory variable is required by 178 | the GNU Coding Standards, and ideally causes no recompilation. 179 | However, some platforms have known limitations with the semantics of 180 | shared libraries that end up requiring recompilation when using this 181 | method, particularly noticeable in packages that use GNU Libtool. 182 | 183 | The second method involves providing the `DESTDIR' variable. For 184 | example, `make install DESTDIR=/alternate/directory' will prepend 185 | `/alternate/directory' before all installation names. The approach of 186 | `DESTDIR' overrides is not required by the GNU Coding Standards, and 187 | does not work on platforms that have drive letters. On the other hand, 188 | it does better at avoiding recompilation issues, and works well even 189 | when some directory options were not specified in terms of `${prefix}' 190 | at `configure' time. 191 | 192 | Optional Features 193 | ================= 194 | 195 | If the package supports it, you can cause programs to be installed 196 | with an extra prefix or suffix on their names by giving `configure' the 197 | option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. 198 | 199 | Some packages pay attention to `--enable-FEATURE' options to 200 | `configure', where FEATURE indicates an optional part of the package. 201 | They may also pay attention to `--with-PACKAGE' options, where PACKAGE 202 | is something like `gnu-as' or `x' (for the X Window System). The 203 | `README' should mention any `--enable-' and `--with-' options that the 204 | package recognizes. 205 | 206 | For packages that use the X Window System, `configure' can usually 207 | find the X include and library files automatically, but if it doesn't, 208 | you can use the `configure' options `--x-includes=DIR' and 209 | `--x-libraries=DIR' to specify their locations. 210 | 211 | Some packages offer the ability to configure how verbose the 212 | execution of `make' will be. For these packages, running `./configure 213 | --enable-silent-rules' sets the default to minimal output, which can be 214 | overridden with `make V=1'; while running `./configure 215 | --disable-silent-rules' sets the default to verbose, which can be 216 | overridden with `make V=0'. 217 | 218 | Particular systems 219 | ================== 220 | 221 | On HP-UX, the default C compiler is not ANSI C compatible. If GNU 222 | CC is not installed, it is recommended to use the following options in 223 | order to use an ANSI C compiler: 224 | 225 | ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" 226 | 227 | and if that doesn't work, install pre-built binaries of GCC for HP-UX. 228 | 229 | HP-UX `make' updates targets which have the same time stamps as 230 | their prerequisites, which makes it generally unusable when shipped 231 | generated files such as `configure' are involved. Use GNU `make' 232 | instead. 233 | 234 | On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot 235 | parse its `' header file. The option `-nodtk' can be used as 236 | a workaround. If GNU CC is not installed, it is therefore recommended 237 | to try 238 | 239 | ./configure CC="cc" 240 | 241 | and if that doesn't work, try 242 | 243 | ./configure CC="cc -nodtk" 244 | 245 | On Solaris, don't put `/usr/ucb' early in your `PATH'. This 246 | directory contains several dysfunctional programs; working variants of 247 | these programs are available in `/usr/bin'. So, if you need `/usr/ucb' 248 | in your `PATH', put it _after_ `/usr/bin'. 249 | 250 | On Haiku, software installed for all users goes in `/boot/common', 251 | not `/usr/local'. It is recommended to use the following options: 252 | 253 | ./configure --prefix=/boot/common 254 | 255 | Specifying the System Type 256 | ========================== 257 | 258 | There may be some features `configure' cannot figure out 259 | automatically, but needs to determine by the type of machine the package 260 | will run on. Usually, assuming the package is built to be run on the 261 | _same_ architectures, `configure' can figure that out, but if it prints 262 | a message saying it cannot guess the machine type, give it the 263 | `--build=TYPE' option. TYPE can either be a short name for the system 264 | type, such as `sun4', or a canonical name which has the form: 265 | 266 | CPU-COMPANY-SYSTEM 267 | 268 | where SYSTEM can have one of these forms: 269 | 270 | OS 271 | KERNEL-OS 272 | 273 | See the file `config.sub' for the possible values of each field. If 274 | `config.sub' isn't included in this package, then this package doesn't 275 | need to know the machine type. 276 | 277 | If you are _building_ compiler tools for cross-compiling, you should 278 | use the option `--target=TYPE' to select the type of system they will 279 | produce code for. 280 | 281 | If you want to _use_ a cross compiler, that generates code for a 282 | platform different from the build platform, you should specify the 283 | "host" platform (i.e., that on which the generated programs will 284 | eventually be run) with `--host=TYPE'. 285 | 286 | Sharing Defaults 287 | ================ 288 | 289 | If you want to set default values for `configure' scripts to share, 290 | you can create a site shell script called `config.site' that gives 291 | default values for variables like `CC', `cache_file', and `prefix'. 292 | `configure' looks for `PREFIX/share/config.site' if it exists, then 293 | `PREFIX/etc/config.site' if it exists. Or, you can set the 294 | `CONFIG_SITE' environment variable to the location of the site script. 295 | A warning: not all `configure' scripts look for a site script. 296 | 297 | Defining Variables 298 | ================== 299 | 300 | Variables not defined in a site shell script can be set in the 301 | environment passed to `configure'. However, some packages may run 302 | configure again during the build, and the customized values of these 303 | variables may be lost. In order to avoid this problem, you should set 304 | them in the `configure' command line, using `VAR=value'. For example: 305 | 306 | ./configure CC=/usr/local2/bin/gcc 307 | 308 | causes the specified `gcc' to be used as the C compiler (unless it is 309 | overridden in the site shell script). 310 | 311 | Unfortunately, this technique does not work for `CONFIG_SHELL' due to 312 | an Autoconf bug. Until the bug is fixed you can use this workaround: 313 | 314 | CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash 315 | 316 | `configure' Invocation 317 | ====================== 318 | 319 | `configure' recognizes the following options to control how it 320 | operates. 321 | 322 | `--help' 323 | `-h' 324 | Print a summary of all of the options to `configure', and exit. 325 | 326 | `--help=short' 327 | `--help=recursive' 328 | Print a summary of the options unique to this package's 329 | `configure', and exit. The `short' variant lists options used 330 | only in the top level, while the `recursive' variant lists options 331 | also present in any nested packages. 332 | 333 | `--version' 334 | `-V' 335 | Print the version of Autoconf used to generate the `configure' 336 | script, and exit. 337 | 338 | `--cache-file=FILE' 339 | Enable the cache: use and save the results of the tests in FILE, 340 | traditionally `config.cache'. FILE defaults to `/dev/null' to 341 | disable caching. 342 | 343 | `--config-cache' 344 | `-C' 345 | Alias for `--cache-file=config.cache'. 346 | 347 | `--quiet' 348 | `--silent' 349 | `-q' 350 | Do not print messages saying which checks are being made. To 351 | suppress all normal output, redirect it to `/dev/null' (any error 352 | messages will still be shown). 353 | 354 | `--srcdir=DIR' 355 | Look for the package's source code in directory DIR. Usually 356 | `configure' can determine that directory automatically. 357 | 358 | `--prefix=DIR' 359 | Use DIR as the installation prefix. *note Installation Names:: 360 | for more details, including other options available for fine-tuning 361 | the installation locations. 362 | 363 | `--no-create' 364 | `-n' 365 | Run the configure checks, but stop before creating any output 366 | files. 367 | 368 | `configure' also accepts some other, not widely useful, options. Run 369 | `configure --help' for more details. 370 | 371 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | 3 | bin_PROGRAMS=vdfuse 4 | AM_CFLAGS = -Iinclude @FUSE_HEADERS@ 5 | vdfuse_SOURCES=src/vdfuse.c 6 | vdfuse_LDADD=$(addprefix @VBOX_INSTALL_DIR@/, @VBOX_BINS@) @FUSE_FLAG@ 7 | vdfuse_LDFLAGS=-Wl,-rpath,@VBOX_INSTALL_DIR@ 8 | 9 | EXTRA_DIST = autogen.sh 10 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SophosLabs-zz/vdfuse/6bfa95d66f2bda940492960cf697c9a6066d75e2/NEWS -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | ######################################################### 2 | This is a clone of https://github.com/jonathanxavier/vdfuse 3 | with a few minor updates to make it compile against the latest 4 | VirtualBox headers as well as a more portable build system 5 | 6 | This Fuse module uses the VBox access library to open a VBox supported VD image file and mount 7 | it as a Fuse file system. The mount point contains a flat directory with the following files 8 | * EntireDisk 9 | * PartitionN 10 | 11 | Note that each file should only be opened once and opening EntireDisk should locks out 12 | the other files. However, since file close isn't passed to the fuse utilities, I can only 13 | enforce this in a brute fashion: If you open EntireDisk then all further I/O to 14 | the PartitionN files will fail. If open any PartitionN file then all further I/O to EntireDisk 15 | will fail. Hence in practice you can only access on or the other within a single mount. 16 | 17 | ########################################################## 18 | ChangeLog: 19 | See ChangeLog 20 | 21 | ########################################################## 22 | Installation: 23 | See INSTALL 24 | 25 | ########################################################## 26 | Usage: (once installed) 27 | 28 | Linux: (TODO) 29 | 30 | 31 | OSX: 32 | > sudo ./vdfuse -tVHD -a -f /path/to/vdi /path/to/mount 33 | 34 | > hdiutil attach -imagekey diskimage-class=CRawDiskImage -nomount /path/to/mount/EntireDisk 35 | > /dev/diskX << Pay attention to disk ids assigned 36 | 37 | > mount -t YourFS /dev/diskXsY /path/to/partition/mount 38 | 39 | ########################################################## 40 | License: 41 | See COPYING 42 | 43 | ########################################################## 44 | Authors: 45 | See AUTHORS 46 | 47 | ########################################################## 48 | 49 | sources: 50 | http://serverfault.com/questions/174278/mount-an-vhd-on-mac-os-x 51 | http://forums.virtualbox.org/viewtopic.php?f=26&t=33355&start=0 52 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | 2 | 3 | - Support for GPT disk partition schemes 4 | - Auto detecting differencing file dependencies 5 | - Code overhaul 6 | - Improve documentation 7 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | autoreconf --install 3 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.67]) 5 | AC_INIT([vdfuse], [0.9], [chris.benninger@sophos.com]) 6 | AC_CONFIG_SRCDIR([src/vdfuse.c]) 7 | AC_CONFIG_HEADERS([src/config.h:config.in]) 8 | 9 | AM_INIT_AUTOMAKE 10 | #AM_INIT_AUTOMAKE(vdfuse, 0.9) 11 | 12 | # Checks for programs. 13 | AC_PROG_CC 14 | AC_PROG_INSTALL 15 | AC_LANG([C]) 16 | CFLAGS=" -D_FILE_OFFSET_BITS=64" 17 | # Checks for libraries. 18 | 19 | AC_CHECK_PROG(SVN,svn,[yes],[AC_MSG_ERROR(Could not find svn)]) 20 | 21 | AC_CANONICAL_HOST 22 | case "$host_os" in 23 | darwin* ) 24 | FUSE_FLAG="-losxfuse" 25 | ARCH=$(uname -p) 26 | CFLAGS+=" -D_DARWIN_USE_64_BIT_INODE -arch ${ARCH} ${FUSE_FLAG}" 27 | VBOX_INSTALL_DIR="/Applications/VirtualBox.app/Contents/MacOS" 28 | VBOX_BINS="VBoxDD.dylib VBoxDDU.dylib VBoxVMM.dylib VBoxRT.dylib VBoxDD2.dylib VBoxREM64.dylib" 29 | 30 | #fuse headers override 31 | AC_ARG_WITH([fuse-headers],[AS_HELP_STRING([--with-fuse-headers],[location of the fuse headers])], 32 | [FUSE_HEADERS_DIR="$withval"], 33 | [FUSE_HEADERS_DIR="/usr/local/include/osxfuse"], 34 | ) 35 | 36 | AC_CHECK_FILE(${FUSE_HEADERS_DIR}/fuse.h,,[AC_MSG_ERROR([Could not find fuse headers, Please install osxfuse development package])]) 37 | FUSE_HEADERS=-I${FUSE_HEADERS_DIR} 38 | AC_CHECK_LIB([osxfuse], [main],[break],[AC_MSG_ERROR(Could not find fuse)]) 39 | 40 | ;; 41 | linux-gnu*) 42 | FUSE_FLAG=$(pkg-config --libs fuse) 43 | VBOX_INSTALL_DIR="/usr/lib/virtualbox" 44 | VBOX_BINS="VBoxDDU.so" 45 | 46 | #fuse headers override 47 | AC_ARG_WITH([fuse-headers],[AS_HELP_STRING([--with-fuse-headers],[location of the fuse headers])], 48 | [ 49 | FUSE_HEADERS_DIR="$withval" 50 | AC_CHECK_FILE(${FUSE_HEADERS_DIR}/fuse.h,,[AC_MSG_ERROR([Could not find fuse headers])]) 51 | FUSE_HEADERS=-I${FUSE_HEADERS_DIR} 52 | ], 53 | [ 54 | FUSE_HEADERS=$(pkg-config --cflags-only-I fuse) 55 | AC_CHECK_HEADER(fuse.h,,[AC_MSG_ERROR([Could not find fuse headers])]) 56 | ] 57 | ) 58 | 59 | # Checks for Fuse header files. 60 | AC_CHECK_LIB([fuse], [main],[break],[AC_MSG_ERROR(Could not find fuse)]) 61 | ;; 62 | *) 63 | #Default Case 64 | AC_MSG_ERROR([Your platform is not currently supported]) 65 | ;; 66 | esac 67 | 68 | AC_SUBST(FUSE_HEADERS) 69 | AC_SUBST(FUSE_FLAG) 70 | 71 | # Checks for VBox header files. 72 | AC_CHECK_FILE([include/VBox/vd.h],,[AC_MSG_ERROR([Could not find vbox headers, please run 'fetch_vbox_headers.sh'])]) 73 | 74 | AC_SUBST(VBOX_INSTALL_DIR) 75 | AC_SUBST(VBOX_BINS) 76 | AC_SUBST(VBOX_BINS_FULL) 77 | 78 | #AC_PATH_X 79 | #AC_FUNC_ALLOCA 80 | 81 | # Checks for typedefs, structures, and compiler characteristics. 82 | #AC_CHECK_HEADER_STDBOOL 83 | #AC_TYPE_UID_T 84 | #AC_C_INLINE 85 | #AC_TYPE_INT16_T 86 | #AC_TYPE_INT32_T 87 | #AC_TYPE_INT64_T 88 | #AC_TYPE_INT8_T 89 | #AC_TYPE_MODE_T 90 | #AC_TYPE_OFF_T 91 | #AC_TYPE_SIZE_T 92 | #AC_TYPE_SSIZE_T 93 | #AC_STRUCT_ST_BLOCKS 94 | #AC_TYPE_UINT16_T 95 | #AC_TYPE_UINT32_T 96 | #AC_TYPE_UINT64_T 97 | #AC_TYPE_UINT8_T 98 | #AC_CHECK_TYPES([ptrdiff_t]) 99 | 100 | # Checks for library functions. 101 | #AC_FUNC_REALLOC 102 | #AC_CHECK_FUNCS([fesetround memchr memmove memset strpbrk]) 103 | 104 | AC_CONFIG_FILES([Makefile]) 105 | AC_OUTPUT 106 | -------------------------------------------------------------------------------- /fetch_vbox_headers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" 3 | svn co http://www.virtualbox.org/svn/vbox/trunk/include@42039 ${SCRIPT_DIR}/include/ 4 | -------------------------------------------------------------------------------- /old/Makefile_old: -------------------------------------------------------------------------------- 1 | 2 | 3 | ##General Variables 4 | CC=gcc 5 | SHELL=/bin/bash 6 | VBOX_HEADERS_DIR:=include/vbox 7 | CCFLAGS=-pipe -Wall 8 | SRC_FILES=src/vdfuse.c 9 | OUT_DIR=bin 10 | OUT_FILE=${OUT_DIR}/vdfuse 11 | 12 | ##OSX Variables 13 | VBOX_OSX_BINS:= VBoxDD.dylib VBoxDDU.dylib VBoxVMM.dylib VBoxRT.dylib VBoxDD2.dylib VBoxREM.dylib 14 | VBOX_OSX_INSTALL_DIR:=/Applications/VirtualBox.app/Contents/MacOS 15 | FUSE_OSX_HEADERS:=/usr/local/include/osxfuse 16 | 17 | ##Linux Variabled (debian) 18 | VBOX_LINUX_BINS:=VBoxDDU.so 19 | VBOX_LINUX_INSTALL_DIR:=/usr/lib/virtualbox 20 | FUSE_LINUX_HEADERS:=`pkg-config --cflags --libs fuse` 21 | 22 | #Decide which to use based on platform 23 | UNAME_S := $(shell uname -s) 24 | ifeq ($(UNAME_S),Linux) 25 | VBOX_BINS:=${VBOX_LINUX_BINS} 26 | VBOX_INSTALL_DIR:=${VBOX_LINUX_INSTALL_DIR} 27 | FUSE_HEADERS:=${FUSE_LINUX_HEADERS} 28 | endif 29 | ifeq ($(UNAME_S),Darwin) 30 | CCFLAGS += -arch i386 -lfuse_ino64 31 | VBOX_BINS:=${VBOX_OSX_BINS} 32 | VBOX_INSTALL_DIR:=${VBOX_OSX_INSTALL_DIR} 33 | FUSE_HEADERS:=${FUSE_OSX_HEADERS} 34 | endif 35 | 36 | VBOX_BINS:=$(addprefix $(VBOX_INSTALL_DIR)/, $(VBOX_BINS)) 37 | 38 | all: deps build 39 | 40 | build: 41 | mkdir -p ${OUT_DIR} 42 | ${CC} ${CCFLAGS} ${SRC_FILES} ${VBOX_BINS} -o ${OUT_FILE} -I${FUSE_HEADERS} -I${VBOX_HEADERS_DIR} -Wl,-rpath,${VBOX_INSTALL_DIR} 43 | 44 | deps: vbox-headers 45 | 46 | vbox-headers: 47 | if [ -d "./$(VBOX_HEADERS_DIR)" ]; then\ 48 | mkdir -p $(VBOX_HEADERS_DIR);\ 49 | cd $(VBOX_HEADERS_DIR);\ 50 | svn update;\ 51 | else\ 52 | svn co http://www.virtualbox.org/svn/vbox/trunk/include $(VBOX_HEADERS_DIR);\ 53 | fi; 54 | 55 | clean: 56 | rm -rf ${OUT_DIR} 57 | 58 | #libfuse-dev: 59 | # if [ `pkg-config --exists fuse` -ne 0]; then\ 60 | # echo "FUSE headers not found. Are they installed?"\ 61 | # echo "(Run 'apt-get install libfuse-dev' on Ubuntu / Debian)"\ 62 | # exit 1\ 63 | # fi; 64 | -------------------------------------------------------------------------------- /old/macbuild.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # http://serverfault.com/questions/174278/mount-an-vhd-on-mac-os-x 4 | # Authors: Chealion and janm 5 | 6 | 7 | infile=vdfuse.c 8 | outfile=vdfuse 9 | incdir="include/" 10 | INSTALL_DIR="/Applications/VirtualBox.app/Contents/MacOS" 11 | CFLAGS="-pipe" 12 | 13 | gcc -arch i386 "${infile}" \ 14 | "${INSTALL_DIR}"/VBoxDD.dylib \ 15 | "${INSTALL_DIR}"/VBoxDDU.dylib \ 16 | "${INSTALL_DIR}"/VBoxVMM.dylib \ 17 | "${INSTALL_DIR}"/VBoxRT.dylib \ 18 | "${INSTALL_DIR}"/VBoxDD2.dylib \ 19 | "${INSTALL_DIR}"/VBoxREM.dylib \ 20 | -o "${outfile}" \ 21 | -I"${incdir}" -I"/usr/local/include/fuse" \ 22 | -Wl,-rpath,"${INSTALL_DIR}" \ 23 | -lfuse_ino64 \ 24 | -Wall ${CFLAGS} -------------------------------------------------------------------------------- /old/vdautomount.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # vdautomount 0.1 4 | # easy-to-use wrapper for vdfuse 5 | # requires vdfuse >= v80 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program. If not, see . 19 | 20 | VERSION = "0.1" 21 | 22 | ### DEFAULT OPTIONS 23 | 24 | # if your vdfuse is not in your PATH change this to the path to your vdfuse 25 | # executable 26 | VDFUSE_COMMAND = "vdfuse" 27 | 28 | ### END OPTIONS 29 | 30 | import os, sys 31 | from optparse import OptionParser 32 | from vboxapi import VirtualBoxManager 33 | 34 | def main (args): 35 | parser = OptionParser (prog="vdautomount", 36 | usage="%prog [options] machine-name-or-uuid mountpoint", version="%prog " + globals()["VERSION"]) 37 | parser.add_option ("-p", help="path to vdfuse", 38 | type="string", default=globals()["VDFUSE_COMMAND"], metavar="vdfuse") 39 | parser.add_option ("-r", help="readonly", action="store_true") 40 | parser.add_option ("-g", help="run in foreground", action="store_true") 41 | parser.add_option ("-v", help="verbose", action="store_true") 42 | parser.add_option ("-d", help="debug", action="store_true") 43 | parser.add_option ("-a", help="allow all users to read disk", action="store_true") 44 | parser.add_option ("-w", help="allow all users to read and write to disk", action="store_true") 45 | parser.add_option ("-m", help="specify which disk to mount, required if machine has more than one disk", 46 | type="int", default=-1, metavar="NUMBER") 47 | 48 | options, args = parser.parse_args (args=args) 49 | 50 | if len (args) != 2: 51 | parser.error ("invalid machine specifier or mountpoint") 52 | 53 | spec = args[0] 54 | mountpoint = args[1] 55 | vbm = VirtualBoxManager (None, None) 56 | 57 | if not (os.access (mountpoint, os.R_OK | os.W_OK) and os.path.isdir (mountpoint)): 58 | parser.error ("mountpoint cannot be accessed or is not a directory") 59 | 60 | try: 61 | machine = vbm.vbox.getMachine (spec) 62 | except: 63 | try: 64 | machine = vbm.vbox.findMachine (spec) 65 | except: 66 | parser.error ("couldn't find machine \"%s\"" % spec) 67 | 68 | mediums = [x.medium for x in machine.getMediumAttachments () if x.type == 3] 69 | 70 | if len (mediums) == 1: 71 | medium = mediums[0] 72 | elif options.m != -1: 73 | medium = mediums[options.m - 1] 74 | else: 75 | ss = sys.stdout 76 | sys.stdout = sys.stderr 77 | print "Multiple disks on machine:" 78 | for index, medium in enumerate (mediums): 79 | print "%d:\tbase:\t%s" % (index + 1, medium.base.location) 80 | if medium.id != medium.base.id: 81 | print "\tsnap:\t%s" % medium.location 82 | sys.stdout = ss 83 | parser.exit (2, "%s: specify the disk number with the -m option\n" % parser.get_prog_name ()) 84 | 85 | paths = [] 86 | while True: 87 | paths.append (medium.location) 88 | if medium.parent: 89 | medium = medium.parent 90 | else: 91 | break 92 | 93 | paths.reverse () 94 | base = paths[0] 95 | diffs = paths[1:] 96 | 97 | if len (diffs) > 100: 98 | parser.error ("too many levels of snapshots") 99 | 100 | args = [options.p] 101 | for option, value in options.__dict__.iteritems (): 102 | if option in ("p", "m"): 103 | continue 104 | if value: 105 | args.append ("-" + option) 106 | 107 | args.append ("-f") 108 | args.append (base.encode ("UTF-8")) 109 | 110 | for x in diffs: 111 | args.append ("-s") 112 | args.append (x.encode ("UTF-8")) 113 | 114 | args.append (mountpoint) 115 | 116 | try: 117 | os.execvp (options.p, args) 118 | except OSError as e: 119 | parser.error ("error running vdfuse. wrong path (-p) ?") 120 | 121 | if __name__ == "__main__": 122 | main (sys.argv[1:]) 123 | -------------------------------------------------------------------------------- /old/vdbuild.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Environment variables (all optional) 4 | # CFLAGS - flags for gcc 5 | # NOSTRIP - don't strip output 6 | # INSTALL_DIR - vbox install directory 7 | 8 | if [ $# -ne 2 ]; then 9 | echo "Usage: $0 include-dir vdfuse.c" 10 | exit 255 11 | fi 12 | 13 | if [ -z "${CFLAGS}" ]; then 14 | CFLAGS="-pipe" 15 | fi 16 | 17 | incdir="$1" 18 | infile="$2" 19 | outfile="${infile%.c}" 20 | 21 | if ! [ -e "${infile}" ]; then 22 | echo "${infile} not found." 23 | exit 1 24 | fi 25 | 26 | if [ -z "${INSTALL_DIR}" ]; then 27 | if [ -e "/etc/vbox/vbox.cfg" ]; then 28 | . /etc/vbox/vbox.cfg 29 | elif [ -d "/usr/lib/virtualbox" ]; then 30 | INSTALL_DIR="/usr/lib/virtualbox" 31 | elif [ -z "${INSTALL_DIR}" ]; then 32 | echo "INSTALL_DIR not defined" 33 | exit 1 34 | fi 35 | fi 36 | 37 | pkg-config --exists fuse 38 | if [ $? -ne 0 ]; then 39 | echo "FUSE headers not found. Are they installed?" 40 | echo "(Run 'apt-get install libfuse-dev' on Ubuntu / Debian)" 41 | exit 1 42 | fi 43 | 44 | oldvboxhdd="" 45 | if [ -e "${incdir}/VBox/VBoxHDD-new.h" ]; then 46 | oldvboxhdd="-DOLDVBOXHDD" 47 | elif ! [ -e "${incdir}/VBox/VBoxHDD.h" ]; then 48 | echo "Invalid include directory. Make sure that it has the VBox directory inside." 49 | exit 1 50 | fi 51 | 52 | gcc "${infile}" -o "${outfile}" \ 53 | `pkg-config --cflags --libs fuse` \ 54 | -I"${incdir}" \ 55 | -Wl,-rpath,"${INSTALL_DIR}" \ 56 | -l:"${INSTALL_DIR}"/VBoxDD.so \ 57 | -Wall ${oldvboxhdd} ${CFLAGS} 58 | 59 | if [ -z "${NOSTRIP}" ]; then 60 | strip -sx "${outfile}" 61 | fi 62 | 63 | if [ $? -eq 0 ]; then 64 | echo "Success!" 65 | else 66 | echo "Compile Failed!" 67 | fi 68 | -------------------------------------------------------------------------------- /old/vdbuild_new: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Environment variables (all optional) 4 | # CFLAGS - flags for gcc 5 | # NOSTRIP - don't strip output 6 | # INSTALL_DIR - vbox install directory 7 | 8 | if [ $# -ne 2 ]; then 9 | echo "Usage: $0 include-dir vdfuse.c" 10 | exit 255 11 | fi 12 | 13 | if [ -z "${CFLAGS}" ]; then 14 | CFLAGS="-pipe" 15 | fi 16 | 17 | incdir="$1" 18 | infile="$2" 19 | outfile="${infile%.c}" 20 | 21 | if ! [ -e "${infile}" ]; then 22 | echo "${infile} not found." 23 | exit 1 24 | fi 25 | 26 | if [ -z "${INSTALL_DIR}" ]; then 27 | if [ -e "/etc/vbox/vbox.cfg" ]; then 28 | . /etc/vbox/vbox.cfg 29 | elif [ -d "/usr/lib/virtualbox" ]; then 30 | INSTALL_DIR="/usr/lib/virtualbox" 31 | elif [ -d "/Applications/VirtualBox.app/Contents/MacOS" ]; then 32 | INSTALL_DIR="/Applications/VirtualBox.app/Contents/MacOS" 33 | elif [ -z "${INSTALL_DIR}" ]; then 34 | echo "INSTALL_DIR not defined" 35 | exit 1 36 | fi 37 | fi 38 | 39 | pkg-config --exists fuse 40 | if [ $? -ne 0 ]; then 41 | echo "FUSE headers not found. Are they installed?" 42 | echo "(Run 'apt-get install libfuse-dev' on Ubuntu / Debian)" 43 | exit 1 44 | fi 45 | 46 | if ! [ -e "${incdir}/VBox/vd.h" ]; then 47 | echo "Invalid include directory. Make sure that it has the VBox directory inside." 48 | exit 1 49 | fi 50 | 51 | gcc "${infile}" -o "${outfile}" \ 52 | `pkg-config --cflags --libs fuse` \ 53 | -I"${incdir}" \ 54 | -Wl,-rpath,"${INSTALL_DIR}" \ 55 | -l:"${INSTALL_DIR}"/VBoxDD.so \ 56 | -Wall ${CFLAGS} 57 | 58 | if [ -z "${NOSTRIP}" ]; then 59 | strip -sx "${outfile}" 60 | fi 61 | 62 | if [ $? -eq 0 ]; then 63 | echo "Success!" 64 | else 65 | echo "Compile Failed!" 66 | fi 67 | -------------------------------------------------------------------------------- /src/vdfuse.c: -------------------------------------------------------------------------------- 1 | /* Commandline tool for mounting VDI/VMDK/VHD files * 2 | * * 3 | * Copyright 2009-2011, 2013 by it's authors. * 4 | * Some rights reserved. See COPYING, AUTHORS. * 5 | * * 6 | * This program is free software: you can redistribute it and/or modify * 7 | * it under the terms of the GNU General Public License as published by * 8 | * the Free Software Foundation, either version 2 of the License, or * 9 | * (at your option) any later version. * 10 | * * 11 | * This program is distributed in the hope that it will be useful, * 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 14 | * GNU General Public License for more details. * 15 | * * 16 | * You should have received a copy of the GNU General Public License * 17 | * along with this program. If not, see . */ 18 | 19 | /* DESCRIPTION 20 | * This code is structured in the following sections: 21 | * * The main(argc, argv) routine including validation of arguments and call to fuse_main 22 | * * MBR and EBR parsing routines 23 | * * The Fuse callback routines for destroy ,flush ,getattr ,open, read, readdir, write 24 | * 25 | * For further details on how this all works see http://fuse.sourceforge.net/ 26 | * 27 | * VirtualBox provided an API to enable you to manipulate VD image files programmatically. 28 | * This is documented in the embedded source comments. See for further details 29 | * http://www.virtualbox.org/svn/vbox/trunk/include/VBox/VBoxHDD-new.h 30 | * 31 | */ 32 | #define FUSE_USE_VERSION 26 33 | #define _FILE_OFFSET_BITS 64 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include "config.h" 45 | 46 | #ifdef __GNUC__ 47 | #define UNUSED __attribute__ ((unused)) 48 | #else 49 | #define UNUSED 50 | #endif 51 | 52 | #define IN_RING3 53 | #define BLOCKSIZE 512 54 | #define UNALLOCATED -1 55 | #define GETOPT_ARGS "rgvawt:s:f:dh?" 56 | #define HOSTPARTITION_MAX 100 57 | #define DIFFERENCING_MAX 100 58 | #define PNAMESIZE 15 59 | #define MBR_START 446 60 | #define EBR_START 446 61 | #define PARTTYPE_IS_EXTENDED(x) ((x) == 0x05 || (x) == 0x0f || (x) == 0x85) 62 | #define ENTIRE_DISK_STR "EntireDisk" 63 | 64 | void usageAndExit (char *optFormat, ...); 65 | void vbprintf (const char *format, ...); 66 | void vdErrorCallback (void *pvUser, int rc, const char *file, unsigned iLine, 67 | const char *function, const char *format, va_list va); 68 | void initialisePartitionTable (void); 69 | int findPartition (const char *filename); 70 | int detectDiskType (char **disktype, char *filename); 71 | static int VD_open (const char *c, struct fuse_file_info *i); 72 | static int VD_release (const char *name, struct fuse_file_info *fi); 73 | static int VD_read (const char *c, char *out, size_t len, off_t offset, 74 | struct fuse_file_info *i UNUSED); 75 | static int VD_write (const char *c, const char *in, size_t len, off_t offset, 76 | struct fuse_file_info *i UNUSED); 77 | static int VD_flush (const char *p, struct fuse_file_info *i UNUSED); 78 | static int VD_readdir (const char *p, void *buf, fuse_fill_dir_t filler, 79 | off_t offset UNUSED, struct fuse_file_info *i UNUSED); 80 | static int VD_getattr (const char *p, struct stat *stbuf); 81 | void VD_destroy (void *u); 82 | 83 | #include 84 | 85 | #define DISKread(o,b,s) VDRead (hdDisk,o,b,s); 86 | #define DISKwrite(o,b,s) VDWrite (hdDisk,o,b,s); 87 | #define DISKclose VDCloseAll(hdDisk) 88 | #define DISKsize VDGetSize(hdDisk, 0) 89 | #define DISKflush VDFlush(hdDisk) 90 | #define DISKopen(t,i) \ 91 | if (RT_FAILURE(VDOpen(hdDisk,t , i, readonly ? VD_OPEN_FLAGS_READONLY : VD_OPEN_FLAGS_NORMAL, NULL))) \ 92 | usageAndExit("opening vbox image failed"); 93 | 94 | PVBOXHDD hdDisk; 95 | PVDINTERFACE pVDifs = NULL; 96 | VDINTERFACE vdError; 97 | VDINTERFACEERROR vdErrorCallbacks = { 98 | // .cbSize = sizeof (VDINTERFACEERROR), 99 | //.enmInterface = VDINTERFACETYPE_ERROR, 100 | .pfnError = vdErrorCallback 101 | }; 102 | 103 | // Partition table information 104 | 105 | typedef struct 106 | { // See http://en.wikipedia.org/wiki/Master_boot_record 107 | uint8_t status; // status[7] (0x80 = bootable, 0x00 = non-bootable,other = invalid[8]) 108 | // ** CHS address of first block ** 109 | uint8_t shead; // first head 110 | uint8_t ssector; // first sector is in bits 5-0; bits 9-8 of cylinder are in bits 7-6 111 | uint8_t sbits; // first bits 7-0 of cylinder 112 | uint8_t type; // partition type 113 | // ** CHS address of last block ** 114 | uint8_t ehead; // last head 115 | uint8_t esector; // last sector is in bits 5-0; bits 9-8 of cylinder are in bits 7-6 116 | uint8_t ebits; // last bits 7-0 of cylinder 117 | uint32_t offset; // LBA of first sector in the partition 118 | uint32_t size; // number of blocks in partition, in little-endian format 119 | } MBRentry; 120 | 121 | typedef struct 122 | { 123 | char name[PNAMESIZE + 1]; // name of partition 124 | off_t offset; // offset into disk in bytes 125 | uint64_t size; // size of partiton in bytes 126 | int no; // partition number 127 | MBRentry descriptor; // copy of MBR / EBR descriptor that defines the partion 128 | } Partition; 129 | 130 | #pragma pack( push ) 131 | #pragma pack( 1 ) 132 | 133 | typedef struct 134 | { 135 | char fill[MBR_START]; 136 | MBRentry descriptor[4]; 137 | uint16_t signature; 138 | } MBRblock; 139 | 140 | 141 | typedef struct 142 | { // See http://en.wikipedia.org/wiki/Extended_boot_record for details 143 | char fill[EBR_START]; 144 | MBRentry descriptor; 145 | MBRentry chain; 146 | MBRentry fill1, fill2; 147 | uint16_t signature; 148 | } EBRentry; 149 | 150 | #pragma pack( pop ) 151 | 152 | Partition partitionTable[HOSTPARTITION_MAX + 1]; // Note the partitionTable[0] is reserved for the EntireDisk descriptor 153 | static int lastPartition = 0; 154 | 155 | static struct fuse_operations fuseOperations = { 156 | .readdir = VD_readdir, 157 | .getattr = VD_getattr, 158 | .open = VD_open, 159 | .release = VD_release, 160 | .read = VD_read, 161 | .write = VD_write, 162 | .flush = VD_flush, 163 | .destroy = VD_destroy 164 | }; 165 | 166 | static struct fuse_args fuseArgs = FUSE_ARGS_INIT (0, NULL); 167 | 168 | static struct stat VDfile_stat; 169 | 170 | static int verbose = 0; 171 | static int readonly = 0; 172 | static int allowall = 0; // allow all users to read from disk 173 | static int allowallw = 0; // allow all users to write to disk 174 | static uid_t myuid = 0; 175 | static gid_t mygid = 0; 176 | static char *processName; 177 | static int entireDiskOpened = 0; 178 | static int partitionOpened = 0; 179 | static int opened = 0; // how many opened instances are there 180 | 181 | // 182 | //==================================================================================================== 183 | // Main routine including validation 184 | //==================================================================================================== 185 | 186 | int 187 | main (int argc, char **argv) 188 | { 189 | char *diskType = "auto"; 190 | char *imagefilename = NULL; 191 | char *mountpoint = NULL; 192 | int debug = 0; 193 | int foreground = 0; 194 | char c; 195 | int i; 196 | char *differencing[DIFFERENCING_MAX]; 197 | int differencingLen = 0; 198 | 199 | extern char *optarg; 200 | extern int optind, optopt; 201 | 202 | // 203 | // *** Parse the command line options *** 204 | // 205 | processName = argv[0]; 206 | 207 | while ((c = getopt (argc, argv, GETOPT_ARGS)) != -1) 208 | { 209 | switch (c) 210 | { 211 | case 'r': 212 | readonly = 1; 213 | break; 214 | case 'g': 215 | foreground = 1; 216 | break; 217 | case 'v': 218 | verbose = 1; 219 | break; 220 | case 'a': 221 | allowall = 1; 222 | break; 223 | case 'w': 224 | allowall = 1; 225 | allowallw = 1; 226 | break; 227 | case 't': 228 | diskType = (char *) optarg; 229 | break; // ignored if OLDAPI 230 | case 's': 231 | if (differencingLen == DIFFERENCING_MAX) 232 | usageAndExit ("Too many differencing disks"); 233 | differencing[differencingLen++] = (char *) optarg; 234 | break; 235 | case 'f': 236 | imagefilename = (char *) optarg; 237 | break; 238 | case 'd': 239 | foreground = 1; 240 | debug = 1; 241 | break; 242 | case 'h': 243 | usageAndExit (NULL); 244 | case '?': 245 | usageAndExit ("Unknown option"); 246 | } 247 | } 248 | // 249 | // *** Validate the command line *** 250 | // 251 | if (argc != optind + 1) 252 | usageAndExit ("a single mountpoint must be specified"); 253 | mountpoint = argv[optind]; 254 | if (!mountpoint) 255 | usageAndExit ("no mountpoint specified"); 256 | if (!imagefilename) 257 | usageAndExit ("no image chosen"); 258 | if (stat (imagefilename, &VDfile_stat) < 0) 259 | usageAndExit ("cannot access imagefile"); 260 | if (access (imagefilename, F_OK | R_OK | ((!readonly) ? W_OK : 0)) < 0) 261 | usageAndExit ("cannot access imagefile"); 262 | for (i = 0; i < differencingLen; i++) 263 | if (access (differencing[i], F_OK | R_OK | ((readonly) ? 0 : W_OK)) < 0) 264 | usageAndExit ("cannot access differencing imagefile %s", 265 | differencing[i]); 266 | 267 | #define IS_TYPE(s) (strcmp (s, diskType) == 0) 268 | if (! 269 | (IS_TYPE ("auto") || IS_TYPE ("VDI") || IS_TYPE ("VMDK") 270 | || IS_TYPE ("VHD") || IS_TYPE ("auto"))) 271 | usageAndExit ("invalid disk type specified"); 272 | if (strcmp ("auto", diskType) == 0 273 | && detectDiskType (&diskType, imagefilename) < 0) 274 | return 1; 275 | 276 | // 277 | // *** Open the VDI, parse the MBR + EBRs and connect to the fuse service *** 278 | // 279 | 280 | if (RT_FAILURE (VDInterfaceAdd (&vdError, "VD Error", VDINTERFACETYPE_ERROR, &vdErrorCallbacks, 0, &pVDifs))) 281 | usageAndExit ("invalid initialisation of VD interface"); 282 | if (RT_FAILURE (VDCreate (&vdError, VDTYPE_HDD, &hdDisk))) 283 | usageAndExit ("invalid initialisation of VD interface"); 284 | DISKopen (diskType, imagefilename); 285 | 286 | for (i = 0; i < differencingLen; i++) 287 | { 288 | char *diffType; 289 | char *diffFilename = differencing[i]; 290 | detectDiskType (&diffType, diffFilename); 291 | DISKopen (diffType, diffFilename); 292 | } 293 | 294 | initialisePartitionTable (); 295 | 296 | myuid = geteuid (); 297 | mygid = getegid (); 298 | 299 | fuse_opt_add_arg (&fuseArgs, "vdfuse"); 300 | 301 | { 302 | char fsname[strlen (imagefilename) + 12]; 303 | strcpy (fsname, "-ofsname=\0"); 304 | strcat (fsname, imagefilename); 305 | fuse_opt_add_arg (&fuseArgs, fsname); 306 | } 307 | 308 | fuse_opt_add_arg (&fuseArgs, "-osubtype=vdfuse"); 309 | fuse_opt_add_arg (&fuseArgs, "-o"); 310 | fuse_opt_add_arg (&fuseArgs, (allowall) ? "allow_other" : "allow_root"); 311 | if (foreground) 312 | fuse_opt_add_arg (&fuseArgs, "-f"); 313 | if (debug) 314 | fuse_opt_add_arg (&fuseArgs, "-d"); 315 | fuse_opt_add_arg (&fuseArgs, mountpoint); 316 | 317 | return fuse_main (fuseArgs.argc, fuseArgs.argv, &fuseOperations 318 | #if FUSE_USE_VERSION >= 26 319 | , NULL 320 | #endif 321 | ); 322 | } 323 | 324 | //==================================================================================================== 325 | // Miscellaneous output utilities 326 | //==================================================================================================== 327 | 328 | void 329 | usageAndExit (char *optFormat, ...) 330 | { 331 | va_list ap; 332 | if (optFormat != NULL) 333 | { 334 | fputs ("\nERROR: ", stderr); 335 | va_start (ap, optFormat); 336 | vfprintf (stderr, optFormat, ap); 337 | va_end (ap); 338 | fputs ("\n\n", stderr); 339 | } 340 | // ---------!---------!---------!---------!---------!---------!---------!---------! 341 | fprintf (stderr, 342 | "DESCRIPTION: This Fuse module uses the VirtualBox access library to open a \n" 343 | "VirtualBox supported VD image file and mount it as a Fuse file system. The\n" 344 | "mount point contains a flat directory containing the files EntireDisk,\n" 345 | "Partition1 .. PartitionN. These can then be loop mounted to access the\n" 346 | "underlying file systems\n\n" 347 | "USAGE: %s [options] -f image-file mountpoint\n" 348 | "\t-h\thelp\n" "\t-r\treadonly\n" 349 | #ifndef OLDAPI 350 | "\t-t\tspecify type (VDI, VMDK, VHD, or raw; default: auto)\n" 351 | #endif 352 | "\t-f\tVDimage file\n" 353 | "\t-s\tdifferencing disk files\n" // prevent misuse 354 | "\t-a\tallow all users to read disk\n" 355 | "\t-w\tallow all users to read and write to disk\n" 356 | "\t-g\trun in foreground\n" 357 | "\t-v\tverbose\n" 358 | "\t-d\tdebug\n\n" 359 | "NOTE: \n" 360 | "Linux: you must add the line \"user_allow_other\" (without quotes) to /etc/fuse.confand set proper permissions on /etc/fuse.conf\n" 361 | "OSX: run with sudo for this to work.\n", processName); 362 | exit (1); 363 | } 364 | 365 | void 366 | vbprintf (const char *format, ...) 367 | { 368 | va_list ap; 369 | if (!verbose) 370 | return; 371 | va_start (ap, format); 372 | vprintf (format, ap); 373 | va_end (ap); 374 | fputs ("\n", stdout); 375 | fflush (stdout); 376 | } 377 | 378 | void 379 | vdErrorCallback (void *pvUser UNUSED, int rc, const char *file, 380 | unsigned iLine, const char *function, const char *format, 381 | va_list va) 382 | { 383 | fprintf (stderr, "\nVD CallbackError rc %d at %s:%u (%s): ", rc, file, 384 | iLine, function); 385 | vfprintf (stderr, format, va); 386 | fputs ("\n", stderr); 387 | } 388 | 389 | 390 | //==================================================================================================== 391 | // MBR + EBR parsing routine 392 | //==================================================================================================== 393 | // 394 | // This code is algorithmically based on partRead in VBoxInternalManage.cpp plus the Wikipedia articles 395 | // on MBR and EBR. As in partRead, a statically allocated partition list is used same to keep things 396 | // simple (but up to a max 100 partitions :lol:). Note than unlike partRead, this doesn't resort the 397 | // partitions. 398 | // 399 | //int VDRead(PVBOXHDD pDisk, uint64_t uOffset, void *pvBuf, size_t cbRead, int ii ); 400 | 401 | void 402 | initialisePartitionTable (void) 403 | { 404 | //uint16_t MBRsignature; 405 | int entendedFlag = UNALLOCATED; 406 | int i; 407 | MBRblock mbrb; 408 | 409 | memset (partitionTable, 0, sizeof (partitionTable)); 410 | for (i = 0; i <= (signed) (sizeof (partitionTable) / sizeof (Partition)); i++) { 411 | partitionTable[i].no = UNALLOCATED; 412 | } 413 | 414 | partitionTable[0].no = 0; 415 | partitionTable[0].offset = 0; 416 | partitionTable[0].size = DISKsize; 417 | strcpy (partitionTable[0].name, ENTIRE_DISK_STR); 418 | // 419 | // Check that this is unformated or a DOS partitioned disk. Sorry but other formats not supported. 420 | // 421 | DISKread (0, &mbrb, sizeof (mbrb)); 422 | if (mbrb.signature == 0x0000) 423 | return; // an unformated disk is allowed but only EntireDisk is defined 424 | if (mbrb.signature != 0xaa55) 425 | usageAndExit ("Invalid MBR found on image with signature 0x%04hX", 426 | mbrb.signature); 427 | 428 | // 429 | // Process the four physical partition entires in the MBR 430 | // 431 | for (i = 1; i <= 4; i++) 432 | { 433 | Partition *p = partitionTable + i; 434 | // MBRentry *m = &(p->descriptor); 435 | //DISKread (MBR_START + (i-1) * sizeof(MBRentry), &(p->descriptor), sizeof(MBRentry)); 436 | memcpy (&(p->descriptor), &mbrb.descriptor[i - 1], sizeof (MBRentry)); 437 | if ((p->descriptor).type == 0) 438 | continue; 439 | if (PARTTYPE_IS_EXTENDED ((p->descriptor).type)) 440 | { 441 | if (entendedFlag != UNALLOCATED) 442 | usageAndExit ("More than one extended partition in MBR"); 443 | entendedFlag = i; 444 | } 445 | else 446 | { 447 | lastPartition = i; 448 | p->no = i; 449 | p->offset = (off_t) ((p->descriptor).offset) * BLOCKSIZE; 450 | p->size = (off_t) ((p->descriptor).size) * BLOCKSIZE; 451 | } 452 | } 453 | // 454 | // Now chain down any EBRs to process the logical partition entries 455 | // 456 | if (entendedFlag != UNALLOCATED) 457 | { 458 | EBRentry ebr; 459 | off_t uStart = 460 | (off_t) ((partitionTable[entendedFlag].descriptor).offset) * BLOCKSIZE; 461 | off_t uOffset = 0; 462 | 463 | if (!uStart) 464 | usageAndExit ("Inconsistency for logical partition start. Aborting\n"); 465 | 466 | for (i = 5; i <= HOSTPARTITION_MAX; i++) 467 | { 468 | lastPartition++; 469 | Partition *p = partitionTable + i; 470 | 471 | DISKread (uStart + uOffset + EBR_START, &ebr, sizeof (ebr)); 472 | 473 | if (ebr.signature != 0xaa55) 474 | usageAndExit ("Invalid EBR signature found on image"); 475 | if ((ebr.descriptor).type == 0) 476 | usageAndExit ("Logical partition with type 0 encountered"); 477 | if (!((ebr.descriptor).offset)) 478 | usageAndExit 479 | ("Logical partition invalid partition start offset encountered"); 480 | 481 | p->descriptor = ebr.descriptor; 482 | p->no = i; 483 | lastPartition = i; 484 | p->offset = 485 | uStart + uOffset + (off_t) ((ebr.descriptor).offset) * BLOCKSIZE; 486 | p->size = (off_t) ((ebr.descriptor).size) * BLOCKSIZE; 487 | 488 | if (ebr.chain.type == 0) 489 | break; 490 | if (!PARTTYPE_IS_EXTENDED (ebr.chain.type)) 491 | usageAndExit ("Logical partition chain broken"); 492 | uOffset = (ebr.chain).offset; 493 | } 494 | } 495 | // 496 | // Now print out the partition table 497 | // 498 | vbprintf ("Partition Size Offset\n" 499 | "========= ==== ======\n"); 500 | for (i = 1; i <= lastPartition; i++) 501 | { 502 | Partition *p = partitionTable + i; 503 | if (p->no != UNALLOCATED) 504 | { 505 | sprintf (p->name, "Partition%d", i); 506 | vbprintf ("%-14s %-13lld %-13lld", p->name, p->offset, p->size); 507 | } 508 | } 509 | vbprintf ("\n"); 510 | } 511 | 512 | int 513 | findPartition (const char *filename) 514 | { 515 | // Use a dumb serial search since there are typically less than 3 entries 516 | int i; 517 | register Partition *p = partitionTable; 518 | for (i = 0; i <= lastPartition; i++, p++) 519 | { 520 | if (p->no != UNALLOCATED && strcmp (filename + 1, p->name) == 0) 521 | return i; 522 | } 523 | return -1; 524 | } 525 | 526 | // detects type of virtual image 527 | int 528 | detectDiskType (char **disktype, char *filename) 529 | { 530 | char buf[8]; 531 | int fd = open (filename, O_RDONLY); 532 | read (fd, buf, sizeof (buf)); 533 | 534 | if (strncmp (buf, "conectix", 8) == 0) 535 | *disktype = "VHD"; 536 | else if (strncmp (buf, "VMDK", 4) == 0) 537 | *disktype = "VMDK"; 538 | else if (strncmp (buf, "KDMV", 4) == 0) 539 | *disktype = "VMDK"; 540 | else if (strncmp (buf, "<<<", 3) == 0) 541 | *disktype = "VDI"; 542 | else 543 | usageAndExit ("cannot autodetect disk type of %s", filename); 544 | 545 | vbprintf ("disktype is %s", *disktype); 546 | close (fd); 547 | return 0; 548 | } 549 | 550 | //==================================================================================================== 551 | // Fuse Callback Routines 552 | //==================================================================================================== 553 | // 554 | // in alphetic order to help find them: destroy ,flush ,getattr ,open, read, readdir, write 555 | 556 | pthread_mutex_t disk_mutex = PTHREAD_MUTEX_INITIALIZER; 557 | pthread_mutex_t part_mutex = PTHREAD_MUTEX_INITIALIZER; 558 | 559 | void 560 | VD_destroy (void *u UNUSED) 561 | { 562 | // called when the fuse filesystem is umounted 563 | vbprintf ("destroy"); 564 | DISKclose; 565 | } 566 | 567 | int 568 | VD_flush (const char *p, struct fuse_file_info *i UNUSED) 569 | { 570 | vbprintf ("flush: %s", p); 571 | DISKflush; 572 | return 0; 573 | } 574 | 575 | static int 576 | VD_getattr (const char *p, struct stat *stbuf) 577 | { 578 | vbprintf ("getattr: %s", p); 579 | int isFileRoot = (strcmp ("/", p) == 0); 580 | int n = findPartition (p); 581 | 582 | if (!isFileRoot && n == -1) 583 | return -ENOENT; 584 | 585 | // Use the container file's stat return as the basis. However since partitions cannot 586 | // be created by creating files, there is no write access to the directory. I also 587 | // treat group access the same as other. 588 | 589 | memcpy (stbuf, &VDfile_stat, sizeof (struct stat)); 590 | 591 | if (isFileRoot) 592 | { 593 | stbuf->st_mode = S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP; 594 | if (allowall) 595 | stbuf->st_mode |= S_IROTH; 596 | stbuf->st_size = 0; 597 | stbuf->st_blocks = 2; 598 | } 599 | else 600 | { 601 | stbuf->st_mode = S_IFREG | S_IRUSR | S_IWUSR; 602 | if (allowall) 603 | stbuf->st_mode |= S_IRGRP | S_IROTH; 604 | if (allowallw) 605 | stbuf->st_mode |= S_IWGRP | S_IWOTH; 606 | stbuf->st_size = partitionTable[n].size; 607 | stbuf->st_blocks = (stbuf->st_size + BLOCKSIZE - 1) / BLOCKSIZE; 608 | } 609 | if (readonly) 610 | { 611 | stbuf->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); 612 | } 613 | 614 | stbuf->st_nlink = 1; 615 | 616 | return 0; 617 | } 618 | 619 | static int 620 | VD_open (const char *cName, struct fuse_file_info *i) 621 | { 622 | vbprintf ("open: %s, %lld, 0X%08lX ", cName, i->fh, i->flags); 623 | int n = findPartition (cName); 624 | if ((n == -1) || (entireDiskOpened && n > 0) || (partitionOpened && n == 0)) 625 | return -ENOENT; 626 | if (readonly && ((i->flags & (O_WRONLY | O_RDWR)) != 0)) 627 | return -EROFS; 628 | 629 | if (n == 0) 630 | entireDiskOpened = 1; 631 | else 632 | partitionOpened = 1; 633 | 634 | pthread_mutex_lock (&part_mutex); 635 | opened++; 636 | pthread_mutex_unlock (&part_mutex); 637 | 638 | return 0; 639 | } 640 | 641 | static int 642 | VD_release (const char *name, struct fuse_file_info *fi) 643 | { 644 | (void) fi; 645 | vbprintf ("release: %s", name); 646 | 647 | pthread_mutex_lock (&part_mutex); 648 | opened--; 649 | if (opened == 0) 650 | { 651 | initialisePartitionTable (); 652 | entireDiskOpened = 0; 653 | partitionOpened = 0; 654 | } 655 | pthread_mutex_unlock (&part_mutex); 656 | 657 | return 0; 658 | } 659 | 660 | static int 661 | VD_read (const char *c, char *out, size_t len, off_t offset, 662 | struct fuse_file_info *i UNUSED) 663 | { 664 | vbprintf ("read: %s, offset=%lld, length=%d", c, offset, len); 665 | int n = findPartition (c); 666 | if (n < 0) 667 | return -ENOENT; 668 | if ((n == 0) ? partitionOpened : entireDiskOpened) 669 | return -EIO; 670 | 671 | Partition *p = &(partitionTable[n]); 672 | // if (offset >= p->size) return 0; 673 | // if (offset + len> p->size) len = p->size - offset; 674 | if ((uint64_t) offset >= p->size) 675 | return 0; 676 | if ((uint64_t) (offset + len) > p->size) 677 | len = p->size - offset; 678 | 679 | pthread_mutex_lock (&disk_mutex); 680 | int ret = DISKread (offset + p->offset, out, len); 681 | pthread_mutex_unlock (&disk_mutex); 682 | 683 | return RT_SUCCESS (ret) ? (signed) len : -EIO; 684 | } 685 | 686 | static int 687 | VD_readdir (const char *p, void *buf, fuse_fill_dir_t filler, 688 | off_t offset UNUSED, struct fuse_file_info *i UNUSED) 689 | { 690 | int n; 691 | vbprintf ("readdir"); 692 | if (strcmp ("/", p) != 0) 693 | return -ENOENT; 694 | filler (buf, ".", NULL, 0); 695 | filler (buf, "..", NULL, 0); 696 | for (n = 0; n <= lastPartition; n++) 697 | { 698 | Partition *p = partitionTable + n; 699 | if (p->no != UNALLOCATED) 700 | filler (buf, p->name, NULL, 0); 701 | } 702 | return 0; 703 | } 704 | 705 | static int 706 | VD_write (const char *c, const char *in, size_t len, off_t offset, 707 | struct fuse_file_info *i UNUSED) 708 | { 709 | vbprintf ("write: %s, offset=%lld, length=%d", c, offset, len); 710 | int n = findPartition (c); 711 | if (n < 0) 712 | return -ENOENT; 713 | if ((n == 0) ? partitionOpened : entireDiskOpened) 714 | return -EIO; 715 | Partition *p = &(partitionTable[n]); 716 | if ((uint64_t) offset >= p->size) 717 | return 0; 718 | if ((uint64_t) (offset + len) > p->size) 719 | len = p->size - offset; 720 | 721 | pthread_mutex_lock (&disk_mutex); 722 | int ret = DISKwrite (offset + p->offset, in, len); 723 | pthread_mutex_unlock (&disk_mutex); 724 | 725 | return RT_SUCCESS (ret) ? (signed) len : -EIO; 726 | } 727 | --------------------------------------------------------------------------------