mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-10-26 08:42:29 +01:00 
			
		
		
		
	import vhd-tools from xen-4.0.1
This commit is contained in:
		
							parent
							
								
									0ef191bed7
								
							
						
					
					
						commit
						fecd83d2b4
					
				
							
								
								
									
										17
									
								
								tools/vhd-tools/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								tools/vhd-tools/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | |||||||
|  | XEN_ROOT = ../.. | ||||||
|  | include $(XEN_ROOT)/tools/Rules.mk | ||||||
|  | 
 | ||||||
|  | CFLAGS  += $(CFLAGS_libxenctrl) | ||||||
|  | LDFLAGS += $(LDFLAGS_libxenctrl) | ||||||
|  | 
 | ||||||
|  | SUBDIRS-y := | ||||||
|  | SUBDIRS-y += include | ||||||
|  | SUBDIRS-y += lvm | ||||||
|  | SUBDIRS-y += vhd | ||||||
|  | SUBDIRS-y += drivers | ||||||
|  | 
 | ||||||
|  | clean: | ||||||
|  | 	rm -rf *.a *.so *.o *.rpm $(LIB) *~ $(DEPS) TAGS | ||||||
|  | 
 | ||||||
|  | .PHONY: all clean install | ||||||
|  | all clean install: %: subdirs-% | ||||||
							
								
								
									
										321
									
								
								tools/vhd-tools/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										321
									
								
								tools/vhd-tools/README
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,321 @@ | |||||||
|  | Blktap2 Userspace Tools + Library | ||||||
|  | ================================ | ||||||
|  | 
 | ||||||
|  | Dutch Meyer | ||||||
|  | 4th June 2009 | ||||||
|  | 
 | ||||||
|  | Andrew Warfield and Julian Chesterfield | ||||||
|  | 16th June 2006 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | The blktap2 userspace toolkit provides a user-level disk I/O | ||||||
|  | interface. The blktap2 mechanism involves a kernel driver that acts | ||||||
|  | similarly to the existing Xen/Linux blkback driver, and a set of | ||||||
|  | associated user-level libraries.  Using these tools, blktap2 allows | ||||||
|  | virtual block devices presented to VMs to be implemented in userspace | ||||||
|  | and to be backed by raw partitions, files, network, etc. | ||||||
|  | 
 | ||||||
|  | The key benefit of blktap2 is that it makes it easy and fast to write | ||||||
|  | arbitrary block backends, and that these user-level backends actually | ||||||
|  | perform very well.  Specifically: | ||||||
|  | 
 | ||||||
|  | - Metadata disk formats such as Copy-on-Write, encrypted disks, sparse | ||||||
|  |   formats and other compression features can be easily implemented. | ||||||
|  | 
 | ||||||
|  | - Accessing file-based images from userspace avoids problems related | ||||||
|  |   to flushing dirty pages which are present in the Linux loopback | ||||||
|  |   driver.  (Specifically, doing a large number of writes to an | ||||||
|  |   NFS-backed image don't result in the OOM killer going berserk.) | ||||||
|  | 
 | ||||||
|  | - Per-disk handler processes enable easier userspace policing of block | ||||||
|  |   resources, and process-granularity QoS techniques (disk scheduling | ||||||
|  |   and related tools) may be trivially applied to block devices. | ||||||
|  | 
 | ||||||
|  | - It's very easy to take advantage of userspace facilities such as | ||||||
|  |   networking libraries, compression utilities, peer-to-peer | ||||||
|  |   file-sharing systems and so on to build more complex block backends. | ||||||
|  | 
 | ||||||
|  | - Crashes are contained -- incremental development/debugging is very | ||||||
|  |   fast. | ||||||
|  | 
 | ||||||
|  | How it works (in one paragraph): | ||||||
|  | 
 | ||||||
|  | Working in conjunction with the kernel blktap2 driver, all disk I/O | ||||||
|  | requests from VMs are passed to the userspace deamon (using a shared | ||||||
|  | memory interface) through a character device. Each active disk is | ||||||
|  | mapped to an individual device node, allowing per-disk processes to | ||||||
|  | implement individual block devices where desired.  The userspace | ||||||
|  | drivers are implemented using asynchronous (Linux libaio), | ||||||
|  | O_DIRECT-based calls to preserve the unbuffered, batched and | ||||||
|  | asynchronous request dispatch achieved with the existing blkback | ||||||
|  | code.  We provide a simple, asynchronous virtual disk interface that | ||||||
|  | makes it quite easy to add new disk implementations. | ||||||
|  | 
 | ||||||
|  | As of June 2009 the current supported disk formats are: | ||||||
|  | 
 | ||||||
|  |  - Raw Images (both on partitions and in image files) | ||||||
|  |  - Fast sharable RAM disk between VMs (requires some form of  | ||||||
|  |    cluster-based filesystem support e.g. OCFS2 in the guest kernel) | ||||||
|  |  - VHD, including snapshots and sparse images | ||||||
|  |  - Qcow, including snapshots and sparse images | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Build and Installation Instructions | ||||||
|  | =================================== | ||||||
|  | 
 | ||||||
|  | Make to configure the blktap2 backend driver in your dom0 kernel.  It | ||||||
|  | will inter-operate with the existing backend and frontend drivers.  It | ||||||
|  | will also cohabitate with the original blktap driver.  However, some | ||||||
|  | formats (currently aio and qcow) will default to their blktap2 | ||||||
|  | versions when specified in a vm configuration file. | ||||||
|  | 
 | ||||||
|  | To build the tools separately, "make && make install" in | ||||||
|  | tools/blktap2. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Using the Tools | ||||||
|  | =============== | ||||||
|  | 
 | ||||||
|  | Preparing an image for boot: | ||||||
|  | 
 | ||||||
|  | The userspace disk agent is configured to start automatically via xend | ||||||
|  | 
 | ||||||
|  | Customize the VM config file to use the 'tap:tapdisk' handler, | ||||||
|  | followed by the driver type. e.g. for a raw image such as a file or | ||||||
|  | partition: | ||||||
|  | 
 | ||||||
|  | disk = ['tap:tapdisk:aio:<FILENAME>,sda1,w'] | ||||||
|  | 
 | ||||||
|  | Alternatively, the vhd-util tool (installed with make install, or in | ||||||
|  | /blktap2/vhd) can be used to build sparse copy-on-write vhd images. | ||||||
|  | 
 | ||||||
|  | For example, to build a sparse image - | ||||||
|  |   vhd-util create -n MyVHDFile -s 1024 | ||||||
|  | 
 | ||||||
|  | This creates a sparse 1GB file named "MyVHDFile" that can be mounted | ||||||
|  | and populated with data. | ||||||
|  | 
 | ||||||
|  | One can also base the image on a raw file - | ||||||
|  |   vhd-util snapshot -n MyVHDFile -p SomeRawFile -m | ||||||
|  | 
 | ||||||
|  | This creates a sparse VHD file named "MyVHDFile" using "SomeRawFile" | ||||||
|  | as a parent image.  Copy-on-write semantics ensure that writes will be | ||||||
|  | stored in "MyVHDFile" while reads will be directed to the most | ||||||
|  | recently written version of the data, either in "MyVHDFile" or | ||||||
|  | "SomeRawFile" as is appropriate.  Other options exist as well, consult | ||||||
|  | the vhd-util application for the complete set of VHD tools. | ||||||
|  | 
 | ||||||
|  | VHD files can be mounted automatically in a guest similarly to the | ||||||
|  | above AIO example simply by specifying the vhd driver. | ||||||
|  | 
 | ||||||
|  | disk = ['tap:tapdisk:vhd:<VHD FILENAME>,sda1,w'] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Snapshots: | ||||||
|  | 
 | ||||||
|  | Pausing a guest will also plug the corresponding IO queue for blktap2 | ||||||
|  | devices and stop blktap2 drivers.  This can be used to implement a | ||||||
|  | safe live snapshot of qcow and vhd disks.  An example script "xmsnap" | ||||||
|  | is shown in the tools/blktap2/drivers directory.  This script will | ||||||
|  | perform a live snapshot of a qcow disk.  VHD files can use the | ||||||
|  | "vhd-util snapshot" tool discussed above.  If this snapshot command is | ||||||
|  | applied to a raw file mounted with tap:tapdisk:AIO, include the -m | ||||||
|  | flag and the driver will be reloaded as VHD.  If applied to an already | ||||||
|  | mounted VHD file, omit the -m flag. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Mounting images in Dom0 using the blktap2 driver | ||||||
|  | =============================================== | ||||||
|  | Tap (and blkback) disks are also mountable in Dom0 without requiring an | ||||||
|  | active VM to attach.  | ||||||
|  | 
 | ||||||
|  | The syntax is - | ||||||
|  |   tapdisk2 -n <type>:<full path to file> | ||||||
|  | 
 | ||||||
|  | For example - | ||||||
|  |   tapdisk2  -n aio:/home/images/rawFile.img | ||||||
|  | 
 | ||||||
|  | When successful the location of the new device will be provided by | ||||||
|  | tapdisk2 to stdout and tapdisk2 will terminate.  From that point | ||||||
|  | forward control of the device is provided through sysfs in the | ||||||
|  | directory- | ||||||
|  | 
 | ||||||
|  |   /sys/class/blktap2/blktap#/ | ||||||
|  | 
 | ||||||
|  | Where # is a blktap2 device number present in the path that tapdisk2 | ||||||
|  | printed before terminating.  The sysfs interface is largely intuitive, | ||||||
|  | for example, to remove tap device 0 one would- | ||||||
|  |    | ||||||
|  |   echo 1 > /sys/class/blktap2/blktap0/remove | ||||||
|  | 
 | ||||||
|  | Similarly, a pause control is available, which is can be used to plug | ||||||
|  | the request queue of a live running guest. | ||||||
|  | 
 | ||||||
|  | Previous versions of blktap mounted devices in dom0 by using blkfront | ||||||
|  | in dom0 and the xm block-attach command.  This approach is still | ||||||
|  | available, though slightly more cumbersome. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Tapdisk Development | ||||||
|  | =============================================== | ||||||
|  | 
 | ||||||
|  | People regularly ask how to develop their own tapdisk drivers, and | ||||||
|  | while it has not yet been well documented, the process is relatively | ||||||
|  | easy.  Here I will provide a brief overview.  The best reference, of | ||||||
|  | course, comes from the existing drivers.  Specifically, | ||||||
|  | blktap2/drivers/block-ram.c and blktap2/drivers/block-aio.c provide | ||||||
|  | the clearest examples of simple drivers. | ||||||
|  |   | ||||||
|  | 
 | ||||||
|  | Setup: | ||||||
|  | 
 | ||||||
|  | First you need to register your new driver with blktap. This is done | ||||||
|  | in disktypes.h.  There are five things that you must do.  To | ||||||
|  | demonstrate, I will create a disk called "mynewdisk", you can name | ||||||
|  | yours freely. | ||||||
|  | 
 | ||||||
|  | 1) Forward declare an instance of struct tap_disk. | ||||||
|  | 
 | ||||||
|  | e.g. -   | ||||||
|  |   extern struct tap_disk tapdisk_mynewdisk; | ||||||
|  | 
 | ||||||
|  | 2) Claim one of the unused disk type numbers, take care to observe the | ||||||
|  | MAX_DISK_TYPES macro, increasing the number if necessary. | ||||||
|  | 
 | ||||||
|  | e.g. - | ||||||
|  |   #define DISK_TYPE_MYNEWDISK         10 | ||||||
|  | 
 | ||||||
|  | 3) Create an instance of disk_info_t.  The bulk of this file contains examples of these. | ||||||
|  | 
 | ||||||
|  | e.g. - | ||||||
|  |   static disk_info_t mynewdisk_disk = { | ||||||
|  |           DISK_TYPE_MYNEWDISK, | ||||||
|  |           "My New Disk (mynewdisk)", | ||||||
|  |           "mynewdisk", | ||||||
|  |           0, | ||||||
|  |   #ifdef TAPDISK | ||||||
|  |           &tapdisk_mynewdisk, | ||||||
|  |   #endif | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  | A few words about what these mean.  The first field must be the disk | ||||||
|  | type number you claimed in step (2).  The second field is a string | ||||||
|  | describing your disk, and may contain any relevant info.  The third | ||||||
|  | field is the name of your disk as will be used by the tapdisk2 utility | ||||||
|  | and xend (for example tapdisk2 -n mynewdisk:/path/to/disk.image, or in | ||||||
|  | your xm create config file).  The forth is binary and determines | ||||||
|  | whether you will have one instance of your driver, or many.  Here, a 1 | ||||||
|  | means that your driver is a singleton and will coordinate access to | ||||||
|  | any number of tap devices.  0 is more common, meaning that you will | ||||||
|  | have one driver for each device that is created.  The final field | ||||||
|  | should contain a reference to the struct tap_disk you created in step | ||||||
|  | (1). | ||||||
|  | 
 | ||||||
|  | 4) Add a reference to your disk info structure (from step (3)) to the | ||||||
|  | dtypes array.  Take care here - you need to place it in the position | ||||||
|  | corresponding to the device type number you claimed in step (2).  So | ||||||
|  | we would place &mynewdisk_disk in dtypes[10].  Look at the other | ||||||
|  | devices in this array and pad with "&null_disk," as necessary. | ||||||
|  | 
 | ||||||
|  | 5) Modify the xend python scripts.  You need to add your disk name to | ||||||
|  | the list of disks that xend recognizes. | ||||||
|  | 
 | ||||||
|  | edit: | ||||||
|  |   tools/python/xen/xend/server/BlktapController.py | ||||||
|  | 
 | ||||||
|  | And add your disk to the "blktap_disk_types" array near the top of | ||||||
|  | your file.  Use the same name you specified in the third field of step | ||||||
|  | (3).  The order of this list is not important. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Now your driver is ready to be written.  Create a block-mynewdisk.c in | ||||||
|  | tools/blktap2/drivers and add it to the Makefile. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Development: | ||||||
|  | 
 | ||||||
|  | Copying block-aio.c and block-ram.c would be a good place to start. | ||||||
|  | Read those files as you go through this, I will be assisting by | ||||||
|  | commenting on a few useful functions and structures. | ||||||
|  | 
 | ||||||
|  | struct tap_disk: | ||||||
|  | 
 | ||||||
|  | Remember the forward declaration in step (1) of the setup phase above? | ||||||
|  | Now is the time to make that structure a reality.  This structure | ||||||
|  | contains a list of function pointers for all the routines that will be | ||||||
|  | asked of your driver.  Currently the required functions are open, | ||||||
|  | close, read, write, get_parent_id, validate_parent, and debug. | ||||||
|  | 
 | ||||||
|  | e.g. - | ||||||
|  |   struct tap_disk tapdisk_mynewdisk = { | ||||||
|  |           .disk_type          = "tapdisk_mynewdisk", | ||||||
|  |           .flags              = 0, | ||||||
|  |           .private_data_size  = sizeof(struct tdmynewdisk_state), | ||||||
|  |           .td_open            = tdmynewdisk_open, | ||||||
|  |                  .... | ||||||
|  | 
 | ||||||
|  | The private_data_size field is used to provide a structure to store | ||||||
|  | the state of your device.  It is very likely that you will want | ||||||
|  | something here, but you are free to design whatever structure you | ||||||
|  | want.  Blktap will allocate this space for you, you just need to tell | ||||||
|  | it how much space you want. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | tdmynewdisk_open: | ||||||
|  | 
 | ||||||
|  | This is the open routine.  The first argument is a structure | ||||||
|  | representing your driver.  Two fields in this array are | ||||||
|  | interesting.  | ||||||
|  | 
 | ||||||
|  | driver->data will contain a block of memory of the size your requested | ||||||
|  | in in the .private_data_size field of your struct tap_disk (above). | ||||||
|  | 
 | ||||||
|  | driver->info contains a structure that details information about your | ||||||
|  | disk.  You need to fill this out.  By convention this is done with a | ||||||
|  | _get_image_info() function.  Assign a size (the total number of | ||||||
|  | sectors), sector_size (the size of each sector in bytes, and set | ||||||
|  | driver->info->info to 0. | ||||||
|  | 
 | ||||||
|  | The second parameter contains the name that was specified in the | ||||||
|  | creation of your device, either through xend, or on the command line | ||||||
|  | with tapdisk2.  Usually this specifies a file that you will open in | ||||||
|  | this routine.  The final parameter, flags, contains one of a number of | ||||||
|  | flags specified in tapdisk.h that may change the way you treat the | ||||||
|  | disk. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | _queue_read/write: | ||||||
|  | 
 | ||||||
|  | These are your read and write operations.  What you do here will | ||||||
|  | depend on your disk, but you should do exactly one of-  | ||||||
|  | 
 | ||||||
|  | 1) call td_complete_request with either error or success code. | ||||||
|  | 
 | ||||||
|  | 2) Call td_forward_request, which will forward the request to the next | ||||||
|  | driver in the stack. | ||||||
|  | 
 | ||||||
|  | 3) Queue the request for asynchronous processing with | ||||||
|  | td_prep_read/write.  In doing so, you will also register a callback | ||||||
|  | for request completion.  When the request completes you must do one of | ||||||
|  | options (1) or (2) above.  Finally, call td_queue_tiocb to submit the | ||||||
|  | request to a wait queue. | ||||||
|  | 
 | ||||||
|  | The above functions are defined in tapdisk-interface.c.  If you don't | ||||||
|  | use them as specified you will run into problems as your driver will | ||||||
|  | fail to inform blktap of the state of requests that have been | ||||||
|  | submitted.  Blktap keeps track of all requests and does not like losing track. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | _close, _get_parent_id, _validate_parent: | ||||||
|  | 
 | ||||||
|  | These last few tend to be very routine.  _close is called when the | ||||||
|  | device is closed, and also when it is paused (in this case, open will | ||||||
|  | also be called later).  The other functions are used in stacking | ||||||
|  | drivers.  Most often drivers will return TD_NO_PARENT and -EINVAL, | ||||||
|  | respectively. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
							
								
								
									
										14
									
								
								tools/vhd-tools/include/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								tools/vhd-tools/include/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | |||||||
|  | XEN_ROOT := ../../.. | ||||||
|  | include $(XEN_ROOT)/tools/Rules.mk | ||||||
|  | 
 | ||||||
|  | .PHONY: all | ||||||
|  | all: | ||||||
|  | 
 | ||||||
|  | .PHONY: install | ||||||
|  | install: | ||||||
|  | 	$(INSTALL_DIR) -p $(DESTDIR)$(INCLUDEDIR) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | .PHONY: clean | ||||||
|  | clean: | ||||||
|  | 	@: | ||||||
							
								
								
									
										33
									
								
								tools/vhd-tools/include/atomicio.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								tools/vhd-tools/include/atomicio.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,33 @@ | |||||||
|  | /*	$OpenBSD: atomicio.h,v 1.6 2005/05/24 17:32:43 avsm Exp $	*/ | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Copyright (c) 1995,1999 Theo de Raadt.  All rights reserved. | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||||||
|  |  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||||||
|  |  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||||||
|  |  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||||||
|  |  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||||
|  |  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||||
|  |  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||||
|  |  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||
|  |  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||||||
|  |  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Ensure all of data on socket comes through. f==read || f==vwrite | ||||||
|  |  */ | ||||||
|  | size_t	atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t); | ||||||
|  | 
 | ||||||
|  | #define vwrite (ssize_t (*)(int, void *, size_t))write | ||||||
							
								
								
									
										130
									
								
								tools/vhd-tools/include/blk_uuid.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								tools/vhd-tools/include/blk_uuid.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,130 @@ | |||||||
|  | /* Copyright (c) 2008, XenSource Inc.
 | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of XenSource Inc. nor the names of its contributors | ||||||
|  |  *       may be used to endorse or promote products derived from this software | ||||||
|  |  *       without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||||||
|  |  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||||
|  |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||||
|  |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||||
|  |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||||
|  |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||||
|  |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | */ | ||||||
|  | #ifndef __BLKTAP2_UUID_H__ | ||||||
|  | #define __BLKTAP2_UUID_H__ | ||||||
|  | 
 | ||||||
|  | #if defined(__linux__) | ||||||
|  | 
 | ||||||
|  | #include <uuid/uuid.h> | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  |     uuid_t uuid; | ||||||
|  | } blk_uuid_t; | ||||||
|  | 
 | ||||||
|  | static inline int blk_uuid_is_nil(blk_uuid_t *uuid) | ||||||
|  | { | ||||||
|  | 	return uuid_is_null(uuid->uuid); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void blk_uuid_generate(blk_uuid_t *uuid) | ||||||
|  | { | ||||||
|  | 	uuid_generate(uuid->uuid); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void blk_uuid_to_string(blk_uuid_t *uuid, char *out, size_t size) | ||||||
|  | { | ||||||
|  | 	uuid_unparse(uuid->uuid, out); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void blk_uuid_from_string(blk_uuid_t *uuid, const char *in) | ||||||
|  | { | ||||||
|  | 	uuid_parse(in, uuid->uuid); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void blk_uuid_copy(blk_uuid_t *dst, blk_uuid_t *src) | ||||||
|  | { | ||||||
|  | 	uuid_copy(dst->uuid, src->uuid); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void blk_uuid_clear(blk_uuid_t *uuid) | ||||||
|  | { | ||||||
|  | 	uuid_clear(uuid->uuid); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline int blk_uuid_compare(blk_uuid_t *uuid1, blk_uuid_t *uuid2) | ||||||
|  | { | ||||||
|  | 	return uuid_compare(uuid1->uuid, uuid2->uuid); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #elif defined(__NetBSD__) | ||||||
|  | 
 | ||||||
|  | #include <uuid.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | 
 | ||||||
|  | typedef uuid_t blk_uuid_t; | ||||||
|  | 
 | ||||||
|  | static inline int blk_uuid_is_nil(blk_uuid_t *uuid) | ||||||
|  | { | ||||||
|  | 	uint32_t status; | ||||||
|  | 	return uuid_is_nil((uuid_t *)uuid, &status); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void blk_uuid_generate(blk_uuid_t *uuid) | ||||||
|  | { | ||||||
|  | 	uint32_t status; | ||||||
|  | 	uuid_create((uuid_t *)uuid, &status); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void blk_uuid_to_string(blk_uuid_t *uuid, char *out, size_t size) | ||||||
|  | { | ||||||
|  | 	uint32_t status; | ||||||
|  | 	char *_out = NULL; | ||||||
|  | 	uuid_to_string((uuid_t *)uuid, &_out, &status); | ||||||
|  | 	strlcpy(out, _out, size); | ||||||
|  | 	free(_out); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void blk_uuid_from_string(blk_uuid_t *uuid, const char *in) | ||||||
|  | { | ||||||
|  | 	uint32_t status; | ||||||
|  | 	uuid_from_string(in, (uuid_t *)uuid, &status); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void blk_uuid_copy(blk_uuid_t *dst, blk_uuid_t *src) | ||||||
|  | { | ||||||
|  | 	memcpy((uuid_t *)dst, (uuid_t *)src, sizeof(uuid_t)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void blk_uuid_clear(blk_uuid_t *uuid) | ||||||
|  | { | ||||||
|  | 	memset((uuid_t *)uuid, 0, sizeof(uuid_t)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline int blk_uuid_compare(blk_uuid_t *uuid1, blk_uuid_t *uuid2) | ||||||
|  | { | ||||||
|  | 	uint32_t status; | ||||||
|  | 	return uuid_compare((uuid_t *)uuid1, (uuid_t *)uuid2, &status); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #else | ||||||
|  | 
 | ||||||
|  | #error "Please update blk_uuid.h for your OS" | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #endif /* __BLKTAP2_UUID_H__ */ | ||||||
							
								
								
									
										250
									
								
								tools/vhd-tools/include/blktaplib.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										250
									
								
								tools/vhd-tools/include/blktaplib.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,250 @@ | |||||||
|  | /* blktaplib.h
 | ||||||
|  |  * | ||||||
|  |  * Blktap library userspace code. | ||||||
|  |  * | ||||||
|  |  * Copyright (c) 2007, XenSource Inc. | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of XenSource Inc. nor the names of its contributors | ||||||
|  |  *       may be used to endorse or promote products derived from this software | ||||||
|  |  *       without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||||||
|  |  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||||
|  |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||||
|  |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||||
|  |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||||
|  |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||||
|  |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef __BLKTAPLIB_H__ | ||||||
|  | #define __BLKTAPLIB_H__ | ||||||
|  | 
 | ||||||
|  | #include <syslog.h> | ||||||
|  | #include <xenctrl.h> | ||||||
|  | #include <xen/io/blkif.h> | ||||||
|  | 
 | ||||||
|  | #if 1 | ||||||
|  | #define DPRINTF(_f, _a...) syslog(LOG_INFO, _f, ##_a) | ||||||
|  | #else | ||||||
|  | #define DPRINTF(_f, _a...) ((void)0) | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #define EPRINTF(_f, _a...) syslog(LOG_ERR, "tap-err:%s: " _f, __func__, ##_a) | ||||||
|  | #define PERROR(_f, _a...)  EPRINTF(_f ": %s", ##_a, strerror(errno)) | ||||||
|  | 
 | ||||||
|  | #define BLK_RING_SIZE __CONST_RING_SIZE(blkif, XC_PAGE_SIZE) | ||||||
|  | 
 | ||||||
|  | /* size of the extra VMA area to map in attached pages. */ | ||||||
|  | #define BLKTAP_VMA_PAGES BLK_RING_SIZE | ||||||
|  | 
 | ||||||
|  | /* blktap IOCTLs: These must correspond with the blktap driver ioctls */ | ||||||
|  | #define BLKTAP_IOCTL_KICK_FE         1 | ||||||
|  | #define BLKTAP_IOCTL_KICK_BE         2 | ||||||
|  | #define BLKTAP_IOCTL_SETMODE         3 | ||||||
|  | #define BLKTAP_IOCTL_SENDPID	     4 | ||||||
|  | #define BLKTAP_IOCTL_NEWINTF	     5 | ||||||
|  | #define BLKTAP_IOCTL_MINOR	     6 | ||||||
|  | #define BLKTAP_IOCTL_MAJOR	     7 | ||||||
|  | #define BLKTAP_QUERY_ALLOC_REQS      8 | ||||||
|  | #define BLKTAP_IOCTL_FREEINTF	     9 | ||||||
|  | #define BLKTAP_IOCTL_PRINT_IDXS      100  | ||||||
|  | #define BLKTAP_IOCTL_BACKDEV_SETUP   200 | ||||||
|  | 
 | ||||||
|  | #define PRIO_SPECIAL_IO             -9999  | ||||||
|  | 
 | ||||||
|  | /* blktap switching modes: (Set with BLKTAP_IOCTL_SETMODE)             */ | ||||||
|  | #define BLKTAP_MODE_PASSTHROUGH      0x00000000  /* default            */ | ||||||
|  | #define BLKTAP_MODE_INTERCEPT_FE     0x00000001 | ||||||
|  | #define BLKTAP_MODE_INTERCEPT_BE     0x00000002 | ||||||
|  | 
 | ||||||
|  | #define BLKTAP_MODE_INTERPOSE \ | ||||||
|  |            (BLKTAP_MODE_INTERCEPT_FE | BLKTAP_MODE_INTERCEPT_BE) | ||||||
|  | 
 | ||||||
|  | static inline int BLKTAP_MODE_VALID(unsigned long arg) | ||||||
|  | { | ||||||
|  | 	return ( | ||||||
|  | 		( arg == BLKTAP_MODE_PASSTHROUGH  ) || | ||||||
|  | 		( arg == BLKTAP_MODE_INTERCEPT_FE ) || | ||||||
|  | 		( arg == BLKTAP_MODE_INTERPOSE    ) ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #define MAX_REQUESTS            BLK_RING_SIZE | ||||||
|  | 
 | ||||||
|  | #define BLKTAP_IOCTL_KICK       1 | ||||||
|  | #define MAX_PENDING_REQS	BLK_RING_SIZE | ||||||
|  | #define BLKTAP_DEV_DIR          "/dev/xen" | ||||||
|  | #define BLKTAP_DEV_NAME         "blktap" | ||||||
|  | #define BACKDEV_NAME            "backdev" | ||||||
|  | #define BLKTAP_DEV_MINOR        0 | ||||||
|  | #define BLKTAP_CTRL_DIR         "/var/run/tap" | ||||||
|  | 
 | ||||||
|  | extern int blktap_major; | ||||||
|  | 
 | ||||||
|  | #define BLKTAP_RING_PAGES       1 /* Front */ | ||||||
|  | #define BLKTAP_MMAP_REGION_SIZE (BLKTAP_RING_PAGES + MMAP_PAGES) | ||||||
|  | 
 | ||||||
|  | struct blkif; | ||||||
|  | struct blkif_info; | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  | 	blkif_request_t  req; | ||||||
|  | 	int              submitting; | ||||||
|  | 	int              secs_pending; | ||||||
|  |         int16_t          status; | ||||||
|  | 	int              num_retries; | ||||||
|  | 	struct timeval   last_try; | ||||||
|  | } pending_req_t; | ||||||
|  | 
 | ||||||
|  | typedef struct blkif { | ||||||
|  | 	domid_t domid; | ||||||
|  | 	long int handle; | ||||||
|  | 	 | ||||||
|  | 	long int pdev; | ||||||
|  | 	long int readonly; | ||||||
|  | 	 | ||||||
|  | 	enum { DISCONNECTED, DISCONNECTING, CONNECTED } state; | ||||||
|  | 	 | ||||||
|  | 	struct blkif_ops *ops; | ||||||
|  | 	struct blkif *hash_next; | ||||||
|  | 	 | ||||||
|  | 	void *prv;  /* device-specific data */ | ||||||
|  | 	struct blkif_info *info; /*Image parameter passing */ | ||||||
|  | 	pending_req_t pending_list[MAX_REQUESTS]; | ||||||
|  | 	int devnum; | ||||||
|  | 	int fds[2]; | ||||||
|  | 	int be_id; | ||||||
|  | 	char *backend_path; | ||||||
|  | 	int major; | ||||||
|  | 	int minor; | ||||||
|  | 	pid_t tappid; | ||||||
|  | 	int drivertype; | ||||||
|  | 	uint16_t cookie; | ||||||
|  | 	int err; | ||||||
|  | } blkif_t; | ||||||
|  | 
 | ||||||
|  | typedef struct blkif_info { | ||||||
|  | 	char *params; | ||||||
|  | 	int   readonly; | ||||||
|  | 	int   storage; | ||||||
|  | } blkif_info_t; | ||||||
|  | 
 | ||||||
|  | typedef struct tapdev_info { | ||||||
|  | 	int fd; | ||||||
|  | 	char *mem; | ||||||
|  | 	blkif_sring_t *sring; | ||||||
|  | 	blkif_back_ring_t  fe_ring; | ||||||
|  | 	unsigned long vstart; | ||||||
|  | 	blkif_t *blkif; | ||||||
|  | } tapdev_info_t; | ||||||
|  | 
 | ||||||
|  | typedef struct domid_translate { | ||||||
|  | 	unsigned short domid; | ||||||
|  | 	unsigned short busid; | ||||||
|  | } domid_translate_t ; | ||||||
|  | 
 | ||||||
|  | typedef struct image { | ||||||
|  | 	unsigned long long size; | ||||||
|  | 	unsigned long secsize; | ||||||
|  | 	unsigned int info; | ||||||
|  | } image_t; | ||||||
|  | 
 | ||||||
|  | typedef struct msg_hdr { | ||||||
|  | 	uint16_t   type; | ||||||
|  | 	uint16_t   len; | ||||||
|  | 	uint16_t   drivertype; | ||||||
|  | 	uint16_t   cookie; | ||||||
|  | } msg_hdr_t; | ||||||
|  | 
 | ||||||
|  | typedef struct msg_params { | ||||||
|  | 	uint8_t    readonly; | ||||||
|  | 	int        path_off; | ||||||
|  | 	int        path_len; | ||||||
|  | 	int        storage; | ||||||
|  | } msg_params_t; | ||||||
|  | 
 | ||||||
|  | typedef struct msg_newdev { | ||||||
|  | 	uint8_t     devnum; | ||||||
|  | 	uint16_t    domid; | ||||||
|  | } msg_newdev_t; | ||||||
|  | 
 | ||||||
|  | typedef struct msg_pid { | ||||||
|  | 	pid_t     pid; | ||||||
|  | } msg_pid_t; | ||||||
|  | 
 | ||||||
|  | typedef struct msg_cp { | ||||||
|  | 	int       cp_uuid_off; | ||||||
|  | 	int       cp_uuid_len; | ||||||
|  | 	int       cp_drivertype; | ||||||
|  | } msg_cp_t; | ||||||
|  | 
 | ||||||
|  | typedef struct msg_lock { | ||||||
|  | 	int       ro; | ||||||
|  | 	int       enforce; | ||||||
|  | 	int       uuid_off; | ||||||
|  | 	int       uuid_len; | ||||||
|  | } msg_lock_t; | ||||||
|  | 
 | ||||||
|  | #define READ 0 | ||||||
|  | #define WRITE 1 | ||||||
|  | 
 | ||||||
|  | /*Control Messages between manager and tapdev*/ | ||||||
|  | #define CTLMSG_PARAMS          1 | ||||||
|  | #define CTLMSG_IMG             2 | ||||||
|  | #define CTLMSG_IMG_FAIL        3 | ||||||
|  | #define CTLMSG_NEWDEV          4 | ||||||
|  | #define CTLMSG_NEWDEV_RSP      5 | ||||||
|  | #define CTLMSG_NEWDEV_FAIL     6 | ||||||
|  | #define CTLMSG_CLOSE           7 | ||||||
|  | #define CTLMSG_CLOSE_RSP       8 | ||||||
|  | #define CTLMSG_PID             9 | ||||||
|  | #define CTLMSG_PID_RSP         10 | ||||||
|  | #define CTLMSG_CHECKPOINT      11 | ||||||
|  | #define CTLMSG_CHECKPOINT_RSP  12 | ||||||
|  | #define CTLMSG_LOCK            13 | ||||||
|  | #define CTLMSG_LOCK_RSP        14 | ||||||
|  | #define CTLMSG_PAUSE           15 | ||||||
|  | #define CTLMSG_PAUSE_RSP       16 | ||||||
|  | #define CTLMSG_RESUME          17 | ||||||
|  | #define CTLMSG_RESUME_RSP      18 | ||||||
|  | 
 | ||||||
|  | #define TAPDISK_STORAGE_TYPE_NFS       1 | ||||||
|  | #define TAPDISK_STORAGE_TYPE_EXT       2 | ||||||
|  | #define TAPDISK_STORAGE_TYPE_LVM       3 | ||||||
|  | #define TAPDISK_STORAGE_TYPE_DEFAULT   TAPDISK_STORAGE_TYPE_EXT | ||||||
|  | 
 | ||||||
|  | /* Abitrary values, must match the underlying driver... */ | ||||||
|  | #define MAX_TAP_DEV 256 | ||||||
|  | 
 | ||||||
|  | /* Accessing attached data page mappings */ | ||||||
|  | #define MMAP_PAGES                                                    \ | ||||||
|  |     (MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST) | ||||||
|  | #define MMAP_VADDR(_vstart,_req,_seg)                                 \ | ||||||
|  |     ((_vstart) +                                                      \ | ||||||
|  |      ((_req) * BLKIF_MAX_SEGMENTS_PER_REQUEST * getpagesize()) +      \ | ||||||
|  |      ((_seg) * getpagesize())) | ||||||
|  | 
 | ||||||
|  | /* Defines that are only used by library clients */ | ||||||
|  | 
 | ||||||
|  | #ifndef __COMPILING_BLKTAP_LIB | ||||||
|  | 
 | ||||||
|  | static char *blkif_op_name[] = { | ||||||
|  | 	[BLKIF_OP_READ]       = "READ", | ||||||
|  | 	[BLKIF_OP_WRITE]      = "WRITE", | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #endif /* __COMPILING_BLKTAP_LIB */ | ||||||
|  | 
 | ||||||
|  | #endif /* __BLKTAPLIB_H__ */ | ||||||
							
								
								
									
										68
									
								
								tools/vhd-tools/include/libvhd-journal.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								tools/vhd-tools/include/libvhd-journal.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,68 @@ | |||||||
|  | /* Copyright (c) 2008, XenSource Inc.
 | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of XenSource Inc. nor the names of its contributors | ||||||
|  |  *       may be used to endorse or promote products derived from this software | ||||||
|  |  *       without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||||||
|  |  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||||
|  |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||||
|  |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||||
|  |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||||
|  |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||||
|  |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | */ | ||||||
|  | #ifndef _VHD_JOURNAL_H_ | ||||||
|  | #define _VHD_JOURNAL_H_ | ||||||
|  | 
 | ||||||
|  | #include <inttypes.h> | ||||||
|  | 
 | ||||||
|  | #include "libvhd.h" | ||||||
|  | 
 | ||||||
|  | #define VHD_JOURNAL_METADATA       0x01 | ||||||
|  | #define VHD_JOURNAL_DATA           0x02 | ||||||
|  | 
 | ||||||
|  | #define VHD_JOURNAL_HEADER_COOKIE  "vjournal" | ||||||
|  | #define VHD_JOURNAL_ENTRY_COOKIE   0xaaaa12344321aaaa | ||||||
|  | 
 | ||||||
|  | typedef struct vhd_journal_header { | ||||||
|  | 	char                       cookie[8]; | ||||||
|  | 	blk_uuid_t                 uuid; | ||||||
|  | 	uint64_t                   vhd_footer_offset; | ||||||
|  | 	uint32_t                   journal_data_entries; | ||||||
|  | 	uint32_t                   journal_metadata_entries; | ||||||
|  | 	uint64_t                   journal_data_offset; | ||||||
|  | 	uint64_t                   journal_metadata_offset; | ||||||
|  | 	uint64_t                   journal_eof; | ||||||
|  | 	char                       pad[448]; | ||||||
|  | } vhd_journal_header_t; | ||||||
|  | 
 | ||||||
|  | typedef struct vhd_journal { | ||||||
|  | 	char                      *jname; | ||||||
|  | 	int                        jfd; | ||||||
|  | 	int                        is_block; /* is jfd a block device */ | ||||||
|  | 	vhd_journal_header_t       header; | ||||||
|  | 	vhd_context_t              vhd; | ||||||
|  | } vhd_journal_t; | ||||||
|  | 
 | ||||||
|  | int vhd_journal_create(vhd_journal_t *, const char *file, const char *jfile); | ||||||
|  | int vhd_journal_open(vhd_journal_t *, const char *file, const char *jfile); | ||||||
|  | int vhd_journal_add_block(vhd_journal_t *, uint32_t block, char mode); | ||||||
|  | int vhd_journal_commit(vhd_journal_t *); | ||||||
|  | int vhd_journal_revert(vhd_journal_t *); | ||||||
|  | int vhd_journal_close(vhd_journal_t *); | ||||||
|  | int vhd_journal_remove(vhd_journal_t *); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
							
								
								
									
										326
									
								
								tools/vhd-tools/include/libvhd.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										326
									
								
								tools/vhd-tools/include/libvhd.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,326 @@ | |||||||
|  | /* Copyright (c) 2008, XenSource Inc.
 | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of XenSource Inc. nor the names of its contributors | ||||||
|  |  *       may be used to endorse or promote products derived from this software | ||||||
|  |  *       without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||||||
|  |  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||||
|  |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||||
|  |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||||
|  |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||||
|  |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||||
|  |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | */ | ||||||
|  | #ifndef _VHD_LIB_H_ | ||||||
|  | #define _VHD_LIB_H_ | ||||||
|  | 
 | ||||||
|  | #include <string.h> | ||||||
|  | #if defined(__linux__) | ||||||
|  | #include <endian.h> | ||||||
|  | #include <byteswap.h> | ||||||
|  | #elif defined(__NetBSD__) | ||||||
|  | #include <sys/endian.h> | ||||||
|  | #include <sys/bswap.h> | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #include "blk_uuid.h" | ||||||
|  | #include "vhd.h" | ||||||
|  | 
 | ||||||
|  | #ifndef O_LARGEFILE | ||||||
|  | #define O_LARGEFILE	0 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #if BYTE_ORDER == LITTLE_ENDIAN | ||||||
|  | #if defined(__linux__) | ||||||
|  |   #define BE16_IN(foo)             (*(foo)) = bswap_16(*(foo)) | ||||||
|  |   #define BE32_IN(foo)             (*(foo)) = bswap_32(*(foo)) | ||||||
|  |   #define BE64_IN(foo)             (*(foo)) = bswap_64(*(foo)) | ||||||
|  |   #define BE16_OUT(foo)            (*(foo)) = bswap_16(*(foo)) | ||||||
|  |   #define BE32_OUT(foo)            (*(foo)) = bswap_32(*(foo)) | ||||||
|  |   #define BE64_OUT(foo)            (*(foo)) = bswap_64(*(foo)) | ||||||
|  | #elif defined(__NetBSD__) | ||||||
|  |   #define BE16_IN(foo)             (*(foo)) = bswap16(*(foo)) | ||||||
|  |   #define BE32_IN(foo)             (*(foo)) = bswap32(*(foo)) | ||||||
|  |   #define BE64_IN(foo)             (*(foo)) = bswap64(*(foo)) | ||||||
|  |   #define BE16_OUT(foo)            (*(foo)) = bswap16(*(foo)) | ||||||
|  |   #define BE32_OUT(foo)            (*(foo)) = bswap32(*(foo)) | ||||||
|  |   #define BE64_OUT(foo)            (*(foo)) = bswap64(*(foo)) | ||||||
|  | #endif | ||||||
|  | #else | ||||||
|  |   #define BE16_IN(foo) | ||||||
|  |   #define BE32_IN(foo) | ||||||
|  |   #define BE64_IN(foo) | ||||||
|  |   #define BE32_OUT(foo) | ||||||
|  |   #define BE32_OUT(foo) | ||||||
|  |   #define BE64_OUT(foo) | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #define MIN(a, b)                  (((a) < (b)) ? (a) : (b)) | ||||||
|  | #define MAX(a, b)                  (((a) > (b)) ? (a) : (b)) | ||||||
|  | 
 | ||||||
|  | #define VHD_MAX_NAME_LEN           1024 | ||||||
|  | 
 | ||||||
|  | #define VHD_BLOCK_SHIFT            21 | ||||||
|  | #define VHD_BLOCK_SIZE             (1ULL << VHD_BLOCK_SHIFT) | ||||||
|  | 
 | ||||||
|  | #define UTF_16                     "UTF-16" | ||||||
|  | #define UTF_16LE                   "UTF-16LE" | ||||||
|  | #define UTF_16BE                   "UTF-16BE" | ||||||
|  | 
 | ||||||
|  | #define VHD_OPEN_RDONLY            0x00001 | ||||||
|  | #define VHD_OPEN_RDWR              0x00002 | ||||||
|  | #define VHD_OPEN_FAST              0x00004 | ||||||
|  | #define VHD_OPEN_STRICT            0x00008 | ||||||
|  | #define VHD_OPEN_IGNORE_DISABLED   0x00010 | ||||||
|  | 
 | ||||||
|  | #define VHD_FLAG_CREAT_PARENT_RAW        0x00001 | ||||||
|  | 
 | ||||||
|  | #define vhd_flag_set(word, flag)         ((word) |= (flag)) | ||||||
|  | #define vhd_flag_clear(word, flag)       ((word) &= ~(flag)) | ||||||
|  | #define vhd_flag_test(word, flag)        ((word) & (flag)) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #define ENABLE_FAILURE_TESTING | ||||||
|  | #define FAIL_REPARENT_BEGIN        0 | ||||||
|  | #define FAIL_REPARENT_LOCATOR      1 | ||||||
|  | #define FAIL_REPARENT_END          2 | ||||||
|  | #define FAIL_RESIZE_BEGIN          3 | ||||||
|  | #define FAIL_RESIZE_DATA_MOVED     4 | ||||||
|  | #define FAIL_RESIZE_METADATA_MOVED 5 | ||||||
|  | #define FAIL_RESIZE_END            6 | ||||||
|  | #define NUM_FAIL_TESTS             7 | ||||||
|  | 
 | ||||||
|  | #ifdef ENABLE_FAILURE_TESTING | ||||||
|  | #define TEST_FAIL_AT(point) \ | ||||||
|  | 	if (TEST_FAIL[point]) { \ | ||||||
|  | 		printf("Failing at %s\n", ENV_VAR_FAIL[point]); exit(EINVAL); } | ||||||
|  | #define TEST_FAIL_EXTERN_VARS              \ | ||||||
|  | 	extern const char* ENV_VAR_FAIL[]; \ | ||||||
|  | 	extern int TEST_FAIL[]; | ||||||
|  | #else | ||||||
|  | #define TEST_FAIL_AT(point) | ||||||
|  | #define TEST_FAIL_EXTERN_VARS | ||||||
|  | #endif // ENABLE_FAILURE_TESTING
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static const char                  VHD_POISON_COOKIE[] = "v_poison"; | ||||||
|  | 
 | ||||||
|  | typedef struct hd_ftr              vhd_footer_t; | ||||||
|  | typedef struct dd_hdr              vhd_header_t; | ||||||
|  | typedef struct vhd_bat             vhd_bat_t; | ||||||
|  | typedef struct vhd_batmap          vhd_batmap_t; | ||||||
|  | typedef struct dd_batmap_hdr       vhd_batmap_header_t; | ||||||
|  | typedef struct prt_loc             vhd_parent_locator_t; | ||||||
|  | typedef struct vhd_context         vhd_context_t; | ||||||
|  | typedef uint32_t                   vhd_flag_creat_t; | ||||||
|  | 
 | ||||||
|  | struct vhd_bat { | ||||||
|  | 	uint32_t                   spb; | ||||||
|  | 	uint32_t                   entries; | ||||||
|  | 	uint32_t                  *bat; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct vhd_batmap { | ||||||
|  | 	vhd_batmap_header_t        header; | ||||||
|  | 	char                      *map; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct vhd_context { | ||||||
|  | 	int                        fd; | ||||||
|  | 	char                      *file; | ||||||
|  | 	int                        oflags; | ||||||
|  | 	int                        is_block; | ||||||
|  | 
 | ||||||
|  | 	uint32_t                   spb; | ||||||
|  | 	uint32_t                   bm_secs; | ||||||
|  | 
 | ||||||
|  | 	vhd_header_t               header; | ||||||
|  | 	vhd_footer_t               footer; | ||||||
|  | 	vhd_bat_t                  bat; | ||||||
|  | 	vhd_batmap_t               batmap; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static inline uint32_t | ||||||
|  | secs_round_up(uint64_t bytes) | ||||||
|  | { | ||||||
|  | 	return ((bytes + (VHD_SECTOR_SIZE - 1)) >> VHD_SECTOR_SHIFT); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline uint32_t | ||||||
|  | secs_round_up_no_zero(uint64_t bytes) | ||||||
|  | { | ||||||
|  | 	return (secs_round_up(bytes) ? : 1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline uint64_t | ||||||
|  | vhd_sectors_to_bytes(uint64_t sectors) | ||||||
|  | { | ||||||
|  | 	return sectors << VHD_SECTOR_SHIFT; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline uint64_t | ||||||
|  | vhd_bytes_padded(uint64_t bytes) | ||||||
|  | { | ||||||
|  | 	return vhd_sectors_to_bytes(secs_round_up_no_zero(bytes)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline int | ||||||
|  | vhd_type_dynamic(vhd_context_t *ctx) | ||||||
|  | { | ||||||
|  | 	return (ctx->footer.type == HD_TYPE_DYNAMIC || | ||||||
|  | 		ctx->footer.type == HD_TYPE_DIFF); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline int | ||||||
|  | vhd_creator_tapdisk(vhd_context_t *ctx) | ||||||
|  | { | ||||||
|  | 	return !strncmp(ctx->footer.crtr_app, "tap", 3); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline int | ||||||
|  | vhd_disabled(vhd_context_t *ctx) | ||||||
|  | { | ||||||
|  | 	return (!memcmp(ctx->footer.cookie, | ||||||
|  | 			VHD_POISON_COOKIE, sizeof(ctx->footer.cookie))); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline size_t | ||||||
|  | vhd_parent_locator_size(vhd_parent_locator_t *loc) | ||||||
|  | { | ||||||
|  | 	/*
 | ||||||
|  | 	 * MICROSOFT_COMPAT | ||||||
|  | 	 * data_space *should* be in sectors, | ||||||
|  | 	 * but sometimes we find it in bytes | ||||||
|  | 	 */ | ||||||
|  | 	if (loc->data_space < 512) | ||||||
|  | 		return vhd_sectors_to_bytes(loc->data_space); | ||||||
|  | 	else if (loc->data_space % 512 == 0) | ||||||
|  | 		return loc->data_space; | ||||||
|  | 	else | ||||||
|  | 		return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline int | ||||||
|  | vhd_parent_raw(vhd_context_t *ctx) | ||||||
|  | { | ||||||
|  | 	return blk_uuid_is_nil(&ctx->header.prt_uuid); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void libvhd_set_log_level(int); | ||||||
|  | 
 | ||||||
|  | int vhd_test_file_fixed(const char *, int *); | ||||||
|  | 
 | ||||||
|  | uint32_t vhd_time(time_t time); | ||||||
|  | size_t vhd_time_to_string(uint32_t timestamp, char *target); | ||||||
|  | uint32_t vhd_chs(uint64_t size); | ||||||
|  | 
 | ||||||
|  | uint32_t vhd_checksum_footer(vhd_footer_t *); | ||||||
|  | uint32_t vhd_checksum_header(vhd_header_t *); | ||||||
|  | uint32_t vhd_checksum_batmap(vhd_batmap_t *); | ||||||
|  | 
 | ||||||
|  | void vhd_footer_in(vhd_footer_t *); | ||||||
|  | void vhd_footer_out(vhd_footer_t *); | ||||||
|  | void vhd_header_in(vhd_header_t *); | ||||||
|  | void vhd_header_out(vhd_header_t *); | ||||||
|  | void vhd_bat_in(vhd_bat_t *); | ||||||
|  | void vhd_bat_out(vhd_bat_t *); | ||||||
|  | void vhd_batmap_header_in(vhd_batmap_t *); | ||||||
|  | void vhd_batmap_header_out(vhd_batmap_t *); | ||||||
|  | 
 | ||||||
|  | int vhd_validate_footer(vhd_footer_t *footer); | ||||||
|  | int vhd_validate_header(vhd_header_t *header); | ||||||
|  | int vhd_validate_batmap_header(vhd_batmap_t *batmap); | ||||||
|  | int vhd_validate_batmap(vhd_batmap_t *batmap); | ||||||
|  | int vhd_validate_platform_code(uint32_t code); | ||||||
|  | 
 | ||||||
|  | int vhd_open(vhd_context_t *, const char *file, int flags); | ||||||
|  | void vhd_close(vhd_context_t *); | ||||||
|  | int vhd_create(const char *name, uint64_t bytes, int type, vhd_flag_creat_t); | ||||||
|  | /* vhd_snapshot: the bytes parameter is optional and can be 0 if the snapshot 
 | ||||||
|  |  * is to have the same size as the (first non-empty) parent */ | ||||||
|  | int vhd_snapshot(const char *snapshot, uint64_t bytes, const char *parent, | ||||||
|  | 		vhd_flag_creat_t); | ||||||
|  | 
 | ||||||
|  | int vhd_hidden(vhd_context_t *, int *); | ||||||
|  | int vhd_chain_depth(vhd_context_t *, int *); | ||||||
|  | 
 | ||||||
|  | off_t vhd_position(vhd_context_t *); | ||||||
|  | int vhd_seek(vhd_context_t *, off_t, int); | ||||||
|  | int vhd_read(vhd_context_t *, void *, size_t); | ||||||
|  | int vhd_write(vhd_context_t *, void *, size_t); | ||||||
|  | 
 | ||||||
|  | int vhd_offset(vhd_context_t *, uint32_t, uint32_t *); | ||||||
|  | 
 | ||||||
|  | int vhd_end_of_headers(vhd_context_t *ctx, off_t *off); | ||||||
|  | int vhd_end_of_data(vhd_context_t *ctx, off_t *off); | ||||||
|  | int vhd_batmap_header_offset(vhd_context_t *ctx, off_t *off); | ||||||
|  | 
 | ||||||
|  | int vhd_get_header(vhd_context_t *); | ||||||
|  | int vhd_get_footer(vhd_context_t *); | ||||||
|  | int vhd_get_bat(vhd_context_t *); | ||||||
|  | int vhd_get_batmap(vhd_context_t *); | ||||||
|  | 
 | ||||||
|  | void vhd_put_header(vhd_context_t *); | ||||||
|  | void vhd_put_footer(vhd_context_t *); | ||||||
|  | void vhd_put_bat(vhd_context_t *); | ||||||
|  | void vhd_put_batmap(vhd_context_t *); | ||||||
|  | 
 | ||||||
|  | int vhd_has_batmap(vhd_context_t *); | ||||||
|  | int vhd_batmap_test(vhd_context_t *, vhd_batmap_t *, uint32_t); | ||||||
|  | void vhd_batmap_set(vhd_context_t *, vhd_batmap_t *, uint32_t); | ||||||
|  | void vhd_batmap_clear(vhd_context_t *, vhd_batmap_t *, uint32_t); | ||||||
|  | 
 | ||||||
|  | int vhd_get_phys_size(vhd_context_t *, off_t *); | ||||||
|  | int vhd_set_phys_size(vhd_context_t *, off_t); | ||||||
|  | 
 | ||||||
|  | int vhd_bitmap_test(vhd_context_t *, char *, uint32_t); | ||||||
|  | void vhd_bitmap_set(vhd_context_t *, char *, uint32_t); | ||||||
|  | void vhd_bitmap_clear(vhd_context_t *, char *, uint32_t); | ||||||
|  | 
 | ||||||
|  | int vhd_parent_locator_count(vhd_context_t *); | ||||||
|  | int vhd_parent_locator_get(vhd_context_t *, char **); | ||||||
|  | int vhd_parent_locator_read(vhd_context_t *, vhd_parent_locator_t *, char **); | ||||||
|  | int vhd_find_parent(vhd_context_t *, const char *, char **); | ||||||
|  | int vhd_parent_locator_write_at(vhd_context_t *, const char *, | ||||||
|  | 				off_t, uint32_t, size_t, | ||||||
|  | 				vhd_parent_locator_t *); | ||||||
|  | 
 | ||||||
|  | int vhd_header_decode_parent(vhd_context_t *, vhd_header_t *, char **); | ||||||
|  | int vhd_change_parent(vhd_context_t *, char *parent_path, int raw); | ||||||
|  | 
 | ||||||
|  | int vhd_read_footer(vhd_context_t *, vhd_footer_t *); | ||||||
|  | int vhd_read_footer_at(vhd_context_t *, vhd_footer_t *, off_t); | ||||||
|  | int vhd_read_footer_strict(vhd_context_t *, vhd_footer_t *); | ||||||
|  | int vhd_read_header(vhd_context_t *, vhd_header_t *); | ||||||
|  | int vhd_read_header_at(vhd_context_t *, vhd_header_t *, off_t); | ||||||
|  | int vhd_read_bat(vhd_context_t *, vhd_bat_t *); | ||||||
|  | int vhd_read_batmap(vhd_context_t *, vhd_batmap_t *); | ||||||
|  | int vhd_read_bitmap(vhd_context_t *, uint32_t block, char **bufp); | ||||||
|  | int vhd_read_block(vhd_context_t *, uint32_t block, char **bufp); | ||||||
|  | 
 | ||||||
|  | int vhd_write_footer(vhd_context_t *, vhd_footer_t *); | ||||||
|  | int vhd_write_footer_at(vhd_context_t *, vhd_footer_t *, off_t); | ||||||
|  | int vhd_write_header(vhd_context_t *, vhd_header_t *); | ||||||
|  | int vhd_write_header_at(vhd_context_t *, vhd_header_t *, off_t); | ||||||
|  | int vhd_write_bat(vhd_context_t *, vhd_bat_t *); | ||||||
|  | int vhd_write_batmap(vhd_context_t *, vhd_batmap_t *); | ||||||
|  | int vhd_write_bitmap(vhd_context_t *, uint32_t block, char *bitmap); | ||||||
|  | int vhd_write_block(vhd_context_t *, uint32_t block, char *data); | ||||||
|  | 
 | ||||||
|  | int vhd_io_read(vhd_context_t *, char *, uint64_t, uint32_t); | ||||||
|  | int vhd_io_write(vhd_context_t *, char *, uint64_t, uint32_t); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
							
								
								
									
										124
									
								
								tools/vhd-tools/include/list.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								tools/vhd-tools/include/list.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,124 @@ | |||||||
|  | /*
 | ||||||
|  |  * list.h | ||||||
|  |  *  | ||||||
|  |  * This is a subset of linux's list.h intended to be used in user-space. | ||||||
|  |  * XXX The namespace conflicts with NetBSD's <sys/queue.h> | ||||||
|  |  *  | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef __LIST_H__ | ||||||
|  | #define __LIST_H__ | ||||||
|  | 
 | ||||||
|  | #define LIST_POISON1  ((void *) 0x00100100) | ||||||
|  | #define LIST_POISON2  ((void *) 0x00200200) | ||||||
|  | 
 | ||||||
|  | struct list_head { | ||||||
|  |         struct list_head *next, *prev; | ||||||
|  | }; | ||||||
|  |   | ||||||
|  | /* XXX workaround for conflicts. The list API should use its own
 | ||||||
|  |  * namespace prefix, i.e. BLK_ | ||||||
|  |  */ | ||||||
|  | #ifdef LIST_HEAD_INIT | ||||||
|  | #undef LIST_HEAD_INIT | ||||||
|  | #endif | ||||||
|  | #ifndef LIST_HEAD | ||||||
|  | #undef LIST_HEAD | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #define LIST_HEAD_INIT(name) { &(name), &(name) } | ||||||
|  |   | ||||||
|  | #define LIST_HEAD(name) \ | ||||||
|  |         struct list_head name = LIST_HEAD_INIT(name) | ||||||
|  | 
 | ||||||
|  | static inline void INIT_LIST_HEAD(struct list_head *list) | ||||||
|  | { | ||||||
|  | 	list->next = list; | ||||||
|  | 	list->prev = list; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void __list_add(struct list_head *new, | ||||||
|  |                               struct list_head *prev, | ||||||
|  |                               struct list_head *next) | ||||||
|  | { | ||||||
|  |         next->prev = new; | ||||||
|  |         new->next = next; | ||||||
|  |         new->prev = prev; | ||||||
|  |         prev->next = new; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void list_add(struct list_head *new, struct list_head *head) | ||||||
|  | { | ||||||
|  |         __list_add(new, head, head->next); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void list_add_tail(struct list_head *new, struct list_head *head) | ||||||
|  | { | ||||||
|  | 	__list_add(new, head->prev, head); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void __list_del(struct list_head * prev, struct list_head * next) | ||||||
|  | { | ||||||
|  |         next->prev = prev; | ||||||
|  |         prev->next = next; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void list_del(struct list_head *entry) | ||||||
|  | { | ||||||
|  |         __list_del(entry->prev, entry->next); | ||||||
|  |         entry->next = LIST_POISON1; | ||||||
|  |         entry->prev = LIST_POISON2; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void list_del_init(struct list_head *entry) | ||||||
|  | { | ||||||
|  | 	__list_del(entry->prev, entry->next); | ||||||
|  | 	INIT_LIST_HEAD(entry); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline int list_empty(const struct list_head *head) | ||||||
|  | { | ||||||
|  | 	return head->next == head; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline int list_is_last(const struct list_head *list, | ||||||
|  | 			       const struct list_head *head) | ||||||
|  | { | ||||||
|  | 	return list->next == head; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void __list_splice(struct list_head *list, | ||||||
|  | 				 struct list_head *head) | ||||||
|  | { | ||||||
|  | 	struct list_head *first = list->next; | ||||||
|  | 	struct list_head *last = list->prev; | ||||||
|  | 	struct list_head *at = head->next; | ||||||
|  | 
 | ||||||
|  | 	first->prev = head; | ||||||
|  | 	head->next = first; | ||||||
|  | 
 | ||||||
|  | 	last->next = at; | ||||||
|  | 	at->prev = last; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void list_splice(struct list_head *list, struct list_head *head) | ||||||
|  | { | ||||||
|  | 	if (!list_empty(list)) | ||||||
|  | 		__list_splice(list, head); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #define list_entry(ptr, type, member)                                   \ | ||||||
|  |         ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) | ||||||
|  | 
 | ||||||
|  | #define list_for_each_entry(pos, head, member)                          \ | ||||||
|  |         for (pos = list_entry((head)->next, typeof(*pos), member);      \ | ||||||
|  |              &pos->member != (head);                                    \ | ||||||
|  |              pos = list_entry(pos->member.next, typeof(*pos), member)) | ||||||
|  | 
 | ||||||
|  | #define list_for_each_entry_safe(pos, n, head, member)			\ | ||||||
|  | 	for (pos = list_entry((head)->next, typeof(*pos), member),	\ | ||||||
|  | 	       n = list_entry(pos->member.next, typeof(*pos), member);	\ | ||||||
|  | 	     &pos->member != (head); 					\ | ||||||
|  | 	     pos = n, n = list_entry(n->member.next, typeof(*n), member)) | ||||||
|  | 
 | ||||||
|  | #endif /* __LIST_H__ */ | ||||||
							
								
								
									
										71
									
								
								tools/vhd-tools/include/lvm-util.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								tools/vhd-tools/include/lvm-util.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,71 @@ | |||||||
|  | /* 
 | ||||||
|  |  * Copyright (c) 2008, XenSource Inc. | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of XenSource Inc. nor the names of its contributors | ||||||
|  |  *       may be used to endorse or promote products derived from this software | ||||||
|  |  *       without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||||||
|  |  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||||
|  |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||||
|  |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||||
|  |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||||
|  |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||||
|  |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | #ifndef _LVM_UTIL_H_ | ||||||
|  | #define _LVM_UTIL_H_ | ||||||
|  | 
 | ||||||
|  | #include <inttypes.h> | ||||||
|  | 
 | ||||||
|  | #define MAX_NAME_SIZE            256 | ||||||
|  | 
 | ||||||
|  | #define LVM_SEG_TYPE_LINEAR      1 | ||||||
|  | #define LVM_SEG_TYPE_UNKNOWN     2 | ||||||
|  | 
 | ||||||
|  | struct lv_segment { | ||||||
|  | 	uint8_t                  type; | ||||||
|  | 	char                     device[MAX_NAME_SIZE]; | ||||||
|  | 	uint64_t                 pe_start; | ||||||
|  | 	uint64_t                 pe_size; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct lv { | ||||||
|  | 	char                     name[MAX_NAME_SIZE]; | ||||||
|  | 	uint64_t                 size; | ||||||
|  | 	uint32_t                 segments; | ||||||
|  | 	struct lv_segment        first_segment; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct pv { | ||||||
|  | 	char                     name[MAX_NAME_SIZE]; | ||||||
|  | 	uint64_t                 start; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct vg { | ||||||
|  | 	char                     name[MAX_NAME_SIZE]; | ||||||
|  | 	uint64_t                 extent_size; | ||||||
|  | 
 | ||||||
|  | 	int                      pv_cnt; | ||||||
|  | 	struct pv               *pvs; | ||||||
|  | 
 | ||||||
|  | 	int                      lv_cnt; | ||||||
|  | 	struct lv               *lvs; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | int lvm_scan_vg(const char *vg_name, struct vg *vg); | ||||||
|  | void lvm_free_vg(struct vg *vg); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
							
								
								
									
										43
									
								
								tools/vhd-tools/include/relative-path.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								tools/vhd-tools/include/relative-path.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | |||||||
|  | /* Copyright (c) 2008, XenSource Inc.
 | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of XenSource Inc. nor the names of its contributors | ||||||
|  |  *       may be used to endorse or promote products derived from this software | ||||||
|  |  *       without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||||||
|  |  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||||
|  |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||||
|  |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||||
|  |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||||
|  |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||||
|  |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | */ | ||||||
|  | #ifndef _RELATIVE_PATH_H_ | ||||||
|  | #define _RELATIVE_PATH_H_ | ||||||
|  | 
 | ||||||
|  | #include <syslog.h> | ||||||
|  | 
 | ||||||
|  | #define DELIMITER    '/' | ||||||
|  | #define MAX_NAME_LEN 1000 | ||||||
|  | 
 | ||||||
|  | #define EPRINTF(_f, _a...) syslog(LOG_ERR, "tap-err:%s: " _f, __func__, ##_a) | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * returns a relative path from @src to @dest | ||||||
|  |  * result should be freed | ||||||
|  |  */ | ||||||
|  | char *relative_path_to(char *src, char *dest, int *err); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
							
								
								
									
										141
									
								
								tools/vhd-tools/include/tapdisk-message.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								tools/vhd-tools/include/tapdisk-message.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,141 @@ | |||||||
|  | /* Copyright (c) 2008, XenSource Inc.
 | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of XenSource Inc. nor the names of its contributors | ||||||
|  |  *       may be used to endorse or promote products derived from this software | ||||||
|  |  *       without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||||||
|  |  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||||
|  |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||||
|  |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||||
|  |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||||
|  |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||||
|  |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | */ | ||||||
|  | #ifndef _TAPDISK_MESSAGE_H_ | ||||||
|  | #define _TAPDISK_MESSAGE_H_ | ||||||
|  | 
 | ||||||
|  | #include <inttypes.h> | ||||||
|  | 
 | ||||||
|  | #define TAPDISK_MESSAGE_MAX_PATH_LENGTH  256 | ||||||
|  | #define TAPDISK_MESSAGE_STRING_LENGTH    256 | ||||||
|  | 
 | ||||||
|  | #define TAPDISK_MESSAGE_FLAG_SHARED      0x01 | ||||||
|  | #define TAPDISK_MESSAGE_FLAG_RDONLY      0x02 | ||||||
|  | #define TAPDISK_MESSAGE_FLAG_ADD_CACHE   0x04 | ||||||
|  | #define TAPDISK_MESSAGE_FLAG_VHD_INDEX   0x08 | ||||||
|  | #define TAPDISK_MESSAGE_FLAG_LOG_DIRTY   0x10 | ||||||
|  | 
 | ||||||
|  | typedef struct tapdisk_message           tapdisk_message_t; | ||||||
|  | typedef uint8_t                          tapdisk_message_flag_t; | ||||||
|  | typedef struct tapdisk_message_image     tapdisk_message_image_t; | ||||||
|  | typedef struct tapdisk_message_params    tapdisk_message_params_t; | ||||||
|  | typedef struct tapdisk_message_string    tapdisk_message_string_t; | ||||||
|  | 
 | ||||||
|  | struct tapdisk_message_params { | ||||||
|  | 	tapdisk_message_flag_t           flags; | ||||||
|  | 	 | ||||||
|  | 	uint8_t                          storage; | ||||||
|  | 	uint32_t                         devnum; | ||||||
|  | 	uint32_t                         domid; | ||||||
|  | 	uint16_t                         path_len; | ||||||
|  | 	char                             path[TAPDISK_MESSAGE_MAX_PATH_LENGTH]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct tapdisk_message_image { | ||||||
|  | 	uint64_t                         sectors; | ||||||
|  | 	uint32_t                         sector_size; | ||||||
|  | 	uint32_t                         info; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct tapdisk_message_string { | ||||||
|  | 	char                             text[TAPDISK_MESSAGE_STRING_LENGTH]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct tapdisk_message { | ||||||
|  | 	uint16_t                         type; | ||||||
|  | 	uint16_t                         cookie; | ||||||
|  | 	uint16_t                         drivertype; | ||||||
|  | 
 | ||||||
|  | 	union { | ||||||
|  | 		pid_t                    tapdisk_pid; | ||||||
|  | 		tapdisk_message_image_t  image; | ||||||
|  | 		tapdisk_message_params_t params; | ||||||
|  | 		tapdisk_message_string_t string; | ||||||
|  | 	} u; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum tapdisk_message_id { | ||||||
|  | 	TAPDISK_MESSAGE_ERROR = 1, | ||||||
|  | 	TAPDISK_MESSAGE_RUNTIME_ERROR, | ||||||
|  | 	TAPDISK_MESSAGE_PID, | ||||||
|  | 	TAPDISK_MESSAGE_PID_RSP, | ||||||
|  | 	TAPDISK_MESSAGE_OPEN, | ||||||
|  | 	TAPDISK_MESSAGE_OPEN_RSP, | ||||||
|  | 	TAPDISK_MESSAGE_PAUSE, | ||||||
|  | 	TAPDISK_MESSAGE_PAUSE_RSP, | ||||||
|  | 	TAPDISK_MESSAGE_RESUME, | ||||||
|  | 	TAPDISK_MESSAGE_RESUME_RSP, | ||||||
|  | 	TAPDISK_MESSAGE_CLOSE, | ||||||
|  | 	TAPDISK_MESSAGE_CLOSE_RSP, | ||||||
|  | 	TAPDISK_MESSAGE_EXIT, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static inline char * | ||||||
|  | tapdisk_message_name(enum tapdisk_message_id id) | ||||||
|  | { | ||||||
|  | 	switch (id) { | ||||||
|  | 	case TAPDISK_MESSAGE_ERROR: | ||||||
|  | 		return "error"; | ||||||
|  | 
 | ||||||
|  | 	case TAPDISK_MESSAGE_PID: | ||||||
|  | 		return "pid"; | ||||||
|  | 
 | ||||||
|  | 	case TAPDISK_MESSAGE_PID_RSP: | ||||||
|  | 		return "pid response"; | ||||||
|  | 
 | ||||||
|  | 	case TAPDISK_MESSAGE_OPEN: | ||||||
|  | 		return "open"; | ||||||
|  | 
 | ||||||
|  | 	case TAPDISK_MESSAGE_OPEN_RSP: | ||||||
|  | 		return "open response"; | ||||||
|  | 
 | ||||||
|  | 	case TAPDISK_MESSAGE_PAUSE: | ||||||
|  | 		return "pause"; | ||||||
|  | 
 | ||||||
|  | 	case TAPDISK_MESSAGE_PAUSE_RSP: | ||||||
|  | 		return "pause response"; | ||||||
|  | 
 | ||||||
|  | 	case TAPDISK_MESSAGE_RESUME: | ||||||
|  | 		return "resume"; | ||||||
|  | 
 | ||||||
|  | 	case TAPDISK_MESSAGE_RESUME_RSP: | ||||||
|  | 		return "resume response"; | ||||||
|  | 
 | ||||||
|  | 	case TAPDISK_MESSAGE_CLOSE: | ||||||
|  | 		return "close"; | ||||||
|  | 
 | ||||||
|  | 	case TAPDISK_MESSAGE_CLOSE_RSP: | ||||||
|  | 		return "close response"; | ||||||
|  | 
 | ||||||
|  | 	case TAPDISK_MESSAGE_EXIT: | ||||||
|  | 		return "exit"; | ||||||
|  | 
 | ||||||
|  | 	default: | ||||||
|  | 		return "unknown"; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
							
								
								
									
										44
									
								
								tools/vhd-tools/include/vhd-util.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								tools/vhd-tools/include/vhd-util.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,44 @@ | |||||||
|  | /* Copyright (c) 2008, XenSource Inc.
 | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of XenSource Inc. nor the names of its contributors | ||||||
|  |  *       may be used to endorse or promote products derived from this software | ||||||
|  |  *       without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||||||
|  |  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||||
|  |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||||
|  |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||||
|  |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||||
|  |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||||
|  |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | */ | ||||||
|  | #ifndef _VHD_UTIL_H_ | ||||||
|  | #define _VHD_UTIL_H_ | ||||||
|  | 
 | ||||||
|  | int vhd_util_create(int argc, char **argv); | ||||||
|  | int vhd_util_snapshot(int argc, char **argv); | ||||||
|  | int vhd_util_query(int argc, char **argv); | ||||||
|  | int vhd_util_read(int argc, char **argv); | ||||||
|  | int vhd_util_set_field(int argc, char **argv); | ||||||
|  | int vhd_util_repair(int argc, char **argv); | ||||||
|  | int vhd_util_fill(int argc, char **argv); | ||||||
|  | int vhd_util_resize(int argc, char **argv); | ||||||
|  | int vhd_util_coalesce(int argc, char **argv); | ||||||
|  | int vhd_util_modify(int argc, char **argv); | ||||||
|  | int vhd_util_scan(int argc, char **argv); | ||||||
|  | int vhd_util_check(int argc, char **argv); | ||||||
|  | int vhd_util_revert(int argc, char **argv); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
							
								
								
									
										219
									
								
								tools/vhd-tools/include/vhd.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										219
									
								
								tools/vhd-tools/include/vhd.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,219 @@ | |||||||
|  | /* Copyright (c) 2008, XenSource Inc.
 | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of XenSource Inc. nor the names of its contributors | ||||||
|  |  *       may be used to endorse or promote products derived from this software | ||||||
|  |  *       without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||||||
|  |  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||||
|  |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||||
|  |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||||
|  |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||||
|  |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||||
|  |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | */ | ||||||
|  | #ifndef __VHD_H__ | ||||||
|  | #define __VHD_H__ | ||||||
|  | 
 | ||||||
|  | #include <inttypes.h> | ||||||
|  | 
 | ||||||
|  | typedef uint32_t u32; | ||||||
|  | typedef uint64_t u64; | ||||||
|  | 
 | ||||||
|  | #define DEBUG 1 | ||||||
|  | 
 | ||||||
|  | /* ---------------------------------------------------------------------- */ | ||||||
|  | /* General definitions.                                                   */ | ||||||
|  | /* ---------------------------------------------------------------------- */ | ||||||
|  | 
 | ||||||
|  | #define VHD_SECTOR_SIZE  512 | ||||||
|  | #define VHD_SECTOR_SHIFT   9 | ||||||
|  | 
 | ||||||
|  | /* ---------------------------------------------------------------------- */ | ||||||
|  | /* This is the generic disk footer, used by all disks.                    */ | ||||||
|  | /* ---------------------------------------------------------------------- */ | ||||||
|  | 
 | ||||||
|  | struct hd_ftr { | ||||||
|  |   char   cookie[8];       /* Identifies original creator of the disk      */ | ||||||
|  |   u32    features;        /* Feature Support -- see below                 */ | ||||||
|  |   u32    ff_version;      /* (major,minor) version of disk file           */ | ||||||
|  |   u64    data_offset;     /* Abs. offset from SOF to next structure       */ | ||||||
|  |   u32    timestamp;       /* Creation time.  secs since 1/1/2000GMT       */ | ||||||
|  |   char   crtr_app[4];     /* Creator application                          */ | ||||||
|  |   u32    crtr_ver;        /* Creator version (major,minor)                */ | ||||||
|  |   u32    crtr_os;         /* Creator host OS                              */ | ||||||
|  |   u64    orig_size;       /* Size at creation (bytes)                     */ | ||||||
|  |   u64    curr_size;       /* Current size of disk (bytes)                 */ | ||||||
|  |   u32    geometry;        /* Disk geometry                                */ | ||||||
|  |   u32    type;            /* Disk type                                    */ | ||||||
|  |   u32    checksum;        /* 1's comp sum of this struct.                 */ | ||||||
|  |   blk_uuid_t uuid;        /* Unique disk ID, used for naming parents      */ | ||||||
|  |   char   saved;           /* one-bit -- is this disk/VM in a saved state? */ | ||||||
|  |   char   hidden;          /* tapdisk-specific field: is this vdi hidden?  */ | ||||||
|  |   char   reserved[426];   /* padding                                      */ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* VHD cookie string. */ | ||||||
|  | static const char HD_COOKIE[9]  =  "conectix"; | ||||||
|  | 
 | ||||||
|  | /* Feature fields in hd_ftr */ | ||||||
|  | #define HD_NO_FEATURES     0x00000000 | ||||||
|  | #define HD_TEMPORARY       0x00000001 /* disk can be deleted on shutdown */ | ||||||
|  | #define HD_RESERVED        0x00000002 /* NOTE: must always be set        */ | ||||||
|  | 
 | ||||||
|  | /* Version field in hd_ftr */ | ||||||
|  | #define HD_FF_VERSION      0x00010000 | ||||||
|  | 
 | ||||||
|  | /* Known creator OS type fields in hd_ftr.crtr_os */ | ||||||
|  | #define HD_CR_OS_WINDOWS   0x5769326B /* (Wi2k) */ | ||||||
|  | #define HD_CR_OS_MACINTOSH 0x4D616320 /* (Mac ) */ | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * version 0.1:  little endian bitmaps | ||||||
|  |  * version 1.1:  big endian bitmaps; batmap | ||||||
|  |  * version 1.2:  libvhd | ||||||
|  |  * version 1.3:  batmap version bump to 1.2 | ||||||
|  |  */ | ||||||
|  | #define VHD_VERSION(major, minor)  (((major) << 16) | ((minor) & 0x0000FFFF)) | ||||||
|  | #define VHD_CURRENT_VERSION        VHD_VERSION(1, 3) | ||||||
|  | 
 | ||||||
|  | /* Disk geometry accessor macros. */ | ||||||
|  | /* Geometry is a triple of (cylinders (2 bytes), tracks (1 byte), and 
 | ||||||
|  |  * secotrs-per-track (1 byte))  | ||||||
|  |  */ | ||||||
|  | #define GEOM_GET_CYLS(_g)  (((_g) >> 16) & 0xffff) | ||||||
|  | #define GEOM_GET_HEADS(_g) (((_g) >> 8)  & 0xff) | ||||||
|  | #define GEOM_GET_SPT(_g)   ((_g) & 0xff) | ||||||
|  | 
 | ||||||
|  | #define GEOM_ENCODE(_c, _h, _s) (((_c) << 16) | ((_h) << 8) | (_s)) | ||||||
|  | 
 | ||||||
|  | /* type field in hd_ftr */ | ||||||
|  | #define HD_TYPE_NONE       0 | ||||||
|  | #define HD_TYPE_FIXED      2  /* fixed-allocation disk */ | ||||||
|  | #define HD_TYPE_DYNAMIC    3  /* dynamic disk */ | ||||||
|  | #define HD_TYPE_DIFF       4  /* differencing disk */ | ||||||
|  | 
 | ||||||
|  | /* String table for hd.type */ | ||||||
|  | static const char *HD_TYPE_STR[7] = { | ||||||
|  |         "None",                    /* 0 */ | ||||||
|  |         "Reserved (deprecated)",   /* 1 */ | ||||||
|  |         "Fixed hard disk",         /* 2 */ | ||||||
|  |         "Dynamic hard disk",       /* 3 */ | ||||||
|  |         "Differencing hard disk",  /* 4 */ | ||||||
|  |         "Reserved (deprecated)",   /* 5 */ | ||||||
|  |         "Reserved (deprecated)"    /* 6 */ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #define HD_TYPE_MAX 6 | ||||||
|  | 
 | ||||||
|  | struct prt_loc { | ||||||
|  |   u32    code;            /* Platform code -- see defines below.          */ | ||||||
|  |   u32    data_space;      /* Number of 512-byte sectors to store locator  */ | ||||||
|  |   u32    data_len;        /* Actual length of parent locator in bytes     */ | ||||||
|  |   u32    res;             /* Must be zero                                 */ | ||||||
|  |   u64    data_offset;     /* Absolute offset of locator data (bytes)      */ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* Platform Codes */ | ||||||
|  | #define PLAT_CODE_NONE  0x0 | ||||||
|  | #define PLAT_CODE_WI2R  0x57693272  /* deprecated                         */ | ||||||
|  | #define PLAT_CODE_WI2K  0x5769326B  /* deprecated                         */ | ||||||
|  | #define PLAT_CODE_W2RU  0x57327275  /* Windows relative path (UTF-16)     */ | ||||||
|  | #define PLAT_CODE_W2KU  0x57326B75  /* Windows absolute path (UTF-16)     */ | ||||||
|  | #define PLAT_CODE_MAC   0x4D616320  /* MacOS alias stored as a blob.      */ | ||||||
|  | #define PLAT_CODE_MACX  0x4D616358  /* File URL (UTF-8), see RFC 2396.    */ | ||||||
|  | 
 | ||||||
|  | /* ---------------------------------------------------------------------- */ | ||||||
|  | /* This is the dynamic disk header.                                       */ | ||||||
|  | /* ---------------------------------------------------------------------- */ | ||||||
|  | 
 | ||||||
|  | struct dd_hdr { | ||||||
|  |   char   cookie[8];       /* Should contain "cxsparse"                    */ | ||||||
|  |   u64    data_offset;     /* Byte offset of next record. (Unused) 0xffs   */ | ||||||
|  |   u64    table_offset;    /* Absolute offset to the BAT.                  */ | ||||||
|  |   u32    hdr_ver;         /* Version of the dd_hdr (major,minor)          */ | ||||||
|  |   u32    max_bat_size;    /* Maximum number of entries in the BAT         */ | ||||||
|  |   u32    block_size;      /* Block size in bytes. Must be power of 2.     */ | ||||||
|  |   u32    checksum;        /* Header checksum.  1's comp of all fields.    */ | ||||||
|  |   blk_uuid_t prt_uuid;    /* ID of the parent disk.                       */ | ||||||
|  |   u32    prt_ts;          /* Modification time of the parent disk         */ | ||||||
|  |   u32    res1;            /* Reserved.                                    */ | ||||||
|  |   char   prt_name[512];   /* Parent unicode name.                         */ | ||||||
|  |   struct prt_loc loc[8];  /* Parent locator entries.                      */ | ||||||
|  |   char   res2[256];       /* Reserved.                                    */ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* VHD cookie string. */ | ||||||
|  | static const char DD_COOKIE[9]  =  "cxsparse"; | ||||||
|  | 
 | ||||||
|  | /* Version field in hd_ftr */ | ||||||
|  | #define DD_VERSION 0x00010000 | ||||||
|  | 
 | ||||||
|  | /* Default blocksize is 2 meg. */ | ||||||
|  | #define DD_BLOCKSIZE_DEFAULT 0x00200000 | ||||||
|  | 
 | ||||||
|  | #define DD_BLK_UNUSED 0xFFFFFFFF | ||||||
|  | 
 | ||||||
|  | struct dd_batmap_hdr { | ||||||
|  |   char   cookie[8];       /* should contain "tdbatmap"                    */ | ||||||
|  |   u64    batmap_offset;   /* byte offset to batmap                        */ | ||||||
|  |   u32    batmap_size;     /* batmap size in sectors                       */ | ||||||
|  |   u32    batmap_version;  /* version of batmap                            */ | ||||||
|  |   u32    checksum;        /* batmap checksum -- 1's complement of batmap  */ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const char VHD_BATMAP_COOKIE[9] = "tdbatmap"; | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * version 1.1: signed char checksum | ||||||
|  |  */ | ||||||
|  | #define VHD_BATMAP_VERSION(major, minor)  (((major) << 16) | ((minor) & 0x0000FFFF)) | ||||||
|  | #define VHD_BATMAP_CURRENT_VERSION        VHD_BATMAP_VERSION(1, 2) | ||||||
|  | 
 | ||||||
|  | /* Layout of a dynamic disk:
 | ||||||
|  |  * | ||||||
|  |  * +-------------------------------------------------+ | ||||||
|  |  * | Mirror image of HD footer (hd_ftr) (512 bytes)  | | ||||||
|  |  * +-------------------------------------------------+ | ||||||
|  |  * | Sparse drive header (dd_hdr) (1024 bytes)       | | ||||||
|  |  * +-------------------------------------------------+ | ||||||
|  |  * | BAT (Block allocation table)                    | | ||||||
|  |  * |   - Array of absolute sector offsets into the   | | ||||||
|  |  * |     file (u32).                                 | | ||||||
|  |  * |   - Rounded up to a sector boundary.            | | ||||||
|  |  * |   - Unused entries are marked as 0xFFFFFFFF     | | ||||||
|  |  * |   - max entries in dd_hdr->max_bat_size         | | ||||||
|  |  * +-------------------------------------------------+ | ||||||
|  |  * | Data Block 0                                    | | ||||||
|  |  * | Bitmap (padded to 512 byte sector boundary)     | | ||||||
|  |  * |   - each bit indicates whether the associated   | | ||||||
|  |  * |     sector within this block is used.           | | ||||||
|  |  * | Data                                            | | ||||||
|  |  * |   - power-of-two multiple of sectors.           | | ||||||
|  |  * |   - default 2MB (4096 * 512)                    | | ||||||
|  |  * |   - Any entries with zero in bitmap should be   | | ||||||
|  |  * |     zero on disk                                | | ||||||
|  |  * +-------------------------------------------------+ | ||||||
|  |  * | Data Block 1                                    | | ||||||
|  |  * +-------------------------------------------------+ | ||||||
|  |  * | ...                                             | | ||||||
|  |  * +-------------------------------------------------+ | ||||||
|  |  * | Data Block n                                    | | ||||||
|  |  * +-------------------------------------------------+ | ||||||
|  |  * | HD Footer (511 bytes)                           | | ||||||
|  |  * +-------------------------------------------------+ | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
							
								
								
									
										38
									
								
								tools/vhd-tools/lvm/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								tools/vhd-tools/lvm/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | |||||||
|  | XEN_ROOT = ../../.. | ||||||
|  | BLKTAP_ROOT := .. | ||||||
|  | include $(XEN_ROOT)/tools/Rules.mk | ||||||
|  | 
 | ||||||
|  | ifeq ($(LVM_UTIL_TEST),y) | ||||||
|  | TEST              := lvm-util | ||||||
|  | endif | ||||||
|  | 
 | ||||||
|  | CFLAGS            += -Werror | ||||||
|  | CFLAGS            += -Wno-unused | ||||||
|  | CFLAGS            += -I../include | ||||||
|  | CFLAGS            += -D_GNU_SOURCE | ||||||
|  | 
 | ||||||
|  | ifeq ($(CONFIG_X86_64),y) | ||||||
|  | CFLAGS            += -fPIC | ||||||
|  | endif | ||||||
|  | 
 | ||||||
|  | # Get gcc to generate the dependencies for us.
 | ||||||
|  | CFLAGS            += -Wp,-MD,.$(@F).d | ||||||
|  | DEPS               = .*.d | ||||||
|  | 
 | ||||||
|  | LVM-OBJS          := lvm-util.o | ||||||
|  | 
 | ||||||
|  | all: build | ||||||
|  | 
 | ||||||
|  | build: $(TEST) $(LVM-OBJS) | ||||||
|  | 
 | ||||||
|  | install: all | ||||||
|  | 
 | ||||||
|  | lvm-util: lvm-util.o | ||||||
|  | 	$(CC) $(CFLAGS) -DLVM_UTIL $(LDFLAGS) -o lvm-util lvm-util.c | ||||||
|  | 
 | ||||||
|  | clean: | ||||||
|  | 	rm -rf *.o *~ $(DEPS) $(IBIN) | ||||||
|  | 
 | ||||||
|  | .PHONY: all build clean install lvm-util | ||||||
|  | 
 | ||||||
|  | -include $(DEPS) | ||||||
							
								
								
									
										349
									
								
								tools/vhd-tools/lvm/lvm-util.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										349
									
								
								tools/vhd-tools/lvm/lvm-util.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,349 @@ | |||||||
|  | /* 
 | ||||||
|  |  * Copyright (c) 2008, XenSource Inc. | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of XenSource Inc. nor the names of its contributors | ||||||
|  |  *       may be used to endorse or promote products derived from this software | ||||||
|  |  *       without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||||||
|  |  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||||
|  |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||||
|  |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||||
|  |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||||
|  |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||||
|  |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | 
 | ||||||
|  | #include "lvm-util.h" | ||||||
|  | 
 | ||||||
|  | #define _NAME "%255s" | ||||||
|  | static char line[1024]; | ||||||
|  | 
 | ||||||
|  | static inline int | ||||||
|  | lvm_read_line(FILE *scan) | ||||||
|  | { | ||||||
|  | 	memset(line, 0, sizeof(line)); | ||||||
|  | 	return (fscanf(scan, "%1023[^\n]", line) != 1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline int | ||||||
|  | lvm_next_line(FILE *scan) | ||||||
|  | { | ||||||
|  | 	return (fscanf(scan, "%1023[\n]", line) != 1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | lvm_copy_name(char *dst, const char *src, size_t size) | ||||||
|  | { | ||||||
|  | 	if (strnlen(src, size) == size) | ||||||
|  | 		return -ENAMETOOLONG; | ||||||
|  | 
 | ||||||
|  | 	strcpy(dst, src); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | lvm_parse_pv(struct vg *vg, const char *name, int pvs, uint64_t start) | ||||||
|  | { | ||||||
|  | 	int i, err; | ||||||
|  | 	struct pv *pv; | ||||||
|  | 
 | ||||||
|  | 	pv = NULL; | ||||||
|  | 
 | ||||||
|  | 	if (!vg->pvs) { | ||||||
|  | 		vg->pvs = calloc(pvs, sizeof(struct pv)); | ||||||
|  | 		if (!vg->pvs) | ||||||
|  | 			return -ENOMEM; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < pvs; i++) { | ||||||
|  | 		pv = vg->pvs + i; | ||||||
|  | 
 | ||||||
|  | 		if (!pv->name[0]) | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 		if (!strcmp(pv->name, name)) | ||||||
|  | 			return -EEXIST; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!pv) | ||||||
|  | 		return -ENOENT; | ||||||
|  | 
 | ||||||
|  | 	if (i == pvs) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	err = lvm_copy_name(pv->name, name, sizeof(pv->name) - 1); | ||||||
|  | 	if (err) | ||||||
|  | 		return err; | ||||||
|  | 
 | ||||||
|  | 	pv->start = start; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | lvm_open_vg(const char *vgname, struct vg *vg) | ||||||
|  | { | ||||||
|  | 	FILE *scan; | ||||||
|  | 	int i, err, pvs, lvs; | ||||||
|  | 	char *cmd, pvname[256]; | ||||||
|  | 	uint64_t size, pv_start; | ||||||
|  | 
 | ||||||
|  | 	memset(vg, 0, sizeof(*vg)); | ||||||
|  | 
 | ||||||
|  | 	err = asprintf(&cmd, "/usr/sbin/vgs %s --noheadings --nosuffix --units=b " | ||||||
|  | 		       "--options=vg_name,vg_extent_size,lv_count,pv_count," | ||||||
|  | 		       "pv_name,pe_start --unbuffered 2> /dev/null", vgname); | ||||||
|  | 	if (err == -1) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	errno = 0; | ||||||
|  | 	scan  = popen(cmd, "r"); | ||||||
|  | 	if (!scan) { | ||||||
|  | 		err = (errno ? -errno : ENOMEM); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (;;) { | ||||||
|  | 		if (lvm_read_line(scan)) | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 		err = -EINVAL; | ||||||
|  |                 if (sscanf(line, _NAME" %"SCNu64" %d %d "_NAME" %"SCNu64, | ||||||
|  | 			   vg->name, &size, &lvs, &pvs, pvname, &pv_start) != 6) | ||||||
|  | 			goto out; | ||||||
|  | 
 | ||||||
|  | 		if (strcmp(vg->name, vgname)) | ||||||
|  | 			goto out; | ||||||
|  | 
 | ||||||
|  | 		err = lvm_parse_pv(vg, pvname, pvs, pv_start); | ||||||
|  | 		if (err) | ||||||
|  | 			goto out; | ||||||
|  | 
 | ||||||
|  | 		if (lvm_next_line(scan)) | ||||||
|  | 			break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = -EINVAL; | ||||||
|  | 	if (strcmp(vg->name, vgname)) | ||||||
|  | 		goto out; | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < pvs; i++) | ||||||
|  | 		if (!vg->pvs[i].name[0]) | ||||||
|  | 			goto out; | ||||||
|  | 
 | ||||||
|  | 	err = -ENOMEM; | ||||||
|  | 	vg->lvs = calloc(lvs, sizeof(struct lv)); | ||||||
|  | 	if (!vg->lvs) | ||||||
|  | 		goto out; | ||||||
|  | 
 | ||||||
|  | 	err             = 0; | ||||||
|  | 	vg->lv_cnt      = lvs; | ||||||
|  | 	vg->pv_cnt      = pvs; | ||||||
|  | 	vg->extent_size = size; | ||||||
|  | 
 | ||||||
|  | out: | ||||||
|  | 	if (scan) | ||||||
|  | 		pclose(scan); | ||||||
|  | 	if (err) | ||||||
|  | 		lvm_free_vg(vg); | ||||||
|  | 	free(cmd); | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | lvm_parse_lv_devices(struct vg *vg, struct lv_segment *seg, char *devices) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	uint64_t start, pe_start; | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < strlen(devices); i++) | ||||||
|  | 		if (strchr(",()", devices[i])) | ||||||
|  | 			devices[i] = ' '; | ||||||
|  | 
 | ||||||
|  |         if (sscanf(devices, _NAME" %"SCNu64, seg->device, &start) != 2) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	pe_start = -1; | ||||||
|  | 	for (i = 0; i < vg->pv_cnt; i++) | ||||||
|  | 		if (!strcmp(vg->pvs[i].name, seg->device)) { | ||||||
|  | 			pe_start = vg->pvs[i].start; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 	if (pe_start == -1) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	seg->pe_start = (start * vg->extent_size) + pe_start; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | lvm_scan_lvs(struct vg *vg) | ||||||
|  | { | ||||||
|  | 	char *cmd; | ||||||
|  | 	FILE *scan; | ||||||
|  | 	int i, err; | ||||||
|  | 
 | ||||||
|  | 	err = asprintf(&cmd, "/usr/sbin/lvs %s --noheadings --nosuffix --units=b " | ||||||
|  | 		       "--options=lv_name,lv_size,segtype,seg_count,seg_start," | ||||||
|  | 		       "seg_size,devices --unbuffered 2> /dev/null", vg->name); | ||||||
|  | 	if (err == -1) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	errno = 0; | ||||||
|  | 	scan  = popen(cmd, "r"); | ||||||
|  | 	if (!scan) { | ||||||
|  | 		err = (errno ? -errno : -ENOMEM); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (i = 0;;) { | ||||||
|  | 		int segs; | ||||||
|  | 		struct lv *lv; | ||||||
|  | 		struct lv_segment seg; | ||||||
|  | 		uint64_t size, seg_start; | ||||||
|  | 		char type[32], name[256], dev[256], devices[1024]; | ||||||
|  | 
 | ||||||
|  | 		if (i >= vg->lv_cnt) | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 		if (lvm_read_line(scan)) { | ||||||
|  | 			vg->lv_cnt = i; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		err = -EINVAL; | ||||||
|  | 		lv  = vg->lvs + i; | ||||||
|  | 
 | ||||||
|  |                 if (sscanf(line, _NAME" %"SCNu64" %31s %u %"SCNu64" %"SCNu64" %1023s", | ||||||
|  | 			   name, &size, type, &segs, &seg_start, | ||||||
|  | 			   &seg.pe_size, devices) != 7) | ||||||
|  | 			goto out; | ||||||
|  | 
 | ||||||
|  | 		if (seg_start) | ||||||
|  | 			goto next; | ||||||
|  | 
 | ||||||
|  | 		if (!strcmp(type, "linear")) | ||||||
|  | 			seg.type = LVM_SEG_TYPE_LINEAR; | ||||||
|  | 		else | ||||||
|  | 			seg.type = LVM_SEG_TYPE_UNKNOWN; | ||||||
|  | 
 | ||||||
|  | 		if (lvm_parse_lv_devices(vg, &seg, devices)) | ||||||
|  | 			goto out; | ||||||
|  | 
 | ||||||
|  | 		i++; | ||||||
|  | 		lv->size          = size; | ||||||
|  | 		lv->segments      = segs; | ||||||
|  | 		lv->first_segment = seg; | ||||||
|  | 
 | ||||||
|  | 		err = lvm_copy_name(lv->name, name, sizeof(lv->name) - 1); | ||||||
|  | 		if (err) | ||||||
|  | 			goto out; | ||||||
|  | 		err = -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	next: | ||||||
|  | 		if (lvm_next_line(scan)) | ||||||
|  | 			goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = 0; | ||||||
|  | 
 | ||||||
|  | out: | ||||||
|  | 	if (scan) | ||||||
|  | 		pclose(scan); | ||||||
|  | 	free(cmd); | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | lvm_free_vg(struct vg *vg) | ||||||
|  | { | ||||||
|  | 	free(vg->lvs); | ||||||
|  | 	free(vg->pvs); | ||||||
|  | 	memset(vg, 0, sizeof(*vg)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | lvm_scan_vg(const char *vg_name, struct vg *vg) | ||||||
|  | { | ||||||
|  | 	int err; | ||||||
|  | 
 | ||||||
|  | 	memset(vg, 0, sizeof(*vg)); | ||||||
|  | 
 | ||||||
|  | 	err = lvm_open_vg(vg_name, vg); | ||||||
|  | 	if (err) | ||||||
|  | 		return err; | ||||||
|  | 
 | ||||||
|  | 	err = lvm_scan_lvs(vg); | ||||||
|  | 	if (err) { | ||||||
|  | 		lvm_free_vg(vg); | ||||||
|  | 		return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #ifdef LVM_UTIL | ||||||
|  | static int | ||||||
|  | usage(void) | ||||||
|  | { | ||||||
|  | 	printf("usage: lvm-util <vgname>\n"); | ||||||
|  | 	exit(EINVAL); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | main(int argc, char **argv) | ||||||
|  | { | ||||||
|  | 	int i, err; | ||||||
|  | 	struct vg vg; | ||||||
|  | 	struct pv *pv; | ||||||
|  | 	struct lv *lv; | ||||||
|  | 	struct lv_segment *seg; | ||||||
|  | 
 | ||||||
|  | 	if (argc != 2) | ||||||
|  | 		usage(); | ||||||
|  | 
 | ||||||
|  | 	err = lvm_scan_vg(argv[1], &vg); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("scan failed: %d\n", err); | ||||||
|  | 		return (err >= 0 ? err : -err); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	 | ||||||
|  |         printf("vg %s: extent_size: %"PRIu64", pvs: %d, lvs: %d\n", | ||||||
|  | 	       vg.name, vg.extent_size, vg.pv_cnt, vg.lv_cnt); | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < vg.pv_cnt; i++) { | ||||||
|  | 		pv = vg.pvs + i; | ||||||
|  |                 printf("pv %s: start %"PRIu64"\n", pv->name, pv->start); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < vg.lv_cnt; i++) { | ||||||
|  | 		lv  = vg.lvs + i; | ||||||
|  | 		seg = &lv->first_segment;                 | ||||||
|  |                 printf("lv %s: size: %"PRIu64", segments: %u, type: %u, " | ||||||
|  |                        "dev: %s, pe_start: %"PRIu64", pe_size: %"PRIu64"\n", | ||||||
|  | 		       lv->name, lv->size, lv->segments, seg->type, | ||||||
|  | 		       seg->device, seg->pe_start, seg->pe_size); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	lvm_free_vg(&vg); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | #endif | ||||||
							
								
								
									
										56
									
								
								tools/vhd-tools/vhd/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								tools/vhd-tools/vhd/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,56 @@ | |||||||
|  | XEN_ROOT=../../.. | ||||||
|  | BLKTAP_ROOT := .. | ||||||
|  | include $(XEN_ROOT)/tools/Rules.mk | ||||||
|  | 
 | ||||||
|  | SUBDIRS-y         := | ||||||
|  | SUBDIRS-y         += lib | ||||||
|  | 
 | ||||||
|  | IBIN               = vhd-util vhd-update | ||||||
|  | INST_DIR           = $(SBINDIR) | ||||||
|  | 
 | ||||||
|  | CFLAGS            += -Werror | ||||||
|  | CFLAGS            += -Wno-unused | ||||||
|  | CFLAGS            += -I../include | ||||||
|  | CFLAGS            += -D_GNU_SOURCE | ||||||
|  | 
 | ||||||
|  | ifeq ($(CONFIG_X86_64),y) | ||||||
|  | CFLAGS            += -fPIC | ||||||
|  | endif | ||||||
|  | 
 | ||||||
|  | ifeq ($(VHD_STATIC),y) | ||||||
|  | CFLAGS            += -static | ||||||
|  | endif | ||||||
|  | 
 | ||||||
|  | LIBS              := -Llib -lvhd | ||||||
|  | ifeq ($(CONFIG_Linux),y) | ||||||
|  | LIBS              += -luuid | ||||||
|  | endif | ||||||
|  | 
 | ||||||
|  | # Get gcc to generate the dependencies for us.
 | ||||||
|  | CFLAGS            += -Wp,-MD,.$(@F).d | ||||||
|  | DEPS               = .*.d | ||||||
|  | 
 | ||||||
|  | all: subdirs-all build | ||||||
|  | 
 | ||||||
|  | build: $(IBIN) | ||||||
|  | 
 | ||||||
|  | LIBS_DEPENDS	  := lib/libvhd.so lib/vhd.a | ||||||
|  | $(LIBS_DEPENDS):subdirs-all | ||||||
|  | 
 | ||||||
|  | vhd-util: vhd-util.o $(LIBS_DEPENDS) | ||||||
|  | 	$(CC) $(CFLAGS) -o vhd-util vhd-util.o $(LDFLAGS) $(LIBS) | ||||||
|  | 
 | ||||||
|  | vhd-update: vhd-update.o $(LIBS_DEPENDS) | ||||||
|  | 	$(CC) $(CFLAGS) -o vhd-update vhd-update.o $(LDFLAGS) $(LIBS) | ||||||
|  | 
 | ||||||
|  | install: all | ||||||
|  | 	$(MAKE) subdirs-install | ||||||
|  | 	$(INSTALL_DIR) -p $(DESTDIR)$(INST_DIR) | ||||||
|  | 	$(INSTALL_PROG) $(IBIN) $(DESTDIR)$(INST_DIR) | ||||||
|  | 
 | ||||||
|  | clean: subdirs-clean | ||||||
|  | 	rm -rf *.o *~ $(DEPS) $(IBIN) | ||||||
|  | 
 | ||||||
|  | .PHONY: all build clean install vhd-util vhd-update | ||||||
|  | 
 | ||||||
|  | -include $(DEPS) | ||||||
							
								
								
									
										75
									
								
								tools/vhd-tools/vhd/lib/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								tools/vhd-tools/vhd/lib/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,75 @@ | |||||||
|  | XEN_ROOT=../../../.. | ||||||
|  | BLKTAP_ROOT := ../.. | ||||||
|  | include $(XEN_ROOT)/tools/Rules.mk | ||||||
|  | 
 | ||||||
|  | LIBVHD-MAJOR     = 1.0 | ||||||
|  | LIBVHD-MINOR     = 0 | ||||||
|  | LIBVHD-SONAME    = libvhd.so.$(LIBVHD-MAJOR) | ||||||
|  | 
 | ||||||
|  | LVM-UTIL-OBJ    := $(BLKTAP_ROOT)/lvm/lvm-util.o | ||||||
|  | 
 | ||||||
|  | LIBVHD-BUILD    := libvhd.a | ||||||
|  | 
 | ||||||
|  | INST-DIR         = $(LIBDIR) | ||||||
|  | 
 | ||||||
|  | CFLAGS          += -Werror | ||||||
|  | CFLAGS          += -Wno-unused | ||||||
|  | CFLAGS          += -I../../include | ||||||
|  | CFLAGS          += -D_GNU_SOURCE | ||||||
|  | CFLAGS          += -fPIC | ||||||
|  | CFLAGS          += -g | ||||||
|  | 
 | ||||||
|  | ifeq ($(CONFIG_Linux),y) | ||||||
|  | LIBS            := -luuid | ||||||
|  | endif | ||||||
|  | 
 | ||||||
|  | # Get gcc to generate the dependencies for us.
 | ||||||
|  | CFLAGS          += -Wp,-MD,.$(@F).d | ||||||
|  | DEPS             = .*.d | ||||||
|  | 
 | ||||||
|  | LIB-SRCS        := libvhd.c | ||||||
|  | LIB-SRCS        += libvhd-journal.c | ||||||
|  | LIB-SRCS        += vhd-util-coalesce.c | ||||||
|  | LIB-SRCS        += vhd-util-create.c | ||||||
|  | LIB-SRCS        += vhd-util-fill.c | ||||||
|  | LIB-SRCS        += vhd-util-modify.c | ||||||
|  | LIB-SRCS        += vhd-util-query.c | ||||||
|  | LIB-SRCS        += vhd-util-read.c | ||||||
|  | LIB-SRCS        += vhd-util-repair.c | ||||||
|  | LIB-SRCS        += vhd-util-resize.c | ||||||
|  | LIB-SRCS        += vhd-util-revert.c | ||||||
|  | LIB-SRCS        += vhd-util-set-field.c | ||||||
|  | LIB-SRCS        += vhd-util-snapshot.c | ||||||
|  | LIB-SRCS        += vhd-util-scan.c | ||||||
|  | LIB-SRCS        += vhd-util-check.c | ||||||
|  | LIB-SRCS        += relative-path.c | ||||||
|  | LIB-SRCS        += atomicio.c | ||||||
|  | 
 | ||||||
|  | LIB-OBJS         = $(patsubst %.c,%.o,$(LIB-SRCS)) | ||||||
|  | LIB-OBJS        += $(LVM-UTIL-OBJ) | ||||||
|  | 
 | ||||||
|  | LIBVHD           = libvhd.a libvhd.so.$(LIBVHD-MAJOR).$(LIBVHD-MINOR) | ||||||
|  | 
 | ||||||
|  | all: build | ||||||
|  | 
 | ||||||
|  | build: $(LIBVHD-BUILD) | ||||||
|  | 
 | ||||||
|  | libvhd.a: $(LIB-OBJS) | ||||||
|  | 	$(CC) $(CFLAGS) -Wl,$(SONAME_LDFLAG),$(LIBVHD-SONAME) $(SHLIB_CFLAGS) \
 | ||||||
|  | 		$(LDFLAGS) -o libvhd.so.$(LIBVHD-MAJOR).$(LIBVHD-MINOR) $(LIBS) $^ | ||||||
|  | 	ln -sf libvhd.so.$(LIBVHD-MAJOR).$(LIBVHD-MINOR) libvhd.so.$(LIBVHD-MAJOR) | ||||||
|  | 	ln -sf libvhd.so.$(LIBVHD-MAJOR) libvhd.so | ||||||
|  | 	$(AR) rc $@ $^ | ||||||
|  | 
 | ||||||
|  | install: all | ||||||
|  | 	$(INSTALL_DIR) -p $(DESTDIR)$(INST-DIR) | ||||||
|  | 	$(INSTALL_DATA) $(LIBVHD) $(DESTDIR)$(INST-DIR) | ||||||
|  | 	ln -sf libvhd.so.$(LIBVHD-MAJOR).$(LIBVHD-MINOR) $(DESTDIR)$(INST-DIR)/libvhd.so.$(LIBVHD-MAJOR) | ||||||
|  | 	ln -sf libvhd.so.$(LIBVHD-MAJOR) $(DESTDIR)$(INST-DIR)/libvhd.so | ||||||
|  | 
 | ||||||
|  | clean: | ||||||
|  | 	rm -rf *.a *.so* *.o *~ $(DEPS) $(LIBVHD) | ||||||
|  | 
 | ||||||
|  | .PHONY: all build clean install libvhd | ||||||
|  | 
 | ||||||
|  | -include $(DEPS) | ||||||
							
								
								
									
										61
									
								
								tools/vhd-tools/vhd/lib/atomicio.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								tools/vhd-tools/vhd/lib/atomicio.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,61 @@ | |||||||
|  | /*
 | ||||||
|  |  * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved. | ||||||
|  |  * Copyright (c) 1995,1999 Theo de Raadt.  All rights reserved. | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||||||
|  |  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||||||
|  |  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||||||
|  |  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||||||
|  |  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||||
|  |  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||||
|  |  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||||
|  |  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||
|  |  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||||||
|  |  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include "atomicio.h" | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * ensure all of data on socket comes through. f==read || f==vwrite | ||||||
|  |  */ | ||||||
|  | size_t | ||||||
|  | atomicio(f, fd, _s, n) | ||||||
|  | 	ssize_t (*f) (int, void *, size_t); | ||||||
|  | 	int fd; | ||||||
|  | 	void *_s; | ||||||
|  | 	size_t n; | ||||||
|  | { | ||||||
|  | 	char *s = _s; | ||||||
|  | 	size_t pos = 0; | ||||||
|  | 	ssize_t res; | ||||||
|  | 
 | ||||||
|  | 	while (n > pos) { | ||||||
|  | 		res = (f) (fd, s + pos, n - pos); | ||||||
|  | 		switch (res) { | ||||||
|  | 		case -1: | ||||||
|  | 			if (errno == EINTR || errno == EAGAIN) | ||||||
|  | 				continue; | ||||||
|  | 			return 0; | ||||||
|  | 		case 0: | ||||||
|  | 			errno = EPIPE; | ||||||
|  | 			return pos; | ||||||
|  | 		default: | ||||||
|  | 			pos += (size_t)res; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return (pos); | ||||||
|  | } | ||||||
|  | 
 | ||||||
							
								
								
									
										1534
									
								
								tools/vhd-tools/vhd/lib/libvhd-journal.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1534
									
								
								tools/vhd-tools/vhd/lib/libvhd-journal.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										3352
									
								
								tools/vhd-tools/vhd/lib/libvhd.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3352
									
								
								tools/vhd-tools/vhd/lib/libvhd.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										299
									
								
								tools/vhd-tools/vhd/lib/relative-path.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										299
									
								
								tools/vhd-tools/vhd/lib/relative-path.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,299 @@ | |||||||
|  | /* Copyright (c) 2008, XenSource Inc.
 | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of XenSource Inc. nor the names of its contributors | ||||||
|  |  *       may be used to endorse or promote products derived from this software | ||||||
|  |  *       without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||||||
|  |  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||||
|  |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||||
|  |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||||
|  |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||||
|  |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||||
|  |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | */ | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | 
 | ||||||
|  | #include "relative-path.h" | ||||||
|  | 
 | ||||||
|  | #define sfree(ptr)         \ | ||||||
|  | do {                       \ | ||||||
|  | 	free(ptr);         \ | ||||||
|  | 	ptr = NULL;        \ | ||||||
|  | } while (0) | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * count number of tokens between DELIMETER characters | ||||||
|  |  */ | ||||||
|  | static int | ||||||
|  | count_nodes(char *path) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	char *tmp; | ||||||
|  | 
 | ||||||
|  | 	if (!path) | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
|  | 	for (i = 0, tmp = path; *tmp != '\0'; tmp++) | ||||||
|  | 		if (*tmp == DELIMITER) | ||||||
|  | 			i++; | ||||||
|  | 
 | ||||||
|  | 	return i; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * return copy of next node in @path, or NULL | ||||||
|  |  * @path is moved to the end of the next node | ||||||
|  |  * @err is set to -errno on failure | ||||||
|  |  * copy should be freed | ||||||
|  |  */ | ||||||
|  | static char * | ||||||
|  | next_node(char **path, int *err) | ||||||
|  | { | ||||||
|  | 	int ret; | ||||||
|  | 	char *tmp, *start; | ||||||
|  | 
 | ||||||
|  | 	if (!path || !*path) { | ||||||
|  | 		*err = -EINVAL; | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	*err  = 0; | ||||||
|  | 	start = *path; | ||||||
|  | 
 | ||||||
|  | 	for (tmp = *path; *tmp != '\0'; tmp++) | ||||||
|  | 		if (*tmp == DELIMITER) { | ||||||
|  | 			int size; | ||||||
|  | 			char *node; | ||||||
|  | 
 | ||||||
|  | 			size = tmp - start + 1; | ||||||
|  | 			node = malloc(size); | ||||||
|  | 			if (!node) { | ||||||
|  | 				*err = -ENOMEM; | ||||||
|  | 				return NULL; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			ret = snprintf(node, size, "%s", start); | ||||||
|  | 			if (ret < 0) { | ||||||
|  | 				free(node); | ||||||
|  | 				*err = -EINVAL; | ||||||
|  | 				return NULL; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			*path = tmp; | ||||||
|  | 			return node; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * count number of nodes in common betwee @to and @from | ||||||
|  |  * returns number of common nodes, or -errno on failure | ||||||
|  |  */ | ||||||
|  | static int | ||||||
|  | count_common_nodes(char *to, char *from) | ||||||
|  | { | ||||||
|  | 	int err, common; | ||||||
|  | 	char *to_node, *from_node; | ||||||
|  | 
 | ||||||
|  | 	if (!to || !from) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	err       = 0; | ||||||
|  | 	common    = 0; | ||||||
|  | 	to_node   = NULL; | ||||||
|  | 	from_node = NULL; | ||||||
|  | 
 | ||||||
|  | 	do { | ||||||
|  | 		to_node = next_node(&to, &err); | ||||||
|  | 		if (err || !to_node) | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 		from_node = next_node(&from, &err); | ||||||
|  | 		if (err || !from_node) | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 		if (strncmp(to_node, from_node, MAX_NAME_LEN)) | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 		++to; | ||||||
|  | 		++from; | ||||||
|  | 		++common; | ||||||
|  | 		sfree(to_node); | ||||||
|  | 		sfree(from_node); | ||||||
|  | 
 | ||||||
|  | 	} while (1); | ||||||
|  | 
 | ||||||
|  | 	sfree(to_node); | ||||||
|  | 	sfree(from_node); | ||||||
|  | 
 | ||||||
|  | 	if (err) | ||||||
|  | 		return err; | ||||||
|  | 
 | ||||||
|  | 	return common; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * construct path of @count '../', './' if @count is zero, or NULL on error | ||||||
|  |  * result should be freed | ||||||
|  |  */ | ||||||
|  | static char * | ||||||
|  | up_nodes(int count) | ||||||
|  | { | ||||||
|  | 	char *path, *tmp; | ||||||
|  | 	int i, ret, len, size; | ||||||
|  | 
 | ||||||
|  | 	if (!count) | ||||||
|  | 		return strdup("./"); | ||||||
|  | 
 | ||||||
|  | 	len  = strlen("../"); | ||||||
|  | 	size = len * count; | ||||||
|  | 	if (size >= MAX_NAME_LEN) | ||||||
|  | 		return NULL; | ||||||
|  | 
 | ||||||
|  | 	path = malloc(size + 1); | ||||||
|  | 	if (!path) | ||||||
|  | 		return NULL; | ||||||
|  | 
 | ||||||
|  | 	tmp = path; | ||||||
|  | 	for (i = 0; i < count; i++) { | ||||||
|  | 		ret = sprintf(tmp, "../"); | ||||||
|  | 		if (ret < 0 || ret != len) { | ||||||
|  | 			free(path); | ||||||
|  | 			return NULL; | ||||||
|  | 		} | ||||||
|  | 		tmp += ret; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return path; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * return pointer to @offset'th node of path or NULL on error | ||||||
|  |  */ | ||||||
|  | static char * | ||||||
|  | node_offset(char *from, int offset) | ||||||
|  | { | ||||||
|  | 	char *path; | ||||||
|  | 
 | ||||||
|  | 	if (!from || !offset) | ||||||
|  | 		return NULL; | ||||||
|  | 
 | ||||||
|  | 	for (path = from; *path != '\0'; path++) { | ||||||
|  | 		if (*path == DELIMITER) | ||||||
|  | 			if (--offset == 0) | ||||||
|  | 				return path + 1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * return a relative path from @from to @to | ||||||
|  |  * result should be freed | ||||||
|  |  */ | ||||||
|  | char * | ||||||
|  | relative_path_to(char *from, char *to, int *err) | ||||||
|  | { | ||||||
|  | 	int from_nodes, common; | ||||||
|  | 	char *to_absolute, *from_absolute; | ||||||
|  | 	char *up, *common_target_path, *relative_path; | ||||||
|  | 
 | ||||||
|  | 	*err          = 0; | ||||||
|  | 	up            = NULL; | ||||||
|  | 	to_absolute   = NULL; | ||||||
|  | 	from_absolute = NULL; | ||||||
|  | 	relative_path = NULL; | ||||||
|  | 
 | ||||||
|  | 	if (strnlen(to, MAX_NAME_LEN)   == MAX_NAME_LEN || | ||||||
|  | 	    strnlen(from, MAX_NAME_LEN) == MAX_NAME_LEN) { | ||||||
|  | 		EPRINTF("invalid input; max path length is %d\n", | ||||||
|  | 			MAX_NAME_LEN); | ||||||
|  | 		*err = -ENAMETOOLONG; | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	to_absolute = realpath(to, NULL); | ||||||
|  | 	if (!to_absolute) { | ||||||
|  | 		EPRINTF("failed to get absolute path of %s\n", to); | ||||||
|  | 		*err = -errno; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	from_absolute = realpath(from, NULL); | ||||||
|  | 	if (!from_absolute) { | ||||||
|  | 		EPRINTF("failed to get absolute path of %s\n", from); | ||||||
|  | 		*err = -errno; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (strnlen(to_absolute, MAX_NAME_LEN)   == MAX_NAME_LEN || | ||||||
|  | 	    strnlen(from_absolute, MAX_NAME_LEN) == MAX_NAME_LEN) { | ||||||
|  | 		EPRINTF("invalid input; max path length is %d\n", | ||||||
|  | 			MAX_NAME_LEN); | ||||||
|  | 		*err = -ENAMETOOLONG; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* count nodes in source path */ | ||||||
|  | 	from_nodes = count_nodes(from_absolute); | ||||||
|  | 
 | ||||||
|  | 	/* count nodes in common */ | ||||||
|  | 	common = count_common_nodes(to_absolute + 1, from_absolute + 1); | ||||||
|  | 	if (common < 0) { | ||||||
|  | 		EPRINTF("failed to count common nodes of %s and %s: %d\n", | ||||||
|  | 			to_absolute, from_absolute, common); | ||||||
|  | 		*err = common; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* move up to common node */ | ||||||
|  | 	up = up_nodes(from_nodes - common - 1); | ||||||
|  | 	if (!up) { | ||||||
|  | 		EPRINTF("failed to allocate relative path for %s: %d\n", | ||||||
|  | 			from_absolute, -ENOMEM); | ||||||
|  | 		*err = -ENOMEM; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* get path from common node to target */ | ||||||
|  | 	common_target_path = node_offset(to_absolute, common + 1); | ||||||
|  | 	if (!common_target_path) { | ||||||
|  | 		EPRINTF("failed to find common target path to %s: %d\n", | ||||||
|  | 			to_absolute, -EINVAL); | ||||||
|  | 		*err = -EINVAL; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* get relative path */ | ||||||
|  | 	if (asprintf(&relative_path, "%s%s", up, common_target_path) == -1) { | ||||||
|  | 		EPRINTF("failed to construct final path %s%s: %d\n", | ||||||
|  | 			up, common_target_path, -ENOMEM); | ||||||
|  | 		relative_path = NULL; | ||||||
|  | 		*err = -ENOMEM; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | out: | ||||||
|  | 	sfree(up); | ||||||
|  | 	sfree(to_absolute); | ||||||
|  | 	sfree(from_absolute); | ||||||
|  | 
 | ||||||
|  | 	return relative_path; | ||||||
|  | } | ||||||
							
								
								
									
										980
									
								
								tools/vhd-tools/vhd/lib/vhd-util-check.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										980
									
								
								tools/vhd-tools/vhd/lib/vhd-util-check.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,980 @@ | |||||||
|  | /* Copyright (c) 2008, XenSource Inc.
 | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of XenSource Inc. nor the names of its contributors | ||||||
|  |  *       may be used to endorse or promote products derived from this software | ||||||
|  |  *       without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||||||
|  |  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||||
|  |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||||
|  |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||||
|  |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||||
|  |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||||
|  |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | */ | ||||||
|  | #include <time.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include <fcntl.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | #include <libgen.h> | ||||||
|  | #include <inttypes.h> | ||||||
|  | #include <sys/stat.h> | ||||||
|  | 
 | ||||||
|  | #include "libvhd.h" | ||||||
|  | #include "vhd-util.h" | ||||||
|  | 
 | ||||||
|  | // allow the VHD timestamp to be at most this many seconds into the future to 
 | ||||||
|  | // account for time skew with NFS servers
 | ||||||
|  | #define TIMESTAMP_MAX_SLACK 1800 | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | vhd_util_check_zeros(void *buf, size_t size) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	char *p; | ||||||
|  | 
 | ||||||
|  | 	p = buf; | ||||||
|  | 	for (i = 0; i < size; i++) | ||||||
|  | 		if (p[i]) | ||||||
|  | 			return i; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | vhd_util_check_footer_opened(vhd_footer_t *footer) | ||||||
|  | { | ||||||
|  | 	int i, n; | ||||||
|  | 	uint32_t *buf; | ||||||
|  | 
 | ||||||
|  | 	buf = (uint32_t *)footer; | ||||||
|  | 	n = sizeof(*footer) / sizeof(uint32_t); | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < n; i++) | ||||||
|  | 		if (buf[i] != 0xc7c7c7c7) | ||||||
|  | 			return 0; | ||||||
|  | 
 | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static char * | ||||||
|  | vhd_util_check_validate_footer(vhd_footer_t *footer) | ||||||
|  | { | ||||||
|  | 	int size; | ||||||
|  | 	uint32_t checksum, now; | ||||||
|  | 
 | ||||||
|  | 	size = sizeof(footer->cookie); | ||||||
|  | 	if (memcmp(footer->cookie, HD_COOKIE, size)) | ||||||
|  | 		return "invalid cookie"; | ||||||
|  | 
 | ||||||
|  | 	checksum = vhd_checksum_footer(footer); | ||||||
|  | 	if (checksum != footer->checksum) { | ||||||
|  | 		if (footer->hidden && | ||||||
|  | 		    !strncmp(footer->crtr_app, "tap", 3) && | ||||||
|  | 		    (footer->crtr_ver == VHD_VERSION(0, 1) || | ||||||
|  | 		     footer->crtr_ver == VHD_VERSION(1, 1))) { | ||||||
|  | 			char tmp = footer->hidden; | ||||||
|  | 			footer->hidden = 0; | ||||||
|  | 			checksum = vhd_checksum_footer(footer); | ||||||
|  | 			footer->hidden = tmp; | ||||||
|  | 
 | ||||||
|  | 			if (checksum == footer->checksum) | ||||||
|  | 				goto ok; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return "invalid checksum"; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | ok: | ||||||
|  | 	if (!(footer->features & HD_RESERVED)) | ||||||
|  | 		return "invalid 'reserved' feature"; | ||||||
|  | 
 | ||||||
|  | 	if (footer->features & ~(HD_TEMPORARY | HD_RESERVED)) | ||||||
|  | 		return "invalid extra features"; | ||||||
|  | 
 | ||||||
|  | 	if (footer->ff_version != HD_FF_VERSION) | ||||||
|  | 		return "invalid file format version"; | ||||||
|  | 
 | ||||||
|  | 	if (footer->type != HD_TYPE_DYNAMIC && | ||||||
|  | 	    footer->type != HD_TYPE_DIFF    && | ||||||
|  | 	    footer->data_offset != ~(0ULL)) | ||||||
|  | 		return "invalid data offset"; | ||||||
|  | 
 | ||||||
|  | 	now = vhd_time(time(NULL)); | ||||||
|  | 	if (footer->timestamp > now + TIMESTAMP_MAX_SLACK) | ||||||
|  | 		return "creation time in future"; | ||||||
|  | 
 | ||||||
|  | 	if (!strncmp(footer->crtr_app, "tap", 3) && | ||||||
|  | 	    footer->crtr_ver > VHD_CURRENT_VERSION) | ||||||
|  | 		return "unsupported tap creator version"; | ||||||
|  | 
 | ||||||
|  | 	if (vhd_chs(footer->curr_size) < footer->geometry) | ||||||
|  | 		return "geometry too large"; | ||||||
|  | 
 | ||||||
|  | 	if (footer->type != HD_TYPE_FIXED   && | ||||||
|  | 	    footer->type != HD_TYPE_DYNAMIC && | ||||||
|  | 	    footer->type != HD_TYPE_DIFF) | ||||||
|  | 		return "invalid type"; | ||||||
|  | 
 | ||||||
|  | 	if (footer->saved && footer->saved != 1) | ||||||
|  | 		return "invalid 'saved' state"; | ||||||
|  | 
 | ||||||
|  | 	if (footer->hidden && footer->hidden != 1) | ||||||
|  | 		return "invalid 'hidden' state"; | ||||||
|  | 
 | ||||||
|  | 	if (vhd_util_check_zeros(footer->reserved, | ||||||
|  | 				 sizeof(footer->reserved))) | ||||||
|  | 		return "invalid 'reserved' bits"; | ||||||
|  | 
 | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static char * | ||||||
|  | vhd_util_check_validate_header(int fd, vhd_header_t *header) | ||||||
|  | { | ||||||
|  | 	off_t eof; | ||||||
|  | 	int i, cnt, size; | ||||||
|  | 	uint32_t checksum; | ||||||
|  | 
 | ||||||
|  | 	size = sizeof(header->cookie); | ||||||
|  | 	if (memcmp(header->cookie, DD_COOKIE, size)) | ||||||
|  | 		return "invalid cookie"; | ||||||
|  | 
 | ||||||
|  | 	checksum = vhd_checksum_header(header); | ||||||
|  | 	if (checksum != header->checksum) | ||||||
|  | 		return "invalid checksum"; | ||||||
|  | 
 | ||||||
|  | 	if (header->hdr_ver != 0x00010000) | ||||||
|  | 		return "invalid header version"; | ||||||
|  | 
 | ||||||
|  | 	if (header->data_offset != ~(0ULL)) | ||||||
|  | 		return "invalid data offset"; | ||||||
|  | 
 | ||||||
|  | 	eof = lseek(fd, 0, SEEK_END); | ||||||
|  | 	if (eof == (off_t)-1) | ||||||
|  | 		return "error finding eof"; | ||||||
|  | 
 | ||||||
|  | 	if (header->table_offset <= 0  || | ||||||
|  | 	    header->table_offset % 512 || | ||||||
|  | 	    (header->table_offset + | ||||||
|  | 	     (header->max_bat_size * sizeof(uint32_t)) > | ||||||
|  | 	     eof - sizeof(vhd_footer_t))) | ||||||
|  | 		return "invalid table offset"; | ||||||
|  | 
 | ||||||
|  | 	for (cnt = 0, i = 0; i < sizeof(header->block_size) * 8; i++) | ||||||
|  | 		if ((header->block_size >> i) & 1) | ||||||
|  | 			cnt++; | ||||||
|  | 
 | ||||||
|  | 	if (cnt != 1) | ||||||
|  | 		return "invalid block size"; | ||||||
|  | 
 | ||||||
|  | 	if (header->res1) | ||||||
|  | 		return "invalid reserved bits"; | ||||||
|  | 
 | ||||||
|  | 	if (vhd_util_check_zeros(header->res2, sizeof(header->res2))) | ||||||
|  | 		return "invalid reserved bits"; | ||||||
|  | 
 | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static char * | ||||||
|  | vhd_util_check_validate_differencing_header(vhd_context_t *vhd) | ||||||
|  | { | ||||||
|  | 	vhd_header_t *header; | ||||||
|  | 
 | ||||||
|  | 	header = &vhd->header; | ||||||
|  | 
 | ||||||
|  | 	if (vhd->footer.type == HD_TYPE_DIFF) { | ||||||
|  | 		char *parent; | ||||||
|  | 		uint32_t now; | ||||||
|  | 
 | ||||||
|  | 		now = vhd_time(time(NULL)); | ||||||
|  | 		if (header->prt_ts > now + TIMESTAMP_MAX_SLACK) | ||||||
|  | 			return "parent creation time in future"; | ||||||
|  | 
 | ||||||
|  | 		if (vhd_header_decode_parent(vhd, header, &parent)) | ||||||
|  | 			return "invalid parent name"; | ||||||
|  | 
 | ||||||
|  | 		free(parent); | ||||||
|  | 	} else { | ||||||
|  | 		if (vhd_util_check_zeros(header->prt_name, | ||||||
|  | 					 sizeof(header->prt_name))) | ||||||
|  | 			return "invalid non-null parent name"; | ||||||
|  | 
 | ||||||
|  | 		if (vhd_util_check_zeros(header->loc, sizeof(header->loc))) | ||||||
|  | 			return "invalid non-null parent locators"; | ||||||
|  | 
 | ||||||
|  | 		if (!blk_uuid_is_nil(&header->prt_uuid)) | ||||||
|  | 			return "invalid non-null parent uuid"; | ||||||
|  | 
 | ||||||
|  | 		if (header->prt_ts) | ||||||
|  | 			return "invalid non-zero parent timestamp"; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static char * | ||||||
|  | vhd_util_check_validate_batmap(vhd_context_t *vhd, vhd_batmap_t *batmap) | ||||||
|  | { | ||||||
|  | 	int size; | ||||||
|  | 	off_t eof; | ||||||
|  | 	uint32_t checksum; | ||||||
|  | 
 | ||||||
|  | 	size = sizeof(batmap->header.cookie); | ||||||
|  | 	if (memcmp(batmap->header.cookie, VHD_BATMAP_COOKIE, size)) | ||||||
|  | 		return "invalid cookie"; | ||||||
|  | 
 | ||||||
|  | 	if (batmap->header.batmap_version > VHD_BATMAP_CURRENT_VERSION) | ||||||
|  | 		return "unsupported batmap version"; | ||||||
|  | 
 | ||||||
|  | 	checksum = vhd_checksum_batmap(batmap); | ||||||
|  | 	if (checksum != batmap->header.checksum) | ||||||
|  | 		return "invalid checksum"; | ||||||
|  | 
 | ||||||
|  | 	if (!batmap->header.batmap_size) | ||||||
|  | 		return "invalid size zero"; | ||||||
|  | 
 | ||||||
|  | 	eof = lseek(vhd->fd, 0, SEEK_END); | ||||||
|  | 	if (eof == (off_t)-1) | ||||||
|  | 		return "error finding eof"; | ||||||
|  | 
 | ||||||
|  | 	if (!batmap->header.batmap_offset || | ||||||
|  | 	    batmap->header.batmap_offset % 512) | ||||||
|  | 		return "invalid batmap offset"; | ||||||
|  | 
 | ||||||
|  | 	if ((batmap->header.batmap_offset + | ||||||
|  | 	     vhd_sectors_to_bytes(batmap->header.batmap_size)) > | ||||||
|  | 	    eof - sizeof(vhd_footer_t)) | ||||||
|  | 		return "invalid batmap size"; | ||||||
|  | 
 | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static char * | ||||||
|  | vhd_util_check_validate_parent_locator(vhd_context_t *vhd, | ||||||
|  | 				       vhd_parent_locator_t *loc) | ||||||
|  | { | ||||||
|  | 	off_t eof; | ||||||
|  | 
 | ||||||
|  | 	if (vhd_validate_platform_code(loc->code)) | ||||||
|  | 		return "invalid platform code"; | ||||||
|  | 
 | ||||||
|  | 	if (loc->code == PLAT_CODE_NONE) { | ||||||
|  | 		if (vhd_util_check_zeros(loc, sizeof(*loc))) | ||||||
|  | 			return "non-zero locator"; | ||||||
|  | 
 | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!loc->data_offset) | ||||||
|  | 		return "invalid data offset"; | ||||||
|  | 
 | ||||||
|  | 	if (!loc->data_space) | ||||||
|  | 		return "invalid data space"; | ||||||
|  | 
 | ||||||
|  | 	if (!loc->data_len) | ||||||
|  | 		return "invalid data length"; | ||||||
|  | 
 | ||||||
|  | 	eof = lseek(vhd->fd, 0, SEEK_END); | ||||||
|  | 	if (eof == (off_t)-1) | ||||||
|  | 		return "error finding eof"; | ||||||
|  | 
 | ||||||
|  | 	if (loc->data_offset + vhd_parent_locator_size(loc) > | ||||||
|  | 	    eof - sizeof(vhd_footer_t)) | ||||||
|  | 		return "invalid size"; | ||||||
|  | 
 | ||||||
|  | 	if (loc->res) | ||||||
|  | 		return "invalid reserved bits"; | ||||||
|  | 
 | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const char * | ||||||
|  | vhd_util_check_validate_parent(vhd_context_t *vhd, const char *ppath) | ||||||
|  | { | ||||||
|  | 	const char *msg; | ||||||
|  | 	vhd_context_t parent; | ||||||
|  | 	uint32_t status; | ||||||
|  | 
 | ||||||
|  | 	msg = NULL; | ||||||
|  | 
 | ||||||
|  | 	if (vhd_parent_raw(vhd)) | ||||||
|  | 		return msg; | ||||||
|  | 
 | ||||||
|  | 	if (vhd_open(&parent, ppath, | ||||||
|  | 				VHD_OPEN_RDONLY | VHD_OPEN_IGNORE_DISABLED)) | ||||||
|  | 		return "error opening parent"; | ||||||
|  | 
 | ||||||
|  | 	if (blk_uuid_compare(&vhd->header.prt_uuid, &parent.footer.uuid)) { | ||||||
|  | 		msg = "invalid parent uuid"; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | out: | ||||||
|  | 	vhd_close(&parent); | ||||||
|  | 	return msg; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | vhd_util_check_footer(int fd, vhd_footer_t *footer, int ignore) | ||||||
|  | { | ||||||
|  | 	size_t size; | ||||||
|  | 	int err, opened; | ||||||
|  | 	char *msg, *buf; | ||||||
|  | 	off_t eof, off; | ||||||
|  | 	vhd_footer_t primary, backup; | ||||||
|  | 
 | ||||||
|  | 	memset(&primary, 0, sizeof(primary)); | ||||||
|  | 	memset(&backup, 0, sizeof(backup)); | ||||||
|  | 
 | ||||||
|  | 	err = posix_memalign((void **)&buf, VHD_SECTOR_SIZE, sizeof(primary)); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("error allocating buffer: %d\n", err); | ||||||
|  | 		return -err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	memset(buf, 0, sizeof(primary)); | ||||||
|  | 
 | ||||||
|  | 	eof = lseek(fd, 0, SEEK_END); | ||||||
|  | 	if (eof == (off_t)-1) { | ||||||
|  | 		err = -errno; | ||||||
|  | 		printf("error calculating end of file: %d\n", err); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	size = ((eof % 512) ? 511 : 512); | ||||||
|  | 	eof  = lseek(fd, eof - size, SEEK_SET); | ||||||
|  | 	if (eof == (off_t)-1) { | ||||||
|  | 		err = -errno; | ||||||
|  | 		printf("error calculating end of file: %d\n", err); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = read(fd, buf, 512); | ||||||
|  | 	if (err != size) { | ||||||
|  | 		err = (errno ? -errno : -EIO); | ||||||
|  | 		printf("error reading primary footer: %d\n", err); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	memcpy(&primary, buf, sizeof(primary)); | ||||||
|  | 	opened = vhd_util_check_footer_opened(&primary); | ||||||
|  | 	vhd_footer_in(&primary); | ||||||
|  | 
 | ||||||
|  | 	msg = vhd_util_check_validate_footer(&primary); | ||||||
|  | 	if (msg) { | ||||||
|  | 		if (opened && ignore) | ||||||
|  | 			goto check_backup; | ||||||
|  | 
 | ||||||
|  | 		err = -EINVAL; | ||||||
|  | 		printf("primary footer invalid: %s\n", msg); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (primary.type == HD_TYPE_FIXED) { | ||||||
|  | 		err = 0; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | check_backup: | ||||||
|  | 	off = lseek(fd, 0, SEEK_SET); | ||||||
|  | 	if (off == (off_t)-1) { | ||||||
|  | 		err = -errno; | ||||||
|  | 		printf("error seeking to backup footer: %d\n", err); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	size = 512; | ||||||
|  | 	memset(buf, 0, sizeof(primary)); | ||||||
|  | 
 | ||||||
|  | 	err = read(fd, buf, size); | ||||||
|  | 	if (err != size) { | ||||||
|  | 		err = (errno ? -errno : -EIO); | ||||||
|  | 		printf("error reading backup footer: %d\n", err); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	memcpy(&backup, buf, sizeof(backup)); | ||||||
|  | 	vhd_footer_in(&backup); | ||||||
|  | 
 | ||||||
|  | 	msg = vhd_util_check_validate_footer(&backup); | ||||||
|  | 	if (msg) { | ||||||
|  | 		err = -EINVAL; | ||||||
|  | 		printf("backup footer invalid: %s\n", msg); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (memcmp(&primary, &backup, sizeof(primary))) { | ||||||
|  | 		if (opened && ignore) { | ||||||
|  | 			memcpy(&primary, &backup, sizeof(primary)); | ||||||
|  | 			goto ok; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (backup.hidden && | ||||||
|  | 		    !strncmp(backup.crtr_app, "tap", 3) && | ||||||
|  | 		    (backup.crtr_ver == VHD_VERSION(0, 1) || | ||||||
|  | 		     backup.crtr_ver == VHD_VERSION(1, 1))) { | ||||||
|  | 			char cmp, tmp = backup.hidden; | ||||||
|  | 			backup.hidden = 0; | ||||||
|  | 			cmp = memcmp(&primary, &backup, sizeof(primary)); | ||||||
|  | 			backup.hidden = tmp; | ||||||
|  | 			if (!cmp) | ||||||
|  | 				goto ok; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		err = -EINVAL; | ||||||
|  | 		printf("primary and backup footers do not match\n"); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | ok: | ||||||
|  | 	err = 0; | ||||||
|  | 	memcpy(footer, &primary, sizeof(primary)); | ||||||
|  | 
 | ||||||
|  | out: | ||||||
|  | 	free(buf); | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | vhd_util_check_header(int fd, vhd_footer_t *footer) | ||||||
|  | { | ||||||
|  | 	int err; | ||||||
|  | 	off_t off; | ||||||
|  | 	char *msg, *buf; | ||||||
|  | 	vhd_header_t header; | ||||||
|  | 
 | ||||||
|  | 	err = posix_memalign((void **)&buf, VHD_SECTOR_SIZE, sizeof(header)); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("error allocating header: %d\n", err); | ||||||
|  | 		return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	off = footer->data_offset; | ||||||
|  | 	off = lseek(fd, off, SEEK_SET); | ||||||
|  | 	if (off == (off_t)-1) { | ||||||
|  | 		err = -errno; | ||||||
|  | 		printf("error seeking to header: %d\n", err); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = read(fd, buf, sizeof(header)); | ||||||
|  | 	if (err != sizeof(header)) { | ||||||
|  | 		err = (errno ? -errno : -EIO); | ||||||
|  | 		printf("error reading header: %d\n", err); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	memcpy(&header, buf, sizeof(header)); | ||||||
|  | 	vhd_header_in(&header); | ||||||
|  | 
 | ||||||
|  | 	msg = vhd_util_check_validate_header(fd, &header); | ||||||
|  | 	if (msg) { | ||||||
|  | 		err = -EINVAL; | ||||||
|  | 		printf("header is invalid: %s\n", msg); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = 0; | ||||||
|  | 
 | ||||||
|  | out: | ||||||
|  | 	free(buf); | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | vhd_util_check_differencing_header(vhd_context_t *vhd) | ||||||
|  | { | ||||||
|  | 	char *msg; | ||||||
|  | 
 | ||||||
|  | 	msg = vhd_util_check_validate_differencing_header(vhd); | ||||||
|  | 	if (msg) { | ||||||
|  | 		printf("differencing header is invalid: %s\n", msg); | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | vhd_util_check_bat(vhd_context_t *vhd) | ||||||
|  | { | ||||||
|  | 	off_t eof, eoh; | ||||||
|  | 	int i, j, err, block_size; | ||||||
|  | 
 | ||||||
|  | 	err = vhd_seek(vhd, 0, SEEK_END); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("error calculating eof: %d\n", err); | ||||||
|  | 		return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	eof = vhd_position(vhd); | ||||||
|  | 	if (eof == (off_t)-1) { | ||||||
|  | 		printf("error calculating eof: %d\n", -errno); | ||||||
|  | 		return -errno; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* adjust eof for vhds with short footers */ | ||||||
|  | 	if (eof % 512) { | ||||||
|  | 		if (eof % 512 != 511) { | ||||||
|  | 			printf("invalid file size: 0x%"PRIx64"\n", eof); | ||||||
|  | 			return -EINVAL; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		eof++; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = vhd_get_bat(vhd); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("error reading bat: %d\n", err); | ||||||
|  | 		return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = vhd_end_of_headers(vhd, &eoh); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("error calculating end of metadata: %d\n", err); | ||||||
|  | 		return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	eof  -= sizeof(vhd_footer_t); | ||||||
|  | 	eof >>= VHD_SECTOR_SHIFT; | ||||||
|  | 	eoh >>= VHD_SECTOR_SHIFT; | ||||||
|  | 	block_size = vhd->spb + vhd->bm_secs; | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < vhd->header.max_bat_size; i++) { | ||||||
|  | 		uint32_t off = vhd->bat.bat[i]; | ||||||
|  | 		if (off == DD_BLK_UNUSED) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		if (off < eoh) { | ||||||
|  | 			printf("block %d (offset 0x%x) clobbers headers\n", | ||||||
|  | 			       i, off); | ||||||
|  | 			return -EINVAL; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (off + block_size > eof) { | ||||||
|  | 			printf("block %d (offset 0x%x) clobbers footer\n", | ||||||
|  | 			       i, off); | ||||||
|  | 			return -EINVAL; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		for (j = 0; j < vhd->header.max_bat_size; j++) { | ||||||
|  | 			uint32_t joff = vhd->bat.bat[j]; | ||||||
|  | 
 | ||||||
|  | 			if (i == j) | ||||||
|  | 				continue; | ||||||
|  | 
 | ||||||
|  | 			if (joff == DD_BLK_UNUSED) | ||||||
|  | 				continue; | ||||||
|  | 
 | ||||||
|  | 			if (off == joff) | ||||||
|  | 				err = -EINVAL; | ||||||
|  | 
 | ||||||
|  | 			if (off > joff && off < joff + block_size) | ||||||
|  | 				err = -EINVAL; | ||||||
|  | 
 | ||||||
|  | 			if (off + block_size > joff && | ||||||
|  | 			    off + block_size < joff + block_size) | ||||||
|  | 				err = -EINVAL; | ||||||
|  | 
 | ||||||
|  | 			if (err) { | ||||||
|  | 				printf("block %d (offset 0x%x) clobbers " | ||||||
|  | 				       "block %d (offset 0x%x)\n", | ||||||
|  | 				       i, off, j, joff); | ||||||
|  | 				return err; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | vhd_util_check_batmap(vhd_context_t *vhd) | ||||||
|  | { | ||||||
|  | 	char *msg; | ||||||
|  | 	int i, err; | ||||||
|  | 
 | ||||||
|  | 	err = vhd_get_bat(vhd); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("error reading bat: %d\n", err); | ||||||
|  | 		return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = vhd_get_batmap(vhd); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("error reading batmap: %d\n", err); | ||||||
|  | 		return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	msg = vhd_util_check_validate_batmap(vhd, &vhd->batmap); | ||||||
|  | 	if (msg) { | ||||||
|  | 		printf("batmap is invalid: %s\n", msg); | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < vhd->header.max_bat_size; i++) { | ||||||
|  | 		if (!vhd_batmap_test(vhd, &vhd->batmap, i)) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		if (vhd->bat.bat[i] == DD_BLK_UNUSED) { | ||||||
|  | 			printf("batmap shows unallocated block %d full\n", i); | ||||||
|  | 			return -EINVAL; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | vhd_util_check_parent_locators(vhd_context_t *vhd) | ||||||
|  | { | ||||||
|  | 	int i, n, err; | ||||||
|  | 	vhd_parent_locator_t *loc; | ||||||
|  | 	char *file, *ppath, *location, *pname; | ||||||
|  | 	const char *msg; | ||||||
|  | 	int mac, macx, w2ku, w2ru, wi2r, wi2k, found; | ||||||
|  | 
 | ||||||
|  | 	mac      = 0; | ||||||
|  | 	macx     = 0; | ||||||
|  | 	w2ku     = 0; | ||||||
|  | 	w2ru     = 0; | ||||||
|  | 	wi2r     = 0; | ||||||
|  | 	wi2k     = 0; | ||||||
|  | 	found    = 0; | ||||||
|  | 	pname    = NULL; | ||||||
|  | 	ppath    = NULL; | ||||||
|  | 	location = NULL; | ||||||
|  | 
 | ||||||
|  | 	err = vhd_header_decode_parent(vhd, &vhd->header, &pname); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("error decoding parent name: %d\n", err); | ||||||
|  | 		return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	n = sizeof(vhd->header.loc) / sizeof(vhd->header.loc[0]); | ||||||
|  | 	for (i = 0; i < n; i++) { | ||||||
|  | 		ppath    = NULL; | ||||||
|  | 		location = NULL; | ||||||
|  | 		loc = vhd->header.loc + i; | ||||||
|  | 
 | ||||||
|  | 		msg = vhd_util_check_validate_parent_locator(vhd, loc); | ||||||
|  | 		if (msg) { | ||||||
|  | 			err = -EINVAL; | ||||||
|  | 			printf("invalid parent locator %d: %s\n", i, msg); | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (loc->code == PLAT_CODE_NONE) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		switch (loc->code) { | ||||||
|  | 		case PLAT_CODE_MACX: | ||||||
|  | 			if (macx++) | ||||||
|  | 				goto dup; | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 		case PLAT_CODE_MAC: | ||||||
|  | 			if (mac++) | ||||||
|  | 				goto dup; | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 		case PLAT_CODE_W2KU: | ||||||
|  | 			if (w2ku++) | ||||||
|  | 				goto dup; | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 		case PLAT_CODE_W2RU: | ||||||
|  | 			if (w2ru++) | ||||||
|  | 				goto dup; | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 		case PLAT_CODE_WI2R: | ||||||
|  | 			if (wi2r++) | ||||||
|  | 				goto dup; | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 		case PLAT_CODE_WI2K: | ||||||
|  | 			if (wi2k++) | ||||||
|  | 				goto dup; | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 		default: | ||||||
|  | 			err = -EINVAL; | ||||||
|  | 			printf("invalid  platform code for locator %d\n", i); | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (loc->code != PLAT_CODE_MACX && | ||||||
|  | 		    loc->code != PLAT_CODE_W2RU && | ||||||
|  | 		    loc->code != PLAT_CODE_W2KU) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		err = vhd_parent_locator_read(vhd, loc, &ppath); | ||||||
|  | 		if (err) { | ||||||
|  | 			printf("error reading parent locator %d: %d\n", i, err); | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		file = basename(ppath); | ||||||
|  | 		if (strcmp(pname, file)) { | ||||||
|  | 			err = -EINVAL; | ||||||
|  | 			printf("parent locator %d name (%s) does not match " | ||||||
|  | 			       "header name (%s)\n", i, file, pname); | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		err = vhd_find_parent(vhd, ppath, &location); | ||||||
|  | 		if (err) { | ||||||
|  | 			printf("error resolving %s: %d\n", ppath, err); | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		err = access(location, R_OK); | ||||||
|  | 		if (err && loc->code == PLAT_CODE_MACX) { | ||||||
|  | 			err = -errno; | ||||||
|  | 			printf("parent locator %d points to missing file %s " | ||||||
|  | 				"(resolved to %s)\n", i, ppath, location); | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		msg = vhd_util_check_validate_parent(vhd, location); | ||||||
|  | 		if (msg) { | ||||||
|  | 			err = -EINVAL; | ||||||
|  | 			printf("invalid parent %s: %s\n", location, msg); | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		found++; | ||||||
|  | 		free(ppath); | ||||||
|  | 		free(location); | ||||||
|  | 		ppath = NULL; | ||||||
|  | 		location = NULL; | ||||||
|  | 
 | ||||||
|  | 		continue; | ||||||
|  | 
 | ||||||
|  | 	dup: | ||||||
|  | 		printf("duplicate platform code in locator %d: 0x%x\n", | ||||||
|  | 		       i, loc->code); | ||||||
|  | 		err = -EINVAL; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!found) { | ||||||
|  | 		err = -EINVAL; | ||||||
|  | 		printf("could not find parent %s\n", pname); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = 0; | ||||||
|  | 
 | ||||||
|  | out: | ||||||
|  | 	free(pname); | ||||||
|  | 	free(ppath); | ||||||
|  | 	free(location); | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | vhd_util_dump_headers(const char *name) | ||||||
|  | { | ||||||
|  | 	char *argv[] = { "read", "-p", "-n", (char *)name }; | ||||||
|  | 	int argc = sizeof(argv) / sizeof(argv[0]); | ||||||
|  | 
 | ||||||
|  | 	printf("%s appears invalid; dumping metadata\n", name); | ||||||
|  | 	vhd_util_read(argc, argv); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | vhd_util_check_vhd(const char *name, int ignore) | ||||||
|  | { | ||||||
|  | 	int fd, err; | ||||||
|  | 	vhd_context_t vhd; | ||||||
|  | 	struct stat stats; | ||||||
|  | 	vhd_footer_t footer; | ||||||
|  | 
 | ||||||
|  | 	fd = -1; | ||||||
|  | 	memset(&vhd, 0, sizeof(vhd)); | ||||||
|  |         memset(&footer, 0, sizeof(footer)); | ||||||
|  | 
 | ||||||
|  | 	err = stat(name, &stats); | ||||||
|  | 	if (err == -1) { | ||||||
|  | 		printf("cannot stat %s: %d\n", name, errno); | ||||||
|  | 		return -errno; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!S_ISREG(stats.st_mode) && !S_ISBLK(stats.st_mode)) { | ||||||
|  | 		printf("%s is not a regular file or block device\n", name); | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	fd = open(name, O_RDONLY | O_DIRECT | O_LARGEFILE); | ||||||
|  | 	if (fd == -1) { | ||||||
|  | 		printf("error opening %s\n", name); | ||||||
|  | 		return -errno; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = vhd_util_check_footer(fd, &footer, ignore); | ||||||
|  | 	if (err) | ||||||
|  | 		goto out; | ||||||
|  | 
 | ||||||
|  | 	if (footer.type != HD_TYPE_DYNAMIC && footer.type != HD_TYPE_DIFF) | ||||||
|  | 		goto out; | ||||||
|  | 
 | ||||||
|  | 	err = vhd_util_check_header(fd, &footer); | ||||||
|  | 	if (err) | ||||||
|  | 		goto out; | ||||||
|  | 
 | ||||||
|  | 	err = vhd_open(&vhd, name, VHD_OPEN_RDONLY | VHD_OPEN_IGNORE_DISABLED); | ||||||
|  | 	if (err) | ||||||
|  | 		goto out; | ||||||
|  | 
 | ||||||
|  | 	err = vhd_util_check_differencing_header(&vhd); | ||||||
|  | 	if (err) | ||||||
|  | 		goto out; | ||||||
|  | 
 | ||||||
|  | 	err = vhd_util_check_bat(&vhd); | ||||||
|  | 	if (err) | ||||||
|  | 		goto out; | ||||||
|  | 
 | ||||||
|  | 	if (vhd_has_batmap(&vhd)) { | ||||||
|  | 		err = vhd_util_check_batmap(&vhd); | ||||||
|  | 		if (err) | ||||||
|  | 			goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (vhd.footer.type == HD_TYPE_DIFF) { | ||||||
|  | 		err = vhd_util_check_parent_locators(&vhd); | ||||||
|  | 		if (err) | ||||||
|  | 			goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = 0; | ||||||
|  | 	printf("%s is valid\n", name); | ||||||
|  | 
 | ||||||
|  | out: | ||||||
|  | 	if (err) | ||||||
|  | 		vhd_util_dump_headers(name); | ||||||
|  | 	if (fd != -1) | ||||||
|  | 		close(fd); | ||||||
|  | 	vhd_close(&vhd); | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | vhd_util_check_parents(const char *name, int ignore) | ||||||
|  | { | ||||||
|  | 	int err; | ||||||
|  | 	vhd_context_t vhd; | ||||||
|  | 	char *cur, *parent; | ||||||
|  | 
 | ||||||
|  | 	cur = (char *)name; | ||||||
|  | 
 | ||||||
|  | 	for (;;) { | ||||||
|  | 		err = vhd_open(&vhd, cur,  | ||||||
|  | 				VHD_OPEN_RDONLY | VHD_OPEN_IGNORE_DISABLED); | ||||||
|  | 		if (err) | ||||||
|  | 			goto out; | ||||||
|  | 
 | ||||||
|  | 		if (vhd.footer.type != HD_TYPE_DIFF || vhd_parent_raw(&vhd)) { | ||||||
|  | 			vhd_close(&vhd); | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		err = vhd_parent_locator_get(&vhd, &parent); | ||||||
|  | 		vhd_close(&vhd); | ||||||
|  | 
 | ||||||
|  | 		if (err) { | ||||||
|  | 			printf("error getting parent: %d\n", err); | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (cur != name) | ||||||
|  | 			free(cur); | ||||||
|  | 		cur = parent; | ||||||
|  | 
 | ||||||
|  | 		err = vhd_util_check_vhd(cur, ignore); | ||||||
|  | 		if (err) | ||||||
|  | 			goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | out: | ||||||
|  | 	if (err) | ||||||
|  | 		printf("error checking parents: %d\n", err); | ||||||
|  | 	if (cur != name) | ||||||
|  | 		free(cur); | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | vhd_util_check(int argc, char **argv) | ||||||
|  | { | ||||||
|  | 	char *name; | ||||||
|  | 	vhd_context_t vhd; | ||||||
|  | 	int c, err, ignore, parents; | ||||||
|  | 
 | ||||||
|  | 	if (!argc || !argv) { | ||||||
|  | 		err = -EINVAL; | ||||||
|  | 		goto usage; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ignore  = 0; | ||||||
|  | 	parents = 0; | ||||||
|  | 	name    = NULL; | ||||||
|  | 
 | ||||||
|  | 	optind = 0; | ||||||
|  | 	while ((c = getopt(argc, argv, "n:iph")) != -1) { | ||||||
|  | 		switch (c) { | ||||||
|  | 		case 'n': | ||||||
|  | 			name = optarg; | ||||||
|  | 			break; | ||||||
|  | 		case 'i': | ||||||
|  | 			ignore = 1; | ||||||
|  | 			break; | ||||||
|  | 		case 'p': | ||||||
|  | 			parents = 1; | ||||||
|  | 			break; | ||||||
|  | 		case 'h': | ||||||
|  | 			err = 0; | ||||||
|  | 			goto usage; | ||||||
|  | 		default: | ||||||
|  | 			err = -EINVAL; | ||||||
|  | 			goto usage; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!name || optind != argc) { | ||||||
|  | 		err = -EINVAL; | ||||||
|  | 		goto usage; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = vhd_util_check_vhd(name, ignore); | ||||||
|  | 	if (err) | ||||||
|  | 		goto out; | ||||||
|  | 
 | ||||||
|  | 	if (parents) | ||||||
|  | 		err = vhd_util_check_parents(name, ignore); | ||||||
|  | 
 | ||||||
|  | out: | ||||||
|  | 	return err; | ||||||
|  | 
 | ||||||
|  | usage: | ||||||
|  | 	printf("options: -n <file> [-i ignore missing primary footers] " | ||||||
|  | 	       "[-p check parents] [-h help]\n"); | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
							
								
								
									
										218
									
								
								tools/vhd-tools/vhd/lib/vhd-util-coalesce.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										218
									
								
								tools/vhd-tools/vhd/lib/vhd-util-coalesce.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,218 @@ | |||||||
|  | /* Copyright (c) 2008, XenSource Inc.
 | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of XenSource Inc. nor the names of its contributors | ||||||
|  |  *       may be used to endorse or promote products derived from this software | ||||||
|  |  *       without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||||||
|  |  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||||
|  |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||||
|  |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||||
|  |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||||
|  |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||||
|  |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | */ | ||||||
|  | #include <errno.h> | ||||||
|  | #include <fcntl.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | 
 | ||||||
|  | #include "libvhd.h" | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | __raw_io_write(int fd, char* buf, uint64_t sec, uint32_t secs) | ||||||
|  | { | ||||||
|  | 	off_t off; | ||||||
|  | 	size_t ret; | ||||||
|  | 
 | ||||||
|  | 	errno = 0; | ||||||
|  | 	off = lseek(fd, vhd_sectors_to_bytes(sec), SEEK_SET); | ||||||
|  | 	if (off == (off_t)-1) { | ||||||
|  | 		printf("raw parent: seek(0x%08"PRIx64") failed: %d\n", | ||||||
|  | 		       vhd_sectors_to_bytes(sec), -errno); | ||||||
|  | 		return -errno; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ret = write(fd, buf, vhd_sectors_to_bytes(secs)); | ||||||
|  | 	if (ret == vhd_sectors_to_bytes(secs)) | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
|  | 	printf("raw parent: write of 0x%"PRIx64" returned %zd, errno: %d\n", | ||||||
|  | 	       vhd_sectors_to_bytes(secs), ret, -errno); | ||||||
|  | 	return (errno ? -errno : -EIO); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Use 'parent' if the parent is VHD, and 'parent_fd' if the parent is raw | ||||||
|  |  */ | ||||||
|  | static int | ||||||
|  | vhd_util_coalesce_block(vhd_context_t *vhd, vhd_context_t *parent, | ||||||
|  | 		int parent_fd, uint64_t block) | ||||||
|  | { | ||||||
|  | 	int i, err; | ||||||
|  | 	char *buf, *map; | ||||||
|  | 	uint64_t sec, secs; | ||||||
|  | 
 | ||||||
|  | 	buf = NULL; | ||||||
|  | 	map = NULL; | ||||||
|  | 	sec = block * vhd->spb; | ||||||
|  | 
 | ||||||
|  | 	if (vhd->bat.bat[block] == DD_BLK_UNUSED) | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
|  | 	err = posix_memalign((void **)&buf, 4096, vhd->header.block_size); | ||||||
|  | 	if (err) | ||||||
|  | 		return -err; | ||||||
|  | 
 | ||||||
|  | 	err = vhd_io_read(vhd, buf, sec, vhd->spb); | ||||||
|  | 	if (err) | ||||||
|  | 		goto done; | ||||||
|  | 
 | ||||||
|  | 	if (vhd_has_batmap(vhd) && vhd_batmap_test(vhd, &vhd->batmap, block)) { | ||||||
|  | 		if (parent->file) | ||||||
|  | 			err = vhd_io_write(parent, buf, sec, vhd->spb); | ||||||
|  | 		else | ||||||
|  | 			err = __raw_io_write(parent_fd, buf, sec, vhd->spb); | ||||||
|  | 		goto done; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = vhd_read_bitmap(vhd, block, &map); | ||||||
|  | 	if (err) | ||||||
|  | 		goto done; | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < vhd->spb; i++) { | ||||||
|  | 		if (!vhd_bitmap_test(vhd, map, i)) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		for (secs = 0; i + secs < vhd->spb; secs++) | ||||||
|  | 			if (!vhd_bitmap_test(vhd, map, i + secs)) | ||||||
|  | 				break; | ||||||
|  | 
 | ||||||
|  | 		if (parent->file) | ||||||
|  | 			err = vhd_io_write(parent, | ||||||
|  | 					   buf + vhd_sectors_to_bytes(i), | ||||||
|  | 					   sec + i, secs); | ||||||
|  | 		else | ||||||
|  | 			err = __raw_io_write(parent_fd, | ||||||
|  | 					     buf + vhd_sectors_to_bytes(i), | ||||||
|  | 					     sec + i, secs); | ||||||
|  | 		if (err) | ||||||
|  | 			goto done; | ||||||
|  | 
 | ||||||
|  | 		i += secs; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = 0; | ||||||
|  | 
 | ||||||
|  | done: | ||||||
|  | 	free(buf); | ||||||
|  | 	free(map); | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | vhd_util_coalesce(int argc, char **argv) | ||||||
|  | { | ||||||
|  | 	int err, c; | ||||||
|  | 	uint64_t i; | ||||||
|  | 	char *name, *pname; | ||||||
|  | 	vhd_context_t vhd, parent; | ||||||
|  | 	int parent_fd = -1; | ||||||
|  | 
 | ||||||
|  | 	name  = NULL; | ||||||
|  | 	pname = NULL; | ||||||
|  | 	parent.file = NULL; | ||||||
|  | 
 | ||||||
|  | 	if (!argc || !argv) | ||||||
|  | 		goto usage; | ||||||
|  | 
 | ||||||
|  | 	optind = 0; | ||||||
|  | 	while ((c = getopt(argc, argv, "n:h")) != -1) { | ||||||
|  | 		switch (c) { | ||||||
|  | 		case 'n': | ||||||
|  | 			name = optarg; | ||||||
|  | 			break; | ||||||
|  | 		case 'h': | ||||||
|  | 		default: | ||||||
|  | 			goto usage; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!name || optind != argc) | ||||||
|  | 		goto usage; | ||||||
|  | 
 | ||||||
|  | 	err = vhd_open(&vhd, name, VHD_OPEN_RDONLY); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("error opening %s: %d\n", name, err); | ||||||
|  | 		return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = vhd_parent_locator_get(&vhd, &pname); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("error finding %s parent: %d\n", name, err); | ||||||
|  | 		vhd_close(&vhd); | ||||||
|  | 		return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (vhd_parent_raw(&vhd)) { | ||||||
|  | 		parent_fd = open(pname, O_RDWR | O_DIRECT | O_LARGEFILE, 0644); | ||||||
|  | 		if (parent_fd == -1) { | ||||||
|  | 			err = -errno; | ||||||
|  | 			printf("failed to open parent %s: %d\n", pname, err); | ||||||
|  | 			vhd_close(&vhd); | ||||||
|  | 			return err; | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		err = vhd_open(&parent, pname, VHD_OPEN_RDWR); | ||||||
|  | 		if (err) { | ||||||
|  | 			printf("error opening %s: %d\n", pname, err); | ||||||
|  | 			free(pname); | ||||||
|  | 			vhd_close(&vhd); | ||||||
|  | 			return err; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = vhd_get_bat(&vhd); | ||||||
|  | 	if (err) | ||||||
|  | 		goto done; | ||||||
|  | 
 | ||||||
|  | 	if (vhd_has_batmap(&vhd)) { | ||||||
|  | 		err = vhd_get_batmap(&vhd); | ||||||
|  | 		if (err) | ||||||
|  | 			goto done; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < vhd.bat.entries; i++) { | ||||||
|  | 		err = vhd_util_coalesce_block(&vhd, &parent, parent_fd, i); | ||||||
|  | 		if (err) | ||||||
|  | 			goto done; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = 0; | ||||||
|  | 
 | ||||||
|  |  done: | ||||||
|  | 	free(pname); | ||||||
|  | 	vhd_close(&vhd); | ||||||
|  | 	if (parent.file) | ||||||
|  | 		vhd_close(&parent); | ||||||
|  | 	else | ||||||
|  | 		close(parent_fd); | ||||||
|  | 	return err; | ||||||
|  | 
 | ||||||
|  | usage: | ||||||
|  | 	printf("options: <-n name> [-h help]\n"); | ||||||
|  | 	return -EINVAL; | ||||||
|  | } | ||||||
							
								
								
									
										80
									
								
								tools/vhd-tools/vhd/lib/vhd-util-create.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								tools/vhd-tools/vhd/lib/vhd-util-create.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,80 @@ | |||||||
|  | /* Copyright (c) 2008, XenSource Inc.
 | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of XenSource Inc. nor the names of its contributors | ||||||
|  |  *       may be used to endorse or promote products derived from this software | ||||||
|  |  *       without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||||||
|  |  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||||
|  |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||||
|  |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||||
|  |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||||
|  |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||||
|  |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | */ | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | 
 | ||||||
|  | #include "libvhd.h" | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | vhd_util_create(int argc, char **argv) | ||||||
|  | { | ||||||
|  | 	char *name; | ||||||
|  | 	uint64_t size; | ||||||
|  | 	int c, sparse, err; | ||||||
|  | 	vhd_flag_creat_t flags; | ||||||
|  | 
 | ||||||
|  | 	err       = -EINVAL; | ||||||
|  | 	size      = 0; | ||||||
|  | 	sparse    = 1; | ||||||
|  | 	name      = NULL; | ||||||
|  | 	flags     = 0; | ||||||
|  | 
 | ||||||
|  | 	if (!argc || !argv) | ||||||
|  | 		goto usage; | ||||||
|  | 
 | ||||||
|  | 	optind = 0; | ||||||
|  | 	while ((c = getopt(argc, argv, "n:s:rh")) != -1) { | ||||||
|  | 		switch (c) { | ||||||
|  | 		case 'n': | ||||||
|  | 			name = optarg; | ||||||
|  | 			break; | ||||||
|  | 		case 's': | ||||||
|  | 			err  = 0; | ||||||
|  | 			size = strtoull(optarg, NULL, 10); | ||||||
|  | 			break; | ||||||
|  | 		case 'r': | ||||||
|  | 			sparse = 0; | ||||||
|  | 			break; | ||||||
|  | 		case 'h': | ||||||
|  | 		default: | ||||||
|  | 			goto usage; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (err || !name || optind != argc) | ||||||
|  | 		goto usage; | ||||||
|  | 
 | ||||||
|  | 	return vhd_create(name, size << 20, | ||||||
|  | 				  (sparse ? HD_TYPE_DYNAMIC : HD_TYPE_FIXED), | ||||||
|  | 				  flags); | ||||||
|  | 
 | ||||||
|  | usage: | ||||||
|  | 	printf("options: <-n name> <-s size (MB)> [-r reserve] [-h help]\n"); | ||||||
|  | 	return -EINVAL; | ||||||
|  | } | ||||||
							
								
								
									
										105
									
								
								tools/vhd-tools/vhd/lib/vhd-util-fill.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								tools/vhd-tools/vhd/lib/vhd-util-fill.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,105 @@ | |||||||
|  | /* Copyright (c) 2008, XenSource Inc.
 | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of XenSource Inc. nor the names of its contributors | ||||||
|  |  *       may be used to endorse or promote products derived from this software | ||||||
|  |  *       without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||||||
|  |  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||||
|  |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||||
|  |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||||
|  |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||||
|  |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||||
|  |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | */ | ||||||
|  | #include <errno.h> | ||||||
|  | #include <fcntl.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | 
 | ||||||
|  | #include "libvhd.h" | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | vhd_util_fill(int argc, char **argv) | ||||||
|  | { | ||||||
|  | 	int err, c; | ||||||
|  | 	char *buf, *name; | ||||||
|  | 	vhd_context_t vhd; | ||||||
|  | 	uint64_t i, sec, secs; | ||||||
|  | 
 | ||||||
|  | 	buf  = NULL; | ||||||
|  | 	name = NULL; | ||||||
|  | 
 | ||||||
|  | 	if (!argc || !argv) | ||||||
|  | 		goto usage; | ||||||
|  | 
 | ||||||
|  | 	optind = 0; | ||||||
|  | 	while ((c = getopt(argc, argv, "n:h")) != -1) { | ||||||
|  | 		switch (c) { | ||||||
|  | 		case 'n': | ||||||
|  | 			name = optarg; | ||||||
|  | 			break; | ||||||
|  | 		case 'h': | ||||||
|  | 		default: | ||||||
|  | 			goto usage; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!name || optind != argc) | ||||||
|  | 		goto usage; | ||||||
|  | 
 | ||||||
|  | 	err = vhd_open(&vhd, name, VHD_OPEN_RDWR); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("error opening %s: %d\n", name, err); | ||||||
|  | 		return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = vhd_get_bat(&vhd); | ||||||
|  | 	if (err) | ||||||
|  | 		goto done; | ||||||
|  | 
 | ||||||
|  | 	err = posix_memalign((void **)&buf, 4096, vhd.header.block_size); | ||||||
|  | 	if (err) { | ||||||
|  | 		err = -err; | ||||||
|  | 		goto done; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	sec  = 0; | ||||||
|  | 	secs = vhd.header.block_size >> VHD_SECTOR_SHIFT; | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < vhd.header.max_bat_size; i++) { | ||||||
|  | 		err = vhd_io_read(&vhd, buf, sec, secs); | ||||||
|  | 		if (err) | ||||||
|  | 			goto done; | ||||||
|  | 
 | ||||||
|  | 		err = vhd_io_write(&vhd, buf, sec, secs); | ||||||
|  | 		if (err) | ||||||
|  | 			goto done; | ||||||
|  | 
 | ||||||
|  | 		sec += secs; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = 0; | ||||||
|  | 
 | ||||||
|  |  done: | ||||||
|  | 	free(buf); | ||||||
|  | 	vhd_close(&vhd); | ||||||
|  | 	return err; | ||||||
|  | 
 | ||||||
|  | usage: | ||||||
|  | 	printf("options: <-n name> [-h help]\n"); | ||||||
|  | 	return -EINVAL; | ||||||
|  | } | ||||||
							
								
								
									
										132
									
								
								tools/vhd-tools/vhd/lib/vhd-util-modify.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								tools/vhd-tools/vhd/lib/vhd-util-modify.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,132 @@ | |||||||
|  | /* Copyright (c) 2008, XenSource Inc.
 | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of XenSource Inc. nor the names of its contributors | ||||||
|  |  *       may be used to endorse or promote products derived from this software | ||||||
|  |  *       without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||||||
|  |  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||||
|  |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||||
|  |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||||
|  |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||||
|  |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||||
|  |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  * | ||||||
|  |  * Altering operations: | ||||||
|  |  * | ||||||
|  |  * 1. Change the parent pointer to another file. | ||||||
|  |  * 2. Change the size of the file containing the VHD image. This does NOT  | ||||||
|  |  * affect the VHD disk capacity, only the physical size of the file containing  | ||||||
|  |  * the VHD. Naturally, it is not possible to set the file size to be less than   | ||||||
|  |  * the what VHD utilizes. | ||||||
|  |  * The operation doesn't actually change the file size, but it writes the  | ||||||
|  |  * footer in the right location such that resizing the file (manually, as a  | ||||||
|  |  * separate step) will produce the correct results. If the new file size is  | ||||||
|  |  * greater than the current file size, the file must first be expanded and then  | ||||||
|  |  * altered with this operation. If the new size is smaller than the current  | ||||||
|  |  * size, the VHD must first be altered with this operation and then the file  | ||||||
|  |  * must be shrunk. Failing to resize the file will result in a corrupted VHD. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <errno.h> | ||||||
|  | #include <fcntl.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | 
 | ||||||
|  | #include "libvhd.h" | ||||||
|  | 
 | ||||||
|  | TEST_FAIL_EXTERN_VARS; | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | vhd_util_modify(int argc, char **argv) | ||||||
|  | { | ||||||
|  | 	char *name; | ||||||
|  | 	vhd_context_t vhd; | ||||||
|  | 	int err, c, size, parent, parent_raw; | ||||||
|  | 	off_t newsize = 0; | ||||||
|  | 	char *newparent = NULL; | ||||||
|  | 
 | ||||||
|  | 	name       = NULL; | ||||||
|  | 	size       = 0; | ||||||
|  | 	parent     = 0; | ||||||
|  | 	parent_raw = 0; | ||||||
|  | 
 | ||||||
|  | 	optind = 0; | ||||||
|  | 	while ((c = getopt(argc, argv, "n:s:p:mh")) != -1) { | ||||||
|  | 		switch (c) { | ||||||
|  | 		case 'n': | ||||||
|  | 			name = optarg; | ||||||
|  | 			break; | ||||||
|  | 		case 's': | ||||||
|  | 			size = 1; | ||||||
|  | 			errno = 0; | ||||||
|  | 			newsize = strtoll(optarg, NULL, 10); | ||||||
|  | 			if (errno) { | ||||||
|  | 				fprintf(stderr, "Invalid size '%s'\n", optarg); | ||||||
|  | 				goto usage; | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 		case 'p': | ||||||
|  | 			parent = 1; | ||||||
|  | 			newparent = optarg; | ||||||
|  | 			break; | ||||||
|  | 		case 'm': | ||||||
|  | 			parent_raw = 1; | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 		case 'h': | ||||||
|  | 		default: | ||||||
|  | 			goto usage; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!name || optind != argc) | ||||||
|  | 		goto usage; | ||||||
|  | 
 | ||||||
|  | 	err = vhd_open(&vhd, name, VHD_OPEN_RDWR); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("error opening %s: %d\n", name, err); | ||||||
|  | 		return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (size) { | ||||||
|  | 		err = vhd_set_phys_size(&vhd, newsize); | ||||||
|  | 		if (err) | ||||||
|  | 			printf("failed to set physical size to %"PRIu64":" | ||||||
|  | 			       " %d\n", newsize, err); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (parent) { | ||||||
|  | 		TEST_FAIL_AT(FAIL_REPARENT_BEGIN); | ||||||
|  | 		err = vhd_change_parent(&vhd, newparent, parent_raw); | ||||||
|  | 		if (err) { | ||||||
|  | 			printf("failed to set parent to '%s': %d\n", | ||||||
|  | 					newparent, err); | ||||||
|  | 			goto done; | ||||||
|  | 		} | ||||||
|  | 		TEST_FAIL_AT(FAIL_REPARENT_END); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | done: | ||||||
|  | 	vhd_close(&vhd); | ||||||
|  | 	return err; | ||||||
|  | 
 | ||||||
|  | usage: | ||||||
|  | 	printf("*** Dangerous operations, use with care ***\n"); | ||||||
|  | 	printf("options: <-n name> [-p NEW_PARENT set parent [-m raw]] " | ||||||
|  | 			"[-s NEW_SIZE set size] [-h help]\n"); | ||||||
|  | 	return -EINVAL; | ||||||
|  | } | ||||||
							
								
								
									
										159
									
								
								tools/vhd-tools/vhd/lib/vhd-util-query.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								tools/vhd-tools/vhd/lib/vhd-util-query.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,159 @@ | |||||||
|  | /* Copyright (c) 2008, XenSource Inc.
 | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of XenSource Inc. nor the names of its contributors | ||||||
|  |  *       may be used to endorse or promote products derived from this software | ||||||
|  |  *       without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||||||
|  |  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||||
|  |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||||
|  |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||||
|  |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||||
|  |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||||
|  |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | */ | ||||||
|  | #include <errno.h> | ||||||
|  | #include <fcntl.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | 
 | ||||||
|  | #include "libvhd.h" | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | vhd_util_query(int argc, char **argv) | ||||||
|  | { | ||||||
|  | 	char *name; | ||||||
|  | 	vhd_context_t vhd; | ||||||
|  | 	off_t currsize; | ||||||
|  | 	int ret, err, c, size, physize, parent, fields, depth; | ||||||
|  | 
 | ||||||
|  | 	name    = NULL; | ||||||
|  | 	size    = 0; | ||||||
|  | 	physize = 0; | ||||||
|  | 	parent  = 0; | ||||||
|  | 	fields  = 0; | ||||||
|  | 	depth   = 0; | ||||||
|  | 
 | ||||||
|  | 	if (!argc || !argv) { | ||||||
|  | 		err = -EINVAL; | ||||||
|  | 		goto usage; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	optind = 0; | ||||||
|  | 	while ((c = getopt(argc, argv, "n:vspfdh")) != -1) { | ||||||
|  | 		switch (c) { | ||||||
|  | 		case 'n': | ||||||
|  | 			name = optarg; | ||||||
|  | 			break; | ||||||
|  | 		case 'v': | ||||||
|  | 			size = 1; | ||||||
|  | 			break; | ||||||
|  | 		case 's': | ||||||
|  | 			physize = 1; | ||||||
|  | 			break; | ||||||
|  | 		case 'p': | ||||||
|  | 			parent = 1; | ||||||
|  | 			break; | ||||||
|  | 		case 'f': | ||||||
|  | 			fields = 1; | ||||||
|  | 			break; | ||||||
|  | 		case 'd': | ||||||
|  | 			depth = 1; | ||||||
|  | 			break; | ||||||
|  | 		case 'h': | ||||||
|  | 			err = 0; | ||||||
|  | 			goto usage; | ||||||
|  | 		default: | ||||||
|  | 			err = -EINVAL; | ||||||
|  | 			goto usage; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!name || optind != argc) { | ||||||
|  | 		err = -EINVAL; | ||||||
|  | 		goto usage; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = vhd_open(&vhd, name, VHD_OPEN_RDONLY | VHD_OPEN_IGNORE_DISABLED); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("error opening %s: %d\n", name, err); | ||||||
|  | 		return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (size) | ||||||
|  | 		printf("%"PRIu64"\n", vhd.footer.curr_size >> 20); | ||||||
|  | 
 | ||||||
|  | 	if (physize) { | ||||||
|  | 		err = vhd_get_phys_size(&vhd, &currsize); | ||||||
|  | 		if (err) | ||||||
|  | 			printf("failed to get physical size: %d\n", err); | ||||||
|  | 		else | ||||||
|  | 			printf("%"PRIu64"\n", currsize); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (parent) { | ||||||
|  | 		ret = 0; | ||||||
|  | 
 | ||||||
|  | 		if (vhd.footer.type != HD_TYPE_DIFF) | ||||||
|  | 			printf("%s has no parent\n", name); | ||||||
|  | 		else { | ||||||
|  | 			char *pname; | ||||||
|  | 
 | ||||||
|  | 			ret = vhd_parent_locator_get(&vhd, &pname); | ||||||
|  | 			if (ret) | ||||||
|  | 				printf("query failed\n"); | ||||||
|  | 			else { | ||||||
|  | 				printf("%s\n", pname); | ||||||
|  | 				free(pname); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		err = (err ? : ret); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (fields) { | ||||||
|  | 		int hidden; | ||||||
|  | 
 | ||||||
|  | 		ret = vhd_hidden(&vhd, &hidden); | ||||||
|  | 		if (ret) | ||||||
|  | 			printf("error checking 'hidden' field: %d\n", ret); | ||||||
|  | 		else | ||||||
|  | 			printf("hidden: %d\n", hidden); | ||||||
|  | 
 | ||||||
|  | 		err = (err ? : ret); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (depth) { | ||||||
|  | 		int length; | ||||||
|  | 
 | ||||||
|  | 		ret = vhd_chain_depth(&vhd, &length); | ||||||
|  | 		if (ret) | ||||||
|  | 			printf("error checking chain depth: %d\n", ret); | ||||||
|  | 		else | ||||||
|  | 			printf("chain depth: %d\n", length); | ||||||
|  | 
 | ||||||
|  | 		err = (err ? : ret); | ||||||
|  | 	} | ||||||
|  | 		 | ||||||
|  | 	vhd_close(&vhd); | ||||||
|  | 	return err; | ||||||
|  | 
 | ||||||
|  | usage: | ||||||
|  | 	printf("options: <-n name> [-v print virtual size (in MB)] " | ||||||
|  | 	       "[-s print physical utilization (bytes)] [-p print parent] " | ||||||
|  | 	       "[-f print fields] [-d print chain depth] [-h help]\n"); | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
							
								
								
									
										742
									
								
								tools/vhd-tools/vhd/lib/vhd-util-read.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										742
									
								
								tools/vhd-tools/vhd/lib/vhd-util-read.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,742 @@ | |||||||
|  | /* Copyright (c) 2008, XenSource Inc.
 | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of XenSource Inc. nor the names of its contributors | ||||||
|  |  *       may be used to endorse or promote products derived from this software | ||||||
|  |  *       without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||||||
|  |  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||||
|  |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||||
|  |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||||
|  |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||||
|  |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||||
|  |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | */ | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include <fcntl.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | #include <inttypes.h> | ||||||
|  | 
 | ||||||
|  | #include "libvhd.h" | ||||||
|  | #include "vhd-util.h" | ||||||
|  | 
 | ||||||
|  | #define nsize     15 | ||||||
|  | static char nbuf[nsize]; | ||||||
|  | 
 | ||||||
|  | static inline char * | ||||||
|  | __xconv(uint64_t num) | ||||||
|  | { | ||||||
|  | 	snprintf(nbuf, nsize, "%#" PRIx64 , num); | ||||||
|  | 	return nbuf; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline char * | ||||||
|  | __dconv(uint64_t num) | ||||||
|  | { | ||||||
|  | 	snprintf(nbuf, nsize, "%" PRIu64, num); | ||||||
|  | 	return nbuf; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #define conv(hex, num) \ | ||||||
|  | 	(hex ? __xconv((uint64_t)num) : __dconv((uint64_t)num)) | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | vhd_print_header(vhd_context_t *vhd, vhd_header_t *h, int hex) | ||||||
|  | { | ||||||
|  | 	int err; | ||||||
|  | 	uint32_t  cksm; | ||||||
|  | 	char      uuid[39], time_str[26], cookie[9], out[512], *name; | ||||||
|  | 
 | ||||||
|  | 	printf("VHD Header Summary:\n-------------------\n"); | ||||||
|  | 
 | ||||||
|  | 	snprintf(cookie, sizeof(cookie), "%s", h->cookie); | ||||||
|  | 	printf("Cookie              : %s\n", cookie); | ||||||
|  | 
 | ||||||
|  | 	printf("Data offset (unusd) : %s\n", conv(hex, h->data_offset)); | ||||||
|  | 	printf("Table offset        : %s\n", conv(hex, h->table_offset)); | ||||||
|  | 	printf("Header version      : 0x%08x\n", h->hdr_ver); | ||||||
|  | 	printf("Max BAT size        : %s\n", conv(hex, h->max_bat_size)); | ||||||
|  | 	printf("Block size          : %s ", conv(hex, h->block_size)); | ||||||
|  | 	printf("(%s MB)\n", conv(hex, h->block_size >> 20)); | ||||||
|  | 
 | ||||||
|  | 	err = vhd_header_decode_parent(vhd, h, &name); | ||||||
|  | 	printf("Parent name         : %s\n", | ||||||
|  | 	       (err ? "failed to read name" : name)); | ||||||
|  | 	free(name); | ||||||
|  | 
 | ||||||
|  | 	blk_uuid_to_string(&h->prt_uuid, uuid, sizeof(uuid)); | ||||||
|  | 	printf("Parent UUID         : %s\n", uuid); | ||||||
|  |      | ||||||
|  | 	vhd_time_to_string(h->prt_ts, time_str); | ||||||
|  | 	printf("Parent timestamp    : %s\n", time_str); | ||||||
|  | 
 | ||||||
|  | 	cksm = vhd_checksum_header(h); | ||||||
|  | 	printf("Checksum            : 0x%x|0x%x (%s)\n", h->checksum, cksm, | ||||||
|  | 		h->checksum == cksm ? "Good!" : "Bad!"); | ||||||
|  | 	printf("\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | vhd_print_footer(vhd_footer_t *f, int hex) | ||||||
|  | { | ||||||
|  | 	uint64_t  c, h, s; | ||||||
|  | 	uint32_t  ff_maj, ff_min, cr_maj, cr_min, cksm, cksm_save; | ||||||
|  | 	char      time_str[26], creator[5], uuid[39], cookie[9]; | ||||||
|  | 
 | ||||||
|  | 	printf("VHD Footer Summary:\n-------------------\n"); | ||||||
|  | 
 | ||||||
|  | 	snprintf(cookie, sizeof(cookie), "%s", f->cookie); | ||||||
|  | 	printf("Cookie              : %s\n", cookie); | ||||||
|  | 
 | ||||||
|  | 	printf("Features            : (0x%08x) %s%s\n", f->features, | ||||||
|  | 		(f->features & HD_TEMPORARY) ? "<TEMP>" : "", | ||||||
|  | 		(f->features & HD_RESERVED)  ? "<RESV>" : ""); | ||||||
|  | 
 | ||||||
|  | 	ff_maj = f->ff_version >> 16; | ||||||
|  | 	ff_min = f->ff_version & 0xffff; | ||||||
|  | 	printf("File format version : Major: %d, Minor: %d\n",  | ||||||
|  | 		ff_maj, ff_min); | ||||||
|  | 
 | ||||||
|  | 	printf("Data offset         : %s\n", conv(hex, f->data_offset)); | ||||||
|  | 
 | ||||||
|  | 	vhd_time_to_string(f->timestamp, time_str); | ||||||
|  | 	printf("Timestamp           : %s\n", time_str); | ||||||
|  | 
 | ||||||
|  | 	memcpy(creator, f->crtr_app, 4); | ||||||
|  | 	creator[4] = '\0'; | ||||||
|  | 	printf("Creator Application : '%s'\n", creator); | ||||||
|  | 
 | ||||||
|  | 	cr_maj = f->crtr_ver >> 16; | ||||||
|  | 	cr_min = f->crtr_ver & 0xffff; | ||||||
|  | 	printf("Creator version     : Major: %d, Minor: %d\n", | ||||||
|  | 		cr_maj, cr_min); | ||||||
|  | 
 | ||||||
|  | 	printf("Creator OS          : %s\n", | ||||||
|  | 		((f->crtr_os == HD_CR_OS_WINDOWS) ? "Windows" : | ||||||
|  | 		 ((f->crtr_os == HD_CR_OS_MACINTOSH) ? "Macintosh" :  | ||||||
|  | 		  "Unknown!"))); | ||||||
|  | 
 | ||||||
|  | 	printf("Original disk size  : %s MB ", conv(hex, f->orig_size >> 20)); | ||||||
|  | 	printf("(%s Bytes)\n", conv(hex, f->orig_size)); | ||||||
|  | 
 | ||||||
|  | 	printf("Current disk size   : %s MB ", conv(hex, f->curr_size >> 20)); | ||||||
|  | 	printf("(%s Bytes)\n", conv(hex, f->curr_size)); | ||||||
|  | 
 | ||||||
|  | 	c = f->geometry >> 16; | ||||||
|  | 	h = (f->geometry & 0x0000FF00) >> 8; | ||||||
|  | 	s = f->geometry & 0x000000FF; | ||||||
|  | 	printf("Geometry            : Cyl: %s, ", conv(hex, c)); | ||||||
|  | 	printf("Hds: %s, ", conv(hex, h)); | ||||||
|  | 	printf("Sctrs: %s\n", conv(hex, s)); | ||||||
|  | 	printf("                    : = %s MB ", conv(hex, (c * h * s) >> 11)); | ||||||
|  | 	printf("(%s Bytes)\n", conv(hex, c * h * s << 9)); | ||||||
|  | 
 | ||||||
|  | 	printf("Disk type           : %s\n",  | ||||||
|  | 		f->type <= HD_TYPE_MAX ?  | ||||||
|  | 		HD_TYPE_STR[f->type] : "Unknown type!\n"); | ||||||
|  | 
 | ||||||
|  | 	cksm = vhd_checksum_footer(f); | ||||||
|  | 	printf("Checksum            : 0x%x|0x%x (%s)\n", f->checksum, cksm, | ||||||
|  | 		f->checksum == cksm ? "Good!" : "Bad!"); | ||||||
|  | 
 | ||||||
|  | 	blk_uuid_to_string(&f->uuid, uuid, sizeof(uuid)); | ||||||
|  | 	printf("UUID                : %s\n", uuid); | ||||||
|  | 
 | ||||||
|  | 	printf("Saved state         : %s\n", f->saved == 0 ? "No" : "Yes"); | ||||||
|  | 	printf("Hidden              : %d\n", f->hidden); | ||||||
|  | 	printf("\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline char * | ||||||
|  | code_name(uint32_t code) | ||||||
|  | { | ||||||
|  | 	switch(code) { | ||||||
|  | 	case PLAT_CODE_NONE: | ||||||
|  | 		return "PLAT_CODE_NONE"; | ||||||
|  | 	case PLAT_CODE_WI2R: | ||||||
|  | 		return "PLAT_CODE_WI2R"; | ||||||
|  | 	case PLAT_CODE_WI2K: | ||||||
|  | 		return "PLAT_CODE_WI2K"; | ||||||
|  | 	case PLAT_CODE_W2RU: | ||||||
|  | 		return "PLAT_CODE_W2RU"; | ||||||
|  | 	case PLAT_CODE_W2KU: | ||||||
|  | 		return "PLAT_CODE_W2KU"; | ||||||
|  | 	case PLAT_CODE_MAC: | ||||||
|  | 		return "PLAT_CODE_MAC"; | ||||||
|  | 	case PLAT_CODE_MACX: | ||||||
|  | 		return "PLAT_CODE_MACX"; | ||||||
|  | 	default: | ||||||
|  | 		return "UNKOWN"; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | vhd_print_parent(vhd_context_t *vhd, vhd_parent_locator_t *loc) | ||||||
|  | { | ||||||
|  | 	int err; | ||||||
|  | 	char *buf; | ||||||
|  | 
 | ||||||
|  | 	err = vhd_parent_locator_read(vhd, loc, &buf); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("failed to read parent name\n"); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	printf("       decoded name : %s\n", buf); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | vhd_print_parent_locators(vhd_context_t *vhd, int hex) | ||||||
|  | { | ||||||
|  | 	int i, n; | ||||||
|  | 	vhd_parent_locator_t *loc; | ||||||
|  | 
 | ||||||
|  | 	printf("VHD Parent Locators:\n--------------------\n"); | ||||||
|  | 
 | ||||||
|  | 	n = sizeof(vhd->header.loc) / sizeof(struct prt_loc); | ||||||
|  | 	for (i = 0; i < n; i++) { | ||||||
|  | 		loc = &vhd->header.loc[i]; | ||||||
|  | 
 | ||||||
|  | 		if (loc->code == PLAT_CODE_NONE) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		printf("locator:            : %d\n", i); | ||||||
|  | 		printf("       code         : %s\n", | ||||||
|  | 		       code_name(loc->code)); | ||||||
|  | 		printf("       data_space   : %s\n", | ||||||
|  | 		       conv(hex, loc->data_space)); | ||||||
|  | 		printf("       data_length  : %s\n", | ||||||
|  | 		       conv(hex, loc->data_len)); | ||||||
|  | 		printf("       data_offset  : %s\n", | ||||||
|  | 		       conv(hex, loc->data_offset)); | ||||||
|  | 		vhd_print_parent(vhd, loc); | ||||||
|  | 		printf("\n"); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | vhd_print_batmap_header(vhd_batmap_t *batmap, int hex) | ||||||
|  | { | ||||||
|  | 	uint32_t cksm; | ||||||
|  | 
 | ||||||
|  | 	printf("VHD Batmap Summary:\n-------------------\n"); | ||||||
|  | 	printf("Batmap offset       : %s\n", | ||||||
|  | 	       conv(hex, batmap->header.batmap_offset)); | ||||||
|  | 	printf("Batmap size (secs)  : %s\n", | ||||||
|  | 	       conv(hex, batmap->header.batmap_size)); | ||||||
|  | 	printf("Batmap version      : 0x%08x\n", | ||||||
|  | 	       batmap->header.batmap_version); | ||||||
|  | 
 | ||||||
|  | 	cksm = vhd_checksum_batmap(batmap); | ||||||
|  | 	printf("Checksum            : 0x%x|0x%x (%s)\n", | ||||||
|  | 	       batmap->header.checksum, cksm, | ||||||
|  | 	       (batmap->header.checksum == cksm ? "Good!" : "Bad!")); | ||||||
|  | 	printf("\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline int | ||||||
|  | check_block_range(vhd_context_t *vhd, uint64_t block, int hex) | ||||||
|  | { | ||||||
|  | 	if (block > vhd->header.max_bat_size) { | ||||||
|  | 		fprintf(stderr, "block %s past end of file\n", | ||||||
|  | 			conv(hex, block)); | ||||||
|  | 		return -ERANGE; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | vhd_print_headers(vhd_context_t *vhd, int hex) | ||||||
|  | { | ||||||
|  | 	int err; | ||||||
|  | 
 | ||||||
|  | 	vhd_print_footer(&vhd->footer, hex); | ||||||
|  | 
 | ||||||
|  | 	if (vhd_type_dynamic(vhd)) { | ||||||
|  | 		vhd_print_header(vhd, &vhd->header, hex); | ||||||
|  | 
 | ||||||
|  | 		if (vhd->footer.type == HD_TYPE_DIFF) | ||||||
|  | 			vhd_print_parent_locators(vhd, hex); | ||||||
|  | 
 | ||||||
|  | 		if (vhd_has_batmap(vhd)) { | ||||||
|  | 			err = vhd_get_batmap(vhd); | ||||||
|  | 			if (err) { | ||||||
|  | 				printf("failed to get batmap header\n"); | ||||||
|  | 				return err; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			vhd_print_batmap_header(&vhd->batmap, hex); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | vhd_dump_headers(const char *name, int hex) | ||||||
|  | { | ||||||
|  | 	vhd_context_t vhd; | ||||||
|  | 
 | ||||||
|  | 	libvhd_set_log_level(1); | ||||||
|  | 	memset(&vhd, 0, sizeof(vhd)); | ||||||
|  | 
 | ||||||
|  | 	printf("\n%s appears invalid; dumping headers\n\n", name); | ||||||
|  | 
 | ||||||
|  | 	vhd.fd = open(name, O_DIRECT | O_LARGEFILE | O_RDONLY); | ||||||
|  | 	if (vhd.fd == -1) | ||||||
|  | 		return -errno; | ||||||
|  | 
 | ||||||
|  | 	vhd.file = strdup(name); | ||||||
|  | 
 | ||||||
|  | 	vhd_read_footer(&vhd, &vhd.footer); | ||||||
|  | 	vhd_read_header(&vhd, &vhd.header); | ||||||
|  | 
 | ||||||
|  | 	vhd_print_footer(&vhd.footer, hex); | ||||||
|  | 	vhd_print_header(&vhd, &vhd.header, hex); | ||||||
|  | 
 | ||||||
|  | 	close(vhd.fd); | ||||||
|  | 	free(vhd.file); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | vhd_print_logical_to_physical(vhd_context_t *vhd, | ||||||
|  | 			      uint64_t sector, int count, int hex) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	uint32_t blk, lsec; | ||||||
|  | 	uint64_t cur, offset; | ||||||
|  | 
 | ||||||
|  | 	if (vhd_sectors_to_bytes(sector + count) > vhd->footer.curr_size) { | ||||||
|  | 		fprintf(stderr, "sector %s past end of file\n", | ||||||
|  | 			conv(hex, sector + count)); | ||||||
|  | 			return -ERANGE; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < count; i++) { | ||||||
|  | 		cur    = sector + i; | ||||||
|  | 		blk    = cur / vhd->spb; | ||||||
|  | 		lsec   = cur % vhd->spb; | ||||||
|  | 		offset = vhd->bat.bat[blk]; | ||||||
|  | 
 | ||||||
|  | 		if (offset != DD_BLK_UNUSED) { | ||||||
|  | 			offset += lsec + 1; | ||||||
|  | 			offset  = vhd_sectors_to_bytes(offset); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		printf("logical sector %s: ", conv(hex, cur)); | ||||||
|  | 		printf("block number: %s, ", conv(hex, blk)); | ||||||
|  | 		printf("sector offset: %s, ", conv(hex, lsec)); | ||||||
|  | 		printf("file offset: %s\n", (offset == DD_BLK_UNUSED ? | ||||||
|  | 			"not allocated" : conv(hex, offset))); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | vhd_print_bat(vhd_context_t *vhd, uint64_t block, int count, int hex) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	uint64_t cur, offset; | ||||||
|  | 
 | ||||||
|  | 	if (check_block_range(vhd, block + count, hex)) | ||||||
|  | 		return -ERANGE; | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < count; i++) { | ||||||
|  | 		cur    = block + i; | ||||||
|  | 		offset = vhd->bat.bat[cur]; | ||||||
|  | 
 | ||||||
|  | 		printf("block: %s: ", conv(hex, cur)); | ||||||
|  | 		printf("offset: %s\n", | ||||||
|  | 		       (offset == DD_BLK_UNUSED ? "not allocated" : | ||||||
|  | 			conv(hex, vhd_sectors_to_bytes(offset)))); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void | ||||||
|  | write_full(int fd, void* buf, size_t count) | ||||||
|  | { | ||||||
|  | 	ssize_t num_written = 0; | ||||||
|  | 	if (!buf) return; | ||||||
|  | 	 | ||||||
|  | 	 | ||||||
|  | 	while(count > 0) { | ||||||
|  | 		 | ||||||
|  | 		num_written = write(fd, buf, count); | ||||||
|  | 		if (num_written == -1) { | ||||||
|  | 			if (errno == EINTR)  | ||||||
|  | 				continue; | ||||||
|  | 			else | ||||||
|  | 				return; | ||||||
|  | 		} | ||||||
|  | 		 | ||||||
|  | 		count -= num_written; | ||||||
|  | 		buf   += num_written; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | vhd_print_bitmap(vhd_context_t *vhd, uint64_t block, int count, int hex) | ||||||
|  | { | ||||||
|  | 	char *buf; | ||||||
|  | 	int i, err; | ||||||
|  | 	uint64_t cur; | ||||||
|  | 
 | ||||||
|  | 	if (check_block_range(vhd, block + count, hex)) | ||||||
|  | 		return -ERANGE; | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < count; i++) { | ||||||
|  | 		cur = block + i; | ||||||
|  | 
 | ||||||
|  | 		if (vhd->bat.bat[cur] == DD_BLK_UNUSED) { | ||||||
|  | 			printf("block %s not allocated\n", conv(hex, cur)); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		err = vhd_read_bitmap(vhd, cur, &buf); | ||||||
|  | 		if (err) | ||||||
|  | 			goto out; | ||||||
|  | 
 | ||||||
|  | 		write_full(STDOUT_FILENO, buf,  | ||||||
|  | 			   vhd_sectors_to_bytes(vhd->bm_secs)); | ||||||
|  | 		free(buf); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = 0; | ||||||
|  | out: | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | vhd_test_bitmap(vhd_context_t *vhd, uint64_t sector, int count, int hex) | ||||||
|  | { | ||||||
|  | 	char *buf; | ||||||
|  | 	uint64_t cur; | ||||||
|  | 	int i, err, bit; | ||||||
|  | 	uint32_t blk, bm_blk, sec; | ||||||
|  | 
 | ||||||
|  | 	if (vhd_sectors_to_bytes(sector + count) > vhd->footer.curr_size) { | ||||||
|  | 		printf("sector %s past end of file\n", conv(hex, sector)); | ||||||
|  | 		return -ERANGE; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bm_blk = -1; | ||||||
|  | 	buf    = NULL; | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < count; i++) { | ||||||
|  | 		cur = sector + i; | ||||||
|  | 		blk = cur / vhd->spb; | ||||||
|  | 		sec = cur % vhd->spb; | ||||||
|  | 
 | ||||||
|  | 		if (blk != bm_blk) { | ||||||
|  | 			bm_blk = blk; | ||||||
|  | 			free(buf); | ||||||
|  | 			buf = NULL; | ||||||
|  | 
 | ||||||
|  | 			if (vhd->bat.bat[blk] != DD_BLK_UNUSED) { | ||||||
|  | 				err = vhd_read_bitmap(vhd, blk, &buf); | ||||||
|  | 				if (err) | ||||||
|  | 					goto out; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (vhd->bat.bat[blk] == DD_BLK_UNUSED) | ||||||
|  | 			bit = 0; | ||||||
|  | 		else | ||||||
|  | 			bit = vhd_bitmap_test(vhd, buf, blk); | ||||||
|  | 
 | ||||||
|  | 	print: | ||||||
|  | 		printf("block %s: ", conv(hex, blk)); | ||||||
|  | 		printf("sec: %s: %d\n", conv(hex, sec), bit); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = 0; | ||||||
|  |  out: | ||||||
|  | 	free(buf); | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | vhd_print_batmap(vhd_context_t *vhd) | ||||||
|  | { | ||||||
|  | 	int err; | ||||||
|  | 	size_t size; | ||||||
|  | 
 | ||||||
|  | 	err = vhd_get_batmap(vhd); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("failed to read batmap: %d\n", err); | ||||||
|  | 		return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	size = vhd_sectors_to_bytes(vhd->batmap.header.batmap_size); | ||||||
|  | 	write_full(STDOUT_FILENO, vhd->batmap.map, size); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | vhd_test_batmap(vhd_context_t *vhd, uint64_t block, int count, int hex) | ||||||
|  | { | ||||||
|  | 	int i, err; | ||||||
|  | 	uint64_t cur; | ||||||
|  | 
 | ||||||
|  | 	if (check_block_range(vhd, block + count, hex)) | ||||||
|  | 		return -ERANGE; | ||||||
|  | 
 | ||||||
|  | 	err = vhd_get_batmap(vhd); | ||||||
|  | 	if (err) { | ||||||
|  | 		fprintf(stderr, "failed to get batmap\n"); | ||||||
|  | 		return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < count; i++) { | ||||||
|  | 		cur = block + i; | ||||||
|  | 		fprintf(stderr, "batmap for block %s: %d\n", conv(hex, cur), | ||||||
|  | 			vhd_batmap_test(vhd, &vhd->batmap, cur)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | vhd_print_data(vhd_context_t *vhd, uint64_t block, int count, int hex) | ||||||
|  | { | ||||||
|  | 	char *buf; | ||||||
|  | 	int i, err; | ||||||
|  | 	uint64_t cur; | ||||||
|  | 
 | ||||||
|  | 	err = 0; | ||||||
|  | 
 | ||||||
|  | 	if (check_block_range(vhd, block + count, hex)) | ||||||
|  | 		return -ERANGE; | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < count; i++) { | ||||||
|  | 		cur = block + i; | ||||||
|  | 
 | ||||||
|  | 		if (vhd->bat.bat[cur] == DD_BLK_UNUSED) { | ||||||
|  | 			printf("block %s not allocated\n", conv(hex, cur)); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		err = vhd_read_block(vhd, cur, &buf); | ||||||
|  | 		if (err) | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 		write_full(STDOUT_FILENO, buf, vhd->header.block_size); | ||||||
|  | 		free(buf); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | vhd_read_data(vhd_context_t *vhd, uint64_t sec, int count, int hex) | ||||||
|  | { | ||||||
|  | 	char *buf; | ||||||
|  | 	uint64_t cur; | ||||||
|  | 	int err, max, secs; | ||||||
|  | 
 | ||||||
|  | 	if (vhd_sectors_to_bytes(sec + count) > vhd->footer.curr_size) | ||||||
|  | 		return -ERANGE; | ||||||
|  | 
 | ||||||
|  | 	max = MIN(vhd_sectors_to_bytes(count), VHD_BLOCK_SIZE); | ||||||
|  | 	err = posix_memalign((void **)&buf, VHD_SECTOR_SIZE, max); | ||||||
|  | 	if (err) | ||||||
|  | 		return -err; | ||||||
|  | 
 | ||||||
|  | 	cur = sec; | ||||||
|  | 	while (count) { | ||||||
|  | 		secs = MIN((max >> VHD_SECTOR_SHIFT), count); | ||||||
|  | 		err  = vhd_io_read(vhd, buf, cur, secs); | ||||||
|  | 		if (err) | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 		write_full(STDOUT_FILENO, buf, vhd_sectors_to_bytes(secs)); | ||||||
|  | 
 | ||||||
|  | 		cur   += secs; | ||||||
|  | 		count -= secs; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	free(buf); | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | vhd_util_read(int argc, char **argv) | ||||||
|  | { | ||||||
|  | 	char *name; | ||||||
|  | 	vhd_context_t vhd; | ||||||
|  | 	int c, err, headers, hex; | ||||||
|  | 	uint64_t bat, bitmap, tbitmap, batmap, tbatmap, data, lsec, count, read; | ||||||
|  | 
 | ||||||
|  | 	err     = 0; | ||||||
|  | 	hex     = 0; | ||||||
|  | 	headers = 0; | ||||||
|  | 	count   = 1; | ||||||
|  | 	bat     = -1; | ||||||
|  | 	bitmap  = -1; | ||||||
|  | 	tbitmap = -1; | ||||||
|  | 	batmap  = -1; | ||||||
|  | 	tbatmap = -1; | ||||||
|  | 	data    = -1; | ||||||
|  | 	lsec    = -1; | ||||||
|  | 	read    = -1; | ||||||
|  | 	name    = NULL; | ||||||
|  | 
 | ||||||
|  | 	if (!argc || !argv) | ||||||
|  | 		goto usage; | ||||||
|  | 
 | ||||||
|  | 	optind = 0; | ||||||
|  | 	while ((c = getopt(argc, argv, "n:pt:b:m:i:aj:d:c:r:xh")) != -1) { | ||||||
|  | 		switch(c) { | ||||||
|  | 		case 'n': | ||||||
|  | 			name = optarg; | ||||||
|  | 			break; | ||||||
|  | 		case 'p': | ||||||
|  | 			headers = 1; | ||||||
|  | 			break; | ||||||
|  | 		case 't': | ||||||
|  | 			lsec = strtoul(optarg, NULL, 10); | ||||||
|  | 			break; | ||||||
|  | 		case 'b': | ||||||
|  | 			bat = strtoull(optarg, NULL, 10); | ||||||
|  | 			break; | ||||||
|  | 		case 'm': | ||||||
|  | 			bitmap = strtoull(optarg, NULL, 10); | ||||||
|  | 			break; | ||||||
|  | 		case 'i': | ||||||
|  | 			tbitmap = strtoul(optarg, NULL, 10); | ||||||
|  | 			break; | ||||||
|  | 		case 'a': | ||||||
|  | 			batmap = 1; | ||||||
|  | 			break; | ||||||
|  | 		case 'j': | ||||||
|  | 			tbatmap = strtoull(optarg, NULL, 10); | ||||||
|  | 			break; | ||||||
|  | 		case 'd': | ||||||
|  | 			data = strtoull(optarg, NULL, 10); | ||||||
|  | 			break; | ||||||
|  | 		case 'r': | ||||||
|  | 			read = strtoull(optarg, NULL, 10); | ||||||
|  | 			break; | ||||||
|  | 		case 'c': | ||||||
|  | 			count = strtoul(optarg, NULL, 10); | ||||||
|  | 			break; | ||||||
|  | 		case 'x': | ||||||
|  | 			hex = 1; | ||||||
|  | 			break; | ||||||
|  | 		case 'h': | ||||||
|  | 		default: | ||||||
|  | 			goto usage; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!name || optind != argc) | ||||||
|  | 		goto usage; | ||||||
|  | 
 | ||||||
|  | 	err = vhd_open(&vhd, name, VHD_OPEN_RDONLY | VHD_OPEN_IGNORE_DISABLED); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("Failed to open %s: %d\n", name, err); | ||||||
|  | 		vhd_dump_headers(name, hex); | ||||||
|  | 		return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = vhd_get_bat(&vhd); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("Failed to get bat for %s: %d\n", name, err); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (headers) | ||||||
|  | 		vhd_print_headers(&vhd, hex); | ||||||
|  | 
 | ||||||
|  | 	if (lsec != -1) { | ||||||
|  | 		err = vhd_print_logical_to_physical(&vhd, lsec, count, hex); | ||||||
|  | 		if (err) | ||||||
|  | 			goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (bat != -1) { | ||||||
|  | 		err = vhd_print_bat(&vhd, bat, count, hex); | ||||||
|  | 		if (err) | ||||||
|  | 			goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (bitmap != -1) { | ||||||
|  | 		err = vhd_print_bitmap(&vhd, bitmap, count, hex); | ||||||
|  | 		if (err) | ||||||
|  | 			goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (tbitmap != -1) { | ||||||
|  | 		err = vhd_test_bitmap(&vhd, tbitmap, count, hex); | ||||||
|  | 		if (err) | ||||||
|  | 			goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (batmap != -1) { | ||||||
|  | 		err = vhd_print_batmap(&vhd); | ||||||
|  | 		if (err) | ||||||
|  | 			goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (tbatmap != -1) { | ||||||
|  | 		err = vhd_test_batmap(&vhd, tbatmap, count, hex); | ||||||
|  | 		if (err) | ||||||
|  | 			goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (data != -1) { | ||||||
|  | 		err = vhd_print_data(&vhd, data, count, hex); | ||||||
|  | 		if (err) | ||||||
|  | 			goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (read != -1) { | ||||||
|  | 		err = vhd_read_data(&vhd, read, count, hex); | ||||||
|  | 		if (err) | ||||||
|  | 			goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = 0; | ||||||
|  | 
 | ||||||
|  |  out: | ||||||
|  | 	vhd_close(&vhd); | ||||||
|  | 	return err; | ||||||
|  | 
 | ||||||
|  |  usage: | ||||||
|  | 	printf("options:\n" | ||||||
|  | 	       "-h          help\n" | ||||||
|  | 	       "-n          name\n" | ||||||
|  | 	       "-p          print VHD headers\n" | ||||||
|  | 	       "-t sec      translate logical sector to VHD location\n" | ||||||
|  | 	       "-b blk      print bat entry\n" | ||||||
|  | 	       "-m blk      print bitmap\n" | ||||||
|  | 	       "-i sec      test bitmap for logical sector\n" | ||||||
|  | 	       "-a          print batmap\n" | ||||||
|  | 	       "-j blk      test batmap for block\n" | ||||||
|  | 	       "-d blk      print data\n" | ||||||
|  | 	       "-c num      num units\n" | ||||||
|  | 	       "-r sec      read num sectors at sec\n" | ||||||
|  | 	       "-x          print in hex\n"); | ||||||
|  | 	return EINVAL; | ||||||
|  | } | ||||||
							
								
								
									
										84
									
								
								tools/vhd-tools/vhd/lib/vhd-util-repair.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								tools/vhd-tools/vhd/lib/vhd-util-repair.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,84 @@ | |||||||
|  | /* Copyright (c) 2008, XenSource Inc.
 | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of XenSource Inc. nor the names of its contributors | ||||||
|  |  *       may be used to endorse or promote products derived from this software | ||||||
|  |  *       without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||||||
|  |  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||||
|  |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||||
|  |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||||
|  |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||||
|  |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||||
|  |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | */ | ||||||
|  | #include <errno.h> | ||||||
|  | #include <fcntl.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | 
 | ||||||
|  | #include "libvhd.h" | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | vhd_util_repair(int argc, char **argv) | ||||||
|  | { | ||||||
|  | 	char *name; | ||||||
|  | 	int err, c; | ||||||
|  | 	off_t eof; | ||||||
|  | 	vhd_context_t vhd; | ||||||
|  | 
 | ||||||
|  | 	name = NULL; | ||||||
|  | 
 | ||||||
|  | 	if (!argc || !argv) | ||||||
|  | 		goto usage; | ||||||
|  | 
 | ||||||
|  | 	optind = 0; | ||||||
|  | 	while ((c = getopt(argc, argv, "n:h")) != -1) { | ||||||
|  | 		switch (c) { | ||||||
|  | 		case 'n': | ||||||
|  | 			name = optarg; | ||||||
|  | 			break; | ||||||
|  | 		case 'h': | ||||||
|  | 		default: | ||||||
|  | 			goto usage; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!name || optind != argc) | ||||||
|  | 		goto usage; | ||||||
|  | 
 | ||||||
|  | 	err = vhd_open(&vhd, name, VHD_OPEN_RDWR); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("error opening %s: %d\n", name, err); | ||||||
|  | 		return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = vhd_end_of_data(&vhd, &eof); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("error finding end of data: %d\n", err); | ||||||
|  | 		goto done; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = vhd_write_footer_at(&vhd, &vhd.footer, eof); | ||||||
|  | 
 | ||||||
|  |  done: | ||||||
|  | 	vhd_close(&vhd); | ||||||
|  | 	return err; | ||||||
|  | 
 | ||||||
|  | usage: | ||||||
|  | 	printf("options: <-n name> [-h help]\n"); | ||||||
|  | 	return -EINVAL; | ||||||
|  | } | ||||||
							
								
								
									
										1131
									
								
								tools/vhd-tools/vhd/lib/vhd-util-resize.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1131
									
								
								tools/vhd-tools/vhd/lib/vhd-util-resize.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										106
									
								
								tools/vhd-tools/vhd/lib/vhd-util-revert.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								tools/vhd-tools/vhd/lib/vhd-util-revert.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,106 @@ | |||||||
|  | /* Copyright (c) 2008, XenSource Inc.
 | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of XenSource Inc. nor the names of its contributors | ||||||
|  |  *       may be used to endorse or promote products derived from this software | ||||||
|  |  *       without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||||||
|  |  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||||
|  |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||||
|  |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||||
|  |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||||
|  |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||||
|  |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  * | ||||||
|  |  * Altering operations: | ||||||
|  |  * | ||||||
|  |  * 1. Change the parent pointer to another file. | ||||||
|  |  * 2. Change the size of the file containing the VHD image. This does NOT  | ||||||
|  |  * affect the VHD disk capacity, only the physical size of the file containing  | ||||||
|  |  * the VHD. Naturally, it is not possible to set the file size to be less than   | ||||||
|  |  * the what VHD utilizes. | ||||||
|  |  * The operation doesn't actually change the file size, but it writes the  | ||||||
|  |  * footer in the right location such that resizing the file (manually, as a  | ||||||
|  |  * separate step) will produce the correct results. If the new file size is  | ||||||
|  |  * greater than the current file size, the file must first be expanded and then  | ||||||
|  |  * altered with this operation. If the new size is smaller than the current  | ||||||
|  |  * size, the VHD must first be altered with this operation and then the file  | ||||||
|  |  * must be shrunk. Failing to resize the file will result in a corrupted VHD. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #include <errno.h> | ||||||
|  | //#include <fcntl.h>
 | ||||||
|  | #include <stdio.h> | ||||||
|  | //#include <stdlib.h>
 | ||||||
|  | #include <unistd.h> | ||||||
|  | 
 | ||||||
|  | #include "libvhd.h" | ||||||
|  | #include "libvhd-journal.h" | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | vhd_util_revert(int argc, char **argv) | ||||||
|  | { | ||||||
|  | 	char *name, *jname; | ||||||
|  | 	vhd_journal_t journal; | ||||||
|  | 	int c, err; | ||||||
|  | 
 | ||||||
|  | 	name  = NULL; | ||||||
|  | 	jname = NULL; | ||||||
|  | 
 | ||||||
|  | 	optind = 0; | ||||||
|  | 	while ((c = getopt(argc, argv, "n:j:h")) != -1) { | ||||||
|  | 		switch (c) { | ||||||
|  | 		case 'n': | ||||||
|  | 			name = optarg; | ||||||
|  | 			break; | ||||||
|  | 		case 'j': | ||||||
|  | 			jname = optarg; | ||||||
|  | 			break; | ||||||
|  | 		case 'h': | ||||||
|  | 		default: | ||||||
|  | 			goto usage; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!name || !jname || argc != optind) | ||||||
|  | 		goto usage; | ||||||
|  | 
 | ||||||
|  | 	libvhd_set_log_level(1); | ||||||
|  | 	err = vhd_journal_open(&journal, name, jname); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("opening journal failed: %d\n", err); | ||||||
|  | 		return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = vhd_journal_revert(&journal); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("reverting journal failed: %d\n", err); | ||||||
|  | 		vhd_journal_close(&journal); | ||||||
|  | 		return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = vhd_journal_remove(&journal); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("removing journal failed: %d\n", err); | ||||||
|  | 		vhd_journal_close(&journal); | ||||||
|  | 		return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | 
 | ||||||
|  | usage: | ||||||
|  | 	printf("options: <-n name> <-j journal> [-h help]\n"); | ||||||
|  | 	return -EINVAL; | ||||||
|  | } | ||||||
							
								
								
									
										1317
									
								
								tools/vhd-tools/vhd/lib/vhd-util-scan.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1317
									
								
								tools/vhd-tools/vhd/lib/vhd-util-scan.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										106
									
								
								tools/vhd-tools/vhd/lib/vhd-util-set-field.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								tools/vhd-tools/vhd/lib/vhd-util-set-field.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,106 @@ | |||||||
|  | /* Copyright (c) 2008, XenSource Inc.
 | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of XenSource Inc. nor the names of its contributors | ||||||
|  |  *       may be used to endorse or promote products derived from this software | ||||||
|  |  *       without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||||||
|  |  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||||
|  |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||||
|  |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||||
|  |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||||
|  |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||||
|  |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | */ | ||||||
|  | #include <errno.h> | ||||||
|  | #include <fcntl.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | 
 | ||||||
|  | #include "libvhd.h" | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | vhd_util_set_field(int argc, char **argv) | ||||||
|  | { | ||||||
|  | 	long value; | ||||||
|  | 	int err, c; | ||||||
|  | 	off_t eof; | ||||||
|  | 	vhd_context_t vhd; | ||||||
|  | 	char *name, *field; | ||||||
|  | 
 | ||||||
|  | 	err   = -EINVAL; | ||||||
|  | 	value = 0; | ||||||
|  | 	name  = NULL; | ||||||
|  | 	field = NULL; | ||||||
|  | 
 | ||||||
|  | 	if (!argc || !argv) | ||||||
|  | 		goto usage; | ||||||
|  | 
 | ||||||
|  | 	optind = 0; | ||||||
|  | 	while ((c = getopt(argc, argv, "n:f:v:h")) != -1) { | ||||||
|  | 		switch (c) { | ||||||
|  | 		case 'n': | ||||||
|  | 			name = optarg; | ||||||
|  | 			break; | ||||||
|  | 		case 'f': | ||||||
|  | 			field = optarg; | ||||||
|  | 			break; | ||||||
|  | 		case 'v': | ||||||
|  | 			err   = 0; | ||||||
|  | 			value = strtol(optarg, NULL, 10); | ||||||
|  | 			break; | ||||||
|  | 		case 'h': | ||||||
|  | 		default: | ||||||
|  | 			goto usage; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!name || !field || optind != argc || err) | ||||||
|  | 		goto usage; | ||||||
|  | 
 | ||||||
|  | 	if (strnlen(field, 25) >= 25) { | ||||||
|  | 		printf("invalid field\n"); | ||||||
|  | 		goto usage; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (strcmp(field, "hidden")) { | ||||||
|  | 		printf("invalid field %s\n", field); | ||||||
|  | 		goto usage; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (value < 0 || value > 255) { | ||||||
|  | 		printf("invalid value %ld\n", value); | ||||||
|  | 		goto usage; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = vhd_open(&vhd, name, VHD_OPEN_RDWR); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("error opening %s: %d\n", name, err); | ||||||
|  | 		return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	vhd.footer.hidden = (char)value; | ||||||
|  | 
 | ||||||
|  | 	err = vhd_write_footer(&vhd, &vhd.footer); | ||||||
|  | 		 | ||||||
|  |  done: | ||||||
|  | 	vhd_close(&vhd); | ||||||
|  | 	return err; | ||||||
|  | 
 | ||||||
|  | usage: | ||||||
|  | 	printf("options: <-n name> <-f field> <-v value> [-h help]\n"); | ||||||
|  | 	return -EINVAL; | ||||||
|  | } | ||||||
							
								
								
									
										216
									
								
								tools/vhd-tools/vhd/lib/vhd-util-snapshot.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										216
									
								
								tools/vhd-tools/vhd/lib/vhd-util-snapshot.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,216 @@ | |||||||
|  | /* Copyright (c) 2008, XenSource Inc.
 | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of XenSource Inc. nor the names of its contributors | ||||||
|  |  *       may be used to endorse or promote products derived from this software | ||||||
|  |  *       without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||||||
|  |  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||||
|  |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||||
|  |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||||
|  |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||||
|  |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||||
|  |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | */ | ||||||
|  | #include <errno.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <fcntl.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | 
 | ||||||
|  | #include "libvhd.h" | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | vhd_util_find_snapshot_target(const char *name, char **result, int *parent_raw) | ||||||
|  | { | ||||||
|  | 	int i, err; | ||||||
|  | 	char *target; | ||||||
|  | 	vhd_context_t vhd; | ||||||
|  | 
 | ||||||
|  | 	*parent_raw = 0; | ||||||
|  | 	*result     = NULL; | ||||||
|  | 
 | ||||||
|  | 	target = strdup(name); | ||||||
|  | 	if (!target) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	for (;;) { | ||||||
|  | 		err = vhd_open(&vhd, target, VHD_OPEN_RDONLY); | ||||||
|  | 		if (err) | ||||||
|  | 			return err; | ||||||
|  | 
 | ||||||
|  | 		if (vhd.footer.type != HD_TYPE_DIFF) | ||||||
|  | 			goto out; | ||||||
|  | 
 | ||||||
|  | 		err = vhd_get_bat(&vhd); | ||||||
|  | 		if (err) | ||||||
|  | 			goto out; | ||||||
|  | 
 | ||||||
|  | 		for (i = 0; i < vhd.bat.entries; i++) | ||||||
|  | 			if (vhd.bat.bat[i] != DD_BLK_UNUSED) | ||||||
|  | 				goto out; | ||||||
|  | 
 | ||||||
|  | 		free(target); | ||||||
|  | 		err = vhd_parent_locator_get(&vhd, &target); | ||||||
|  | 		if (err) | ||||||
|  | 			goto out; | ||||||
|  | 
 | ||||||
|  | 		if (vhd_parent_raw(&vhd)) { | ||||||
|  | 			*parent_raw = 1; | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		vhd_close(&vhd); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | out: | ||||||
|  | 	vhd_close(&vhd); | ||||||
|  | 	if (err) | ||||||
|  | 		free(target); | ||||||
|  | 	else | ||||||
|  | 		*result = target; | ||||||
|  | 
 | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | vhd_util_check_depth(const char *name, int *depth) | ||||||
|  | { | ||||||
|  | 	int err; | ||||||
|  | 	vhd_context_t vhd; | ||||||
|  | 
 | ||||||
|  | 	err = vhd_open(&vhd, name, VHD_OPEN_RDONLY); | ||||||
|  | 	if (err) | ||||||
|  | 		return err; | ||||||
|  | 
 | ||||||
|  | 	err = vhd_chain_depth(&vhd, depth); | ||||||
|  | 	vhd_close(&vhd); | ||||||
|  | 
 | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | vhd_util_snapshot(int argc, char **argv) | ||||||
|  | { | ||||||
|  | 	vhd_flag_creat_t flags; | ||||||
|  | 	int c, err, prt_raw, limit; | ||||||
|  | 	char *name, *pname, *ppath, *backing; | ||||||
|  | 	uint64_t size; | ||||||
|  | 	vhd_context_t vhd; | ||||||
|  | 
 | ||||||
|  | 	name    = NULL; | ||||||
|  | 	pname   = NULL; | ||||||
|  | 	ppath   = NULL; | ||||||
|  | 	backing = NULL; | ||||||
|  | 	size    = 0; | ||||||
|  | 	flags   = 0; | ||||||
|  | 	limit   = 0; | ||||||
|  | 
 | ||||||
|  | 	if (!argc || !argv) { | ||||||
|  | 		err = -EINVAL; | ||||||
|  | 		goto usage; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	optind = 0; | ||||||
|  | 	while ((c = getopt(argc, argv, "n:p:l:mh")) != -1) { | ||||||
|  | 		switch (c) { | ||||||
|  | 		case 'n': | ||||||
|  | 			name = optarg; | ||||||
|  | 			break; | ||||||
|  | 		case 'p': | ||||||
|  | 			pname = optarg; | ||||||
|  | 			break; | ||||||
|  | 		case 'l': | ||||||
|  | 			limit = strtol(optarg, NULL, 10); | ||||||
|  | 			break; | ||||||
|  | 		case 'm': | ||||||
|  | 			vhd_flag_set(flags, VHD_FLAG_CREAT_PARENT_RAW); | ||||||
|  | 			break; | ||||||
|  | 		case 'h': | ||||||
|  | 			err = 0; | ||||||
|  | 			goto usage; | ||||||
|  | 		default: | ||||||
|  | 			err = -EINVAL; | ||||||
|  | 			goto usage; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!name || !pname || optind != argc) { | ||||||
|  | 		err = -EINVAL; | ||||||
|  | 		goto usage; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ppath = realpath(pname, NULL); | ||||||
|  | 	if (!ppath) | ||||||
|  | 		return -errno; | ||||||
|  | 
 | ||||||
|  | 	if (vhd_flag_test(flags, VHD_FLAG_CREAT_PARENT_RAW)) { | ||||||
|  | 		backing = strdup(ppath); | ||||||
|  | 		if (!backing) { | ||||||
|  | 			err = -ENOMEM; | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		err = vhd_util_find_snapshot_target(ppath, &backing, &prt_raw); | ||||||
|  | 		if (err) { | ||||||
|  | 			backing = NULL; | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		/* 
 | ||||||
|  | 		 * if the sizes of the parent chain are non-uniform, we need to  | ||||||
|  | 		 * pick the right size: that of the supplied parent | ||||||
|  | 		 */ | ||||||
|  | 		if (strcmp(ppath, backing)) { | ||||||
|  | 			err = vhd_open(&vhd, ppath, VHD_OPEN_RDONLY); | ||||||
|  | 			if (err) | ||||||
|  | 				goto out; | ||||||
|  | 			size = vhd.footer.curr_size; | ||||||
|  | 			vhd_close(&vhd); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (prt_raw) | ||||||
|  | 			vhd_flag_set(flags, VHD_FLAG_CREAT_PARENT_RAW); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (limit && !vhd_flag_test(flags, VHD_FLAG_CREAT_PARENT_RAW)) { | ||||||
|  | 		int depth; | ||||||
|  | 
 | ||||||
|  | 		err = vhd_util_check_depth(backing, &depth); | ||||||
|  | 		if (err) | ||||||
|  | 			printf("error checking snapshot depth: %d\n", err); | ||||||
|  | 		else if (depth + 1 > limit) { | ||||||
|  | 			err = -ENOSPC; | ||||||
|  | 			printf("snapshot depth exceeded: " | ||||||
|  | 			       "current depth: %d, limit: %d\n", depth, limit); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (err) | ||||||
|  | 			goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = vhd_snapshot(name, size, backing, flags); | ||||||
|  | 
 | ||||||
|  | out: | ||||||
|  | 	free(ppath); | ||||||
|  | 	free(backing); | ||||||
|  | 
 | ||||||
|  | 	return err; | ||||||
|  | 
 | ||||||
|  | usage: | ||||||
|  | 	printf("options: <-n name> <-p parent name> [-l snapshot depth limit]" | ||||||
|  | 	       " [-m parent_is_raw] [-h help]\n"); | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
							
								
								
									
										259
									
								
								tools/vhd-tools/vhd/vhd-update.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										259
									
								
								tools/vhd-tools/vhd/vhd-update.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,259 @@ | |||||||
|  | /* Copyright (c) 2008, XenSource Inc.
 | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of XenSource Inc. nor the names of its contributors | ||||||
|  |  *       may be used to endorse or promote products derived from this software | ||||||
|  |  *       without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||||||
|  |  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||||
|  |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||||
|  |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||||
|  |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||||
|  |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||||
|  |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  * | ||||||
|  |  * Before updating a VHD file, we create a journal consisting of: | ||||||
|  |  *   - all data at the beginning of the file, up to and including the BAT | ||||||
|  |  *   - each allocated bitmap (existing at the same offset in the journal as | ||||||
|  |  *                            its corresponding bitmap in the original file) | ||||||
|  |  * Updates are performed in place by writing appropriately  | ||||||
|  |  * transformed versions of journaled bitmaps to the original file. | ||||||
|  |  */ | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include <fcntl.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | 
 | ||||||
|  | #include "atomicio.h" | ||||||
|  | #include "libvhd.h" | ||||||
|  | #include "libvhd-journal.h" | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | usage(void) | ||||||
|  | { | ||||||
|  | 	printf("usage: vhd-update <-n name> [-j existing journal] [-h]\n"); | ||||||
|  | 	exit(EINVAL); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * update vhd creator version to reflect its new bitmap ordering | ||||||
|  |  */ | ||||||
|  | static inline int | ||||||
|  | update_creator_version(vhd_journal_t *journal) | ||||||
|  | { | ||||||
|  | 	journal->vhd.footer.crtr_ver = VHD_VERSION(1, 1); | ||||||
|  | 	return vhd_write_footer(&journal->vhd, &journal->vhd.footer); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | journal_bitmaps(vhd_journal_t *journal) | ||||||
|  | { | ||||||
|  | 	int i, err; | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < journal->vhd.bat.entries; i++) { | ||||||
|  | 		err = vhd_journal_add_block(journal, i, VHD_JOURNAL_METADATA); | ||||||
|  | 		if (err) | ||||||
|  | 			return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * older VHD bitmaps were little endian | ||||||
|  |  * and bits within a word were set from right to left | ||||||
|  |  */ | ||||||
|  | static inline int | ||||||
|  | old_test_bit(int nr, volatile void * addr) | ||||||
|  | { | ||||||
|  |         return (((unsigned long*)addr)[nr/(sizeof(unsigned long)*8)] >> | ||||||
|  |                 (nr % (sizeof(unsigned long)*8))) & 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * new VHD bitmaps are big endian | ||||||
|  |  * and bits within a word are set from left to right | ||||||
|  |  */ | ||||||
|  | #define BIT_MASK 0x80 | ||||||
|  | static inline void | ||||||
|  | new_set_bit (int nr, volatile char *addr) | ||||||
|  | { | ||||||
|  |         addr[nr >> 3] |= (BIT_MASK >> (nr & 7)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | convert_bitmap(char *in, char *out, int bytes) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 
 | ||||||
|  | 	memset(out, 0, bytes); | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < bytes << 3; i++) | ||||||
|  | 		if (old_test_bit(i, (void *)in)) | ||||||
|  | 			new_set_bit(i, out); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | update_vhd(vhd_journal_t *journal, int rollback) | ||||||
|  | { | ||||||
|  | 	int i, err; | ||||||
|  | 	size_t size; | ||||||
|  | 	char *buf, *converted; | ||||||
|  | 
 | ||||||
|  | 	buf       = NULL; | ||||||
|  | 	converted = NULL; | ||||||
|  | 
 | ||||||
|  | 	size = vhd_bytes_padded(journal->vhd.spb / 8); | ||||||
|  | 	err  = posix_memalign((void **)&converted, 512, size); | ||||||
|  | 	if (err) { | ||||||
|  | 		converted = NULL; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < journal->vhd.bat.entries; i++) { | ||||||
|  | 		if (journal->vhd.bat.bat[i] == DD_BLK_UNUSED) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		err = vhd_read_bitmap(&journal->vhd, i, &buf); | ||||||
|  | 		if (err) | ||||||
|  | 			goto out; | ||||||
|  | 
 | ||||||
|  | 		if (rollback) | ||||||
|  | 			memcpy(converted, buf, size); | ||||||
|  | 		else | ||||||
|  | 			convert_bitmap(buf, converted, size); | ||||||
|  | 
 | ||||||
|  | 		free(buf); | ||||||
|  | 
 | ||||||
|  | 		err = vhd_write_bitmap(&journal->vhd, i, converted); | ||||||
|  | 		if (err) | ||||||
|  | 			goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = 0; | ||||||
|  |  out: | ||||||
|  | 	free(converted); | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | open_journal(vhd_journal_t *journal, const char *file, const char *jfile) | ||||||
|  | { | ||||||
|  | 	int err; | ||||||
|  | 
 | ||||||
|  | 	err = vhd_journal_create(journal, file, jfile); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("error creating journal for %s: %d\n", file, err); | ||||||
|  | 		return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | close_journal(vhd_journal_t *journal, int err) | ||||||
|  | { | ||||||
|  | 	if (err) | ||||||
|  | 		err = vhd_journal_revert(journal); | ||||||
|  | 	else | ||||||
|  | 		err = vhd_journal_commit(journal); | ||||||
|  | 
 | ||||||
|  | 	if (err) | ||||||
|  | 		return vhd_journal_close(journal); | ||||||
|  | 	else | ||||||
|  | 		return vhd_journal_remove(journal); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | main(int argc, char **argv) | ||||||
|  | { | ||||||
|  | 	char *file, *jfile; | ||||||
|  | 	int c, err, rollback; | ||||||
|  | 	vhd_journal_t journal; | ||||||
|  | 
 | ||||||
|  | 	file     = NULL; | ||||||
|  | 	jfile    = NULL; | ||||||
|  | 	rollback = 0; | ||||||
|  | 
 | ||||||
|  | 	while ((c = getopt(argc, argv, "n:j:rh")) != -1) { | ||||||
|  | 		switch(c) { | ||||||
|  | 		case 'n': | ||||||
|  | 			file = optarg; | ||||||
|  | 			break; | ||||||
|  | 		case 'j': | ||||||
|  | 			jfile = optarg; | ||||||
|  | 			err = access(jfile, R_OK); | ||||||
|  | 			if (err == -1) { | ||||||
|  | 				printf("invalid journal arg %s\n", jfile); | ||||||
|  | 				return -errno; | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 		case 'r': | ||||||
|  | 			/* add a rollback option for debugging which
 | ||||||
|  | 			 * pushes journalled bitmaps to original file | ||||||
|  | 			 * without transforming them */ | ||||||
|  | 			rollback = 1; | ||||||
|  | 			break; | ||||||
|  | 		default: | ||||||
|  | 			usage(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!file) | ||||||
|  | 		usage(); | ||||||
|  | 
 | ||||||
|  | 	if (rollback && !jfile) { | ||||||
|  | 		printf("rollback requires a journal argument\n"); | ||||||
|  | 		usage(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = open_journal(&journal, file, jfile); | ||||||
|  | 	if (err) | ||||||
|  | 		return err; | ||||||
|  | 
 | ||||||
|  | 	if (!vhd_creator_tapdisk(&journal.vhd) || | ||||||
|  | 	    journal.vhd.footer.crtr_ver != VHD_VERSION(0, 1) || | ||||||
|  | 	    journal.vhd.footer.type == HD_TYPE_FIXED) { | ||||||
|  | 		err = 0; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = journal_bitmaps(&journal); | ||||||
|  | 	if (err) { | ||||||
|  | 		/* no changes to vhd file yet,
 | ||||||
|  | 		 * so close the journal and bail */ | ||||||
|  | 		vhd_journal_close(&journal); | ||||||
|  | 		return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = update_vhd(&journal, rollback); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("update failed: %d; saving journal\n", err); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = update_creator_version(&journal); | ||||||
|  | 	if (err) { | ||||||
|  | 		printf("failed to udpate creator version: %d\n", err); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = 0; | ||||||
|  | 
 | ||||||
|  | out: | ||||||
|  | 	err = close_journal(&journal, err); | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
							
								
								
									
										160
									
								
								tools/vhd-tools/vhd/vhd-util.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										160
									
								
								tools/vhd-tools/vhd/vhd-util.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,160 @@ | |||||||
|  | /* Copyright (c) 2008, XenSource Inc.
 | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *     * Neither the name of XenSource Inc. nor the names of its contributors | ||||||
|  |  *       may be used to endorse or promote products derived from this software | ||||||
|  |  *       without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | ||||||
|  |  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||||
|  |  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||||
|  |  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||||
|  |  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||||
|  |  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||||
|  |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | */ | ||||||
|  | #include <errno.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | 
 | ||||||
|  | #include "libvhd.h" | ||||||
|  | #include "vhd-util.h" | ||||||
|  | 
 | ||||||
|  | #if 1 | ||||||
|  | #define DFPRINTF(_f, _a...) fprintf(stdout, _f , ##_a) | ||||||
|  | #else | ||||||
|  | #define DFPRINTF(_f, _a...) ((void)0) | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | typedef int (*vhd_util_func_t) (int, char **); | ||||||
|  | 
 | ||||||
|  | struct command { | ||||||
|  | 	char               *name; | ||||||
|  | 	vhd_util_func_t     func; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct command commands[] = { | ||||||
|  | 	{ .name = "create",      .func = vhd_util_create        }, | ||||||
|  | 	{ .name = "snapshot",    .func = vhd_util_snapshot      }, | ||||||
|  | 	{ .name = "query",       .func = vhd_util_query         }, | ||||||
|  | 	{ .name = "read",        .func = vhd_util_read          }, | ||||||
|  | 	{ .name = "set",         .func = vhd_util_set_field     }, | ||||||
|  | 	{ .name = "repair",      .func = vhd_util_repair        }, | ||||||
|  | 	{ .name = "resize",      .func = vhd_util_resize        }, | ||||||
|  | 	{ .name = "fill",        .func = vhd_util_fill          }, | ||||||
|  | 	{ .name = "coalesce",    .func = vhd_util_coalesce      }, | ||||||
|  | 	{ .name = "modify",      .func = vhd_util_modify        }, | ||||||
|  | 	{ .name = "scan",        .func = vhd_util_scan          }, | ||||||
|  | 	{ .name = "check",       .func = vhd_util_check         }, | ||||||
|  | 	{ .name = "revert",      .func = vhd_util_revert        }, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #define print_commands()					\ | ||||||
|  | 	do {							\ | ||||||
|  | 		int i, n;					\ | ||||||
|  | 		n = sizeof(commands) / sizeof(struct command);	\ | ||||||
|  | 		printf("COMMAND := { ");			\ | ||||||
|  | 		printf("%s", commands[0].name);			\ | ||||||
|  | 		for (i = 1; i < n; i++)				\ | ||||||
|  | 			printf(" | %s", commands[i].name);	\ | ||||||
|  | 		printf(" }\n");					\ | ||||||
|  | 	} while (0) | ||||||
|  | 
 | ||||||
|  | TEST_FAIL_EXTERN_VARS; | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | help(void) | ||||||
|  | { | ||||||
|  | 	printf("usage: vhd-util COMMAND [OPTIONS]\n"); | ||||||
|  | 	print_commands(); | ||||||
|  | 	exit(0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct command * | ||||||
|  | get_command(char *command) | ||||||
|  | { | ||||||
|  | 	int i, n; | ||||||
|  | 
 | ||||||
|  | 	if (strnlen(command, 25) >= 25) | ||||||
|  | 		return NULL; | ||||||
|  | 
 | ||||||
|  | 	n = sizeof(commands) / sizeof (struct command); | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < n; i++) | ||||||
|  | 		if (!strcmp(command, commands[i].name)) | ||||||
|  | 			return &commands[i]; | ||||||
|  | 
 | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | main(int argc, char *argv[]) | ||||||
|  | { | ||||||
|  | 	char **cargv; | ||||||
|  | 	struct command *cmd; | ||||||
|  | 	int cargc, i, cnt, ret; | ||||||
|  | 
 | ||||||
|  | #ifdef CORE_DUMP | ||||||
|  | 	#include <sys/resource.h> | ||||||
|  | 	struct rlimit rlim; | ||||||
|  | 	rlim.rlim_cur = RLIM_INFINITY; | ||||||
|  | 	rlim.rlim_max = RLIM_INFINITY; | ||||||
|  | 	if (setrlimit(RLIMIT_CORE, &rlim) < 0) | ||||||
|  | 		fprintf(stderr, "setrlimit failed: %d\n", errno); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 	ret = 0; | ||||||
|  | 
 | ||||||
|  | 	if (argc < 2) | ||||||
|  | 		help(); | ||||||
|  | 
 | ||||||
|  | 	cargc = argc - 1; | ||||||
|  | 	cmd   = get_command(argv[1]); | ||||||
|  | 	if (!cmd) { | ||||||
|  | 		fprintf(stderr, "invalid COMMAND %s\n", argv[1]); | ||||||
|  | 		help(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	cargv = malloc(sizeof(char *) * cargc); | ||||||
|  | 	if (!cargv) | ||||||
|  | 		exit(ENOMEM); | ||||||
|  | 
 | ||||||
|  | 	cnt      = 1; | ||||||
|  | 	cargv[0] = cmd->name; | ||||||
|  | 	for (i = 1; i < cargc; i++) { | ||||||
|  | 		char *arg = argv[i + (argc - cargc)]; | ||||||
|  | 
 | ||||||
|  | 		if (!strcmp(arg, "--debug")) { | ||||||
|  | 			libvhd_set_log_level(1); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		cargv[cnt++] = arg; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | #ifdef ENABLE_FAILURE_TESTING | ||||||
|  | 	for (i = 0; i < NUM_FAIL_TESTS; i++) { | ||||||
|  | 		TEST_FAIL[i] = 0; | ||||||
|  | 		if (getenv(ENV_VAR_FAIL[i])) | ||||||
|  | 			TEST_FAIL[i] = 1; | ||||||
|  | 	} | ||||||
|  | #endif // ENABLE_FAILURE_TESTING
 | ||||||
|  | 
 | ||||||
|  | 	ret = cmd->func(cnt, cargv); | ||||||
|  | 
 | ||||||
|  | 	free(cargv); | ||||||
|  | 
 | ||||||
|  | 	return (ret >= 0 ? ret : -ret); | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user