Changeset 32536 in vbox
- Timestamp:
- Sep 15, 2010 6:25:32 PM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 65918
- Location:
- trunk
- Files:
-
- 30 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Config.kmk
r32471 r32536 397 397 if1of ($(KBUILD_TARGET), darwin freebsd linux solaris win) 398 398 VBOX_WITH_HOSTNETIF_API = 1 399 endif400 # Enable the new storage I/O path.401 if1of ($(KBUILD_TARGET), darwin freebsd linux solaris win)402 VBOX_WITH_NEW_IO_CODE = 1403 399 endif 404 400 ## @} -
trunk/include/VBox/VBoxHDD-CachePlugin.h
r32370 r32536 74 74 * @returns VBox status code. 75 75 * @param pszFilename Name of the image file. 76 * @param pVDIfsCache Pointer to the per-cache VD interface list. 77 */ 78 DECLR3CALLBACKMEMBER(int, pfnProbe, (const char *pszFilename, PVDINTERFACE pVDIfsCache)); 76 * @param pVDIfsDisk Pointer to the per-disk VD interface list. 77 * @param pVDIfsImage Pointer to the per-image VD interface list. 78 */ 79 DECLR3CALLBACKMEMBER(int, pfnProbe, (const char *pszFilename, PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage)); 79 80 80 81 /** … … 87 88 * @param pVDIfsDisk Pointer to the per-disk VD interface list. 88 89 * @param pVDIfsImage Pointer to the per-image VD interface list. 89 * @param pp vBackendDataOpaque state data for this image.90 * @param ppBackendData Opaque state data for this image. 90 91 */ 91 92 DECLR3CALLBACKMEMBER(int, pfnOpen, (const char *pszFilename, unsigned uOpenFlags, 92 93 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage, 93 void **pp vBackendData));94 void **ppBackendData)); 94 95 95 96 /** … … 109 110 * @param pVDIfsImage Pointer to the per-image VD interface list. 110 111 * @param pVDIfsOperation Pointer to the per-operation VD interface list. 111 * @param pp vBackendDataOpaque state data for this image.112 * @param ppBackendData Opaque state data for this image. 112 113 */ 113 114 DECLR3CALLBACKMEMBER(int, pfnCreate, (const char *pszFilename, uint64_t cbSize, … … 118 119 PVDINTERFACE pVDIfsImage, 119 120 PVDINTERFACE pVDIfsOperation, 120 void **pp vBackendData));121 void **ppBackendData)); 121 122 122 123 /** … … 124 125 * 125 126 * @returns VBox status code. 126 * @param p vBackendDataOpaque state data for this image.127 * @param pBackendData Opaque state data for this image. 127 128 * @param fDelete If true, delete the image from the host disk. 128 129 */ 129 DECLR3CALLBACKMEMBER(int, pfnClose, (void *p vBackendData, bool fDelete));130 DECLR3CALLBACKMEMBER(int, pfnClose, (void *pBackendData, bool fDelete)); 130 131 131 132 /** … … 135 136 * @returns VBox status code. 136 137 * @returns VERR_VD_BLOCK_FREE if this image contains no data for this block. 137 * @param p vBackendDataOpaque state data for this image.138 * @param pBackendData Opaque state data for this image. 138 139 * @param uOffset Offset to start reading from. 139 140 * @param pvBuf Where to store the read bits. … … 141 142 * @param pcbActuallyRead Pointer to returned number of bytes read. 142 143 */ 143 DECLR3CALLBACKMEMBER(int, pfnRead, (void *p vBackendData, uint64_t uOffset, void *pvBuf,144 DECLR3CALLBACKMEMBER(int, pfnRead, (void *pBackendData, uint64_t uOffset, void *pvBuf, 144 145 size_t cbRead, size_t *pcbActuallyRead)); 145 146 … … 149 150 * 150 151 * @returns VBox status code. 151 * @param p vBackendDataOpaque state data for this image.152 * @param pBackendData Opaque state data for this image. 152 153 * @param uOffset Offset to start writing to. 153 154 * @param pvBuf Where to retrieve the written bits. … … 156 157 * be processed. 157 158 */ 158 DECLR3CALLBACKMEMBER(int, pfnWrite, (void *p vBackendData, uint64_t uOffset,159 DECLR3CALLBACKMEMBER(int, pfnWrite, (void *pBackendData, uint64_t uOffset, 159 160 const void *pvBuf, size_t cbWrite, 160 161 size_t *pcbWriteProcess)); … … 164 165 * 165 166 * @returns VBox status code. 166 * @param p vBackendDataOpaque state data for this image.167 */ 168 DECLR3CALLBACKMEMBER(int, pfnFlush, (void *p vBackendData));167 * @param pBackendData Opaque state data for this image. 168 */ 169 DECLR3CALLBACKMEMBER(int, pfnFlush, (void *pBackendData)); 169 170 170 171 /** … … 172 173 * 173 174 * @returns version of cache image. 174 * @param p vBackendDataOpaque state data for this image.175 */ 176 DECLR3CALLBACKMEMBER(unsigned, pfnGetVersion, (void *p vBackendData));175 * @param pBackendData Opaque state data for this image. 176 */ 177 DECLR3CALLBACKMEMBER(unsigned, pfnGetVersion, (void *pBackendData)); 177 178 178 179 /** … … 180 181 * 181 182 * @returns size of cache image in bytes. 182 * @param p vBackendDataOpaque state data for this image.183 */ 184 DECLR3CALLBACKMEMBER(uint64_t, pfnGetSize, (void *p vBackendData));183 * @param pBackendData Opaque state data for this image. 184 */ 185 DECLR3CALLBACKMEMBER(uint64_t, pfnGetSize, (void *pBackendData)); 185 186 186 187 /** … … 188 189 * 189 190 * @returns size of cache image in bytes. 190 * @param p vBackendDataOpaque state data for this image.191 */ 192 DECLR3CALLBACKMEMBER(uint64_t, pfnGetFileSize, (void *p vBackendData));191 * @param pBackendData Opaque state data for this image. 192 */ 193 DECLR3CALLBACKMEMBER(uint64_t, pfnGetFileSize, (void *pBackendData)); 193 194 194 195 /** … … 196 197 * 197 198 * @returns image flags of cache image. 198 * @param p vBackendDataOpaque state data for this image.199 */ 200 DECLR3CALLBACKMEMBER(unsigned, pfnGetImageFlags, (void *p vBackendData));199 * @param pBackendData Opaque state data for this image. 200 */ 201 DECLR3CALLBACKMEMBER(unsigned, pfnGetImageFlags, (void *pBackendData)); 201 202 202 203 /** … … 204 205 * 205 206 * @returns open flags of cache image. 206 * @param p vBackendDataOpaque state data for this image.207 */ 208 DECLR3CALLBACKMEMBER(unsigned, pfnGetOpenFlags, (void *p vBackendData));207 * @param pBackendData Opaque state data for this image. 208 */ 209 DECLR3CALLBACKMEMBER(unsigned, pfnGetOpenFlags, (void *pBackendData)); 209 210 210 211 /** … … 213 214 * 214 215 * @returns VBox status code. 215 * @param p vBackendDataOpaque state data for this image.216 * @param pBackendData Opaque state data for this image. 216 217 * @param uOpenFlags New open flags for this image. 217 218 */ 218 DECLR3CALLBACKMEMBER(int, pfnSetOpenFlags, (void *p vBackendData, unsigned uOpenFlags));219 DECLR3CALLBACKMEMBER(int, pfnSetOpenFlags, (void *pBackendData, unsigned uOpenFlags)); 219 220 220 221 /** … … 222 223 * 223 224 * @returns VBox status code. 224 * @param p vBackendDataOpaque state data for this image.225 * @param pBackendData Opaque state data for this image. 225 226 * @param pszComment Where to store the comment. 226 227 * @param cbComment Size of the comment buffer. 227 228 */ 228 DECLR3CALLBACKMEMBER(int, pfnGetComment, (void *p vBackendData, char *pszComment, size_t cbComment));229 DECLR3CALLBACKMEMBER(int, pfnGetComment, (void *pBackendData, char *pszComment, size_t cbComment)); 229 230 230 231 /** … … 232 233 * 233 234 * @returns VBox status code. 234 * @param p vBackendDataOpaque state data for this image.235 * @param pBackendData Opaque state data for this image. 235 236 * @param pszComment Where to get the comment from. NULL resets comment. 236 237 * The comment is silently truncated if the image format 237 238 * limit is exceeded. 238 239 */ 239 DECLR3CALLBACKMEMBER(int, pfnSetComment, (void *p vBackendData, const char *pszComment));240 DECLR3CALLBACKMEMBER(int, pfnSetComment, (void *pBackendData, const char *pszComment)); 240 241 241 242 /** … … 243 244 * 244 245 * @returns VBox status code. 245 * @param p vBackendDataOpaque state data for this image.246 * @param pBackendData Opaque state data for this image. 246 247 * @param pUuid Where to store the image UUID. 247 248 */ 248 DECLR3CALLBACKMEMBER(int, pfnGetUuid, (void *p vBackendData, PRTUUID pUuid));249 DECLR3CALLBACKMEMBER(int, pfnGetUuid, (void *pBackendData, PRTUUID pUuid)); 249 250 250 251 /** … … 252 253 * 253 254 * @returns VBox status code. 254 * @param p vBackendDataOpaque state data for this image.255 * @param pBackendData Opaque state data for this image. 255 256 * @param pUuid Where to get the image UUID from. 256 257 */ 257 DECLR3CALLBACKMEMBER(int, pfnSetUuid, (void *p vBackendData, PCRTUUID pUuid));258 DECLR3CALLBACKMEMBER(int, pfnSetUuid, (void *pBackendData, PCRTUUID pUuid)); 258 259 259 260 /** … … 261 262 * 262 263 * @returns VBox status code. 263 * @param p vBackendDataOpaque state data for this image.264 * @param pBackendData Opaque state data for this image. 264 265 * @param pUuid Where to store the image modification UUID. 265 266 */ 266 DECLR3CALLBACKMEMBER(int, pfnGetModificationUuid, (void *p vBackendData, PRTUUID pUuid));267 DECLR3CALLBACKMEMBER(int, pfnGetModificationUuid, (void *pBackendData, PRTUUID pUuid)); 267 268 268 269 /** … … 270 271 * 271 272 * @returns VBox status code. 272 * @param p vBackendDataOpaque state data for this image.273 * @param pBackendData Opaque state data for this image. 273 274 * @param pUuid Where to get the image modification UUID from. 274 275 */ 275 DECLR3CALLBACKMEMBER(int, pfnSetModificationUuid, (void *p vBackendData, PCRTUUID pUuid));276 DECLR3CALLBACKMEMBER(int, pfnSetModificationUuid, (void *pBackendData, PCRTUUID pUuid)); 276 277 277 278 /** 278 279 * Dump information about a cache image. 279 280 * 280 * @param p vBackendDataOpaque state data for this image.281 */ 282 DECLR3CALLBACKMEMBER(void, pfnDump, (void *p vBackendData));281 * @param pBackendData Opaque state data for this image. 282 */ 283 DECLR3CALLBACKMEMBER(void, pfnDump, (void *pBackendData)); 283 284 284 285 /** … … 286 287 * 287 288 * @returns VBox status code. 288 * @param p vBackendDataOpaque state data for this image.289 * @param pBackendData Opaque state data for this image. 289 290 * @param uOffset The offset of the virtual disk to read from. 290 291 * @param cbRead How many bytes to read. … … 292 293 * @param pcbActuallyRead Pointer to returned number of bytes read. 293 294 */ 294 DECLR3CALLBACKMEMBER(int, pfnAsyncRead, (void *p vBackendData, uint64_t uOffset, size_t cbRead,295 DECLR3CALLBACKMEMBER(int, pfnAsyncRead, (void *pBackendData, uint64_t uOffset, size_t cbRead, 295 296 PVDIOCTX pIoCtx, size_t *pcbActuallyRead)); 296 297 … … 299 300 * 300 301 * @returns VBox status code. 301 * @param p vBackendDataOpaque state data for this image.302 * @param pBackendData Opaque state data for this image. 302 303 * @param uOffset The offset of the virtual disk to write to. 303 304 * @param cbWrite How many bytes to write. … … 310 311 * amount of (previously read) padding data. 311 312 */ 312 DECLR3CALLBACKMEMBER(int, pfnAsyncWrite, (void *p vBackendData, uint64_t uOffset, size_t cbWrite,313 DECLR3CALLBACKMEMBER(int, pfnAsyncWrite, (void *pBackendData, uint64_t uOffset, size_t cbWrite, 313 314 PVDIOCTX pIoCtx, size_t *pcbWriteProcess)); 314 315 … … 317 318 * 318 319 * @returns VBox status code. 319 * @param p vBackendDataOpaque state data for this image.320 * @param pBackendData Opaque state data for this image. 320 321 * @param pIoCtx I/O context associated with this request. 321 322 */ 322 DECLR3CALLBACKMEMBER(int, pfnAsyncFlush, (void *p vBackendData, PVDIOCTX pIoCtx));323 DECLR3CALLBACKMEMBER(int, pfnAsyncFlush, (void *pBackendData, PVDIOCTX pIoCtx)); 323 324 324 325 /** Returns a human readable hard disk location string given a -
trunk/include/VBox/VBoxHDD-Plugin.h
r32370 r32536 27 27 #define __VBoxHDD_Plugin_h__ 28 28 29 #include <VBox/pdm.h>30 29 #include <VBox/VBoxHDD.h> 31 30 … … 87 86 * @param pszFilename Name of the image file. 88 87 * @param pVDIfsDisk Pointer to the per-disk VD interface list. 89 */ 90 DECLR3CALLBACKMEMBER(int, pfnCheckIfValid, (const char *pszFilename, PVDINTERFACE pVDIfsDisk)); 88 * @param pVDIfsImage Pointer to the per-image VD interface list. 89 */ 90 DECLR3CALLBACKMEMBER(int, pfnCheckIfValid, (const char *pszFilename, PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage)); 91 91 92 92 /** … … 99 99 * @param pVDIfsDisk Pointer to the per-disk VD interface list. 100 100 * @param pVDIfsImage Pointer to the per-image VD interface list. 101 * @param pp vBackendDataOpaque state data for this image.101 * @param ppBackendData Opaque state data for this image. 102 102 */ 103 103 DECLR3CALLBACKMEMBER(int, pfnOpen, (const char *pszFilename, unsigned uOpenFlags, 104 104 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage, 105 void **pp vBackendData));105 void **ppBackendData)); 106 106 107 107 /** … … 123 123 * @param pVDIfsImage Pointer to the per-image VD interface list. 124 124 * @param pVDIfsOperation Pointer to the per-operation VD interface list. 125 * @param pp vBackendDataOpaque state data for this image.125 * @param ppBackendData Opaque state data for this image. 126 126 */ 127 127 DECLR3CALLBACKMEMBER(int, pfnCreate, (const char *pszFilename, uint64_t cbSize, 128 128 unsigned uImageFlags, const char *pszComment, 129 PC PDMMEDIAGEOMETRY pPCHSGeometry,130 PC PDMMEDIAGEOMETRY pLCHSGeometry,129 PCVDGEOMETRY pPCHSGeometry, 130 PCVDGEOMETRY pLCHSGeometry, 131 131 PCRTUUID pUuid, unsigned uOpenFlags, 132 132 unsigned uPercentStart, unsigned uPercentSpan, … … 134 134 PVDINTERFACE pVDIfsImage, 135 135 PVDINTERFACE pVDIfsOperation, 136 void **pp vBackendData));136 void **ppBackendData)); 137 137 138 138 /** … … 142 142 * may just fail with an appropriate error code (not changing the opened 143 143 * image data at all). Also works only on images which actually refer to 144 * files (and not for raw disk images).145 * 146 * @returns VBox status code. 147 * @param p vBackendDataOpaque state data for this image.144 * regular files. May be NULL. 145 * 146 * @returns VBox status code. 147 * @param pBackendData Opaque state data for this image. 148 148 * @param pszFilename New name of the image file. Guaranteed to be available and 149 149 * unchanged during the lifetime of this image. 150 150 */ 151 DECLR3CALLBACKMEMBER(int, pfnRename, (void *p vBackendData, const char *pszFilename));151 DECLR3CALLBACKMEMBER(int, pfnRename, (void *pBackendData, const char *pszFilename)); 152 152 153 153 /** … … 155 155 * 156 156 * @returns VBox status code. 157 * @param p vBackendDataOpaque state data for this image.157 * @param pBackendData Opaque state data for this image. 158 158 * @param fDelete If true, delete the image from the host disk. 159 159 */ 160 DECLR3CALLBACKMEMBER(int, pfnClose, (void *p vBackendData, bool fDelete));160 DECLR3CALLBACKMEMBER(int, pfnClose, (void *pBackendData, bool fDelete)); 161 161 162 162 /** … … 166 166 * @returns VBox status code. 167 167 * @returns VERR_VD_BLOCK_FREE if this image contains no data for this block. 168 * @param p vBackendDataOpaque state data for this image.168 * @param pBackendData Opaque state data for this image. 169 169 * @param uOffset Offset to start reading from. 170 170 * @param pvBuf Where to store the read bits. … … 172 172 * @param pcbActuallyRead Pointer to returned number of bytes read. 173 173 */ 174 DECLR3CALLBACKMEMBER(int, pfnRead, (void *p vBackendData, uint64_t uOffset, void *pvBuf,174 DECLR3CALLBACKMEMBER(int, pfnRead, (void *pBackendData, uint64_t uOffset, void *pvBuf, 175 175 size_t cbRead, size_t *pcbActuallyRead)); 176 176 … … 186 186 * but it works with arbitrary block sizes, especially when the image 187 187 * stack uses different block sizes. 188 * @param p vBackendDataOpaque state data for this image.188 * @param pBackendData Opaque state data for this image. 189 189 * @param uOffset Offset to start writing to. 190 190 * @param pvBuf Where to retrieve the written bits. … … 203 203 * of the VD_WRITE_* flags. 204 204 */ 205 DECLR3CALLBACKMEMBER(int, pfnWrite, (void *p vBackendData, uint64_t uOffset,205 DECLR3CALLBACKMEMBER(int, pfnWrite, (void *pBackendData, uint64_t uOffset, 206 206 const void *pvBuf, size_t cbWrite, 207 207 size_t *pcbWriteProcess, size_t *pcbPreRead, … … 212 212 * 213 213 * @returns VBox status code. 214 * @param p vBackendDataOpaque state data for this image.215 */ 216 DECLR3CALLBACKMEMBER(int, pfnFlush, (void *p vBackendData));214 * @param pBackendData Opaque state data for this image. 215 */ 216 DECLR3CALLBACKMEMBER(int, pfnFlush, (void *pBackendData)); 217 217 218 218 /** … … 220 220 * 221 221 * @returns version of disk image. 222 * @param p vBackendDataOpaque state data for this image.223 */ 224 DECLR3CALLBACKMEMBER(unsigned, pfnGetVersion, (void *p vBackendData));222 * @param pBackendData Opaque state data for this image. 223 */ 224 DECLR3CALLBACKMEMBER(unsigned, pfnGetVersion, (void *pBackendData)); 225 225 226 226 /** … … 228 228 * 229 229 * @returns size of disk image in bytes. 230 * @param p vBackendDataOpaque state data for this image.231 */ 232 DECLR3CALLBACKMEMBER(uint64_t, pfnGetSize, (void *p vBackendData));230 * @param pBackendData Opaque state data for this image. 231 */ 232 DECLR3CALLBACKMEMBER(uint64_t, pfnGetSize, (void *pBackendData)); 233 233 234 234 /** … … 236 236 * 237 237 * @returns size of disk image in bytes. 238 * @param p vBackendDataOpaque state data for this image.239 */ 240 DECLR3CALLBACKMEMBER(uint64_t, pfnGetFileSize, (void *p vBackendData));238 * @param pBackendData Opaque state data for this image. 239 */ 240 DECLR3CALLBACKMEMBER(uint64_t, pfnGetFileSize, (void *pBackendData)); 241 241 242 242 /** … … 245 245 * @returns VBox status code. 246 246 * @returns VERR_VD_GEOMETRY_NOT_SET if no geometry present in the image. 247 * @param p vBackendDataOpaque state data for this image.247 * @param pBackendData Opaque state data for this image. 248 248 * @param pPCHSGeometry Where to store the geometry. Not NULL. 249 249 */ 250 DECLR3CALLBACKMEMBER(int, pfnGetPCHSGeometry, (void *p vBackendData, PPDMMEDIAGEOMETRY pPCHSGeometry));250 DECLR3CALLBACKMEMBER(int, pfnGetPCHSGeometry, (void *pBackendData, PVDGEOMETRY pPCHSGeometry)); 251 251 252 252 /** … … 255 255 * 256 256 * @returns VBox status code. 257 * @param p vBackendDataOpaque state data for this image.257 * @param pBackendData Opaque state data for this image. 258 258 * @param pPCHSGeometry Where to load the geometry from. Not NULL. 259 259 */ 260 DECLR3CALLBACKMEMBER(int, pfnSetPCHSGeometry, (void *p vBackendData, PCPDMMEDIAGEOMETRY pPCHSGeometry));260 DECLR3CALLBACKMEMBER(int, pfnSetPCHSGeometry, (void *pBackendData, PCVDGEOMETRY pPCHSGeometry)); 261 261 262 262 /** … … 265 265 * @returns VBox status code. 266 266 * @returns VERR_VD_GEOMETRY_NOT_SET if no geometry present in the image. 267 * @param p vBackendDataOpaque state data for this image.267 * @param pBackendData Opaque state data for this image. 268 268 * @param pLCHSGeometry Where to store the geometry. Not NULL. 269 269 */ 270 DECLR3CALLBACKMEMBER(int, pfnGetLCHSGeometry, (void *p vBackendData, PPDMMEDIAGEOMETRY pLCHSGeometry));270 DECLR3CALLBACKMEMBER(int, pfnGetLCHSGeometry, (void *pBackendData, PVDGEOMETRY pLCHSGeometry)); 271 271 272 272 /** … … 275 275 * 276 276 * @returns VBox status code. 277 * @param p vBackendDataOpaque state data for this image.277 * @param pBackendData Opaque state data for this image. 278 278 * @param pLCHSGeometry Where to load the geometry from. Not NULL. 279 279 */ 280 DECLR3CALLBACKMEMBER(int, pfnSetLCHSGeometry, (void *p vBackendData, PCPDMMEDIAGEOMETRY pLCHSGeometry));280 DECLR3CALLBACKMEMBER(int, pfnSetLCHSGeometry, (void *pBackendData, PCVDGEOMETRY pLCHSGeometry)); 281 281 282 282 /** … … 284 284 * 285 285 * @returns image flags of disk image. 286 * @param p vBackendDataOpaque state data for this image.287 */ 288 DECLR3CALLBACKMEMBER(unsigned, pfnGetImageFlags, (void *p vBackendData));286 * @param pBackendData Opaque state data for this image. 287 */ 288 DECLR3CALLBACKMEMBER(unsigned, pfnGetImageFlags, (void *pBackendData)); 289 289 290 290 /** … … 292 292 * 293 293 * @returns open flags of disk image. 294 * @param p vBackendDataOpaque state data for this image.295 */ 296 DECLR3CALLBACKMEMBER(unsigned, pfnGetOpenFlags, (void *p vBackendData));294 * @param pBackendData Opaque state data for this image. 295 */ 296 DECLR3CALLBACKMEMBER(unsigned, pfnGetOpenFlags, (void *pBackendData)); 297 297 298 298 /** … … 301 301 * 302 302 * @returns VBox status code. 303 * @param p vBackendDataOpaque state data for this image.303 * @param pBackendData Opaque state data for this image. 304 304 * @param uOpenFlags New open flags for this image. 305 305 */ 306 DECLR3CALLBACKMEMBER(int, pfnSetOpenFlags, (void *p vBackendData, unsigned uOpenFlags));306 DECLR3CALLBACKMEMBER(int, pfnSetOpenFlags, (void *pBackendData, unsigned uOpenFlags)); 307 307 308 308 /** … … 310 310 * 311 311 * @returns VBox status code. 312 * @param p vBackendDataOpaque state data for this image.312 * @param pBackendData Opaque state data for this image. 313 313 * @param pszComment Where to store the comment. 314 314 * @param cbComment Size of the comment buffer. 315 315 */ 316 DECLR3CALLBACKMEMBER(int, pfnGetComment, (void *p vBackendData, char *pszComment, size_t cbComment));316 DECLR3CALLBACKMEMBER(int, pfnGetComment, (void *pBackendData, char *pszComment, size_t cbComment)); 317 317 318 318 /** … … 320 320 * 321 321 * @returns VBox status code. 322 * @param p vBackendDataOpaque state data for this image.322 * @param pBackendData Opaque state data for this image. 323 323 * @param pszComment Where to get the comment from. NULL resets comment. 324 324 * The comment is silently truncated if the image format 325 325 * limit is exceeded. 326 326 */ 327 DECLR3CALLBACKMEMBER(int, pfnSetComment, (void *p vBackendData, const char *pszComment));327 DECLR3CALLBACKMEMBER(int, pfnSetComment, (void *pBackendData, const char *pszComment)); 328 328 329 329 /** … … 331 331 * 332 332 * @returns VBox status code. 333 * @param p vBackendDataOpaque state data for this image.333 * @param pBackendData Opaque state data for this image. 334 334 * @param pUuid Where to store the image UUID. 335 335 */ 336 DECLR3CALLBACKMEMBER(int, pfnGetUuid, (void *p vBackendData, PRTUUID pUuid));336 DECLR3CALLBACKMEMBER(int, pfnGetUuid, (void *pBackendData, PRTUUID pUuid)); 337 337 338 338 /** … … 340 340 * 341 341 * @returns VBox status code. 342 * @param p vBackendDataOpaque state data for this image.342 * @param pBackendData Opaque state data for this image. 343 343 * @param pUuid Where to get the image UUID from. 344 344 */ 345 DECLR3CALLBACKMEMBER(int, pfnSetUuid, (void *p vBackendData, PCRTUUID pUuid));345 DECLR3CALLBACKMEMBER(int, pfnSetUuid, (void *pBackendData, PCRTUUID pUuid)); 346 346 347 347 /** … … 349 349 * 350 350 * @returns VBox status code. 351 * @param p vBackendDataOpaque state data for this image.351 * @param pBackendData Opaque state data for this image. 352 352 * @param pUuid Where to store the image modification UUID. 353 353 */ 354 DECLR3CALLBACKMEMBER(int, pfnGetModificationUuid, (void *p vBackendData, PRTUUID pUuid));354 DECLR3CALLBACKMEMBER(int, pfnGetModificationUuid, (void *pBackendData, PRTUUID pUuid)); 355 355 356 356 /** … … 358 358 * 359 359 * @returns VBox status code. 360 * @param p vBackendDataOpaque state data for this image.360 * @param pBackendData Opaque state data for this image. 361 361 * @param pUuid Where to get the image modification UUID from. 362 362 */ 363 DECLR3CALLBACKMEMBER(int, pfnSetModificationUuid, (void *p vBackendData, PCRTUUID pUuid));363 DECLR3CALLBACKMEMBER(int, pfnSetModificationUuid, (void *pBackendData, PCRTUUID pUuid)); 364 364 365 365 /** … … 367 367 * 368 368 * @returns VBox status code. 369 * @param p vBackendDataOpaque state data for this image.369 * @param pBackendData Opaque state data for this image. 370 370 * @param pUuid Where to store the parent image UUID. 371 371 */ 372 DECLR3CALLBACKMEMBER(int, pfnGetParentUuid, (void *p vBackendData, PRTUUID pUuid));372 DECLR3CALLBACKMEMBER(int, pfnGetParentUuid, (void *pBackendData, PRTUUID pUuid)); 373 373 374 374 /** … … 376 376 * 377 377 * @returns VBox status code. 378 * @param p vBackendDataOpaque state data for this image.378 * @param pBackendData Opaque state data for this image. 379 379 * @param pUuid Where to get the parent image UUID from. 380 380 */ 381 DECLR3CALLBACKMEMBER(int, pfnSetParentUuid, (void *p vBackendData, PCRTUUID pUuid));381 DECLR3CALLBACKMEMBER(int, pfnSetParentUuid, (void *pBackendData, PCRTUUID pUuid)); 382 382 383 383 /** … … 385 385 * 386 386 * @returns VBox status code. 387 * @param p vBackendDataOpaque state data for this image.387 * @param pBackendData Opaque state data for this image. 388 388 * @param pUuid Where to store the parent image modification UUID. 389 389 */ 390 DECLR3CALLBACKMEMBER(int, pfnGetParentModificationUuid, (void *p vBackendData, PRTUUID pUuid));390 DECLR3CALLBACKMEMBER(int, pfnGetParentModificationUuid, (void *pBackendData, PRTUUID pUuid)); 391 391 392 392 /** … … 394 394 * 395 395 * @returns VBox status code. 396 * @param p vBackendDataOpaque state data for this image.396 * @param pBackendData Opaque state data for this image. 397 397 * @param pUuid Where to get the parent image modification UUID from. 398 398 */ 399 DECLR3CALLBACKMEMBER(int, pfnSetParentModificationUuid, (void *p vBackendData, PCRTUUID pUuid));399 DECLR3CALLBACKMEMBER(int, pfnSetParentModificationUuid, (void *pBackendData, PCRTUUID pUuid)); 400 400 401 401 /** 402 402 * Dump information about a disk image. 403 403 * 404 * @param p vBackendDataOpaque state data for this image.405 */ 406 DECLR3CALLBACKMEMBER(void, pfnDump, (void *p vBackendData));407 408 /** 409 * Get a time stamp of a disk image. 410 * 411 * @returns VBox status code. 412 * @param p vBackendDataOpaque state data for this image.404 * @param pBackendData Opaque state data for this image. 405 */ 406 DECLR3CALLBACKMEMBER(void, pfnDump, (void *pBackendData)); 407 408 /** 409 * Get a time stamp of a disk image. May be NULL. 410 * 411 * @returns VBox status code. 412 * @param pBackendData Opaque state data for this image. 413 413 * @param pTimeStamp Where to store the time stamp. 414 414 */ 415 DECLR3CALLBACKMEMBER(int, pfnGetTimeStamp, (void *p vBackendData, PRTTIMESPEC pTimeStamp));416 417 /** 418 * Get the parent time stamp of a disk image. 419 * 420 * @returns VBox status code. 421 * @param p vBackendDataOpaque state data for this image.415 DECLR3CALLBACKMEMBER(int, pfnGetTimeStamp, (void *pBackendData, PRTTIMESPEC pTimeStamp)); 416 417 /** 418 * Get the parent time stamp of a disk image. May be NULL. 419 * 420 * @returns VBox status code. 421 * @param pBackendData Opaque state data for this image. 422 422 * @param pTimeStamp Where to store the time stamp. 423 423 */ 424 DECLR3CALLBACKMEMBER(int, pfnGetParentTimeStamp, (void *p vBackendData, PRTTIMESPEC pTimeStamp));425 426 /** 427 * Set the parent time stamp of a disk image. 428 * 429 * @returns VBox status code. 430 * @param p vBackendDataOpaque state data for this image.424 DECLR3CALLBACKMEMBER(int, pfnGetParentTimeStamp, (void *pBackendData, PRTTIMESPEC pTimeStamp)); 425 426 /** 427 * Set the parent time stamp of a disk image. May be NULL. 428 * 429 * @returns VBox status code. 430 * @param pBackendData Opaque state data for this image. 431 431 * @param pTimeStamp Where to get the time stamp from. 432 432 */ 433 DECLR3CALLBACKMEMBER(int, pfnSetParentTimeStamp, (void *p vBackendData, PCRTTIMESPEC pTimeStamp));434 435 /** 436 * Get the relative path to parent image. 437 * 438 * @returns VBox status code. 439 * @param p vBackendDataOpaque state data for this image.433 DECLR3CALLBACKMEMBER(int, pfnSetParentTimeStamp, (void *pBackendData, PCRTTIMESPEC pTimeStamp)); 434 435 /** 436 * Get the relative path to parent image. May be NULL. 437 * 438 * @returns VBox status code. 439 * @param pBackendData Opaque state data for this image. 440 440 * @param pszParentFilename Where to store the path. 441 441 */ 442 DECLR3CALLBACKMEMBER(int, pfnGetParentFilename, (void *p vBackendData, char **ppszParentFilename));443 444 /** 445 * Set the relative path to parent image. 446 * 447 * @returns VBox status code. 448 * @param p vBackendDataOpaque state data for this image.442 DECLR3CALLBACKMEMBER(int, pfnGetParentFilename, (void *pBackendData, char **ppszParentFilename)); 443 444 /** 445 * Set the relative path to parent image. May be NULL. 446 * 447 * @returns VBox status code. 448 * @param pBackendData Opaque state data for this image. 449 449 * @param pszParentFilename Where to get the path from. 450 450 */ 451 DECLR3CALLBACKMEMBER(int, pfnSetParentFilename, (void *p vBackendData, const char *pszParentFilename));451 DECLR3CALLBACKMEMBER(int, pfnSetParentFilename, (void *pBackendData, const char *pszParentFilename)); 452 452 453 453 /** … … 456 456 * @returns true if asynchronous I/O is supported 457 457 * false otherwise. 458 * @param p vBackendDataOpaque state data for this image.459 */ 460 DECLR3CALLBACKMEMBER(bool, pfnIsAsyncIOSupported, (void *p vBackendData));458 * @param pBackendData Opaque state data for this image. 459 */ 460 DECLR3CALLBACKMEMBER(bool, pfnIsAsyncIOSupported, (void *pBackendData)); 461 461 462 462 /** … … 464 464 * 465 465 * @returns VBox status code. 466 * @param p vBackendDataOpaque state data for this image.466 * @param pBackendData Opaque state data for this image. 467 467 * @param uOffset The offset of the virtual disk to read from. 468 468 * @param cbRead How many bytes to read. … … 470 470 * @param pcbActuallyRead Pointer to returned number of bytes read. 471 471 */ 472 DECLR3CALLBACKMEMBER(int, pfnAsyncRead, (void *p vBackendData, uint64_t uOffset, size_t cbRead,472 DECLR3CALLBACKMEMBER(int, pfnAsyncRead, (void *pBackendData, uint64_t uOffset, size_t cbRead, 473 473 PVDIOCTX pIoCtx, size_t *pcbActuallyRead)); 474 474 … … 477 477 * 478 478 * @returns VBox status code. 479 * @param p vBackendDataOpaque state data for this image.479 * @param pBackendData Opaque state data for this image. 480 480 * @param uOffset The offset of the virtual disk to write to. 481 481 * @param cbWrite How many bytes to write. … … 494 494 * of the VD_WRITE_* flags. 495 495 */ 496 DECLR3CALLBACKMEMBER(int, pfnAsyncWrite, (void *p vBackendData, uint64_t uOffset, size_t cbWrite,496 DECLR3CALLBACKMEMBER(int, pfnAsyncWrite, (void *pBackendData, uint64_t uOffset, size_t cbWrite, 497 497 PVDIOCTX pIoCtx, 498 498 size_t *pcbWriteProcess, size_t *pcbPreRead, … … 503 503 * 504 504 * @returns VBox status code. 505 * @param p vBackendDataOpaque state data for this image.505 * @param pBackendData Opaque state data for this image. 506 506 * @param pIoCtx I/O context associated with this request. 507 507 */ 508 DECLR3CALLBACKMEMBER(int, pfnAsyncFlush, (void *p vBackendData, PVDIOCTX pIoCtx));508 DECLR3CALLBACKMEMBER(int, pfnAsyncFlush, (void *pBackendData, PVDIOCTX pIoCtx)); 509 509 510 510 /** Returns a human readable hard disk location string given a … … 527 527 * @returns VBox status code. 528 528 * @returns VERR_NOT_SUPPORTED if this image cannot be compacted yet. 529 * @param p vBackendDataOpaque state data for this image.529 * @param pBackendData Opaque state data for this image. 530 530 * @param uPercentStart Starting value for progress percentage. 531 531 * @param uPercentSpan Span for varying progress percentage. … … 534 534 * @param pVDIfsOperation Pointer to the per-operation VD interface list. 535 535 */ 536 DECLR3CALLBACKMEMBER(int, pfnCompact, (void *p vBackendData,536 DECLR3CALLBACKMEMBER(int, pfnCompact, (void *pBackendData, 537 537 unsigned uPercentStart, unsigned uPercentSpan, 538 538 PVDINTERFACE pVDIfsDisk, … … 546 546 * @returns VBox status code. 547 547 * @returns VERR_NOT_SUPPORTED if this image cannot be compacted yet. 548 * @param p vBackendDataOpaque state data for this image.548 * @param pBackendData Opaque state data for this image. 549 549 * @param cbSize New size of the image. 550 550 * @param pPCHSGeometry Pointer to the new physical disk geometry <= (16383,16,63). Not NULL. … … 556 556 * @param pVDIfsOperation Pointer to the per-operation VD interface list. 557 557 */ 558 DECLR3CALLBACKMEMBER(int, pfnResize, (void *p vBackendData,558 DECLR3CALLBACKMEMBER(int, pfnResize, (void *pBackendData, 559 559 uint64_t cbSize, 560 PC PDMMEDIAGEOMETRY pPCHSGeometry,561 PC PDMMEDIAGEOMETRY pLCHSGeometry,560 PCVDGEOMETRY pPCHSGeometry, 561 PCVDGEOMETRY pLCHSGeometry, 562 562 unsigned uPercentStart, unsigned uPercentSpan, 563 563 PVDINTERFACE pVDIfsDisk, -
trunk/include/VBox/VBoxHDD.h
r32431 r32536 30 30 #include <iprt/string.h> 31 31 #include <iprt/mem.h> 32 #include <iprt/file.h> 32 33 #include <iprt/net.h> 33 34 #include <iprt/sg.h> … … 35 36 #include <VBox/types.h> 36 37 #include <VBox/err.h> 37 #include <VBox/pdmifs.h>38 38 39 39 RT_C_DECLS_BEGIN … … 166 166 * used for querying information, and nothing else. */ 167 167 #define VD_OPEN_FLAGS_INFO RT_BIT(3) 168 /** Open image for asynchronous access. 169 * Only available if VD_CAP_ASYNC_IO is set 170 * Check with VDIsAsynchonousIoSupported wether 171 * asynchronous I/O is really supported for this file. */ 168 /** Open image for asynchronous access. Only available if VD_CAP_ASYNC_IO is 169 * set. Check with VDIsAsynchonousIoSupported whether asynchronous I/O is 170 * really supported for this file. */ 172 171 #define VD_OPEN_FLAGS_ASYNC_IO RT_BIT(4) 173 172 /** Allow sharing of the image for writable images. May be ignored if the … … 177 176 #define VD_OPEN_FLAGS_MASK (VD_OPEN_FLAGS_NORMAL | VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_HONOR_ZEROES | VD_OPEN_FLAGS_HONOR_SAME | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE) 178 177 /** @}*/ 178 179 /** 180 * Helper functions to handle open flags. 181 */ 182 183 /** 184 * Translate VD_OPEN_FLAGS_* to RTFile open flags. 185 * 186 * @return RTFile open flags. 187 * @param uOpenFlags VD_OPEN_FLAGS_* open flags. 188 * @param fCreate Flag that the file should be created. 189 */ 190 DECLINLINE(uint32_t) VDOpenFlagsToFileOpenFlags(unsigned uOpenFlags, bool fCreate) 191 { 192 AssertMsg(!((uOpenFlags & VD_OPEN_FLAGS_READONLY) && fCreate), ("Image can't be opened readonly while being created\n")); 193 194 uint32_t fOpen = 0; 195 196 if (RT_UNLIKELY(uOpenFlags & VD_OPEN_FLAGS_READONLY)) 197 fOpen |= RTFILE_O_READ | RTFILE_O_DENY_NONE; 198 else 199 { 200 fOpen |= RTFILE_O_READWRITE; 201 202 if (RT_UNLIKELY(uOpenFlags & VD_OPEN_FLAGS_SHAREABLE)) 203 fOpen |= RTFILE_O_DENY_NONE; 204 else 205 fOpen |= RTFILE_O_DENY_WRITE; 206 } 207 208 if (RT_UNLIKELY(fCreate)) 209 fOpen |= RTFILE_O_CREATE | RTFILE_O_NOT_CONTENT_INDEXED; 210 else 211 fOpen |= RTFILE_O_OPEN; 212 213 return fOpen; 214 } 179 215 180 216 … … 203 239 * the appropriate interface. */ 204 240 #define VD_CAP_TCPNET RT_BIT(8) 241 /** The backend supports VFS (virtual filesystem) functionality since it uses 242 * VDINTERFACEIO exclusively for all file operations. */ 243 #define VD_CAP_VFS RT_BIT(9) 205 244 /** @}*/ 206 245 … … 422 461 * @return VBox status code. 423 462 * @param pvUser The opaque data passed on container creation. 424 * @param pszFormat Error message format string.425 * @param ... Error message arguments.426 */ 427 DECLR3CALLBACKMEMBER(int, pfnMessage, (void *pvUser, const char *pszFormat, ...));463 * @param pszFormat Message format string. 464 * @param va Message arguments. 465 */ 466 DECLR3CALLBACKMEMBER(int, pfnMessage, (void *pvUser, const char *pszFormat, va_list va)); 428 467 429 468 } VDINTERFACEERROR, *PVDINTERFACEERROR; … … 466 505 typedef FNVDCOMPLETED *PFNVDCOMPLETED; 467 506 468 /** Open the storage readonly. */469 #define VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY RT_BIT(0)470 /** Create the storage backend if it doesn't exist. */471 #define VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE RT_BIT(1)472 /** Don't write lock the opened file. */473 #define VD_INTERFACEASYNCIO_OPEN_FLAGS_DONT_LOCK RT_BIT(2)474 475 507 /** 476 508 * Support interface for asynchronous I/O … … 496 528 * @param pvUser The opaque data passed on container creation. 497 529 * @param pszLocation Name of the location to open. 498 * @param uOpenFlags Flags for opening the backend. 499 * See VD_INTERFACEASYNCIO_OPEN_FLAGS_* #defines 530 * @param fOpen Flags for opening the backend. 531 * See RTFILE_O_* #defines, inventing another set 532 * of open flags is not worth the mapping effort. 500 533 * @param pfnCompleted The callback which is called whenever a task 501 534 * completed. The backend has to pass the user data … … 507 540 */ 508 541 DECLR3CALLBACKMEMBER(int, pfnOpen, (void *pvUser, const char *pszLocation, 509 u nsigned uOpenFlags,542 uint32_t fOpen, 510 543 PFNVDCOMPLETED pfnCompleted, 511 544 PVDINTERFACE pVDIfsDisk, … … 549 582 * @param pStorage The storage handle to use. 550 583 * @param uOffset The offset to start from. 551 * @param cbWrite How many bytes to write.552 * @param pvBuf Pointer to the bits need to be written.584 * @param pvBuffer Pointer to the bits need to be written. 585 * @param cbBuffer How many bytes to write. 553 586 * @param pcbWritten Where to store how many bytes where actually written. 554 587 */ 555 588 DECLR3CALLBACKMEMBER(int, pfnWriteSync, (void *pvUser, void *pStorage, uint64_t uOffset, 556 size_t cbWrite, const void *pvBuf, size_t *pcbWritten));589 const void *pvBuffer, size_t cbBuffer, size_t *pcbWritten)); 557 590 558 591 /** … … 563 596 * @param pStorage The storage handle to use. 564 597 * @param uOffset The offset to start from. 565 * @param cbRead How many bytes to read.566 * @param pvBuf Where to store the read bits.598 * @param pvBuffer Where to store the read bits. 599 * @param cbBuffer How many bytes to read. 567 600 * @param pcbRead Where to store how many bytes where actually read. 568 601 */ 569 602 DECLR3CALLBACKMEMBER(int, pfnReadSync, (void *pvUser, void *pStorage, uint64_t uOffset, 570 size_t cbRead, void *pvBuf, size_t *pcbRead));603 void *pvBuffer, size_t cbBuffer, size_t *pcbRead)); 571 604 572 605 /** 573 606 * Flush data to the storage backend. 574 607 * 575 * @return VBox stat is code.608 * @return VBox status code. 576 609 * @param pvUser The opaque data passed on container creation. 577 610 * @param pStorage The storage handle to flush. … … 618 651 * Initiates a async flush request. 619 652 * 620 * @return VBox stat is code.653 * @return VBox status code. 621 654 * @param pvUser The opaque data passed on container creation. 622 655 * @param pStorage The storage handle to flush. … … 1141 1174 * @return iprt status code. 1142 1175 * @param Sock Socket descriptor. 1143 * @param pSgBuf 1144 */ 1145 DECLR3CALLBACKMEMBER(int, pfnSgWrite, (VDSOCKET Sock, PCRTSGBUF pSgBuf ));1176 * @param pSgBuffer Scatter/gather buffer to write data to socket. 1177 */ 1178 DECLR3CALLBACKMEMBER(int, pfnSgWrite, (VDSOCKET Sock, PCRTSGBUF pSgBuffer)); 1146 1179 1147 1180 /** … … 1172 1205 * @return iprt status code. 1173 1206 * @param Sock Socket descriptor. 1174 * @param pSgBuf 1207 * @param pSgBuffer Scatter/gather buffer to write data to socket. 1175 1208 * @param pcbWritten Number of bytes written. 1176 1209 */ 1177 DECLR3CALLBACKMEMBER(int, pfnSgWriteNB, (VDSOCKET Sock, PRTSGBUF pSgBuf , size_t *pcbWritten));1210 DECLR3CALLBACKMEMBER(int, pfnSgWriteNB, (VDSOCKET Sock, PRTSGBUF pSgBuffer, size_t *pcbWritten)); 1178 1211 1179 1212 /** … … 1288 1321 * @param uOffset Offset of first reading byte from start of disk. 1289 1322 * Must be aligned to a sector boundary. 1290 * @param pvBuf 1291 * @param cb ReadNumber of bytes to read.1323 * @param pvBuffer Pointer to buffer for reading data. 1324 * @param cbBuffer Number of bytes to read. 1292 1325 * Must be aligned to a sector boundary. 1293 1326 */ 1294 DECLR3CALLBACKMEMBER(int, pfnParentRead, (void *pvUser, uint64_t uOffset, void *pvBuf , size_t cbRead));1327 DECLR3CALLBACKMEMBER(int, pfnParentRead, (void *pvUser, uint64_t uOffset, void *pvBuffer, size_t cbBuffer)); 1295 1328 1296 1329 } VDINTERFACEPARENTSTATE, *PVDINTERFACEPARENTSTATE; … … 1498 1531 * VINF_SUCCESS if everything was successful and the transfer can continue. 1499 1532 * VERR_VD_ASYNC_IO_IN_PROGRESS if there is another data transfer pending. 1500 * @param p vBackendDataThe opaque backend data.1533 * @param pBackendData The opaque backend data. 1501 1534 * @param pIoCtx I/O context associated with this request. 1502 1535 * @param pvUser Opaque user data passed during a read/write request. 1503 1536 * @param rcReq Status code for the completed request. 1504 1537 */ 1505 typedef DECLCALLBACK(int) FNVDXFERCOMPLETED(void *p vBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq);1538 typedef DECLCALLBACK(int) FNVDXFERCOMPLETED(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq); 1506 1539 /** Pointer to FNVDXFERCOMPLETED() */ 1507 1540 typedef FNVDXFERCOMPLETED *PFNVDXFERCOMPLETED; … … 1514 1547 1515 1548 /** 1516 * Support interface for I/O1517 * 1518 * Per-image. Required.1549 * Support interface for file I/O 1550 * 1551 * Per-image. Optional as input, always passed to backends. 1519 1552 */ 1520 1553 typedef struct VDINTERFACEIO … … 1536 1569 * @param pvUser The opaque data passed on container creation. 1537 1570 * @param pszLocation Name of the location to open. 1538 * @param uOpenFlags Flags for opening the backend. 1539 * See VD_INTERFACEASYNCIO_OPEN_FLAGS_* #defines 1571 * @param fOpen Flags for opening the backend. 1572 * See RTFILE_O_* #defines, inventing another set 1573 * of open flags is not worth the mapping effort. 1540 1574 * @param ppStorage Where to store the storage handle. 1541 1575 */ 1542 1576 DECLR3CALLBACKMEMBER(int, pfnOpen, (void *pvUser, const char *pszLocation, 1543 u nsigned uOpenFlags, PPVDIOSTORAGE ppStorage));1577 uint32_t fOpen, PPVDIOSTORAGE ppStorage)); 1544 1578 1545 1579 /** … … 1551 1585 */ 1552 1586 DECLR3CALLBACKMEMBER(int, pfnClose, (void *pvUser, PVDIOSTORAGE pStorage)); 1587 1588 /** 1589 * Delete callback. 1590 * 1591 * @return VBox status code. 1592 * @param pvUser The opaque data passed on container creation. 1593 * @param pcszFilename Name of the file to delete. 1594 */ 1595 DECLR3CALLBACKMEMBER(int, pfnDelete, (void *pvUser, const char *pcszFilename)); 1596 1597 /** 1598 * Move callback. 1599 * 1600 * @return VBox status code. 1601 * @param pvUser The opaque data passed on container creation. 1602 * @param pcszSrc The path to the source file. 1603 * @param pcszDst The path to the destination file. 1604 * This file will be created. 1605 * @param fMove A combination of the RTFILEMOVE_* flags. 1606 */ 1607 DECLR3CALLBACKMEMBER(int, pfnMove, (void *pvUser, const char *pcszSrc, const char *pcszDst, unsigned fMove)); 1608 1609 /** 1610 * Returns the free space on a disk. 1611 * 1612 * @return VBox status code. 1613 * @param pvUser The opaque data passed on container creation. 1614 * @param pcszFilename Name of a file to identify the disk. 1615 * @param pcbFreeSpace Where to store the free space of the disk. 1616 */ 1617 DECLR3CALLBACKMEMBER(int, pfnGetFreeSpace, (void *pvUser, const char *pcszFilename, int64_t *pcbFreeSpace)); 1618 1619 /** 1620 * Returns the last modification timestamp of a file. 1621 * 1622 * @return VBox status code. 1623 * @param pvUser The opaque data passed on container creation. 1624 * @param pcszFilename Name of a file to identify the disk. 1625 * @param pModificationTime Where to store the timestamp of the file. 1626 */ 1627 DECLR3CALLBACKMEMBER(int, pfnGetModificationTime, (void *pvUser, const char *pcszFilename, PRTTIMESPEC pModificationTime)); 1553 1628 1554 1629 /** … … 1582 1657 * @param pStorage The storage handle to use. 1583 1658 * @param uOffset The offset to start from. 1584 * @param cbWrite How many bytes to write.1585 * @param pvBuf Pointer to the bits need to be written.1659 * @param pvBuffer Pointer to the bits need to be written. 1660 * @param cbBuffer How many bytes to write. 1586 1661 * @param pcbWritten Where to store how many bytes where actually written. 1587 1662 * … … 1591 1666 */ 1592 1667 DECLR3CALLBACKMEMBER(int, pfnWriteSync, (void *pvUser, PVDIOSTORAGE pStorage, uint64_t uOffset, 1593 size_t cbWrite, const void *pvBuf, size_t *pcbWritten));1668 const void *pvBuffer, size_t cbBuffer, size_t *pcbWritten)); 1594 1669 1595 1670 /** … … 1600 1675 * @param pStorage The storage handle to use. 1601 1676 * @param uOffset The offset to start from. 1602 * @param cbRead How many bytes to read.1603 * @param pvBuf Where to store the read bits.1677 * @param pvBuffer Where to store the read bits. 1678 * @param cbBuffer How many bytes to read. 1604 1679 * @param pcbRead Where to store how many bytes where actually read. 1605 1680 * … … 1607 1682 */ 1608 1683 DECLR3CALLBACKMEMBER(int, pfnReadSync, (void *pvUser, PVDIOSTORAGE pStorage, uint64_t uOffset, 1609 size_t cbRead, void *pvBuf, size_t *pcbRead));1684 void *pvBuffer, size_t cbBuffer, size_t *pcbRead)); 1610 1685 1611 1686 /** … … 1660 1735 * @param pStorage The storage handle. 1661 1736 * @param uOffset Offset to start reading from. 1662 * @param pvBuf 1663 * @param cb ReadHow many bytes to read.1737 * @param pvBuffer Where to store the data. 1738 * @param cbBuffer How many bytes to read. 1664 1739 * @param pIoCtx The I/O context which triggered the read. 1665 1740 * @param ppMetaXfer Where to store the metadata transfer handle on success. … … 1668 1743 */ 1669 1744 DECLR3CALLBACKMEMBER(int, pfnReadMetaAsync, (void *pvUser, PVDIOSTORAGE pStorage, 1670 uint64_t uOffset, void *pvBuf ,1671 size_t cb Read, PVDIOCTX pIoCtx,1745 uint64_t uOffset, void *pvBuffer, 1746 size_t cbBuffer, PVDIOCTX pIoCtx, 1672 1747 PPVDMETAXFER ppMetaXfer, 1673 1748 PFNVDXFERCOMPLETED pfnComplete, … … 1681 1756 * @param pStorage The storage handle. 1682 1757 * @param uOffset Offset to start writing to. 1683 * @param pvBuf 1684 * @param cb WriteHow many bytes to write.1758 * @param pvBuffer Written data. 1759 * @param cbBuffer How many bytes to write. 1685 1760 * @param pIoCtx The I/O context which triggered the write. 1686 1761 * @param pfnCompleted Completion callback. … … 1688 1763 */ 1689 1764 DECLR3CALLBACKMEMBER(int, pfnWriteMetaAsync, (void *pvUser, PVDIOSTORAGE pStorage, 1690 uint64_t uOffset, void *pvBuf ,1691 size_t cb Write, PVDIOCTX pIoCtx,1765 uint64_t uOffset, void *pvBuffer, 1766 size_t cbBuffer, PVDIOCTX pIoCtx, 1692 1767 PFNVDXFERCOMPLETED pfnComplete, 1693 1768 void *pvCompleteUser)); … … 1724 1799 * @param pvUser The opaque user data passed on container creation. 1725 1800 * @param pIoCtx I/O context to copy the data to. 1726 * @param pvBuf 1727 * @param cbBuf 1801 * @param pvBuffer Buffer to copy. 1802 * @param cbBuffer Number of bytes to copy. 1728 1803 */ 1729 1804 DECLR3CALLBACKMEMBER(size_t, pfnIoCtxCopyTo, (void *pvUser, PVDIOCTX pIoCtx, 1730 void *pvBuf , size_t cbBuf));1805 void *pvBuffer, size_t cbBuffer)); 1731 1806 1732 1807 /** … … 1736 1811 * @param pvUser The opaque user data passed on container creation. 1737 1812 * @param pIoCtx I/O context to copy the data from. 1738 * @param pvBuf 1739 * @param cbBuf 1813 * @param pvBuffer Destination buffer. 1814 * @param cbBuffer Number of bytes to copy. 1740 1815 */ 1741 1816 DECLR3CALLBACKMEMBER(size_t, pfnIoCtxCopyFrom, (void *pvUser, PVDIOCTX pIoCtx, 1742 void *pvBuf , size_t cbBuf));1817 void *pvBuffer, size_t cbBuffer)); 1743 1818 1744 1819 /** … … 1809 1884 1810 1885 /** 1886 * Request completion callback for the async read/write API. 1887 */ 1888 typedef void (FNVDASYNCTRANSFERCOMPLETE) (void *pvUser1, void *pvUser2, int rcReq); 1889 /** Pointer to a transfer compelte callback. */ 1890 typedef FNVDASYNCTRANSFERCOMPLETE *PFNVDASYNCTRANSFERCOMPLETE; 1891 1892 /** 1893 * Disk geometry. 1894 */ 1895 typedef struct VDGEOMETRY 1896 { 1897 /** Number of cylinders. */ 1898 uint32_t cCylinders; 1899 /** Number of heads. */ 1900 uint32_t cHeads; 1901 /** Number of sectors. */ 1902 uint32_t cSectors; 1903 } VDGEOMETRY; 1904 1905 /** Pointer to disk geometry. */ 1906 typedef VDGEOMETRY *PVDGEOMETRY; 1907 /** Pointer to constant disk geometry. */ 1908 typedef const VDGEOMETRY *PCVDGEOMETRY; 1909 1910 /** 1811 1911 * VBox HDD Container main structure. 1812 1912 */ … … 1817 1917 1818 1918 /** 1819 * Request completion callback for the async read/write API.1820 */1821 typedef void (FNVDASYNCTRANSFERCOMPLETE) (void *pvUser1, void *pvUser2, int rcReq);1822 /** Pointer to a transfer compelte callback. */1823 typedef FNVDASYNCTRANSFERCOMPLETE *PFNVDASYNCTRANSFERCOMPLETE;1824 1825 /**1826 1919 * Initializes HDD backends. 1827 1920 * … … 1880 1973 * 1881 1974 * @return VBox status code. 1975 * VINF_SUCCESS if a plugin was found. 1976 * ppszFormat contains the string which can be used as backend name. 1977 * VERR_NOT_SUPPORTED if no backend was found. 1882 1978 * @param pVDIfsDisk Pointer to the per-disk VD interface list. 1979 * @param pVDIfsImage Pointer to the per-image VD interface list. 1883 1980 * @param pszFilename Name of the image file for which the backend is queried. 1884 1981 * @param ppszFormat Receives pointer of the UTF-8 string which contains the format name. 1885 1982 * The returned pointer must be freed using RTStrFree(). 1886 1983 */ 1887 VBOXDDU_DECL(int) VDGetFormat(PVDINTERFACE pVDIfsDisk, const char *pszFilename, char **ppszFormat); 1984 VBOXDDU_DECL(int) VDGetFormat(PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage, 1985 const char *pszFilename, char **ppszFormat); 1888 1986 1889 1987 /** … … 1945 2043 const char *pszFilename, uint64_t cbSize, 1946 2044 unsigned uImageFlags, const char *pszComment, 1947 PC PDMMEDIAGEOMETRY pPCHSGeometry,1948 PC PDMMEDIAGEOMETRY pLCHSGeometry,2045 PCVDGEOMETRY pPCHSGeometry, 2046 PCVDGEOMETRY pLCHSGeometry, 1949 2047 PCRTUUID pUuid, unsigned uOpenFlags, 1950 2048 PVDINTERFACE pVDIfsImage, … … 2091 2189 */ 2092 2190 VBOXDDU_DECL(int) VDResize(PVBOXHDD pDisk, uint64_t cbSize, 2093 PC PDMMEDIAGEOMETRY pPCHSGeometry,2094 PC PDMMEDIAGEOMETRY pLCHSGeometry,2191 PCVDGEOMETRY pPCHSGeometry, 2192 PCVDGEOMETRY pLCHSGeometry, 2095 2193 PVDINTERFACE pVDIfsOperation); 2096 2194 … … 2134 2232 * @param uOffset Offset of first reading byte from start of disk. 2135 2233 * Must be aligned to a sector boundary. 2136 * @param pvBuf 2137 * @param cb ReadNumber of bytes to read.2234 * @param pvBuffer Pointer to buffer for reading data. 2235 * @param cbBuffer Number of bytes to read. 2138 2236 * Must be aligned to a sector boundary. 2139 2237 */ 2140 VBOXDDU_DECL(int) VDRead(PVBOXHDD pDisk, uint64_t uOffset, void *pvBuf , size_t cbRead);2238 VBOXDDU_DECL(int) VDRead(PVBOXHDD pDisk, uint64_t uOffset, void *pvBuffer, size_t cbBuffer); 2141 2239 2142 2240 /** … … 2148 2246 * @param uOffset Offset of first writing byte from start of disk. 2149 2247 * Must be aligned to a sector boundary. 2150 * @param pvBuf 2151 * @param cb WriteNumber of bytes to write.2248 * @param pvBuffer Pointer to buffer for writing data. 2249 * @param cbBuffer Number of bytes to write. 2152 2250 * Must be aligned to a sector boundary. 2153 2251 */ 2154 VBOXDDU_DECL(int) VDWrite(PVBOXHDD pDisk, uint64_t uOffset, const void *pvBuf , size_t cbWrite);2252 VBOXDDU_DECL(int) VDWrite(PVBOXHDD pDisk, uint64_t uOffset, const void *pvBuffer, size_t cbBuffer); 2155 2253 2156 2254 /** … … 2211 2309 */ 2212 2310 VBOXDDU_DECL(int) VDGetPCHSGeometry(PVBOXHDD pDisk, unsigned nImage, 2213 P PDMMEDIAGEOMETRY pPCHSGeometry);2311 PVDGEOMETRY pPCHSGeometry); 2214 2312 2215 2313 /** … … 2223 2321 */ 2224 2322 VBOXDDU_DECL(int) VDSetPCHSGeometry(PVBOXHDD pDisk, unsigned nImage, 2225 PC PDMMEDIAGEOMETRY pPCHSGeometry);2323 PCVDGEOMETRY pPCHSGeometry); 2226 2324 2227 2325 /** … … 2236 2334 */ 2237 2335 VBOXDDU_DECL(int) VDGetLCHSGeometry(PVBOXHDD pDisk, unsigned nImage, 2238 P PDMMEDIAGEOMETRY pLCHSGeometry);2336 PVDGEOMETRY pLCHSGeometry); 2239 2337 2240 2338 /** … … 2248 2346 */ 2249 2347 VBOXDDU_DECL(int) VDSetLCHSGeometry(PVBOXHDD pDisk, unsigned nImage, 2250 PC PDMMEDIAGEOMETRY pLCHSGeometry);2348 PCVDGEOMETRY pLCHSGeometry); 2251 2349 2252 2350 /** -
trunk/include/VBox/err.h
r32370 r32536 1247 1247 /** VHD: Invalid image file header. */ 1248 1248 #define VERR_VD_VHD_INVALID_HEADER (-3260) 1249 /** Parallels HDD: Invalid image file header. */ 1250 #define VERR_VD_PARALLELS_INVALID_HEADER (-3265) 1251 /** DMG: Invalid image file header. */ 1252 #define VERR_VD_DMG_INVALID_HEADER (-3267) 1249 1253 /** Raw: Invalid image file header. */ 1250 1254 #define VERR_VD_RAW_INVALID_HEADER (-3270) -
trunk/include/VBox/log.h
r31860 r32536 172 172 /** The internal networking transport driver group. */ 173 173 LOG_GROUP_DRV_INTNET, 174 /** iSCSI Initiator driver group. */175 LOG_GROUP_DRV_ISCSI,176 /** iSCSI TCP transport driver group. */177 LOG_GROUP_DRV_ISCSI_TRANSPORT_TCP,178 174 /** ISO (CD/DVD) media driver group. */ 179 175 LOG_GROUP_DRV_ISO, … … 326 322 /** iSCSI virtual disk backend. */ 327 323 LOG_GROUP_VD_ISCSI, 324 /** Parallels HDD virtual disk backend. */ 325 LOG_GROUP_VD_PARALLELS, 328 326 /** Raw virtual disk backend. */ 329 327 LOG_GROUP_VD_RAW, … … 421 419 "DRV_HOST_SERIAL", \ 422 420 "DRV_INTNET", \ 423 "DRV_ISCSI", \424 "DRV_ISCSI_TRANSPORT_TCP", \425 421 "DRV_ISO", \ 426 422 "DRV_KBD_QUEUE", \ … … 498 494 "VD", \ 499 495 "VD_ISCSI", \ 496 "VD_PARALLELS", \ 500 497 "VD_RAW", \ 501 498 "VD_VDI", \ -
trunk/src/VBox/Devices/Makefile.kmk
r32471 r32536 75 75 else 76 76 VBoxDDU_SDKS.win = WINPSDK 77 endif78 ifdef VBOX_WITH_NEW_IO_CODE79 VBoxDDU_DEFS += VBOX_WITH_NEW_IO_CODE80 77 endif 81 78 VBoxDDU_SOURCES = \ -
trunk/src/VBox/Devices/Storage/DMGHDDCore.cpp
r32500 r32536 23 23 #include <VBox/log.h> 24 24 #include <VBox/err.h> 25 #include <iprt/file.h>26 25 #include <iprt/assert.h> 27 26 #include <iprt/asm.h> … … 293 292 typedef struct DMGIMAGE 294 293 { 294 /** Image name. 295 * Kept around for logging and delete-on-close purposes. */ 296 const char *pszFilename; 297 /** Storage handle. */ 298 PVDIOSTORAGE pStorage; 299 /** I/O interface. */ 300 PVDINTERFACE pInterfaceIO; 301 /** Async I/O interface callbacks. */ 302 PVDINTERFACEIO pInterfaceIOCallbacks; 303 295 304 /** Pointer to the per-disk VD interface list. */ 296 305 PVDINTERFACE pVDIfsDisk; … … 298 307 PVDINTERFACE pVDIfsImage; 299 308 300 /** Storage handle. */301 PVDIOSTORAGE pStorage;302 /** Size of the image. */303 uint64_t cbFile;304 /** I/O interface. */305 PVDINTERFACE pInterfaceIO;306 /** Async I/O interface callbacks. */307 PVDINTERFACEIO pInterfaceIOCallbacks;308 309 /** Error callback. */ 309 310 PVDINTERFACE pInterfaceError; 310 311 /** Opaque data for error callback. */ 311 312 PVDINTERFACEERROR pInterfaceErrorCallbacks; 313 312 314 /** Flags the image was opened with. */ 313 315 uint32_t uOpenFlags; 314 316 /** Image flags. */ 315 317 unsigned uImageFlags; 316 /** The filename. 317 * Kept around for logging and delete-on-close purposes. */ 318 const char *pszFilename; 318 /** Total size of the virtual image. */ 319 uint64_t cbSize; 320 /** Size of the image. */ 321 uint64_t cbFile; 322 /** Physical geometry of this image. */ 323 VDGEOMETRY PCHSGeometry; 324 /** Logical geometry of this image. */ 325 VDGEOMETRY LCHSGeometry; 326 319 327 /** The resources. 320 328 * A lazy bird ASSUME there are only two arrays in the resource-fork section in … … 324 332 VBOXUDIF Ftr; 325 333 326 /** Total size of the virtual image. */327 uint64_t cbSize;328 /** Physical geometry of this image. */329 PDMMEDIAGEOMETRY PCHSGeometry;330 /** Logical geometry of this image. */331 PDMMEDIAGEOMETRY LCHSGeometry;332 334 /** First extent in the list. */ 333 335 PDMGEXTENT pExtentFirst; … … 388 390 389 391 /******************************************************************************* 392 * Static Variables * 393 *******************************************************************************/ 394 395 /** NULL-terminated array of supported file extensions. */ 396 static const char *const s_apszDmgFileExtensions[] = 397 { 398 "dmg", 399 NULL 400 }; 401 402 /******************************************************************************* 390 403 * Internal Functions * 391 404 *******************************************************************************/ … … 403 416 * Internal: signal an error to the frontend. 404 417 */ 405 DECLINLINE(int) dmgError(PDMGIMAGE p Image, int rc, RT_SRC_POS_DECL,418 DECLINLINE(int) dmgError(PDMGIMAGE pThis, int rc, RT_SRC_POS_DECL, 406 419 const char *pszFormat, ...) 407 420 { 408 421 va_list va; 409 422 va_start(va, pszFormat); 410 if (p Image->pInterfaceError)411 p Image->pInterfaceErrorCallbacks->pfnError(pImage->pInterfaceError->pvUser, rc, RT_SRC_POS_ARGS,412 423 if (pThis->pInterfaceError) 424 pThis->pInterfaceErrorCallbacks->pfnError(pThis->pInterfaceError->pvUser, rc, RT_SRC_POS_ARGS, 425 pszFormat, va); 413 426 va_end(va); 414 427 return rc; 415 428 } 416 429 417 static int dmgFileOpen(PDMGIMAGE pImage, bool fReadonly, bool fCreate) 418 { 419 AssertMsg(!(fReadonly && fCreate), ("Image can't be opened readonly while being created\n")); 420 421 unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0; 422 423 if (fCreate) 424 uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE; 425 426 return pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser, 427 pImage->pszFilename, 428 uOpenFlags, 429 &pImage->pStorage); 430 } 431 432 static int dmgFileClose(PDMGIMAGE pImage) 430 /** 431 * Internal: signal an informational message to the frontend. 432 */ 433 DECLINLINE(int) dmgMessage(PDMGIMAGE pThis, const char *pszFormat, ...) 433 434 { 434 435 int rc = VINF_SUCCESS; 435 436 if (pImage->pStorage) 437 rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser, 438 pImage->pStorage); 439 440 pImage->pStorage = NULL; 441 442 return rc; 443 } 444 445 static int dmgFileFlushSync(PDMGIMAGE pImage) 446 { 447 return pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser, 448 pImage->pStorage); 449 } 450 451 static int dmgFileGetSize(PDMGIMAGE pImage, uint64_t *pcbSize) 452 { 453 return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser, 454 pImage->pStorage, 455 pcbSize); 456 } 457 458 static int dmgFileSetSize(PDMGIMAGE pImage, uint64_t cbSize) 459 { 460 return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser, 461 pImage->pStorage, 462 cbSize); 463 } 464 465 static int dmgFileWriteSync(PDMGIMAGE pImage, uint64_t off, const void *pcvBuf, size_t cbWrite, size_t *pcbWritten) 466 { 467 return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser, 468 pImage->pStorage, 469 off, cbWrite, pcvBuf, 470 pcbWritten); 471 } 472 473 static int dmgFileReadSync(PDMGIMAGE pImage, uint64_t off, void *pvBuf, size_t cbRead, size_t *pcbRead) 474 { 475 return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser, 476 pImage->pStorage, 477 off, cbRead, pvBuf, 478 pcbRead); 479 } 480 481 static bool dmgFileOpened(PDMGIMAGE pImage) 482 { 483 return pImage->pStorage != NULL; 484 } 436 va_list va; 437 va_start(va, pszFormat); 438 if (pThis->pInterfaceError) 439 rc = pThis->pInterfaceErrorCallbacks->pfnMessage(pThis->pInterfaceError->pvUser, 440 pszFormat, va); 441 va_end(va); 442 return rc; 443 } 444 445 446 DECLINLINE(int) dmgFileOpen(PDMGIMAGE pThis, const char *pszFilename, 447 uint32_t fOpen) 448 { 449 return pThis->pInterfaceIOCallbacks->pfnOpen(pThis->pInterfaceIO->pvUser, 450 pszFilename, fOpen, 451 &pThis->pStorage); 452 } 453 454 DECLINLINE(int) dmgFileClose(PDMGIMAGE pThis) 455 { 456 return pThis->pInterfaceIOCallbacks->pfnClose(pThis->pInterfaceIO->pvUser, 457 pThis->pStorage); 458 } 459 460 DECLINLINE(int) dmgFileDelete(PDMGIMAGE pThis, const char *pszFilename) 461 { 462 return pThis->pInterfaceIOCallbacks->pfnDelete(pThis->pInterfaceIO->pvUser, 463 pszFilename); 464 } 465 466 DECLINLINE(int) dmgFileMove(PDMGIMAGE pThis, const char *pszSrc, 467 const char *pszDst, unsigned fMove) 468 { 469 return pThis->pInterfaceIOCallbacks->pfnMove(pThis->pInterfaceIO->pvUser, 470 pszSrc, pszDst, fMove); 471 } 472 473 DECLINLINE(int) dmgFileGetFreeSpace(PDMGIMAGE pThis, const char *pszFilename, 474 int64_t *pcbFree) 475 { 476 return pThis->pInterfaceIOCallbacks->pfnGetFreeSpace(pThis->pInterfaceIO->pvUser, 477 pszFilename, pcbFree); 478 } 479 480 DECLINLINE(int) dmgFileGetSize(PDMGIMAGE pThis, uint64_t *pcbSize) 481 { 482 return pThis->pInterfaceIOCallbacks->pfnGetSize(pThis->pInterfaceIO->pvUser, 483 pThis->pStorage, pcbSize); 484 } 485 486 DECLINLINE(int) dmgFileSetSize(PDMGIMAGE pThis, uint64_t cbSize) 487 { 488 return pThis->pInterfaceIOCallbacks->pfnSetSize(pThis->pInterfaceIO->pvUser, 489 pThis->pStorage, cbSize); 490 } 491 492 DECLINLINE(int) dmgFileWriteSync(PDMGIMAGE pThis, uint64_t uOffset, 493 const void *pvBuffer, size_t cbBuffer, 494 size_t *pcbWritten) 495 { 496 return pThis->pInterfaceIOCallbacks->pfnWriteSync(pThis->pInterfaceIO->pvUser, 497 pThis->pStorage, uOffset, 498 pvBuffer, cbBuffer, pcbWritten); 499 } 500 501 DECLINLINE(int) dmgFileReadSync(PDMGIMAGE pThis, uint64_t uOffset, 502 void *pvBuffer, size_t cbBuffer, size_t *pcbRead) 503 { 504 return pThis->pInterfaceIOCallbacks->pfnReadSync(pThis->pInterfaceIO->pvUser, 505 pThis->pStorage, uOffset, 506 pvBuffer, cbBuffer, pcbRead); 507 } 508 509 DECLINLINE(int) dmgFileFlushSync(PDMGIMAGE pThis) 510 { 511 return pThis->pInterfaceIOCallbacks->pfnFlushSync(pThis->pInterfaceIO->pvUser, 512 pThis->pStorage); 513 } 514 485 515 486 516 /** … … 712 742 713 743 714 /** @copydoc VBOXHDDBACKEND::pfnClose */ 715 static DECLCALLBACK(int) vboxdmgClose(void *pvBackendData, bool fDelete) 716 { 717 PDMGIMAGE pThis = (PDMGIMAGE)pvBackendData; 718 719 if (dmgFileOpened(pThis)) 720 { 721 /* 722 * If writable, flush changes, fix checksums, ++. 723 */ 724 /** @todo writable images. */ 725 726 /* 727 * Close the file. 728 */ 729 dmgFileClose(pThis); 730 } 731 732 /* 733 * Delete the file if requested, then free the remaining resources. 734 */ 744 /** 745 * Internal. Flush image data to disk. 746 */ 747 static int dmgFlushImage(PDMGIMAGE pThis) 748 { 735 749 int rc = VINF_SUCCESS; 736 if (fDelete) 737 rc = RTFileDelete(pThis->pszFilename); 738 739 for (unsigned iRsrc = 0; iRsrc < RT_ELEMENTS(pThis->aRsrcs); iRsrc++) 740 for (unsigned i = 0; i < pThis->aRsrcs[iRsrc].cEntries; i++) 750 751 if ( pThis->pStorage 752 && !(pThis->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 753 { 754 /* @todo handle writable files, update checksums etc. */ 755 } 756 757 return rc; 758 } 759 760 761 /** 762 * Internal. Free all allocated space for representing an image except pThis, 763 * and optionally delete the image from disk. 764 */ 765 static int dmgFreeImage(PDMGIMAGE pThis, bool fDelete) 766 { 767 int rc = VINF_SUCCESS; 768 769 /* Freeing a never allocated image (e.g. because the open failed) is 770 * not signalled as an error. After all nothing bad happens. */ 771 if (pThis) 772 { 773 if (pThis->pStorage) 741 774 { 742 if (pThis->aRsrcs[iRsrc].aEntries[i].pbData) 775 /* No point updating the file that is deleted anyway. */ 776 if (!fDelete) 777 dmgFlushImage(pThis); 778 779 dmgFileClose(pThis); 780 pThis->pStorage = NULL; 781 } 782 783 for (unsigned iRsrc = 0; iRsrc < RT_ELEMENTS(pThis->aRsrcs); iRsrc++) 784 for (unsigned i = 0; i < pThis->aRsrcs[iRsrc].cEntries; i++) 743 785 { 744 RTMemFree(pThis->aRsrcs[iRsrc].aEntries[i].pbData); 745 pThis->aRsrcs[iRsrc].aEntries[i].pbData = NULL; 786 if (pThis->aRsrcs[iRsrc].aEntries[i].pbData) 787 { 788 RTMemFree(pThis->aRsrcs[iRsrc].aEntries[i].pbData); 789 pThis->aRsrcs[iRsrc].aEntries[i].pbData = NULL; 790 } 791 if (pThis->aRsrcs[iRsrc].aEntries[i].pszName) 792 { 793 RTMemFree(pThis->aRsrcs[iRsrc].aEntries[i].pszName); 794 pThis->aRsrcs[iRsrc].aEntries[i].pszName = NULL; 795 } 796 if (pThis->aRsrcs[iRsrc].aEntries[i].pszCFName) 797 { 798 RTMemFree(pThis->aRsrcs[iRsrc].aEntries[i].pszCFName); 799 pThis->aRsrcs[iRsrc].aEntries[i].pszCFName = NULL; 800 } 746 801 } 747 if (pThis->aRsrcs[iRsrc].aEntries[i].pszName) 748 { 749 RTMemFree(pThis->aRsrcs[iRsrc].aEntries[i].pszName); 750 pThis->aRsrcs[iRsrc].aEntries[i].pszName = NULL; 751 } 752 if (pThis->aRsrcs[iRsrc].aEntries[i].pszCFName) 753 { 754 RTMemFree(pThis->aRsrcs[iRsrc].aEntries[i].pszCFName); 755 pThis->aRsrcs[iRsrc].aEntries[i].pszCFName = NULL; 756 } 757 } 758 RTMemFree(pThis); 759 802 803 if (fDelete && pThis->pszFilename) 804 dmgFileDelete(pThis, pThis->pszFilename); 805 } 806 807 LogFlowFunc(("returns %Rrc\n", rc)); 760 808 return rc; 761 809 } … … 1278 1326 break; 1279 1327 default: 1280 rc = VERR_VD_ GEN_INVALID_HEADER;1328 rc = VERR_VD_DMG_INVALID_HEADER; 1281 1329 break; 1282 1330 } … … 1293 1341 1294 1342 /** 1295 * Worker for vboxdmgOpen that reads in and validates all the necessary1343 * Worker for dmgOpen that reads in and validates all the necessary 1296 1344 * structures from the image. 1297 *1298 * This worker is really just a construct to avoid gotos and do-break-while-zero1299 * uglyness.1300 1345 * 1301 1346 * @returns VBox status code. 1302 1347 * @param pThis The DMG instance data. 1303 */ 1304 static int vboxdmgOpenWorker(PDMGIMAGE pThis) 1305 { 1348 * @param uOpenFlags Flags for defining the open type. 1349 */ 1350 static int dmgOpenImage(PDMGIMAGE pThis, unsigned uOpenFlags) 1351 { 1352 pThis->uOpenFlags = uOpenFlags; 1353 1354 pThis->pInterfaceError = VDInterfaceGet(pThis->pVDIfsDisk, VDINTERFACETYPE_ERROR); 1355 if (pThis->pInterfaceError) 1356 pThis->pInterfaceErrorCallbacks = VDGetInterfaceError(pThis->pInterfaceError); 1357 1358 /* Get I/O interface. */ 1359 pThis->pInterfaceIO = VDInterfaceGet(pThis->pVDIfsImage, VDINTERFACETYPE_IO); 1360 AssertPtrReturn(pThis->pInterfaceIO, VERR_INVALID_PARAMETER); 1361 pThis->pInterfaceIOCallbacks = VDGetInterfaceIO(pThis->pInterfaceIO); 1362 AssertPtrReturn(pThis->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER); 1363 1364 int rc = dmgFileOpen(pThis, pThis->pszFilename, 1365 VDOpenFlagsToFileOpenFlags(uOpenFlags, 1366 false /* fCreate */)); 1367 if (RT_FAILURE(rc)) 1368 { 1369 /* Do NOT signal an appropriate error here, as the VD layer has the 1370 * choice of retrying the open if it failed. */ 1371 return rc; 1372 } 1373 1306 1374 /* 1307 1375 * Read the footer. 1308 1376 */ 1309 intrc = dmgFileGetSize(pThis, &pThis->cbFile);1377 rc = dmgFileGetSize(pThis, &pThis->cbFile); 1310 1378 if (RT_FAILURE(rc)) 1311 1379 return rc; 1312 1380 if (pThis->cbFile < 1024) 1313 return VERR_VD_ GEN_INVALID_HEADER;1381 return VERR_VD_DMG_INVALID_HEADER; 1314 1382 rc = dmgFileReadSync(pThis, pThis->cbFile - sizeof(pThis->Ftr), &pThis->Ftr, sizeof(pThis->Ftr), NULL); 1315 1383 if (RT_FAILURE(rc)) … … 1321 1389 */ 1322 1390 if (pThis->Ftr.u32Magic != VBOXUDIF_MAGIC) 1323 return VERR_VD_ GEN_INVALID_HEADER;1391 return VERR_VD_DMG_INVALID_HEADER; 1324 1392 if (pThis->Ftr.u32Version != VBOXUDIF_VER_CURRENT) 1325 return VERR_VD_ GEN_INVALID_HEADER;1393 return VERR_VD_DMG_INVALID_HEADER; 1326 1394 if (pThis->Ftr.cbFooter != sizeof(pThis->Ftr)) 1327 return VERR_VD_ GEN_INVALID_HEADER;1395 return VERR_VD_DMG_INVALID_HEADER; 1328 1396 1329 1397 if (!vboxdmgUdifFtrIsValid(&pThis->Ftr, pThis->cbFile - sizeof(pThis->Ftr))) 1330 1398 { 1331 1399 VBOXDMG_PRINTF(("Bad DMG: '%s' cbFile=%RTfoff\n", pThis->pszFilename, pThis->cbFile)); 1332 return VERR_VD_ GEN_INVALID_HEADER;1400 return VERR_VD_DMG_INVALID_HEADER; 1333 1401 } 1334 1402 … … 1360 1428 if (pRsrcBlkx->aEntries[idxBlkx].cbData < sizeof(VBOXBLKX)) 1361 1429 { 1362 rc = VERR_VD_ GEN_INVALID_HEADER;1430 rc = VERR_VD_DMG_INVALID_HEADER; 1363 1431 break; 1364 1432 } … … 1379 1447 rc = vboxdmgBlkxParse(pThis, pBlkx); 1380 1448 else 1381 rc = VERR_VD_ GEN_INVALID_HEADER;1449 rc = VERR_VD_DMG_INVALID_HEADER; 1382 1450 1383 1451 if (RT_FAILURE(rc)) … … 1389 1457 } 1390 1458 else 1391 rc = VERR_VD_ GEN_INVALID_HEADER;1459 rc = VERR_VD_DMG_INVALID_HEADER; 1392 1460 } 1393 1461 else … … 1400 1468 } 1401 1469 RTMemFree(pszXml); 1470 1402 1471 if (RT_FAILURE(rc)) 1403 return rc; 1404 1405 1406 return VINF_SUCCESS; 1407 } 1408 1472 dmgFreeImage(pThis, false); 1473 return rc; 1474 } 1475 1476 1477 /** @copydoc VBOXHDDBACKEND::pfnCheckIfValid */ 1478 static int dmgCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk, 1479 PVDINTERFACE pVDIfsImage) 1480 { 1481 LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p\n", pszFilename, pVDIfsDisk, pVDIfsImage)); 1482 int rc; 1483 PVDIOSTORAGE pStorage; 1484 uint64_t cbFile, offFtr = 0; 1485 VBOXUDIF Ftr; 1486 1487 /* Get I/O interface. */ 1488 PVDINTERFACE pInterfaceIO = VDInterfaceGet(pVDIfsImage, VDINTERFACETYPE_IO); 1489 AssertPtrReturn(pInterfaceIO, VERR_INVALID_PARAMETER); 1490 PVDINTERFACEIO pInterfaceIOCallbacks = VDGetInterfaceIO(pInterfaceIO); 1491 AssertPtrReturn(pInterfaceIOCallbacks, VERR_INVALID_PARAMETER); 1492 1493 /* 1494 * Open the file and read the footer. 1495 */ 1496 rc = pInterfaceIOCallbacks->pfnOpen(pInterfaceIO->pvUser, pszFilename, 1497 VDOpenFlagsToFileOpenFlags(VD_OPEN_FLAGS_READONLY, 1498 false /* fCreate */), 1499 &pStorage); 1500 if (RT_SUCCESS(rc)) 1501 rc = pInterfaceIOCallbacks->pfnGetSize(pInterfaceIO->pvUser, pStorage, 1502 &cbFile); 1503 if (RT_SUCCESS(rc)) 1504 { 1505 offFtr = cbFile - sizeof(Ftr); 1506 rc = pInterfaceIOCallbacks->pfnReadSync(pInterfaceIO->pvUser, pStorage, 1507 offFtr, &Ftr, sizeof(Ftr), NULL); 1508 } 1509 else 1510 { 1511 pInterfaceIOCallbacks->pfnClose(pInterfaceIO->pvUser, pStorage); 1512 rc = VERR_VD_DMG_INVALID_HEADER; 1513 } 1514 if (RT_SUCCESS(rc)) 1515 { 1516 vboxdmgUdifFtrFile2HostEndian(&Ftr); 1517 1518 /* 1519 * Do we recognize this stuff? Does it look valid? 1520 */ 1521 if ( Ftr.u32Magic == VBOXUDIF_MAGIC 1522 && Ftr.u32Version == VBOXUDIF_VER_CURRENT 1523 && Ftr.cbFooter == sizeof(Ftr)) 1524 { 1525 if (vboxdmgUdifFtrIsValid(&Ftr, offFtr)) 1526 rc = VINF_SUCCESS; 1527 else 1528 { 1529 VBOXDMG_PRINTF(("Bad DMG: '%s' offFtr=%RTfoff\n", pszFilename, offFtr)); 1530 rc = VERR_VD_DMG_INVALID_HEADER; 1531 } 1532 } 1533 else 1534 rc = VERR_VD_DMG_INVALID_HEADER; 1535 } 1536 1537 pInterfaceIOCallbacks->pfnClose(pInterfaceIO->pvUser, pStorage); 1538 1539 LogFlowFunc(("returns %Rrc\n", rc)); 1540 return rc; 1541 } 1409 1542 1410 1543 /** @copydoc VBOXHDDBACKEND::pfnOpen */ 1411 static DECLCALLBACK(int) dmgOpen(const char *pszFilename, unsigned fOpenFlags, 1412 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage, 1413 void **ppvBackendData) 1414 { 1544 static int dmgOpen(const char *pszFilename, unsigned uOpenFlags, 1545 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage, 1546 void **ppBackendData) 1547 { 1548 LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p ppBackendData=%#p\n", pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, ppBackendData)); 1549 int rc = VINF_SUCCESS; 1550 PDMGIMAGE pThis; 1551 1552 /* Check open flags. All valid flags are (in principle) supported. */ 1553 if (uOpenFlags & ~VD_OPEN_FLAGS_MASK) 1554 { 1555 rc = VERR_INVALID_PARAMETER; 1556 goto out; 1557 } 1558 1559 /* Check remaining arguments. */ 1560 if ( !VALID_PTR(pszFilename) 1561 || !*pszFilename) 1562 { 1563 rc = VERR_INVALID_PARAMETER; 1564 goto out; 1565 } 1566 1415 1567 /* 1416 1568 * Reject combinations we don't currently support. … … 1420 1572 * have validate what it passes thru to us. 1421 1573 */ 1422 if (!(fOpenFlags & VD_OPEN_FLAGS_READONLY)) 1423 return VERR_NOT_SUPPORTED; 1574 if (!(uOpenFlags & VD_OPEN_FLAGS_READONLY)) 1575 { 1576 rc = VERR_NOT_SUPPORTED; 1577 goto out; 1578 } 1424 1579 1425 1580 /* … … 1427 1582 * then hand it over to a worker function that does all the rest. 1428 1583 */ 1429 PDMGIMAGEpThis = (PDMGIMAGE)RTMemAllocZ(sizeof(*pThis));1584 pThis = (PDMGIMAGE)RTMemAllocZ(sizeof(*pThis)); 1430 1585 if (!pThis) 1431 return VERR_NO_MEMORY; 1432 pThis->uOpenFlags = fOpenFlags; 1586 { 1587 rc = VERR_NO_MEMORY; 1588 goto out; 1589 } 1590 1433 1591 pThis->pszFilename = pszFilename; 1434 1592 pThis->pStorage = NULL; … … 1436 1594 pThis->pVDIfsImage = pVDIfsImage; 1437 1595 1438 pThis->pInterfaceError = VDInterfaceGet(pThis->pVDIfsDisk, VDINTERFACETYPE_ERROR); 1439 if (pThis->pInterfaceError) 1440 pThis->pInterfaceErrorCallbacks = VDGetInterfaceError(pThis->pInterfaceError); 1441 1442 /* Try to get I/O interface. */ 1443 pThis->pInterfaceIO = VDInterfaceGet(pThis->pVDIfsImage, VDINTERFACETYPE_IO); 1444 AssertPtr(pThis->pInterfaceIO); 1445 pThis->pInterfaceIOCallbacks = VDGetInterfaceIO(pThis->pInterfaceIO); 1446 AssertPtr(pThis->pInterfaceIOCallbacks); 1447 1448 int rc = dmgFileOpen(pThis, (fOpenFlags & VD_OPEN_FLAGS_READONLY ? true : false), 1449 false); 1450 if (RT_SUCCESS(rc)) 1451 { 1452 rc = vboxdmgOpenWorker(pThis); 1453 if (RT_SUCCESS(rc)) 1454 { 1455 *ppvBackendData = pThis; 1456 return rc; 1457 } 1458 } 1459 1460 /* We failed, let the close method clean up. */ 1461 vboxdmgClose(pThis, false /* fDelete */); 1462 return rc; 1463 } 1464 1465 1466 /** @copydoc VBOXHDDBACKEND::pfnCheckIfValid */ 1467 static DECLCALLBACK(int) dmgCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk) 1468 { 1469 /* 1470 * Open the file and read the footer. 1471 */ 1472 RTFILE hFile; 1473 int rc = RTFileOpen(&hFile, pszFilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); 1474 if (RT_FAILURE(rc)) 1475 return rc; 1476 1477 VBOXUDIF Ftr; 1478 uint64_t offFtr; 1479 rc = RTFileSeek(hFile, -(RTFOFF)sizeof(Ftr), RTFILE_SEEK_END, &offFtr); 1480 if (RT_SUCCESS(rc)) 1481 { 1482 rc = RTFileRead(hFile, &Ftr, sizeof(Ftr), NULL); 1483 if (RT_SUCCESS(rc)) 1484 { 1485 vboxdmgUdifFtrFile2HostEndian(&Ftr); 1486 1487 /* 1488 * Do we recognize this stuff? Does it look valid? 1489 */ 1490 if ( Ftr.u32Magic == VBOXUDIF_MAGIC 1491 && Ftr.u32Version == VBOXUDIF_VER_CURRENT 1492 && Ftr.cbFooter == sizeof(Ftr)) 1493 { 1494 if (vboxdmgUdifFtrIsValid(&Ftr, offFtr)) 1495 rc = VINF_SUCCESS; 1496 else 1497 { 1498 VBOXDMG_PRINTF(("Bad DMG: '%s' offFtr=%RTfoff\n", pszFilename, offFtr)); 1499 rc = VERR_VD_GEN_INVALID_HEADER; 1500 } 1501 1502 } 1503 else 1504 rc = VERR_VD_GEN_INVALID_HEADER; 1505 } 1506 } 1507 1508 RTFileClose(hFile); 1596 rc = dmgOpenImage(pThis, uOpenFlags); 1597 if (RT_SUCCESS(rc)) 1598 *ppBackendData = pThis; 1599 else 1600 RTMemFree(pThis); 1601 1602 out: 1603 LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData)); 1509 1604 return rc; 1510 1605 } … … 1513 1608 static int dmgCreate(const char *pszFilename, uint64_t cbSize, 1514 1609 unsigned uImageFlags, const char *pszComment, 1515 PCPDMMEDIAGEOMETRY pPCHSGeometry, 1516 PCPDMMEDIAGEOMETRY pLCHSGeometry, PCRTUUID pUuid, 1517 unsigned uOpenFlags, unsigned uPercentStart, 1518 unsigned uPercentSpan, PVDINTERFACE pVDIfsDisk, 1519 PVDINTERFACE pVDIfsImage, PVDINTERFACE pVDIfsOperation, 1520 void **ppBackendData) 1521 { 1522 LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p ppBackendData=%#p", 1523 pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppBackendData)); 1524 return VERR_NOT_SUPPORTED; 1610 PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry, 1611 PCRTUUID pUuid, unsigned uOpenFlags, 1612 unsigned uPercentStart, unsigned uPercentSpan, 1613 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage, 1614 PVDINTERFACE pVDIfsOperation, void **ppBackendData) 1615 { 1616 LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p ppBackendData=%#p", pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppBackendData)); 1617 int rc = VERR_NOT_SUPPORTED; 1618 1619 LogFlowFunc(("returns %Rrc\n", rc)); 1620 return rc; 1525 1621 } 1526 1622 … … 1539 1635 { 1540 1636 LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete)); 1541 PDMGIMAGE pImage = (PDMGIMAGE)pBackendData; 1542 int rc = VINF_SUCCESS; 1543 1544 /* Freeing a never allocated image (e.g. because the open failed) is 1545 * not signalled as an error. After all nothing bad happens. */ 1546 if (pImage) 1547 vboxdmgClose(pImage, fDelete); 1637 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 1638 int rc; 1639 1640 rc = dmgFreeImage(pThis, fDelete); 1641 RTMemFree(pThis); 1548 1642 1549 1643 LogFlowFunc(("returns %Rrc\n", rc)); … … 1556 1650 { 1557 1651 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead)); 1558 PDMGIMAGE p Image= (PDMGIMAGE)pBackendData;1652 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 1559 1653 PDMGEXTENT pExtent = NULL; 1560 1654 int rc = VINF_SUCCESS; 1561 1655 1562 Assert (pImage);1656 AssertPtr(pThis); 1563 1657 Assert(uOffset % 512 == 0); 1564 1658 Assert(cbToRead % 512 == 0); 1565 1659 1566 if ( uOffset + cbToRead > p Image->cbSize1660 if ( uOffset + cbToRead > pThis->cbSize 1567 1661 || cbToRead == 0) 1568 1662 { … … 1571 1665 } 1572 1666 1573 pExtent = dmgExtentGetFromOffset(p Image, uOffset);1667 pExtent = dmgExtentGetFromOffset(pThis, uOffset); 1574 1668 1575 1669 if (pExtent) … … 1584 1678 case DMGEXTENTTYPE_RAW: 1585 1679 { 1586 rc = dmgFileReadSync(p Image, pExtent->offFileStart + offExtentRel, pvBuf, cbToRead, NULL);1680 rc = dmgFileReadSync(pThis, pExtent->offFileStart + offExtentRel, pvBuf, cbToRead, NULL); 1587 1681 break; 1588 1682 } … … 1614 1708 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", 1615 1709 pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead)); 1616 PDMGIMAGE p Image= (PDMGIMAGE)pBackendData;1710 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 1617 1711 int rc = VERR_NOT_IMPLEMENTED; 1618 1712 1619 Assert (pImage);1713 AssertPtr(pThis); 1620 1714 Assert(uOffset % 512 == 0); 1621 1715 Assert(cbToWrite % 512 == 0); 1622 1716 1623 if (p Image->uOpenFlags & VD_OPEN_FLAGS_READONLY)1717 if (pThis->uOpenFlags & VD_OPEN_FLAGS_READONLY) 1624 1718 { 1625 1719 rc = VERR_VD_IMAGE_READ_ONLY; … … 1638 1732 { 1639 1733 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1640 PDMGIMAGE pImage = (PDMGIMAGE)pBackendData; 1641 int rc = VINF_SUCCESS; 1642 1643 AssertMsgFailed(("Not implemented\n")); 1734 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 1735 int rc; 1736 1737 AssertPtr(pThis); 1738 1739 rc = dmgFlushImage(pThis); 1740 1644 1741 LogFlowFunc(("returns %Rrc\n", rc)); 1645 1742 return rc; … … 1650 1747 { 1651 1748 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1652 PDMGIMAGE p Image= (PDMGIMAGE)pBackendData;1653 1654 Assert (pImage);1655 1656 if (p Image)1749 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 1750 1751 AssertPtr(pThis); 1752 1753 if (pThis) 1657 1754 return 1; 1658 1755 else … … 1664 1761 { 1665 1762 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1666 PDMGIMAGE pImage = (PDMGIMAGE)pBackendData; 1667 1668 Assert(pImage); 1669 1670 if (pImage) 1671 return pImage->cbSize; 1672 else 1673 return 0; 1763 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 1764 uint64_t cb = 0; 1765 1766 AssertPtr(pThis); 1767 1768 if (pThis && pThis->pStorage) 1769 cb = pThis->cbSize; 1770 1771 LogFlowFunc(("returns %llu\n", cb)); 1772 return cb; 1674 1773 } 1675 1774 … … 1678 1777 { 1679 1778 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1680 PDMGIMAGE p Image= (PDMGIMAGE)pBackendData;1779 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 1681 1780 uint64_t cb = 0; 1682 1781 1683 Assert (pImage);1684 1685 if (p Image)1782 AssertPtr(pThis); 1783 1784 if (pThis) 1686 1785 { 1687 1786 uint64_t cbFile; 1688 if ( dmgFileOpened(pImage))1787 if (pThis->pStorage) 1689 1788 { 1690 int rc = dmgFileGetSize(p Image, &cbFile);1789 int rc = dmgFileGetSize(pThis, &cbFile); 1691 1790 if (RT_SUCCESS(rc)) 1692 cb += cbFile;1791 cb = cbFile; 1693 1792 } 1694 1793 } … … 1699 1798 1700 1799 /** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */ 1701 static int dmgGetPCHSGeometry(void *pBackendData, 1702 PPDMMEDIAGEOMETRY pPCHSGeometry) 1800 static int dmgGetPCHSGeometry(void *pBackendData, PVDGEOMETRY pPCHSGeometry) 1703 1801 { 1704 1802 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry)); 1705 PDMGIMAGE p Image= (PDMGIMAGE)pBackendData;1803 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 1706 1804 int rc; 1707 1805 1708 Assert (pImage);1709 1710 if (p Image)1711 { 1712 if (p Image->PCHSGeometry.cCylinders)1806 AssertPtr(pThis); 1807 1808 if (pThis) 1809 { 1810 if (pThis->PCHSGeometry.cCylinders) 1713 1811 { 1714 *pPCHSGeometry = p Image->PCHSGeometry;1812 *pPCHSGeometry = pThis->PCHSGeometry; 1715 1813 rc = VINF_SUCCESS; 1716 1814 } … … 1726 1824 1727 1825 /** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */ 1728 static int dmgSetPCHSGeometry(void *pBackendData, 1729 PCPDMMEDIAGEOMETRY pPCHSGeometry) 1826 static int dmgSetPCHSGeometry(void *pBackendData, PCVDGEOMETRY pPCHSGeometry) 1730 1827 { 1731 1828 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", 1732 1829 pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 1733 PDMGIMAGE p Image= (PDMGIMAGE)pBackendData;1830 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 1734 1831 int rc; 1735 1832 1736 Assert (pImage);1737 1738 if (p Image)1739 { 1740 if (p Image->uOpenFlags & VD_OPEN_FLAGS_READONLY)1833 AssertPtr(pThis); 1834 1835 if (pThis) 1836 { 1837 if (pThis->uOpenFlags & VD_OPEN_FLAGS_READONLY) 1741 1838 { 1742 1839 rc = VERR_VD_IMAGE_READ_ONLY; … … 1744 1841 } 1745 1842 1746 p Image->PCHSGeometry = *pPCHSGeometry;1843 pThis->PCHSGeometry = *pPCHSGeometry; 1747 1844 rc = VINF_SUCCESS; 1748 1845 } … … 1756 1853 1757 1854 /** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */ 1758 static int dmgGetLCHSGeometry(void *pBackendData, 1759 PPDMMEDIAGEOMETRY pLCHSGeometry) 1855 static int dmgGetLCHSGeometry(void *pBackendData, PVDGEOMETRY pLCHSGeometry) 1760 1856 { 1761 1857 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry)); 1762 PDMGIMAGE p Image= (PDMGIMAGE)pBackendData;1858 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 1763 1859 int rc; 1764 1860 1765 Assert (pImage);1766 1767 if (p Image)1768 { 1769 if (p Image->LCHSGeometry.cCylinders)1861 AssertPtr(pThis); 1862 1863 if (pThis) 1864 { 1865 if (pThis->LCHSGeometry.cCylinders) 1770 1866 { 1771 *pLCHSGeometry = p Image->LCHSGeometry;1867 *pLCHSGeometry = pThis->LCHSGeometry; 1772 1868 rc = VINF_SUCCESS; 1773 1869 } … … 1783 1879 1784 1880 /** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */ 1785 static int dmgSetLCHSGeometry(void *pBackendData, 1786 PCPDMMEDIAGEOMETRY pLCHSGeometry) 1881 static int dmgSetLCHSGeometry(void *pBackendData, PCVDGEOMETRY pLCHSGeometry) 1787 1882 { 1788 1883 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", 1789 1884 pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 1790 PDMGIMAGE p Image= (PDMGIMAGE)pBackendData;1885 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 1791 1886 int rc; 1792 1887 1793 Assert (pImage);1794 1795 if (p Image)1796 { 1797 if (p Image->uOpenFlags & VD_OPEN_FLAGS_READONLY)1888 AssertPtr(pThis); 1889 1890 if (pThis) 1891 { 1892 if (pThis->uOpenFlags & VD_OPEN_FLAGS_READONLY) 1798 1893 { 1799 1894 rc = VERR_VD_IMAGE_READ_ONLY; … … 1801 1896 } 1802 1897 1803 p Image->LCHSGeometry = *pLCHSGeometry;1898 pThis->LCHSGeometry = *pLCHSGeometry; 1804 1899 rc = VINF_SUCCESS; 1805 1900 } … … 1816 1911 { 1817 1912 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1818 PDMGIMAGE p Image= (PDMGIMAGE)pBackendData;1913 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 1819 1914 unsigned uImageFlags; 1820 1915 1821 Assert (pImage);1822 1823 if (p Image)1824 uImageFlags = p Image->uImageFlags;1916 AssertPtr(pThis); 1917 1918 if (pThis) 1919 uImageFlags = pThis->uImageFlags; 1825 1920 else 1826 1921 uImageFlags = 0; … … 1834 1929 { 1835 1930 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1836 PDMGIMAGE p Image= (PDMGIMAGE)pBackendData;1931 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 1837 1932 unsigned uOpenFlags; 1838 1933 1839 Assert (pImage);1840 1841 if (p Image)1842 uOpenFlags = p Image->uOpenFlags;1934 AssertPtr(pThis); 1935 1936 if (pThis) 1937 uOpenFlags = pThis->uOpenFlags; 1843 1938 else 1844 1939 uOpenFlags = 0; … … 1852 1947 { 1853 1948 LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags)); 1854 PDMGIMAGE p Image= (PDMGIMAGE)pBackendData;1949 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 1855 1950 int rc; 1856 1951 1857 1952 /* Image must be opened and the new flags must be valid. Just readonly and 1858 1953 * info flags are supported. */ 1859 if (!p Image || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO)))1954 if (!pThis || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO || VD_OPEN_FLAGS_SHAREABLE))) 1860 1955 { 1861 1956 rc = VERR_INVALID_PARAMETER; … … 1863 1958 } 1864 1959 1865 #if 01866 1960 /* Implement this operation via reopening the image. */ 1867 rawFreeImage(pImage, false); 1868 rc = rawOpenImage(pImage, uOpenFlags); 1869 #endif 1961 rc = dmgFreeImage(pThis, false); 1962 if (RT_FAILURE(rc)) 1963 goto out; 1964 rc = dmgOpenImage(pThis, uOpenFlags); 1870 1965 1871 1966 out: … … 1879 1974 { 1880 1975 LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment)); 1881 PDMGIMAGE p Image= (PDMGIMAGE)pBackendData;1976 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 1882 1977 int rc; 1883 1978 1884 Assert(pImage); 1885 1886 if (pImage) 1887 { 1888 if (pszComment) 1889 *pszComment = '\0'; 1890 rc = VINF_SUCCESS; 1891 } 1892 else 1893 rc = VERR_VD_NOT_OPENED; 1894 1895 LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment)); 1896 return rc; 1897 } 1898 1899 /** @copydoc VBOXHDDBACKEND::pfnSetComment */ 1900 static int dmgSetComment(void *pBackendData, const char *pszComment) 1901 { 1902 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment)); 1903 PDMGIMAGE pImage = (PDMGIMAGE)pBackendData; 1904 int rc; 1905 1906 Assert(pImage); 1907 1908 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 1909 { 1910 rc = VERR_VD_IMAGE_READ_ONLY; 1911 goto out; 1912 } 1913 1914 if (pImage) 1979 AssertPtr(pThis); 1980 1981 if (pThis) 1915 1982 rc = VERR_NOT_SUPPORTED; 1916 1983 else 1917 1984 rc = VERR_VD_NOT_OPENED; 1918 1985 1919 out: 1920 LogFlowFunc(("returns %Rrc\n", rc)); 1921 return rc; 1922 } 1923 1924 /** @copydoc VBOXHDDBACKEND::pfnGetUuid */ 1925 static int dmgGetUuid(void *pBackendData, PRTUUID pUuid) 1926 { 1927 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 1928 PDMGIMAGE pImage = (PDMGIMAGE)pBackendData; 1986 LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment)); 1987 return rc; 1988 } 1989 1990 /** @copydoc VBOXHDDBACKEND::pfnSetComment */ 1991 static int dmgSetComment(void *pBackendData, const char *pszComment) 1992 { 1993 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment)); 1994 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 1929 1995 int rc; 1930 1996 1931 Assert(pImage); 1932 1933 if (pImage) 1997 AssertPtr(pThis); 1998 1999 if (pThis->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2000 { 2001 rc = VERR_VD_IMAGE_READ_ONLY; 2002 goto out; 2003 } 2004 2005 if (pThis) 1934 2006 rc = VERR_NOT_SUPPORTED; 1935 2007 else 1936 2008 rc = VERR_VD_NOT_OPENED; 1937 2009 2010 out: 2011 LogFlowFunc(("returns %Rrc\n", rc)); 2012 return rc; 2013 } 2014 2015 /** @copydoc VBOXHDDBACKEND::pfnGetUuid */ 2016 static int dmgGetUuid(void *pBackendData, PRTUUID pUuid) 2017 { 2018 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2019 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 2020 int rc; 2021 2022 AssertPtr(pThis); 2023 2024 if (pThis) 2025 rc = VERR_NOT_SUPPORTED; 2026 else 2027 rc = VERR_VD_NOT_OPENED; 2028 1938 2029 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 1939 2030 return rc; … … 1944 2035 { 1945 2036 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 1946 PDMGIMAGE p Image= (PDMGIMAGE)pBackendData;2037 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 1947 2038 int rc; 1948 2039 1949 2040 LogFlowFunc(("%RTuuid\n", pUuid)); 1950 Assert (pImage);1951 1952 if (p Image)1953 { 1954 if (!(p Image->uOpenFlags & VD_OPEN_FLAGS_READONLY))2041 AssertPtr(pThis); 2042 2043 if (pThis) 2044 { 2045 if (!(pThis->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 1955 2046 rc = VERR_NOT_SUPPORTED; 1956 2047 else … … 1968 2059 { 1969 2060 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 1970 PDMGIMAGE p Image= (PDMGIMAGE)pBackendData;2061 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 1971 2062 int rc; 1972 2063 1973 Assert (pImage);1974 1975 if (p Image)2064 AssertPtr(pThis); 2065 2066 if (pThis) 1976 2067 rc = VERR_NOT_SUPPORTED; 1977 2068 else … … 1986 2077 { 1987 2078 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 1988 PDMGIMAGE p Image= (PDMGIMAGE)pBackendData;2079 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 1989 2080 int rc; 1990 2081 1991 Assert (pImage);1992 1993 if (p Image)1994 { 1995 if (!(p Image->uOpenFlags & VD_OPEN_FLAGS_READONLY))2082 AssertPtr(pThis); 2083 2084 if (pThis) 2085 { 2086 if (!(pThis->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 1996 2087 rc = VERR_NOT_SUPPORTED; 1997 2088 else … … 2009 2100 { 2010 2101 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2011 PDMGIMAGE p Image= (PDMGIMAGE)pBackendData;2102 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 2012 2103 int rc; 2013 2104 2014 Assert (pImage);2015 2016 if (p Image)2105 AssertPtr(pThis); 2106 2107 if (pThis) 2017 2108 rc = VERR_NOT_SUPPORTED; 2018 2109 else … … 2027 2118 { 2028 2119 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2029 PDMGIMAGE p Image= (PDMGIMAGE)pBackendData;2120 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 2030 2121 int rc; 2031 2122 2032 Assert (pImage);2033 2034 if (p Image)2035 { 2036 if (!(p Image->uOpenFlags & VD_OPEN_FLAGS_READONLY))2123 AssertPtr(pThis); 2124 2125 if (pThis) 2126 { 2127 if (!(pThis->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2037 2128 rc = VERR_NOT_SUPPORTED; 2038 2129 else … … 2050 2141 { 2051 2142 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2052 PDMGIMAGE p Image= (PDMGIMAGE)pBackendData;2143 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 2053 2144 int rc; 2054 2145 2055 Assert (pImage);2056 2057 if (p Image)2146 AssertPtr(pThis); 2147 2148 if (pThis) 2058 2149 rc = VERR_NOT_SUPPORTED; 2059 2150 else … … 2068 2159 { 2069 2160 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2070 PDMGIMAGE p Image= (PDMGIMAGE)pBackendData;2161 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 2071 2162 int rc; 2072 2163 2073 Assert (pImage);2074 2075 if (p Image)2076 { 2077 if (!(p Image->uOpenFlags & VD_OPEN_FLAGS_READONLY))2164 AssertPtr(pThis); 2165 2166 if (pThis) 2167 { 2168 if (!(pThis->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2078 2169 rc = VERR_NOT_SUPPORTED; 2079 2170 else … … 2090 2181 static void dmgDump(void *pBackendData) 2091 2182 { 2092 PDMGIMAGE pImage = (PDMGIMAGE)pBackendData; 2093 2094 Assert(pImage); 2095 if (pImage) 2096 { 2097 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n", 2098 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors, 2099 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors, 2100 pImage->cbSize / 512); 2101 } 2102 } 2103 2104 static int dmgGetTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp) 2105 { 2106 int rc = VERR_NOT_IMPLEMENTED; 2107 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc)); 2108 return rc; 2109 } 2110 2111 static int dmgGetParentTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp) 2112 { 2113 int rc = VERR_NOT_IMPLEMENTED; 2114 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc)); 2115 return rc; 2116 } 2117 2118 static int dmgSetParentTimeStamp(void *pvBackendData, PCRTTIMESPEC pTimeStamp) 2119 { 2120 int rc = VERR_NOT_IMPLEMENTED; 2121 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc)); 2122 return rc; 2123 } 2124 2125 static int dmgGetParentFilename(void *pvBackendData, char **ppszParentFilename) 2126 { 2127 int rc = VERR_NOT_IMPLEMENTED; 2128 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc)); 2129 return rc; 2130 } 2131 2132 static int dmgSetParentFilename(void *pvBackendData, const char *pszParentFilename) 2133 { 2134 int rc = VERR_NOT_IMPLEMENTED; 2135 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc)); 2136 return rc; 2183 PDMGIMAGE pThis = (PDMGIMAGE)pBackendData; 2184 2185 AssertPtr(pThis); 2186 if (pThis) 2187 { 2188 dmgMessage(pThis, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n", 2189 pThis->PCHSGeometry.cCylinders, pThis->PCHSGeometry.cHeads, pThis->PCHSGeometry.cSectors, 2190 pThis->LCHSGeometry.cCylinders, pThis->LCHSGeometry.cHeads, pThis->LCHSGeometry.cSectors, 2191 pThis->cbSize / 512); 2192 } 2137 2193 } 2138 2194 … … 2145 2201 sizeof(VBOXHDDBACKEND), 2146 2202 /* uBackendCaps */ 2147 VD_CAP_FILE ,2203 VD_CAP_FILE | VD_CAP_VFS, 2148 2204 /* papszFileExtensions */ 2149 NULL,2205 s_apszDmgFileExtensions, 2150 2206 /* paConfigInfo */ 2151 2207 NULL, … … 2211 2267 dmgDump, 2212 2268 /* pfnGetTimeStamp */ 2213 dmgGetTimeStamp,2269 NULL, 2214 2270 /* pfnGetParentTimeStamp */ 2215 dmgGetParentTimeStamp,2271 NULL, 2216 2272 /* pfnSetParentTimeStamp */ 2217 dmgSetParentTimeStamp,2273 NULL, 2218 2274 /* pfnGetParentFilename */ 2219 dmgGetParentFilename,2275 NULL, 2220 2276 /* pfnSetParentFilename */ 2221 dmgSetParentFilename,2277 NULL, 2222 2278 /* pfnIsAsyncIOSupported */ 2223 2279 NULL, … … 2237 2293 NULL 2238 2294 }; 2239 -
trunk/src/VBox/Devices/Storage/DrvVD.cpp
r32430 r32536 332 332 333 333 static DECLCALLBACK(int) drvvdAsyncIOOpen(void *pvUser, const char *pszLocation, 334 u nsigned uOpenFlags,334 uint32_t fOpen, 335 335 PFNVDCOMPLETED pfnCompleted, 336 336 PVDINTERFACE pVDIfsDisk, … … 360 360 if (RT_SUCCESS(rc)) 361 361 { 362 uint32_t fFlags = uOpenFlags & VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY362 uint32_t fFlags = (fOpen & RTFILE_O_ACCESS_MASK) == RTFILE_O_READ 363 363 ? PDMACEP_FILE_FLAGS_READ_ONLY | PDMACEP_FILE_FLAGS_CACHING 364 364 : 0; 365 365 if (pThis->fShareable) 366 366 { 367 Assert( uOpenFlags & VD_INTERFACEASYNCIO_OPEN_FLAGS_DONT_LOCK);367 Assert((fOpen & RTFILE_O_DENY_MASK) == RTFILE_O_DENY_NONE); 368 368 369 369 fFlags |= PDMACEP_FILE_FLAGS_DONT_LOCK; … … 406 406 407 407 static DECLCALLBACK(int) drvvdAsyncIOReadSync(void *pvUser, void *pStorage, uint64_t uOffset, 408 size_t cbRead, void *pvBuf, size_t *pcbRead)408 void *pvBuf, size_t cbRead, size_t *pcbRead) 409 409 { 410 410 PVBOXDISK pThis = (PVBOXDISK)pvUser; … … 438 438 439 439 static DECLCALLBACK(int) drvvdAsyncIOWriteSync(void *pvUser, void *pStorage, uint64_t uOffset, 440 size_t cbWrite, const void *pvBuf, size_t *pcbWritten)440 const void *pvBuf, size_t cbWrite, size_t *pcbWritten) 441 441 { 442 442 PVBOXDISK pThis = (PVBOXDISK)pvUser; … … 1445 1445 int rc = VINF_SUCCESS; 1446 1446 1447 LogFlow(("%s: off=%#llx pvBuf=%p cbRead=%d\n", __FUNCTION__, 1448 off, pvBuf, cbRead)); 1447 LogFlowFunc(("off=%#llx pvBuf=%p cbRead=%d\n", off, pvBuf, cbRead)); 1449 1448 PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface); 1450 1449 … … 1486 1485 Log2(("%s: off=%#llx pvBuf=%p cbRead=%d %.*Rhxd\n", __FUNCTION__, 1487 1486 off, pvBuf, cbRead, cbRead, pvBuf)); 1488 LogFlow (("%s: returns %Rrc\n", __FUNCTION__, rc));1487 LogFlowFunc(("returns %Rrc\n", rc)); 1489 1488 return rc; 1490 1489 } … … 1495 1494 size_t cbWrite) 1496 1495 { 1497 LogFlow(("%s: off=%#llx pvBuf=%p cbWrite=%d\n", __FUNCTION__, 1498 off, pvBuf, cbWrite)); 1496 LogFlowFunc(("off=%#llx pvBuf=%p cbWrite=%d\n", off, pvBuf, cbWrite)); 1499 1497 PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface); 1500 1498 Log2(("%s: off=%#llx pvBuf=%p cbWrite=%d %.*Rhxd\n", __FUNCTION__, … … 1509 1507 1510 1508 int rc = VDWrite(pThis->pDisk, off, pvBuf, cbWrite); 1511 LogFlow (("%s: returns %Rrc\n", __FUNCTION__, rc));1509 LogFlowFunc(("returns %Rrc\n", rc)); 1512 1510 return rc; 1513 1511 } … … 1516 1514 static DECLCALLBACK(int) drvvdFlush(PPDMIMEDIA pInterface) 1517 1515 { 1518 LogFlow (("%s:\n", __FUNCTION__));1516 LogFlowFunc(("\n")); 1519 1517 PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface); 1520 1518 int rc = VDFlush(pThis->pDisk); 1521 LogFlow (("%s: returns %Rrc\n", __FUNCTION__, rc));1519 LogFlowFunc(("returns %Rrc\n", rc)); 1522 1520 return rc; 1523 1521 } … … 1528 1526 void *pvUser) 1529 1527 { 1530 LogFlow (("%s:\n", __FUNCTION__));1528 LogFlowFunc(("\n")); 1531 1529 PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface); 1532 1530 int rc = VINF_SUCCESS; … … 1557 1555 rc2 = RTSemFastMutexRelease(pThis->MergeCompleteMutex); 1558 1556 AssertRC(rc2); 1559 LogFlow (("%s: returns %Rrc\n", __FUNCTION__, rc));1557 LogFlowFunc(("returns %Rrc\n", rc)); 1560 1558 return rc; 1561 1559 } … … 1564 1562 static DECLCALLBACK(uint64_t) drvvdGetSize(PPDMIMEDIA pInterface) 1565 1563 { 1566 LogFlow (("%s:\n", __FUNCTION__));1564 LogFlowFunc(("\n")); 1567 1565 PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface); 1568 1566 uint64_t cb = VDGetSize(pThis->pDisk, VD_LAST_IMAGE); 1569 LogFlow (("%s: returns %#llx (%llu)\n", __FUNCTION__, cb, cb));1567 LogFlowFunc(("returns %#llx (%llu)\n", cb, cb)); 1570 1568 return cb; 1571 1569 } … … 1574 1572 static DECLCALLBACK(bool) drvvdIsReadOnly(PPDMIMEDIA pInterface) 1575 1573 { 1576 LogFlow (("%s:\n", __FUNCTION__));1574 LogFlowFunc(("\n")); 1577 1575 PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface); 1578 1576 bool f = VDIsReadOnly(pThis->pDisk); 1579 LogFlow (("%s: returns %d\n", __FUNCTION__, f));1577 LogFlowFunc(("returns %d\n", f)); 1580 1578 return f; 1581 1579 } … … 1585 1583 PPDMMEDIAGEOMETRY pPCHSGeometry) 1586 1584 { 1587 LogFlow (("%s:\n", __FUNCTION__));1585 LogFlowFunc(("\n")); 1588 1586 PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface); 1589 int rc = VDGetPCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pPCHSGeometry); 1590 if (RT_FAILURE(rc)) 1591 { 1592 Log(("%s: geometry not available.\n", __FUNCTION__)); 1587 VDGEOMETRY geo; 1588 int rc = VDGetPCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, &geo); 1589 if (RT_SUCCESS(rc)) 1590 { 1591 pPCHSGeometry->cCylinders = geo.cCylinders; 1592 pPCHSGeometry->cHeads = geo.cHeads; 1593 pPCHSGeometry->cSectors = geo.cSectors; 1594 } 1595 else 1596 { 1597 LogFunc(("geometry not available.\n")); 1593 1598 rc = VERR_PDM_GEOMETRY_NOT_SET; 1594 1599 } 1595 LogFlow (("%s: returns %Rrc (CHS=%d/%d/%d)\n", __FUNCTION__,1596 rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));1600 LogFlowFunc(("returns %Rrc (CHS=%d/%d/%d)\n", 1601 rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 1597 1602 return rc; 1598 1603 } … … 1602 1607 PCPDMMEDIAGEOMETRY pPCHSGeometry) 1603 1608 { 1604 LogFlow (("%s: CHS=%d/%d/%d\n", __FUNCTION__,1605 pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));1609 LogFlowFunc(("CHS=%d/%d/%d\n", 1610 pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 1606 1611 PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface); 1607 int rc = VDSetPCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pPCHSGeometry); 1612 VDGEOMETRY geo; 1613 geo.cCylinders = pPCHSGeometry->cCylinders; 1614 geo.cHeads = pPCHSGeometry->cHeads; 1615 geo.cSectors = pPCHSGeometry->cSectors; 1616 int rc = VDSetPCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, &geo); 1608 1617 if (rc == VERR_VD_GEOMETRY_NOT_SET) 1609 1618 rc = VERR_PDM_GEOMETRY_NOT_SET; 1610 LogFlow (("%s: returns %Rrc\n", __FUNCTION__, rc));1619 LogFlowFunc(("returns %Rrc\n", rc)); 1611 1620 return rc; 1612 1621 } … … 1616 1625 PPDMMEDIAGEOMETRY pLCHSGeometry) 1617 1626 { 1618 LogFlow (("%s:\n", __FUNCTION__));1627 LogFlowFunc(("\n")); 1619 1628 PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface); 1620 int rc = VDGetLCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pLCHSGeometry); 1621 if (RT_FAILURE(rc)) 1622 { 1623 Log(("%s: geometry not available.\n", __FUNCTION__)); 1629 VDGEOMETRY geo; 1630 int rc = VDGetLCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, &geo); 1631 if (RT_SUCCESS(rc)) 1632 { 1633 pLCHSGeometry->cCylinders = geo.cCylinders; 1634 pLCHSGeometry->cHeads = geo.cHeads; 1635 pLCHSGeometry->cSectors = geo.cSectors; 1636 } 1637 else 1638 { 1639 LogFunc(("geometry not available.\n")); 1624 1640 rc = VERR_PDM_GEOMETRY_NOT_SET; 1625 1641 } 1626 LogFlow (("%s: returns %Rrc (CHS=%d/%d/%d)\n", __FUNCTION__,1627 rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));1642 LogFlowFunc(("returns %Rrc (CHS=%d/%d/%d)\n", 1643 rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 1628 1644 return rc; 1629 1645 } … … 1633 1649 PCPDMMEDIAGEOMETRY pLCHSGeometry) 1634 1650 { 1635 LogFlow (("%s: CHS=%d/%d/%d\n", __FUNCTION__,1636 pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));1651 LogFlowFunc(("CHS=%d/%d/%d\n", 1652 pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 1637 1653 PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface); 1638 int rc = VDSetLCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pLCHSGeometry); 1654 VDGEOMETRY geo; 1655 geo.cCylinders = pLCHSGeometry->cCylinders; 1656 geo.cHeads = pLCHSGeometry->cHeads; 1657 geo.cSectors = pLCHSGeometry->cSectors; 1658 int rc = VDSetLCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, &geo); 1639 1659 if (rc == VERR_VD_GEOMETRY_NOT_SET) 1640 1660 rc = VERR_PDM_GEOMETRY_NOT_SET; 1641 LogFlow (("%s: returns %Rrc\n", __FUNCTION__, rc));1661 LogFlowFunc(("returns %Rrc\n", rc)); 1642 1662 return rc; 1643 1663 } … … 1646 1666 static DECLCALLBACK(int) drvvdGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid) 1647 1667 { 1648 LogFlow (("%s:\n", __FUNCTION__));1668 LogFlowFunc(("\n")); 1649 1669 PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface); 1650 1670 int rc = VDGetUuid(pThis->pDisk, 0, pUuid); 1651 LogFlow (("%s: returns %Rrc ({%RTuuid})\n", __FUNCTION__, rc, pUuid));1671 LogFlowFunc(("returns %Rrc ({%RTuuid})\n", rc, pUuid)); 1652 1672 return rc; 1653 1673 } … … 1670 1690 size_t cbRead, void *pvUser) 1671 1691 { 1672 LogFlow(("%s: uOffset=%#llx paSeg=%#p cSeg=%u cbRead=%d\n pvUser=%#p", __FUNCTION__,1673 uOffset, paSeg, cSeg, cbRead, pvUser));1692 LogFlowFunc(("uOffset=%#llx paSeg=%#p cSeg=%u cbRead=%d\n pvUser=%#p", 1693 uOffset, paSeg, cSeg, cbRead, pvUser)); 1674 1694 PVBOXDISK pThis = PDMIMEDIAASYNC_2_VBOXDISK(pInterface); 1675 1695 … … 1678 1698 int rc = VDAsyncRead(pThis->pDisk, uOffset, cbRead, paSeg, cSeg, 1679 1699 drvvdAsyncReqComplete, pThis, pvUser); 1680 LogFlow (("%s: returns %Rrc\n", __FUNCTION__, rc));1700 LogFlowFunc(("returns %Rrc\n", rc)); 1681 1701 return rc; 1682 1702 } … … 1686 1706 size_t cbWrite, void *pvUser) 1687 1707 { 1688 LogFlow(("%s: uOffset=%#llx paSeg=%#p cSeg=%u cbWrite=%d pvUser=%#p\n", __FUNCTION__,1689 uOffset, paSeg, cSeg, cbWrite, pvUser));1708 LogFlowFunc(("uOffset=%#llx paSeg=%#p cSeg=%u cbWrite=%d pvUser=%#p\n", 1709 uOffset, paSeg, cSeg, cbWrite, pvUser)); 1690 1710 PVBOXDISK pThis = PDMIMEDIAASYNC_2_VBOXDISK(pInterface); 1691 1711 … … 1694 1714 int rc = VDAsyncWrite(pThis->pDisk, uOffset, cbWrite, paSeg, cSeg, 1695 1715 drvvdAsyncReqComplete, pThis, pvUser); 1696 LogFlow (("%s: returns %Rrc\n", __FUNCTION__, rc));1716 LogFlowFunc(("returns %Rrc\n", rc)); 1697 1717 return rc; 1698 1718 } … … 1700 1720 static DECLCALLBACK(int) drvvdStartFlush(PPDMIMEDIAASYNC pInterface, void *pvUser) 1701 1721 { 1702 LogFlow(("%s: pvUser=%#p\n", __FUNCTION__, pvUser));1722 LogFlowFunc(("pvUser=%#p\n", pvUser)); 1703 1723 PVBOXDISK pThis = PDMIMEDIAASYNC_2_VBOXDISK(pInterface); 1704 1724 int rc = VDAsyncFlush(pThis->pDisk, drvvdAsyncReqComplete, pThis, pvUser); 1705 LogFlow (("%s: returns %Rrc\n", __FUNCTION__, rc));1725 LogFlowFunc(("returns %Rrc\n", rc)); 1706 1726 return rc; 1707 1727 } … … 1765 1785 static DECLCALLBACK(void) drvvdPowerOff(PPDMDRVINS pDrvIns) 1766 1786 { 1767 LogFlow (("%s:\n", __FUNCTION__));1787 LogFlowFunc(("\n")); 1768 1788 PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK); 1769 1789 … … 1791 1811 static DECLCALLBACK(void) drvvdResume(PPDMDRVINS pDrvIns) 1792 1812 { 1793 LogFlow (("%s:\n", __FUNCTION__));1813 LogFlowFunc(("\n")); 1794 1814 PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK); 1795 1815 drvvdSetWritable(pThis); … … 1814 1834 static DECLCALLBACK(void) drvvdSuspend(PPDMDRVINS pDrvIns) 1815 1835 { 1816 LogFlow (("%s:\n", __FUNCTION__));1836 LogFlowFunc(("\n")); 1817 1837 PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK); 1818 1838 drvvdSetReadonly(pThis); … … 1830 1850 static DECLCALLBACK(void) drvvdPowerOn(PPDMDRVINS pDrvIns) 1831 1851 { 1832 LogFlow (("%s:\n", __FUNCTION__));1852 LogFlowFunc(("\n")); 1833 1853 PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK); 1834 1854 drvvdSetWritable(pThis); … … 1841 1861 static DECLCALLBACK(void) drvvdReset(PPDMDRVINS pDrvIns) 1842 1862 { 1843 LogFlow (("%s:\n", __FUNCTION__));1863 LogFlowFunc(("\n")); 1844 1864 PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK); 1845 1865 … … 1858 1878 { 1859 1879 PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK); 1860 LogFlow (("%s:\n", __FUNCTION__));1880 LogFlowFunc(("\n")); 1861 1881 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns); 1862 1882 … … 1902 1922 uint32_t fFlags) 1903 1923 { 1904 LogFlow (("%s:\n", __FUNCTION__));1924 LogFlowFunc(("\n")); 1905 1925 PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK); 1906 1926 int rc = VINF_SUCCESS; … … 2355 2375 if (RT_SUCCESS(rc)) 2356 2376 { 2357 Log (("%s: %d - Opened '%s' in %s mode\n", __FUNCTION__,2358 iLevel, pszName,2359 VDIsReadOnly(pThis->pDisk) ? "read-only" : "read-write"));2377 LogFunc(("%d - Opened '%s' in %s mode\n", 2378 iLevel, pszName, 2379 VDIsReadOnly(pThis->pDisk) ? "read-only" : "read-write")); 2360 2380 if ( VDIsReadOnly(pThis->pDisk) 2361 2381 && !fReadOnly … … 2435 2455 } 2436 2456 2437 LogFlow (("%s: returns %Rrc\n", __FUNCTION__, rc));2457 LogFlowFunc(("returns %Rrc\n", rc)); 2438 2458 return rc; 2439 2459 } -
trunk/src/VBox/Devices/Storage/ISCSIHDDCore.cpp
r32442 r32536 30 30 #include <iprt/assert.h> 31 31 #include <iprt/uuid.h> 32 #include <iprt/file.h>33 32 #include <iprt/string.h> 34 33 #include <iprt/asm.h> … … 339 338 SCSIXFER enmXfer; 340 339 /** Length of command block. */ 341 size_t cbC md;340 size_t cbCDB; 342 341 /** Length of Initiator2Target data buffer. */ 343 342 size_t cbI2TData; … … 350 349 uint8_t status; 351 350 /** Pointer to command block. */ 352 void *pvC md;351 void *pvCDB; 353 352 /** Pointer to sense buffer. */ 354 353 void *pvSense; … … 376 375 PSCSIREQ pScsiReq; 377 376 /** The CDB. */ 378 uint8_t abCDB[1 0];377 uint8_t abCDB[16]; 379 378 /** The sense buffer. */ 380 379 uint8_t abSense[96]; … … 720 719 va_end(va); 721 720 #endif 721 return rc; 722 } 723 724 /** 725 * Internal: signal an informational message to the frontend. 726 */ 727 DECLINLINE(int) iscsiMessage(PISCSIIMAGE pImage, const char *pszFormat, ...) 728 { 729 int rc = VINF_SUCCESS; 730 va_list va; 731 va_start(va, pszFormat); 732 if (pImage->pInterfaceError) 733 rc = pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, 734 pszFormat, va); 735 va_end(va); 722 736 return rc; 723 737 } … … 1751 1765 Assert(pRequest->enmXfer != SCSIXFER_TO_FROM_TARGET); /**< @todo not yet supported, would require AHS. */ 1752 1766 Assert(pRequest->cbI2TData <= 0xffffff); /* larger transfers would require R2T support. */ 1753 Assert(pRequest->cbC md<= 16); /* would cause buffer overrun below. */1767 Assert(pRequest->cbCDB <= 16); /* would cause buffer overrun below. */ 1754 1768 1755 1769 /* If not in normal state, then the transport connection was dropped. Try … … 1789 1803 aReqBHS[6] = RT_H2N_U32(pImage->CmdSN); 1790 1804 aReqBHS[7] = RT_H2N_U32(pImage->ExpStatSN); 1791 memcpy(aReqBHS + 8, pRequest->pvC md, pRequest->cbCmd);1805 memcpy(aReqBHS + 8, pRequest->pvCDB, pRequest->cbCDB); 1792 1806 pImage->CmdSN++; 1793 1807 … … 2631 2645 paReqBHS[6] = RT_H2N_U32(pImage->CmdSN); 2632 2646 paReqBHS[7] = RT_H2N_U32(pImage->ExpStatSN); 2633 memcpy(paReqBHS + 8, pScsiReq->pvC md, pScsiReq->cbCmd);2647 memcpy(paReqBHS + 8, pScsiReq->pvCDB, pScsiReq->cbCDB); 2634 2648 2635 2649 pIScsiPDU->CmdSN = pImage->CmdSN; … … 3605 3619 * delete the image from disk. 3606 3620 */ 3607 static voidiscsiFreeImage(PISCSIIMAGE pImage, bool fDelete)3608 { 3609 Assert(pImage);3621 static int iscsiFreeImage(PISCSIIMAGE pImage, bool fDelete) 3622 { 3623 int rc = VINF_SUCCESS; 3610 3624 Assert(!fDelete); /* This MUST be false, the flag isn't supported. */ 3611 3625 3612 if (pImage->Mutex != NIL_RTSEMMUTEX) 3613 { 3614 /* Detaching only makes sense when the mutex is there. Otherwise the 3615 * failure happened long before we could attach to the target. */ 3616 iscsiExecSync(pImage, iscsiDetach, pImage); 3617 RTSemMutexDestroy(pImage->Mutex); 3618 pImage->Mutex = NIL_RTSEMMUTEX; 3619 } 3620 if (pImage->hThreadIo != NIL_RTTHREAD) 3621 { 3622 int rc; 3623 3624 ASMAtomicXchgBool(&pImage->fRunning, false); 3625 rc = iscsiIoThreadPoke(pImage); 3626 AssertRC(rc); 3627 3628 /* Wait for the thread to terminate. */ 3629 rc = RTThreadWait(pImage->hThreadIo, RT_INDEFINITE_WAIT, NULL); 3630 AssertRC(rc); 3631 } 3632 /* Destroy the socket. */ 3633 if (pImage->Socket != NIL_VDSOCKET) 3634 { 3635 pImage->pInterfaceNetCallbacks->pfnSocketDestroy(pImage->Socket); 3636 } 3637 if (pImage->MutexReqQueue != NIL_RTSEMMUTEX) 3638 { 3639 RTSemMutexDestroy(pImage->MutexReqQueue); 3640 pImage->MutexReqQueue = NIL_RTSEMMUTEX; 3641 } 3642 if (pImage->pszTargetName) 3643 { 3644 RTMemFree(pImage->pszTargetName); 3645 pImage->pszTargetName = NULL; 3646 } 3647 if (pImage->pszInitiatorName) 3648 { 3649 if (pImage->fAutomaticInitiatorName) 3650 RTStrFree(pImage->pszInitiatorName); 3651 else 3652 RTMemFree(pImage->pszInitiatorName); 3653 pImage->pszInitiatorName = NULL; 3654 } 3655 if (pImage->pszInitiatorUsername) 3656 { 3657 RTMemFree(pImage->pszInitiatorUsername); 3658 pImage->pszInitiatorUsername = NULL; 3659 } 3660 if (pImage->pbInitiatorSecret) 3661 { 3662 RTMemFree(pImage->pbInitiatorSecret); 3663 pImage->pbInitiatorSecret = NULL; 3664 } 3665 if (pImage->pszTargetUsername) 3666 { 3667 RTMemFree(pImage->pszTargetUsername); 3668 pImage->pszTargetUsername = NULL; 3669 } 3670 if (pImage->pbTargetSecret) 3671 { 3672 RTMemFree(pImage->pbTargetSecret); 3673 pImage->pbTargetSecret = NULL; 3674 } 3675 if (pImage->pvRecvPDUBuf) 3676 { 3677 RTMemFree(pImage->pvRecvPDUBuf); 3678 pImage->pvRecvPDUBuf = NULL; 3679 } 3626 /* Freeing a never allocated image (e.g. because the open failed) is 3627 * not signalled as an error. After all nothing bad happens. */ 3628 if (pImage) 3629 { 3630 if (pImage->Mutex != NIL_RTSEMMUTEX) 3631 { 3632 /* Detaching only makes sense when the mutex is there. Otherwise the 3633 * failure happened long before we could attach to the target. */ 3634 iscsiExecSync(pImage, iscsiDetach, pImage); 3635 RTSemMutexDestroy(pImage->Mutex); 3636 pImage->Mutex = NIL_RTSEMMUTEX; 3637 } 3638 if (pImage->hThreadIo != NIL_RTTHREAD) 3639 { 3640 ASMAtomicXchgBool(&pImage->fRunning, false); 3641 rc = iscsiIoThreadPoke(pImage); 3642 AssertRC(rc); 3643 3644 /* Wait for the thread to terminate. */ 3645 rc = RTThreadWait(pImage->hThreadIo, RT_INDEFINITE_WAIT, NULL); 3646 AssertRC(rc); 3647 } 3648 /* Destroy the socket. */ 3649 if (pImage->Socket != NIL_VDSOCKET) 3650 { 3651 pImage->pInterfaceNetCallbacks->pfnSocketDestroy(pImage->Socket); 3652 } 3653 if (pImage->MutexReqQueue != NIL_RTSEMMUTEX) 3654 { 3655 RTSemMutexDestroy(pImage->MutexReqQueue); 3656 pImage->MutexReqQueue = NIL_RTSEMMUTEX; 3657 } 3658 if (pImage->pszTargetName) 3659 { 3660 RTMemFree(pImage->pszTargetName); 3661 pImage->pszTargetName = NULL; 3662 } 3663 if (pImage->pszInitiatorName) 3664 { 3665 if (pImage->fAutomaticInitiatorName) 3666 RTStrFree(pImage->pszInitiatorName); 3667 else 3668 RTMemFree(pImage->pszInitiatorName); 3669 pImage->pszInitiatorName = NULL; 3670 } 3671 if (pImage->pszInitiatorUsername) 3672 { 3673 RTMemFree(pImage->pszInitiatorUsername); 3674 pImage->pszInitiatorUsername = NULL; 3675 } 3676 if (pImage->pbInitiatorSecret) 3677 { 3678 RTMemFree(pImage->pbInitiatorSecret); 3679 pImage->pbInitiatorSecret = NULL; 3680 } 3681 if (pImage->pszTargetUsername) 3682 { 3683 RTMemFree(pImage->pszTargetUsername); 3684 pImage->pszTargetUsername = NULL; 3685 } 3686 if (pImage->pbTargetSecret) 3687 { 3688 RTMemFree(pImage->pbTargetSecret); 3689 pImage->pbTargetSecret = NULL; 3690 } 3691 if (pImage->pvRecvPDUBuf) 3692 { 3693 RTMemFree(pImage->pvRecvPDUBuf); 3694 pImage->pvRecvPDUBuf = NULL; 3695 } 3696 } 3697 3698 LogFlowFunc(("returns %Rrc\n", rc)); 3699 return rc; 3680 3700 } 3681 3701 … … 3999 4019 * Inquire available LUNs - purely dummy request. 4000 4020 */ 4001 uint8_t cdb_rlun[12];4021 uint8_t CDB_rlun[12]; 4002 4022 uint8_t rlundata[16]; 4003 cdb_rlun[0] = SCSI_REPORT_LUNS;4004 cdb_rlun[1] = 0; /* reserved */4005 cdb_rlun[2] = 0; /* reserved */4006 cdb_rlun[3] = 0; /* reserved */4007 cdb_rlun[4] = 0; /* reserved */4008 cdb_rlun[5] = 0; /* reserved */4009 cdb_rlun[6] = sizeof(rlundata) >> 24;4010 cdb_rlun[7] = (sizeof(rlundata) >> 16) & 0xff;4011 cdb_rlun[8] = (sizeof(rlundata) >> 8) & 0xff;4012 cdb_rlun[9] = sizeof(rlundata) & 0xff;4013 cdb_rlun[10] = 0; /* reserved */4014 cdb_rlun[11] = 0; /* control */4023 CDB_rlun[0] = SCSI_REPORT_LUNS; 4024 CDB_rlun[1] = 0; /* reserved */ 4025 CDB_rlun[2] = 0; /* reserved */ 4026 CDB_rlun[3] = 0; /* reserved */ 4027 CDB_rlun[4] = 0; /* reserved */ 4028 CDB_rlun[5] = 0; /* reserved */ 4029 CDB_rlun[6] = sizeof(rlundata) >> 24; 4030 CDB_rlun[7] = (sizeof(rlundata) >> 16) & 0xff; 4031 CDB_rlun[8] = (sizeof(rlundata) >> 8) & 0xff; 4032 CDB_rlun[9] = sizeof(rlundata) & 0xff; 4033 CDB_rlun[10] = 0; /* reserved */ 4034 CDB_rlun[11] = 0; /* control */ 4015 4035 4016 4036 DataSeg.pvSeg = rlundata; … … 4018 4038 4019 4039 sr.enmXfer = SCSIXFER_FROM_TARGET; 4020 sr.cbC md = sizeof(cdb_rlun);4021 sr.pvC md = cdb_rlun;4040 sr.cbCDB = sizeof(CDB_rlun); 4041 sr.pvCDB = CDB_rlun; 4022 4042 sr.cbI2TData = 0; 4023 4043 sr.paI2TSegs = NULL; … … 4039 4059 * Inquire device characteristics - no tapes, scanners etc., please. 4040 4060 */ 4041 uint8_t cdb_inq[6];4042 cdb_inq[0] = SCSI_INQUIRY;4043 cdb_inq[1] = 0; /* reserved */4044 cdb_inq[2] = 0; /* reserved */4045 cdb_inq[3] = 0; /* reserved */4046 cdb_inq[4] = sizeof(data8);4047 cdb_inq[5] = 0; /* control */4061 uint8_t CDB_inq[6]; 4062 CDB_inq[0] = SCSI_INQUIRY; 4063 CDB_inq[1] = 0; /* reserved */ 4064 CDB_inq[2] = 0; /* reserved */ 4065 CDB_inq[3] = 0; /* reserved */ 4066 CDB_inq[4] = sizeof(data8); 4067 CDB_inq[5] = 0; /* control */ 4048 4068 4049 4069 DataSeg.pvSeg = data8; … … 4051 4071 4052 4072 sr.enmXfer = SCSIXFER_FROM_TARGET; 4053 sr.cbC md = sizeof(cdb_inq);4054 sr.pvC md = cdb_inq;4073 sr.cbCDB = sizeof(CDB_inq); 4074 sr.pvCDB = CDB_inq; 4055 4075 sr.cbI2TData = 0; 4056 4076 sr.paI2TSegs = NULL; … … 4099 4119 */ 4100 4120 4101 uint8_t cdb_ms[6];4121 uint8_t CDB_ms[6]; 4102 4122 uint8_t data4[4]; 4103 cdb_ms[0] = SCSI_MODE_SENSE_6;4104 cdb_ms[1] = 0; /* dbd=0/reserved */4105 cdb_ms[2] = 0x3f; /* pc=0/page code=0x3f, ask for all pages */4106 cdb_ms[3] = 0; /* subpage code=0, return everything in page_0 format */4107 cdb_ms[4] = sizeof(data4); /* allocation length=4 */4108 cdb_ms[5] = 0; /* control */4123 CDB_ms[0] = SCSI_MODE_SENSE_6; 4124 CDB_ms[1] = 0; /* dbd=0/reserved */ 4125 CDB_ms[2] = 0x3f; /* pc=0/page code=0x3f, ask for all pages */ 4126 CDB_ms[3] = 0; /* subpage code=0, return everything in page_0 format */ 4127 CDB_ms[4] = sizeof(data4); /* allocation length=4 */ 4128 CDB_ms[5] = 0; /* control */ 4109 4129 4110 4130 DataSeg.pvSeg = data4; … … 4112 4132 4113 4133 sr.enmXfer = SCSIXFER_FROM_TARGET; 4114 sr.cbC md = sizeof(cdb_ms);4115 sr.pvC md = cdb_ms;4134 sr.cbCDB = sizeof(CDB_ms); 4135 sr.pvCDB = CDB_ms; 4116 4136 sr.cbI2TData = 0; 4117 4137 sr.paI2TSegs = NULL; … … 4141 4161 * Determine sector size and capacity of the volume immediately. 4142 4162 */ 4143 uint8_t cdb_cap[16];4163 uint8_t CDB_cap[16]; 4144 4164 4145 4165 RT_ZERO(data12); 4146 RT_ZERO( cdb_cap);4147 cdb_cap[0] = SCSI_SERVICE_ACTION_IN_16;4148 cdb_cap[1] = SCSI_SVC_ACTION_IN_READ_CAPACITY_16; /* subcommand */4149 cdb_cap[10+3] = sizeof(data12); /* allocation length (dword) */4166 RT_ZERO(CDB_cap); 4167 CDB_cap[0] = SCSI_SERVICE_ACTION_IN_16; 4168 CDB_cap[1] = SCSI_SVC_ACTION_IN_READ_CAPACITY_16; /* subcommand */ 4169 CDB_cap[10+3] = sizeof(data12); /* allocation length (dword) */ 4150 4170 4151 4171 DataSeg.pvSeg = data12; … … 4153 4173 4154 4174 sr.enmXfer = SCSIXFER_FROM_TARGET; 4155 sr.cbC md = sizeof(cdb_cap);4156 sr.pvC md = cdb_cap;4175 sr.cbCDB = sizeof(CDB_cap); 4176 sr.pvCDB = CDB_cap; 4157 4177 sr.cbI2TData = 0; 4158 4178 sr.paI2TSegs = NULL; … … 4182 4202 else 4183 4203 { 4184 uint8_t cdb_capfb[10];4204 uint8_t CDB_capfb[10]; 4185 4205 4186 4206 RT_ZERO(data8); 4187 cdb_capfb[0] = SCSI_READ_CAPACITY;4188 cdb_capfb[1] = 0; /* reserved */4189 cdb_capfb[2] = 0; /* reserved */4190 cdb_capfb[3] = 0; /* reserved */4191 cdb_capfb[4] = 0; /* reserved */4192 cdb_capfb[5] = 0; /* reserved */4193 cdb_capfb[6] = 0; /* reserved */4194 cdb_capfb[7] = 0; /* reserved */4195 cdb_capfb[8] = 0; /* reserved */4196 cdb_capfb[9] = 0; /* control */4207 CDB_capfb[0] = SCSI_READ_CAPACITY; 4208 CDB_capfb[1] = 0; /* reserved */ 4209 CDB_capfb[2] = 0; /* reserved */ 4210 CDB_capfb[3] = 0; /* reserved */ 4211 CDB_capfb[4] = 0; /* reserved */ 4212 CDB_capfb[5] = 0; /* reserved */ 4213 CDB_capfb[6] = 0; /* reserved */ 4214 CDB_capfb[7] = 0; /* reserved */ 4215 CDB_capfb[8] = 0; /* reserved */ 4216 CDB_capfb[9] = 0; /* control */ 4197 4217 4198 4218 DataSeg.pvSeg = data8; … … 4200 4220 4201 4221 sr.enmXfer = SCSIXFER_FROM_TARGET; 4202 sr.cbC md = sizeof(cdb_capfb);4203 sr.pvC md = cdb_capfb;4222 sr.cbCDB = sizeof(CDB_capfb); 4223 sr.pvCDB = CDB_capfb; 4204 4224 sr.cbI2TData = 0; 4205 4225 sr.paI2TSegs = NULL; … … 4255 4275 4256 4276 sr.enmXfer = SCSIXFER_FROM_TARGET; 4257 sr.cbC md= sizeof(aCDBModeSense6);4258 sr.pvC md= aCDBModeSense6;4277 sr.cbCDB = sizeof(aCDBModeSense6); 4278 sr.pvCDB = aCDBModeSense6; 4259 4279 sr.cbI2TData = 0; 4260 4280 sr.paI2TSegs = NULL; … … 4300 4320 4301 4321 sr.enmXfer = SCSIXFER_TO_TARGET; 4302 sr.cbC md= sizeof(aCDBCaching);4303 sr.pvC md= aCDBCaching;4322 sr.cbCDB = sizeof(aCDBCaching); 4323 sr.pvCDB = aCDBCaching; 4304 4324 sr.cbI2TData = DataSeg.cbSeg; 4305 4325 sr.paI2TSegs = &DataSeg; … … 4343 4363 4344 4364 /** @copydoc VBOXHDDBACKEND::pfnCheckIfValid */ 4345 static int iscsiCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk) 4365 static int iscsiCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk, 4366 PVDINTERFACE pVDIfsImage) 4346 4367 { 4347 4368 LogFlowFunc(("pszFilename=\"%s\"\n", pszFilename)); … … 4349 4370 /* iSCSI images can't be checked for validity this way, as the filename 4350 4371 * just can't supply enough configuration information. */ 4351 int rc = VERR_ VD_ISCSI_INVALID_HEADER;4372 int rc = VERR_NOT_SUPPORTED; 4352 4373 4353 4374 LogFlowFunc(("returns %Rrc\n", rc)); 4354 4375 return rc; 4355 4376 } 4356 4357 4377 4358 4378 /** @copydoc VBOXHDDBACKEND::pfnOpen */ … … 4409 4429 *ppBackendData = pImage; 4410 4430 } 4431 else 4432 RTMemFree(pImage); 4411 4433 4412 4434 out: … … 4415 4437 } 4416 4438 4417 4418 4439 /** @copydoc VBOXHDDBACKEND::pfnCreate */ 4419 4440 static int iscsiCreate(const char *pszFilename, uint64_t cbSize, 4420 4441 unsigned uImageFlags, const char *pszComment, 4421 PCPDMMEDIAGEOMETRY pPCHSGeometry, 4422 PCPDMMEDIAGEOMETRY pLCHSGeometry, PCRTUUID pUuid, 4423 unsigned uOpenFlags, unsigned uPercentStart, 4424 unsigned uPercentSpan, PVDINTERFACE pVDIfsDisk, 4425 PVDINTERFACE pVDIfsImage, PVDINTERFACE pVDIfsOperation, 4426 void **ppBackendData) 4442 PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry, 4443 PCRTUUID pUuid, unsigned uOpenFlags, 4444 unsigned uPercentStart, unsigned uPercentSpan, 4445 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage, 4446 PVDINTERFACE pVDIfsOperation, void **ppBackendData) 4427 4447 { 4428 4448 LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p ppBackendData=%#p", pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppBackendData)); … … 4433 4453 } 4434 4454 4435 4436 /** @copydoc VBOXHDDBACKEND::pfnRename */ 4437 static int iscsiRename(void *pBackendData, const char *pszFilename) 4438 { 4439 LogFlowFunc(("pBackendData=%#p pszFilename=%#p\n", pBackendData, pszFilename)); 4440 int rc = VERR_NOT_SUPPORTED; 4455 /** @copydoc VBOXHDDBACKEND::pfnClose */ 4456 static int iscsiClose(void *pBackendData, bool fDelete) 4457 { 4458 LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete)); 4459 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 4460 int rc; 4461 4462 Assert(!fDelete); /* This flag is unsupported. */ 4463 4464 rc = iscsiFreeImage(pImage, fDelete); 4465 RTMemFree(pImage); 4441 4466 4442 4467 LogFlowFunc(("returns %Rrc\n", rc)); 4443 4468 return rc; 4444 4469 } 4445 4446 4447 /** @copydoc VBOXHDDBACKEND::pfnClose */4448 static int iscsiClose(void *pBackendData, bool fDelete)4449 {4450 LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete));4451 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;4452 int rc = VINF_SUCCESS;4453 4454 Assert(!fDelete); /* This flag is unsupported. */4455 4456 /* Freeing a never allocated image (e.g. because the open failed) is4457 * not signalled as an error. After all nothing bad happens. */4458 if (pImage)4459 iscsiFreeImage(pImage, fDelete);4460 4461 LogFlowFunc(("returns %Rrc\n", rc));4462 return rc;4463 }4464 4465 4470 4466 4471 /** @copydoc VBOXHDDBACKEND::pfnRead */ … … 4498 4503 SCSIREQ sr; 4499 4504 RTSGSEG T2ISeg; 4500 uint8_t cdb[10]; 4505 size_t cbCDB; 4506 uint8_t abCDB[16]; 4501 4507 uint8_t sense[96]; 4502 4508 4503 cdb[0] = SCSI_READ_10; 4504 cdb[1] = 0; /* reserved */ 4505 cdb[2] = (lba >> 24) & 0xff; 4506 cdb[3] = (lba >> 16) & 0xff; 4507 cdb[4] = (lba >> 8) & 0xff; 4508 cdb[5] = lba & 0xff; 4509 cdb[6] = 0; /* reserved */ 4510 cdb[7] = (tls >> 8) & 0xff; 4511 cdb[8] = tls & 0xff; 4512 cdb[9] = 0; /* control */ 4509 if (pImage->cVolume < _4G) 4510 { 4511 cbCDB = 10; 4512 abCDB[0] = SCSI_READ_10; 4513 abCDB[1] = 0; /* reserved */ 4514 abCDB[2] = (lba >> 24) & 0xff; 4515 abCDB[3] = (lba >> 16) & 0xff; 4516 abCDB[4] = (lba >> 8) & 0xff; 4517 abCDB[5] = lba & 0xff; 4518 abCDB[6] = 0; /* reserved */ 4519 abCDB[7] = (tls >> 8) & 0xff; 4520 abCDB[8] = tls & 0xff; 4521 abCDB[9] = 0; /* control */ 4522 } 4523 else 4524 { 4525 cbCDB = 16; 4526 abCDB[0] = SCSI_READ_16; 4527 abCDB[1] = 0; /* reserved */ 4528 abCDB[2] = (lba >> 56) & 0xff; 4529 abCDB[3] = (lba >> 48) & 0xff; 4530 abCDB[4] = (lba >> 40) & 0xff; 4531 abCDB[5] = (lba >> 32) & 0xff; 4532 abCDB[6] = (lba >> 24) & 0xff; 4533 abCDB[7] = (lba >> 16) & 0xff; 4534 abCDB[8] = (lba >> 8) & 0xff; 4535 abCDB[9] = lba & 0xff; 4536 abCDB[10] = 0; /* tls unused */ 4537 abCDB[11] = 0; /* tls unused */ 4538 abCDB[12] = (tls >> 8) & 0xff; 4539 abCDB[13] = tls & 0xff; 4540 abCDB[14] = 0; /* reserved */ 4541 abCDB[15] = 0; /* reserved */ 4542 } 4513 4543 4514 4544 T2ISeg.pvSeg = pvBuf; … … 4516 4546 4517 4547 sr.enmXfer = SCSIXFER_FROM_TARGET; 4518 sr.cbC md = sizeof(cdb);4519 sr.pvC md = cdb;4548 sr.cbCDB = cbCDB; 4549 sr.pvCDB = abCDB; 4520 4550 sr.cbI2TData = 0; 4521 4551 sr.paI2TSegs = NULL; … … 4541 4571 } 4542 4572 4543 4544 4573 /** @copydoc VBOXHDDBACKEND::pfnWrite */ 4545 4574 static int iscsiWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf, … … 4578 4607 SCSIREQ sr; 4579 4608 RTSGSEG I2TSeg; 4580 uint8_t cdb[10]; 4609 size_t cbCDB; 4610 uint8_t abCDB[16]; 4581 4611 uint8_t sense[96]; 4582 4612 4583 cdb[0] = SCSI_WRITE_10; 4584 cdb[1] = 0; /* reserved */ 4585 cdb[2] = (lba >> 24) & 0xff; 4586 cdb[3] = (lba >> 16) & 0xff; 4587 cdb[4] = (lba >> 8) & 0xff; 4588 cdb[5] = lba & 0xff; 4589 cdb[6] = 0; /* reserved */ 4590 cdb[7] = (tls >> 8) & 0xff; 4591 cdb[8] = tls & 0xff; 4592 cdb[9] = 0; /* control */ 4613 if (pImage->cVolume < _4G) 4614 { 4615 cbCDB = 10; 4616 abCDB[0] = SCSI_WRITE_10; 4617 abCDB[1] = 0; /* reserved */ 4618 abCDB[2] = (lba >> 24) & 0xff; 4619 abCDB[3] = (lba >> 16) & 0xff; 4620 abCDB[4] = (lba >> 8) & 0xff; 4621 abCDB[5] = lba & 0xff; 4622 abCDB[6] = 0; /* reserved */ 4623 abCDB[7] = (tls >> 8) & 0xff; 4624 abCDB[8] = tls & 0xff; 4625 abCDB[9] = 0; /* control */ 4626 } 4627 else 4628 { 4629 cbCDB = 16; 4630 abCDB[0] = SCSI_WRITE_16; 4631 abCDB[1] = 0; /* reserved */ 4632 abCDB[2] = (lba >> 56) & 0xff; 4633 abCDB[3] = (lba >> 48) & 0xff; 4634 abCDB[4] = (lba >> 40) & 0xff; 4635 abCDB[5] = (lba >> 32) & 0xff; 4636 abCDB[6] = (lba >> 24) & 0xff; 4637 abCDB[7] = (lba >> 16) & 0xff; 4638 abCDB[8] = (lba >> 8) & 0xff; 4639 abCDB[9] = lba & 0xff; 4640 abCDB[10] = 0; /* tls unused */ 4641 abCDB[11] = 0; /* tls unused */ 4642 abCDB[12] = (tls >> 8) & 0xff; 4643 abCDB[13] = tls & 0xff; 4644 abCDB[14] = 0; /* reserved */ 4645 abCDB[15] = 0; /* reserved */ 4646 } 4593 4647 4594 4648 I2TSeg.pvSeg = (void *)pvBuf; … … 4596 4650 4597 4651 sr.enmXfer = SCSIXFER_TO_TARGET; 4598 sr.cbC md = sizeof(cdb);4599 sr.pvC md = cdb;4652 sr.cbCDB = cbCDB; 4653 sr.pvCDB = abCDB; 4600 4654 sr.cbI2TData = cbToWrite; 4601 4655 sr.paI2TSegs = &I2TSeg; … … 4621 4675 } 4622 4676 4623 4624 4677 /** @copydoc VBOXHDDBACKEND::pfnFlush */ 4625 4678 static int iscsiFlush(void *pBackendData) … … 4632 4685 4633 4686 SCSIREQ sr; 4634 uint8_t cdb[10];4687 uint8_t abCDB[10]; 4635 4688 uint8_t sense[96]; 4636 4689 4637 cdb[0] = SCSI_SYNCHRONIZE_CACHE;4638 cdb[1] = 0;/* reserved */4639 cdb[2] = 0;/* LBA 0 */4640 cdb[3] = 0;/* LBA 0 */4641 cdb[4] = 0;/* LBA 0 */4642 cdb[5] = 0;/* LBA 0 */4643 cdb[6] = 0;/* reserved */4644 cdb[7] = 0;/* transfer everything to disk */4645 cdb[8] = 0;/* transfer everything to disk */4646 cdb[9] = 0;/* control */4690 abCDB[0] = SCSI_SYNCHRONIZE_CACHE; 4691 abCDB[1] = 0; /* reserved */ 4692 abCDB[2] = 0; /* LBA 0 */ 4693 abCDB[3] = 0; /* LBA 0 */ 4694 abCDB[4] = 0; /* LBA 0 */ 4695 abCDB[5] = 0; /* LBA 0 */ 4696 abCDB[6] = 0; /* reserved */ 4697 abCDB[7] = 0; /* transfer everything to disk */ 4698 abCDB[8] = 0; /* transfer everything to disk */ 4699 abCDB[9] = 0; /* control */ 4647 4700 4648 4701 sr.enmXfer = SCSIXFER_NONE; 4649 sr.cbC md = sizeof(cdb);4650 sr.pvC md = cdb;4702 sr.cbCDB = sizeof(abCDB); 4703 sr.pvCDB = abCDB; 4651 4704 sr.cbI2TData = 0; 4652 4705 sr.paI2TSegs = NULL; … … 4665 4718 } 4666 4719 4667 4668 4720 /** @copydoc VBOXHDDBACKEND::pfnGetVersion */ 4669 4721 static unsigned iscsiGetVersion(void *pBackendData) … … 4677 4729 return 0; 4678 4730 } 4679 4680 4731 4681 4732 /** @copydoc VBOXHDDBACKEND::pfnGetSize */ … … 4693 4744 } 4694 4745 4695 4696 4746 /** @copydoc VBOXHDDBACKEND::pfnGetFileSize */ 4697 4747 static uint64_t iscsiGetFileSize(void *pBackendData) … … 4709 4759 } 4710 4760 4711 4712 4761 /** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */ 4713 static int iscsiGetPCHSGeometry(void *pBackendData, 4714 PPDMMEDIAGEOMETRY pPCHSGeometry) 4762 static int iscsiGetPCHSGeometry(void *pBackendData, PVDGEOMETRY pPCHSGeometry) 4715 4763 { 4716 4764 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry)); … … 4729 4777 } 4730 4778 4731 4732 4779 /** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */ 4733 static int iscsiSetPCHSGeometry(void *pBackendData, 4734 PCPDMMEDIAGEOMETRY pPCHSGeometry) 4780 static int iscsiSetPCHSGeometry(void *pBackendData, PCVDGEOMETRY pPCHSGeometry) 4735 4781 { 4736 4782 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); … … 4757 4803 } 4758 4804 4759 4760 4805 /** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */ 4761 static int iscsiGetLCHSGeometry(void *pBackendData, 4762 PPDMMEDIAGEOMETRY pLCHSGeometry) 4806 static int iscsiGetLCHSGeometry(void *pBackendData, PVDGEOMETRY pLCHSGeometry) 4763 4807 { 4764 4808 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry)); … … 4777 4821 } 4778 4822 4823 /** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */ 4824 static int iscsiSetLCHSGeometry(void *pBackendData, PCVDGEOMETRY pLCHSGeometry) 4825 { 4826 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 4827 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 4828 int rc; 4829 4830 Assert(pImage); 4831 4832 if (pImage) 4833 { 4834 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 4835 { 4836 rc = VERR_VD_IMAGE_READ_ONLY; 4837 goto out; 4838 } 4839 rc = VERR_VD_GEOMETRY_NOT_SET; 4840 } 4841 else 4842 rc = VERR_VD_NOT_OPENED; 4843 4844 out: 4845 LogFlowFunc(("returns %Rrc\n", rc)); 4846 return rc; 4847 } 4779 4848 4780 4849 /** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */ … … 4793 4862 return uImageFlags; 4794 4863 } 4795 4796 4864 4797 4865 /** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */ … … 4813 4881 } 4814 4882 4815 4816 4883 /** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */ 4817 4884 static int iscsiSetOpenFlags(void *pBackendData, unsigned uOpenFlags) … … 4823 4890 /* Image must be opened and the new flags must be valid. Just readonly and 4824 4891 * info flags are supported. */ 4825 if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO )))4892 if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE))) 4826 4893 { 4827 4894 rc = VERR_INVALID_PARAMETER; … … 4850 4917 } 4851 4918 4852 4853 /** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */4854 static int iscsiSetLCHSGeometry(void *pBackendData,4855 PCPDMMEDIAGEOMETRY pLCHSGeometry)4856 {4857 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));4858 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;4859 int rc;4860 4861 Assert(pImage);4862 4863 if (pImage)4864 {4865 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)4866 {4867 rc = VERR_VD_IMAGE_READ_ONLY;4868 goto out;4869 }4870 rc = VERR_VD_GEOMETRY_NOT_SET;4871 }4872 else4873 rc = VERR_VD_NOT_OPENED;4874 4875 out:4876 LogFlowFunc(("returns %Rrc\n", rc));4877 return rc;4878 }4879 4880 4881 4919 /** @copydoc VBOXHDDBACKEND::pfnGetComment */ 4882 4920 static int iscsiGetComment(void *pBackendData, char *pszComment, … … 4898 4936 } 4899 4937 4900 4901 4938 /** @copydoc VBOXHDDBACKEND::pfnSetComment */ 4902 4939 static int iscsiSetComment(void *pBackendData, const char *pszComment) … … 4922 4959 } 4923 4960 4924 4925 4961 /** @copydoc VBOXHDDBACKEND::pfnGetUuid */ 4926 4962 static int iscsiGetUuid(void *pBackendData, PRTUUID pUuid) … … 4941 4977 } 4942 4978 4943 4944 4979 /** @copydoc VBOXHDDBACKEND::pfnSetUuid */ 4945 4980 static int iscsiSetUuid(void *pBackendData, PCRTUUID pUuid) … … 4966 5001 } 4967 5002 4968 4969 5003 /** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */ 4970 5004 static int iscsiGetModificationUuid(void *pBackendData, PRTUUID pUuid) … … 4985 5019 } 4986 5020 4987 4988 5021 /** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */ 4989 5022 static int iscsiSetModificationUuid(void *pBackendData, PCRTUUID pUuid) … … 5010 5043 } 5011 5044 5012 5013 5045 /** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */ 5014 5046 static int iscsiGetParentUuid(void *pBackendData, PRTUUID pUuid) … … 5029 5061 } 5030 5062 5031 5032 5063 /** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */ 5033 5064 static int iscsiSetParentUuid(void *pBackendData, PCRTUUID pUuid) … … 5054 5085 } 5055 5086 5056 5057 5087 /** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */ 5058 5088 static int iscsiGetParentModificationUuid(void *pBackendData, PRTUUID pUuid) … … 5073 5103 } 5074 5104 5075 5076 5105 /** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */ 5077 5106 static int iscsiSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid) … … 5098 5127 } 5099 5128 5100 5101 5129 /** @copydoc VBOXHDDBACKEND::pfnDump */ 5102 5130 static void iscsiDump(void *pBackendData) … … 5108 5136 { 5109 5137 /** @todo put something useful here */ 5110 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: cVolume=%u\n", pImage->cVolume); 5111 } 5112 } 5113 5114 5115 /** @copydoc VBOXHDDBACKEND::pfnGetTimeStamp */ 5116 static int iscsiGetTimeStamp(void *pBackendData, PRTTIMESPEC pTimeStamp) 5117 { 5118 LogFlowFunc(("pBackendData=%#p pTimeStamp=%#p\n", pBackendData, pTimeStamp)); 5138 iscsiMessage(pImage, "Header: cVolume=%u\n", pImage->cVolume); 5139 } 5140 } 5141 5142 /** @copydoc VBOXHDDBACKEND::pfnIsAsyncIOSupported */ 5143 static bool iscsiIsAsyncIOSupported(void *pBackendData) 5144 { 5119 5145 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5120 int rc = VERR_NOT_SUPPORTED; 5121 5122 Assert(pImage); 5123 NOREF(pImage); 5124 5125 LogFlowFunc(("returns %Rrc\n", rc)); 5126 return rc; 5127 } 5128 5129 5130 /** @copydoc VBOXHDDBACKEND::pfnGetParentTimeStamp */ 5131 static int iscsiGetParentTimeStamp(void *pBackendData, PRTTIMESPEC pTimeStamp) 5132 { 5133 LogFlowFunc(("pBackendData=%#p pTimeStamp=%#p\n", pBackendData, pTimeStamp)); 5146 return pImage->fCmdQueuingSupported; 5147 } 5148 5149 /** @copydoc VBOXHDDBACKEND::pfnAsyncRead */ 5150 static int iscsiAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbToRead, 5151 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 5152 { 5153 LogFlowFunc(("pBackendData=%p uOffset=%#llx pIoCtx=%#p cbToRead=%u pcbActuallyRead=%p\n", 5154 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead)); 5134 5155 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5135 int rc = VERR_NOT_SUPPORTED;5136 5137 Assert(pImage);5138 NOREF(pImage);5139 5140 LogFlowFunc(("returns %Rrc\n", rc));5141 return rc;5142 }5143 5144 5145 /** @copydoc VBOXHDDBACKEND::pfnSetParentTimeStamp */5146 static int iscsiSetParentTimeStamp(void *pBackendData, PCRTTIMESPEC pTimeStamp)5147 {5148 LogFlowFunc(("pBackendData=%#p pTimeStamp=%#p\n", pBackendData, pTimeStamp));5149 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;5150 int rc = VERR_NOT_SUPPORTED;5151 5152 Assert(pImage);5153 NOREF(pImage);5154 5155 LogFlowFunc(("returns %Rrc\n", rc));5156 return rc;5157 }5158 5159 5160 /** @copydoc VBOXHDDBACKEND::pfnGetParentFilename */5161 static int iscsiGetParentFilename(void *pBackendData, char **ppszParentFilename)5162 {5163 LogFlowFunc(("pBackendData=%#p ppszParentFilename=%#p\n", pBackendData, ppszParentFilename));5164 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;5165 int rc = VERR_NOT_SUPPORTED;5166 5167 Assert(pImage);5168 NOREF(pImage);5169 5170 LogFlowFunc(("returns %Rrc\n", rc));5171 return rc;5172 }5173 5174 5175 /** @copydoc VBOXHDDBACKEND::pfnSetParentFilename */5176 static int iscsiSetParentFilename(void *pBackendData, const char *pszParentFilename)5177 {5178 LogFlowFunc(("pBackendData=%#p pszParentFilename=%s\n", pBackendData, pszParentFilename));5179 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;5180 int rc = VERR_NOT_SUPPORTED;5181 5182 Assert(pImage);5183 NOREF(pImage);5184 5185 LogFlowFunc(("returns %Rrc\n", rc));5186 return rc;5187 }5188 5189 /** @copydoc VBOXHDDBACKEND::pfnComposeLocation */5190 static int iscsiComposeLocation(PVDINTERFACE pConfig, char **pszLocation)5191 {5192 char *pszTarget = NULL;5193 char *pszLUN = NULL;5194 char *pszAddress = NULL;5195 int rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "TargetName", &pszTarget);5196 if (RT_SUCCESS(rc))5197 {5198 rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "LUN", &pszLUN);5199 if (RT_SUCCESS(rc))5200 {5201 rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "TargetAddress", &pszAddress);5202 if (RT_SUCCESS(rc))5203 {5204 if (RTStrAPrintf(pszLocation, "iscsi://%s/%s/%s",5205 pszAddress, pszTarget, pszLUN) < 0)5206 rc = VERR_NO_MEMORY;5207 }5208 }5209 }5210 RTMemFree(pszTarget);5211 RTMemFree(pszLUN);5212 RTMemFree(pszAddress);5213 return rc;5214 }5215 5216 /** @copydoc VBOXHDDBACKEND::pfnComposeName */5217 static int iscsiComposeName(PVDINTERFACE pConfig, char **pszName)5218 {5219 char *pszTarget = NULL;5220 char *pszLUN = NULL;5221 char *pszAddress = NULL;5222 int rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "TargetName", &pszTarget);5223 if (RT_SUCCESS(rc))5224 {5225 rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "LUN", &pszLUN);5226 if (RT_SUCCESS(rc))5227 {5228 rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "TargetAddress", &pszAddress);5229 if (RT_SUCCESS(rc))5230 {5231 /** @todo think about a nicer looking location scheme for iSCSI */5232 if (RTStrAPrintf(pszName, "%s/%s/%s",5233 pszAddress, pszTarget, pszLUN) < 0)5234 rc = VERR_NO_MEMORY;5235 }5236 }5237 }5238 RTMemFree(pszTarget);5239 RTMemFree(pszLUN);5240 RTMemFree(pszAddress);5241 5242 return rc;5243 }5244 5245 static bool iscsiIsAsyncIOSupported(void *pvBackendData)5246 {5247 PISCSIIMAGE pImage = (PISCSIIMAGE)pvBackendData;5248 return pImage->fCmdQueuingSupported;5249 }5250 5251 static int iscsiAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbToRead,5252 PVDIOCTX pIoCtx, size_t *pcbActuallyRead)5253 {5254 PISCSIIMAGE pImage = (PISCSIIMAGE)pvBackendData;5255 5156 int rc = VINF_SUCCESS; 5256 5257 LogFlowFunc(("pBackendData=%p uOffset=%#llx pIoCtx=%#p cbToRead=%u pcbActuallyRead=%p\n",5258 pvBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));5259 5157 5260 5158 if (uOffset + cbToRead > pImage->cbSize) … … 5283 5181 uint16_t tls; 5284 5182 uint8_t *pbCDB = &pReqAsync->abCDB[0]; 5183 size_t cbCDB; 5285 5184 5286 5185 lba = uOffset / pImage->cbSector; … … 5297 5196 pReqAsync->rcSense = VERR_READ_ERROR; 5298 5197 5299 pbCDB[0] = SCSI_READ_10; 5300 pbCDB[1] = 0; /* reserved */ 5301 pbCDB[2] = (lba >> 24) & 0xff; 5302 pbCDB[3] = (lba >> 16) & 0xff; 5303 pbCDB[4] = (lba >> 8) & 0xff; 5304 pbCDB[5] = lba & 0xff; 5305 pbCDB[6] = 0; /* reserved */ 5306 pbCDB[7] = (tls >> 8) & 0xff; 5307 pbCDB[8] = tls & 0xff; 5308 pbCDB[9] = 0; /* control */ 5198 if (pImage->cVolume < _4G) 5199 { 5200 cbCDB = 10; 5201 pbCDB[0] = SCSI_READ_10; 5202 pbCDB[1] = 0; /* reserved */ 5203 pbCDB[2] = (lba >> 24) & 0xff; 5204 pbCDB[3] = (lba >> 16) & 0xff; 5205 pbCDB[4] = (lba >> 8) & 0xff; 5206 pbCDB[5] = lba & 0xff; 5207 pbCDB[6] = 0; /* reserved */ 5208 pbCDB[7] = (tls >> 8) & 0xff; 5209 pbCDB[8] = tls & 0xff; 5210 pbCDB[9] = 0; /* control */ 5211 } 5212 else 5213 { 5214 cbCDB = 16; 5215 pbCDB[0] = SCSI_READ_16; 5216 pbCDB[1] = 0; /* reserved */ 5217 pbCDB[2] = (lba >> 56) & 0xff; 5218 pbCDB[3] = (lba >> 48) & 0xff; 5219 pbCDB[4] = (lba >> 40) & 0xff; 5220 pbCDB[5] = (lba >> 32) & 0xff; 5221 pbCDB[6] = (lba >> 24) & 0xff; 5222 pbCDB[7] = (lba >> 16) & 0xff; 5223 pbCDB[8] = (lba >> 8) & 0xff; 5224 pbCDB[9] = lba & 0xff; 5225 pbCDB[10] = 0; /* tls unused */ 5226 pbCDB[11] = 0; /* tls unused */ 5227 pbCDB[12] = (tls >> 8) & 0xff; 5228 pbCDB[13] = tls & 0xff; 5229 pbCDB[14] = 0; /* reserved */ 5230 pbCDB[15] = 0; /* reserved */ 5231 } 5309 5232 5310 5233 pReq->enmXfer = SCSIXFER_FROM_TARGET; 5311 pReq->cbC md = sizeof(pReqAsync->abCDB);5312 pReq->pvC md= pReqAsync->abCDB;5234 pReq->cbCDB = cbCDB; 5235 pReq->pvCDB = pReqAsync->abCDB; 5313 5236 pReq->cbI2TData = 0; 5314 5237 pReq->paI2TSegs = NULL; … … 5343 5266 } 5344 5267 5345 static int iscsiAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbToWrite, 5268 /** @copydoc VBOXHDDBACKEND::pfnAsyncWrite */ 5269 static int iscsiAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite, 5346 5270 PVDIOCTX pIoCtx, 5347 5271 size_t *pcbWriteProcess, size_t *pcbPreRead, 5348 5272 size_t *pcbPostRead, unsigned fWrite) 5349 5273 { 5350 PISCSIIMAGE pImage = (PISCSIIMAGE)pvBackendData; 5274 LogFlowFunc(("pBackendData=%p uOffset=%llu pIoCtx=%#p cbToWrite=%u pcbWriteProcess=%p pcbPreRead=%p pcbPostRead=%p fWrite=%u\n", 5275 pBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead, fWrite)); 5276 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5351 5277 int rc = VINF_SUCCESS; 5352 5353 LogFlowFunc(("pBackendData=%p uOffset=%llu pIoCtx=%#p cbToWrite=%u pcbWriteProcess=%p pcbPreRead=%p pcbPostRead=%p fWrite=%u\n",5354 pvBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead, fWrite));5355 5278 5356 5279 AssertPtr(pImage); … … 5383 5306 uint16_t tls; 5384 5307 uint8_t *pbCDB = &pReqAsync->abCDB[0]; 5308 size_t cbCDB; 5385 5309 5386 5310 lba = uOffset / pImage->cbSector; … … 5397 5321 pReqAsync->rcSense = VERR_WRITE_ERROR; 5398 5322 5399 pbCDB[0] = SCSI_WRITE_10; 5400 pbCDB[1] = 0; /* reserved */ 5401 pbCDB[2] = (lba >> 24) & 0xff; 5402 pbCDB[3] = (lba >> 16) & 0xff; 5403 pbCDB[4] = (lba >> 8) & 0xff; 5404 pbCDB[5] = lba & 0xff; 5405 pbCDB[6] = 0; /* reserved */ 5406 pbCDB[7] = (tls >> 8) & 0xff; 5407 pbCDB[8] = tls & 0xff; 5408 pbCDB[9] = 0; /* control */ 5323 if (pImage->cVolume < _4G) 5324 { 5325 cbCDB = 10; 5326 pbCDB[0] = SCSI_WRITE_10; 5327 pbCDB[1] = 0; /* reserved */ 5328 pbCDB[2] = (lba >> 24) & 0xff; 5329 pbCDB[3] = (lba >> 16) & 0xff; 5330 pbCDB[4] = (lba >> 8) & 0xff; 5331 pbCDB[5] = lba & 0xff; 5332 pbCDB[6] = 0; /* reserved */ 5333 pbCDB[7] = (tls >> 8) & 0xff; 5334 pbCDB[8] = tls & 0xff; 5335 pbCDB[9] = 0; /* control */ 5336 } 5337 else 5338 { 5339 cbCDB = 16; 5340 pbCDB[0] = SCSI_WRITE_16; 5341 pbCDB[1] = 0; /* reserved */ 5342 pbCDB[2] = (lba >> 56) & 0xff; 5343 pbCDB[3] = (lba >> 48) & 0xff; 5344 pbCDB[4] = (lba >> 40) & 0xff; 5345 pbCDB[5] = (lba >> 32) & 0xff; 5346 pbCDB[6] = (lba >> 24) & 0xff; 5347 pbCDB[7] = (lba >> 16) & 0xff; 5348 pbCDB[8] = (lba >> 8) & 0xff; 5349 pbCDB[9] = lba & 0xff; 5350 pbCDB[10] = 0; /* tls unused */ 5351 pbCDB[11] = 0; /* tls unused */ 5352 pbCDB[12] = (tls >> 8) & 0xff; 5353 pbCDB[13] = tls & 0xff; 5354 pbCDB[14] = 0; /* reserved */ 5355 pbCDB[15] = 0; /* reserved */ 5356 } 5409 5357 5410 5358 pReq->enmXfer = SCSIXFER_TO_TARGET; 5411 pReq->cbC md = sizeof(pReqAsync->abCDB);5412 pReq->pvC md= pReqAsync->abCDB;5359 pReq->cbCDB = cbCDB; 5360 pReq->pvCDB = pReqAsync->abCDB; 5413 5361 pReq->cbI2TData = cbToWrite; 5414 5362 pReq->paI2TSegs = &pReqAsync->aSegs[0]; … … 5443 5391 } 5444 5392 5445 static int iscsiAsyncFlush(void *pvBackendData, PVDIOCTX pIoCtx) 5446 { 5447 PISCSIIMAGE pImage = (PISCSIIMAGE)pvBackendData; 5393 /** @copydoc VBOXHDDBACKEND::pfnAsyncFlush */ 5394 static int iscsiAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx) 5395 { 5396 LogFlowFunc(("pBackendData=%p pIoCtx=%#p\n", pBackendData, pIoCtx)); 5397 PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData; 5448 5398 int rc = VINF_SUCCESS; 5449 5450 LogFlowFunc(("pvBackendData=%p pIoCtx=%#p\n", pvBackendData, pIoCtx));5451 5399 5452 5400 PSCSIREQASYNC pReqAsync = (PSCSIREQASYNC)RTMemAllocZ(sizeof(SCSIREQASYNC)); … … 5475 5423 5476 5424 pReq->enmXfer = SCSIXFER_NONE; 5477 pReq->cbC md = sizeof(pReqAsync->abCDB);5478 pReq->pvC md= pReqAsync->abCDB;5425 pReq->cbCDB = 10; 5426 pReq->pvCDB = pReqAsync->abCDB; 5479 5427 pReq->cbI2TData = 0; 5480 5428 pReq->paI2TSegs = NULL; … … 5503 5451 5504 5452 LogFlowFunc(("returns rc=%Rrc\n", rc)); 5453 return rc; 5454 } 5455 5456 /** @copydoc VBOXHDDBACKEND::pfnComposeLocation */ 5457 static int iscsiComposeLocation(PVDINTERFACE pConfig, char **pszLocation) 5458 { 5459 char *pszTarget = NULL; 5460 char *pszLUN = NULL; 5461 char *pszAddress = NULL; 5462 int rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "TargetName", &pszTarget); 5463 if (RT_SUCCESS(rc)) 5464 { 5465 rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "LUN", &pszLUN); 5466 if (RT_SUCCESS(rc)) 5467 { 5468 rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "TargetAddress", &pszAddress); 5469 if (RT_SUCCESS(rc)) 5470 { 5471 if (RTStrAPrintf(pszLocation, "iscsi://%s/%s/%s", 5472 pszAddress, pszTarget, pszLUN) < 0) 5473 rc = VERR_NO_MEMORY; 5474 } 5475 } 5476 } 5477 RTMemFree(pszTarget); 5478 RTMemFree(pszLUN); 5479 RTMemFree(pszAddress); 5480 return rc; 5481 } 5482 5483 /** @copydoc VBOXHDDBACKEND::pfnComposeName */ 5484 static int iscsiComposeName(PVDINTERFACE pConfig, char **pszName) 5485 { 5486 char *pszTarget = NULL; 5487 char *pszLUN = NULL; 5488 char *pszAddress = NULL; 5489 int rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "TargetName", &pszTarget); 5490 if (RT_SUCCESS(rc)) 5491 { 5492 rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "LUN", &pszLUN); 5493 if (RT_SUCCESS(rc)) 5494 { 5495 rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "TargetAddress", &pszAddress); 5496 if (RT_SUCCESS(rc)) 5497 { 5498 /** @todo think about a nicer looking location scheme for iSCSI */ 5499 if (RTStrAPrintf(pszName, "%s/%s/%s", 5500 pszAddress, pszTarget, pszLUN) < 0) 5501 rc = VERR_NO_MEMORY; 5502 } 5503 } 5504 } 5505 RTMemFree(pszTarget); 5506 RTMemFree(pszLUN); 5507 RTMemFree(pszAddress); 5508 5505 5509 return rc; 5506 5510 } … … 5528 5532 iscsiCreate, 5529 5533 /* pfnRename */ 5530 iscsiRename,5534 NULL, 5531 5535 /* pfnClose */ 5532 5536 iscsiClose, … … 5580 5584 iscsiDump, 5581 5585 /* pfnGetTimeStamp */ 5582 iscsiGetTimeStamp,5586 NULL, 5583 5587 /* pfnGetParentTimeStamp */ 5584 iscsiGetParentTimeStamp,5588 NULL, 5585 5589 /* pfnSetParentTimeStamp */ 5586 iscsiSetParentTimeStamp,5590 NULL, 5587 5591 /* pfnGetParentFilename */ 5588 iscsiGetParentFilename,5592 NULL, 5589 5593 /* pfnSetParentFilename */ 5590 iscsiSetParentFilename,5594 NULL, 5591 5595 /* pfnIsAsyncIOSupported */ 5592 5596 iscsiIsAsyncIOSupported, -
trunk/src/VBox/Devices/Storage/ParallelsHDDCore.cpp
r31776 r32536 17 17 */ 18 18 19 #define LOG_GROUP LOG_GROUP_VD_ VMDK /** @todo: Logging group */19 #define LOG_GROUP LOG_GROUP_VD_PARALLELS 20 20 #include <VBox/VBoxHDD-Plugin.h> 21 21 #include <VBox/err.h> … … 23 23 #include <VBox/log.h> 24 24 #include <iprt/assert.h> 25 #include <iprt/ alloc.h>25 #include <iprt/mem.h> 26 26 #include <iprt/uuid.h> 27 #include <iprt/file.h>28 27 #include <iprt/path.h> 29 28 #include <iprt/string.h> … … 60 59 typedef struct PARALLELSIMAGE 61 60 { 61 /** Image file name. */ 62 const char *pszFilename; 63 /** Opaque storage handle. */ 64 PVDIOSTORAGE pStorage; 65 66 /** I/O interface. */ 67 PVDINTERFACE pInterfaceIO; 68 /** I/O interface callbacks. */ 69 PVDINTERFACEIO pInterfaceIOCallbacks; 70 62 71 /** Pointer to the per-disk VD interface list. */ 63 72 PVDINTERFACE pVDIfsDisk; … … 68 77 /** Error interface callbacks. */ 69 78 PVDINTERFACEERROR pInterfaceErrorCallbacks; 70 #ifdef VBOX_WITH_NEW_IO_CODE 71 /** Async I/O interface. */ 72 PVDINTERFACE pInterfaceIO; 73 /** Async I/O interface callbacks. */ 74 PVDINTERFACEIO pInterfaceIOCallbacks; 75 #endif 76 77 /** Image file name. */ 78 const char *pszFilename; 79 #ifndef VBOX_WITH_NEW_IO_CODE 80 /** File descriptor. */ 81 RTFILE File; 82 #else 83 /** Opaque storage handle. */ 84 PVDIOSTORAGE pStorage; 85 #endif 86 /** Open flags passed by VBoxHD layer. */ 79 80 /** Open flags passed by VBoxHDD layer. */ 87 81 unsigned uOpenFlags; 88 82 /** Image flags defined during creation or determined during open. */ … … 90 84 /** Total size of the image. */ 91 85 uint64_t cbSize; 86 92 87 /** Physical geometry of this image. */ 93 PDMMEDIAGEOMETRYPCHSGeometry;88 VDGEOMETRY PCHSGeometry; 94 89 /** Logical geometry of this image. */ 95 PDMMEDIAGEOMETRY LCHSGeometry; 90 VDGEOMETRY LCHSGeometry; 91 96 92 /** Pointer to the allocation bitmap. */ 97 93 uint32_t *pAllocationBitmap; … … 134 130 } 135 131 136 static int parallelsFileOpen(PPARALLELSIMAGE pImage, bool fReadonly, bool fCreate) 132 /** 133 * Internal: signal an informational message to the frontend. 134 */ 135 DECLINLINE(int) parallelsMessage(PPARALLELSIMAGE pImage, const char *pszFormat, ...) 137 136 { 138 137 int rc = VINF_SUCCESS; 139 140 AssertMsg(!(fReadonly && fCreate), ("Image can't be opened readonly while being created\n")); 141 142 #ifndef VBOX_WITH_NEW_IO_CODE 143 uint32_t fOpen = fReadonly ? RTFILE_O_READ | RTFILE_O_DENY_NONE 144 : RTFILE_O_READWRITE | RTFILE_O_DENY_WRITE; 145 146 if (fCreate) 147 fOpen |= RTFILE_O_CREATE; 148 else 149 fOpen |= RTFILE_O_OPEN; 150 151 rc = RTFileOpen(&pImage->File, pImage->pszFilename, fOpen); 152 #else 153 unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0; 154 155 if (fCreate) 156 uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE; 157 158 rc = pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser, 159 pImage->pszFilename, 160 uOpenFlags, 161 &pImage->pStorage); 162 #endif 163 164 return rc; 165 } 166 167 static int parallelsFileClose(PPARALLELSIMAGE pImage) 138 va_list va; 139 va_start(va, pszFormat); 140 if (pImage->pInterfaceError && pImage->pInterfaceErrorCallbacks) 141 rc = pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, 142 pszFormat, va); 143 va_end(va); 144 return rc; 145 } 146 147 148 DECLINLINE(int) parallelsFileOpen(PPARALLELSIMAGE pImage, const char *pszFilename, 149 uint32_t fOpen) 150 { 151 return pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser, 152 pszFilename, fOpen, 153 &pImage->pStorage); 154 } 155 156 DECLINLINE(int) parallelsFileClose(PPARALLELSIMAGE pImage) 157 { 158 return pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser, 159 pImage->pStorage); 160 } 161 162 DECLINLINE(int) parallelsFileDelete(PPARALLELSIMAGE pImage, const char *pszFilename) 163 { 164 return pImage->pInterfaceIOCallbacks->pfnDelete(pImage->pInterfaceIO->pvUser, 165 pszFilename); 166 } 167 168 DECLINLINE(int) parallelsFileMove(PPARALLELSIMAGE pImage, const char *pszSrc, 169 const char *pszDst, unsigned fMove) 170 { 171 return pImage->pInterfaceIOCallbacks->pfnMove(pImage->pInterfaceIO->pvUser, 172 pszSrc, pszDst, fMove); 173 } 174 175 DECLINLINE(int) parallelsFileGetSize(PPARALLELSIMAGE pImage, uint64_t *pcbSize) 176 { 177 return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser, 178 pImage->pStorage, pcbSize); 179 } 180 181 DECLINLINE(int) parallelsFileSetSize(PPARALLELSIMAGE pImage, uint64_t cbSize) 182 { 183 return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser, 184 pImage->pStorage, cbSize); 185 } 186 187 DECLINLINE(int) parallelsFileWriteSync(PPARALLELSIMAGE pImage, uint64_t uOffset, 188 const void *pvBuffer, size_t cbBuffer, 189 size_t *pcbWritten) 190 { 191 return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser, 192 pImage->pStorage, uOffset, 193 pvBuffer, cbBuffer, pcbWritten); 194 } 195 196 DECLINLINE(int) parallelsFileReadSync(PPARALLELSIMAGE pImage, uint64_t uOffset, 197 void *pvBuffer, size_t cbBuffer, size_t *pcbRead) 198 { 199 return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser, 200 pImage->pStorage, uOffset, 201 pvBuffer, cbBuffer, pcbRead); 202 } 203 204 DECLINLINE(int) parallelsFileFlushSync(PPARALLELSIMAGE pImage) 205 { 206 return pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser, 207 pImage->pStorage); 208 } 209 210 DECLINLINE(int) parallelsFileReadUserAsync(PPARALLELSIMAGE pImage, uint64_t uOffset, 211 PVDIOCTX pIoCtx, size_t cbRead) 212 { 213 return pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser, 214 pImage->pStorage, 215 uOffset, pIoCtx, 216 cbRead); 217 } 218 219 DECLINLINE(int) parallelsFileWriteUserAsync(PPARALLELSIMAGE pImage, uint64_t uOffset, 220 PVDIOCTX pIoCtx, size_t cbWrite, 221 PFNVDXFERCOMPLETED pfnComplete, 222 void *pvCompleteUser) 223 { 224 return pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser, 225 pImage->pStorage, 226 uOffset, pIoCtx, 227 cbWrite, 228 pfnComplete, 229 pvCompleteUser); 230 } 231 232 DECLINLINE(int) parallelsFileWriteMetaAsync(PPARALLELSIMAGE pImage, uint64_t uOffset, 233 void *pvBuffer, size_t cbBuffer, 234 PVDIOCTX pIoCtx, 235 PFNVDXFERCOMPLETED pfnComplete, 236 void *pvCompleteUser) 237 { 238 return pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pImage->pInterfaceIO->pvUser, 239 pImage->pStorage, 240 uOffset, pvBuffer, 241 cbBuffer, pIoCtx, 242 pfnComplete, 243 pvCompleteUser); 244 } 245 246 DECLINLINE(int) parallelsFileFlushAsync(PPARALLELSIMAGE pImage, PVDIOCTX pIoCtx, 247 PFNVDXFERCOMPLETED pfnComplete, 248 void *pvCompleteUser) 249 { 250 return pImage->pInterfaceIOCallbacks->pfnFlushAsync(pImage->pInterfaceIO->pvUser, 251 pImage->pStorage, 252 pIoCtx, pfnComplete, 253 pvCompleteUser); 254 } 255 256 257 /** 258 * Internal. Flush image data to disk. 259 */ 260 static int parallelsFlushImage(PPARALLELSIMAGE pImage) 168 261 { 169 262 int rc = VINF_SUCCESS; 170 263 171 #ifndef VBOX_WITH_NEW_IO_CODE 172 if (pImage->File != NIL_RTFILE) 173 rc = RTFileClose(pImage->File); 174 175 pImage->File = NIL_RTFILE; 176 #else 177 rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser, 178 pImage->pStorage); 179 180 pImage->pStorage = NULL; 181 #endif 182 183 return rc; 184 } 185 186 static int parallelsFileFlushSync(PPARALLELSIMAGE pImage) 187 { 188 int rc = VINF_SUCCESS; 189 190 #ifndef VBOX_WITH_NEW_IO_CODE 191 rc = RTFileFlush(pImage->File); 192 #else 193 rc = pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser, 194 pImage->pStorage); 195 #endif 196 197 return rc; 198 } 199 200 static int parallelsFileGetSize(PPARALLELSIMAGE pImage, uint64_t *pcbSize) 201 { 202 int rc = VINF_SUCCESS; 203 204 #ifndef VBOX_WITH_NEW_IO_CODE 205 rc = RTFileGetSize(pImage->File, pcbSize); 206 #else 207 rc = pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser, 208 pImage->pStorage, pcbSize); 209 #endif 210 211 return rc; 212 213 } 214 215 static int parallelsFileSetSize(PPARALLELSIMAGE pImage, uint64_t cbSize) 216 { 217 int rc = VINF_SUCCESS; 218 219 #ifndef VBOX_WITH_NEW_IO_CODE 220 rc = RTFileSetSize(pImage->File, cbSize); 221 #else 222 rc = pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser, 223 pImage->pStorage, 224 cbSize); 225 #endif 226 227 return rc; 228 } 229 230 231 static int parallelsFileWriteSync(PPARALLELSIMAGE pImage, uint64_t off, const void *pcvBuf, size_t cbWrite, size_t *pcbWritten) 232 { 233 int rc = VINF_SUCCESS; 234 235 #ifndef VBOX_WITH_NEW_IO_CODE 236 rc = RTFileWriteAt(pImage->File, off, pcvBuf, cbWrite, pcbWritten); 237 #else 238 rc = pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser, 239 pImage->pStorage, 240 off, cbWrite, pcvBuf, 241 pcbWritten); 242 #endif 243 244 return rc; 245 } 246 247 static int parallelsFileReadSync(PPARALLELSIMAGE pImage, uint64_t off, void *pvBuf, size_t cbRead, size_t *pcbRead) 248 { 249 int rc = VINF_SUCCESS; 250 251 #ifndef VBOX_WITH_NEW_IO_CODE 252 rc = RTFileReadAt(pImage->File, off, pvBuf, cbRead, pcbRead); 253 #else 254 rc = pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser, 255 pImage->pStorage, 256 off, cbRead, pvBuf, 257 pcbRead); 258 #endif 259 260 return rc; 261 } 262 263 static bool parallelsFileOpened(PPARALLELSIMAGE pImage) 264 { 265 #ifndef VBOX_WITH_NEW_IO_CODE 266 return pImage->File != NIL_RTFILE; 267 #else 268 return pImage->pStorage != NULL; 269 #endif 270 } 271 272 static int parallelsOpenImage(PPARALLELSIMAGE pImage, unsigned uOpenFlags) 273 { 274 int rc = VINF_SUCCESS; 275 ParallelsHeader parallelsHeader; 276 277 /* Try to get error interface. */ 278 pImage->pInterfaceError = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ERROR); 279 if (pImage->pInterfaceError) 280 pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError); 281 282 #ifdef VBOX_WITH_NEW_IO_CODE 283 /* Try to get async I/O interface. */ 284 pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IO); 285 AssertPtr(pImage->pInterfaceIO); 286 pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO); 287 AssertPtr(pImage->pInterfaceIOCallbacks); 288 #endif 289 290 rc = parallelsFileOpen(pImage, !!(uOpenFlags & VD_OPEN_FLAGS_READONLY), false); 291 if (RT_FAILURE(rc)) 292 goto out; 293 294 rc = parallelsFileGetSize(pImage, &pImage->cbFileCurrent); 295 if (RT_FAILURE(rc)) 296 goto out; 297 AssertMsg(pImage->cbFileCurrent % 512 == 0, ("File size is not a multiple of 512\n")); 298 299 rc = parallelsFileReadSync(pImage, 0, ¶llelsHeader, sizeof(parallelsHeader), NULL); 300 if (RT_FAILURE(rc)) 301 goto out; 302 303 if (memcmp(parallelsHeader.HeaderIdentifier, PARALLELS_HEADER_MAGIC, 16)) 304 { 305 /* Check if the file has hdd as extension. It is a fixed size raw image then. */ 306 char *pszExtension = RTPathExt(pImage->pszFilename); 307 if (strcmp(pszExtension, ".hdd")) 308 { 309 rc = VERR_VD_GEN_INVALID_HEADER; 310 goto out; 311 } 312 313 /* This is a fixed size image. */ 314 pImage->uImageFlags |= VD_IMAGE_FLAGS_FIXED; 315 pImage->cbSize = pImage->cbFileCurrent; 316 317 pImage->PCHSGeometry.cHeads = 16; 318 pImage->PCHSGeometry.cSectors = 63; 319 uint64_t cCylinders = pImage->cbSize / (512 * pImage->PCHSGeometry.cSectors * pImage->PCHSGeometry.cHeads); 320 pImage->PCHSGeometry.cCylinders = (uint32_t)cCylinders; 321 } 322 else 323 { 324 if (parallelsHeader.uVersion != PARALLELS_DISK_VERSION) 325 { 326 rc = VERR_NOT_SUPPORTED; 327 goto out; 328 } 329 330 if (parallelsHeader.cEntriesInAllocationBitmap > (1 << 30)) 331 { 332 rc = VERR_NOT_SUPPORTED; 333 goto out; 334 } 335 336 Log(("cSectors=%u\n", parallelsHeader.cSectors)); 337 pImage->cbSize = ((uint64_t)parallelsHeader.cSectors) * 512; 338 pImage->uImageFlags = VD_IMAGE_FLAGS_NONE; 339 pImage->cAllocationBitmapEntries = parallelsHeader.cEntriesInAllocationBitmap; 340 pImage->pAllocationBitmap = (uint32_t *)RTMemAllocZ((uint32_t)pImage->cAllocationBitmapEntries * sizeof(uint32_t)); 341 if (!pImage->pAllocationBitmap) 342 { 343 rc = VERR_NO_MEMORY; 344 goto out; 345 } 346 347 rc = parallelsFileReadSync(pImage, sizeof(ParallelsHeader), 348 pImage->pAllocationBitmap, 349 pImage->cAllocationBitmapEntries * sizeof(uint32_t), 350 NULL); 351 if (RT_FAILURE(rc)) 352 goto out; 353 354 pImage->PCHSGeometry.cCylinders = parallelsHeader.cCylinders; 355 pImage->PCHSGeometry.cHeads = parallelsHeader.cHeads; 356 pImage->PCHSGeometry.cSectors = parallelsHeader.cSectorsPerTrack; 357 } 358 359 out: 360 LogFlowFunc(("returns %Rrc\n", rc)); 361 return rc; 362 } 363 364 static int parallelsFlushImage(PPARALLELSIMAGE pImage) 365 { 366 LogFlowFunc(("pImage=#%p\n", pImage)); 367 int rc = VINF_SUCCESS; 264 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 265 return VINF_SUCCESS; 368 266 369 267 if ( !(pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED) … … 387 285 } 388 286 389 static void parallelsFreeImage(PPARALLELSIMAGE pImage, bool fDelete) 390 { 391 (void)parallelsFlushImage(pImage); 392 393 if (pImage->pAllocationBitmap) 394 RTMemFree(pImage->pAllocationBitmap); 395 396 if (parallelsFileOpened(pImage)) 397 parallelsFileClose(pImage); 398 } 287 /** 288 * Internal. Free all allocated space for representing an image except pImage, 289 * and optionally delete the image from disk. 290 */ 291 static int parallelsFreeImage(PPARALLELSIMAGE pImage, bool fDelete) 292 { 293 int rc = VINF_SUCCESS; 294 295 /* Freeing a never allocated image (e.g. because the open failed) is 296 * not signalled as an error. After all nothing bad happens. */ 297 if (pImage) 298 { 299 if (pImage->pStorage) 300 { 301 /* No point updating the file that is deleted anyway. */ 302 if (!fDelete) 303 parallelsFlushImage(pImage); 304 305 parallelsFileClose(pImage); 306 pImage->pStorage = NULL; 307 } 308 309 if (pImage->pAllocationBitmap) 310 { 311 RTMemFree(pImage->pAllocationBitmap); 312 pImage->pAllocationBitmap = NULL; 313 } 314 315 if (fDelete && pImage->pszFilename) 316 parallelsFileDelete(pImage, pImage->pszFilename); 317 } 318 319 return rc; 320 } 321 322 static int parallelsOpenImage(PPARALLELSIMAGE pImage, unsigned uOpenFlags) 323 { 324 int rc = VINF_SUCCESS; 325 ParallelsHeader parallelsHeader; 326 327 /* Try to get error interface. */ 328 pImage->pInterfaceError = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ERROR); 329 if (pImage->pInterfaceError) 330 pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError); 331 332 /* Get I/O interface. */ 333 pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IO); 334 AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER); 335 pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO); 336 AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER); 337 338 rc = parallelsFileOpen(pImage, pImage->pszFilename, 339 VDOpenFlagsToFileOpenFlags(uOpenFlags, 340 false /* fCreate */)); 341 if (RT_FAILURE(rc)) 342 goto out; 343 344 rc = parallelsFileGetSize(pImage, &pImage->cbFileCurrent); 345 if (RT_FAILURE(rc)) 346 goto out; 347 AssertMsg(pImage->cbFileCurrent % 512 == 0, ("File size is not a multiple of 512\n")); 348 349 rc = parallelsFileReadSync(pImage, 0, ¶llelsHeader, sizeof(parallelsHeader), NULL); 350 if (RT_FAILURE(rc)) 351 goto out; 352 353 if (memcmp(parallelsHeader.HeaderIdentifier, PARALLELS_HEADER_MAGIC, 16)) 354 { 355 /* Check if the file has hdd as extension. It is a fixed size raw image then. */ 356 char *pszExtension = RTPathExt(pImage->pszFilename); 357 if (strcmp(pszExtension, ".hdd")) 358 { 359 rc = VERR_VD_PARALLELS_INVALID_HEADER; 360 goto out; 361 } 362 363 /* This is a fixed size image. */ 364 pImage->uImageFlags |= VD_IMAGE_FLAGS_FIXED; 365 pImage->cbSize = pImage->cbFileCurrent; 366 367 pImage->PCHSGeometry.cHeads = 16; 368 pImage->PCHSGeometry.cSectors = 63; 369 uint64_t cCylinders = pImage->cbSize / (512 * pImage->PCHSGeometry.cSectors * pImage->PCHSGeometry.cHeads); 370 pImage->PCHSGeometry.cCylinders = (uint32_t)cCylinders; 371 } 372 else 373 { 374 if (parallelsHeader.uVersion != PARALLELS_DISK_VERSION) 375 { 376 rc = VERR_NOT_SUPPORTED; 377 goto out; 378 } 379 380 if (parallelsHeader.cEntriesInAllocationBitmap > (1 << 30)) 381 { 382 rc = VERR_NOT_SUPPORTED; 383 goto out; 384 } 385 386 Log(("cSectors=%u\n", parallelsHeader.cSectors)); 387 pImage->cbSize = ((uint64_t)parallelsHeader.cSectors) * 512; 388 pImage->uImageFlags = VD_IMAGE_FLAGS_NONE; 389 pImage->cAllocationBitmapEntries = parallelsHeader.cEntriesInAllocationBitmap; 390 pImage->pAllocationBitmap = (uint32_t *)RTMemAllocZ((uint32_t)pImage->cAllocationBitmapEntries * sizeof(uint32_t)); 391 if (!pImage->pAllocationBitmap) 392 { 393 rc = VERR_NO_MEMORY; 394 goto out; 395 } 396 397 rc = parallelsFileReadSync(pImage, sizeof(ParallelsHeader), 398 pImage->pAllocationBitmap, 399 pImage->cAllocationBitmapEntries * sizeof(uint32_t), 400 NULL); 401 if (RT_FAILURE(rc)) 402 goto out; 403 404 pImage->PCHSGeometry.cCylinders = parallelsHeader.cCylinders; 405 pImage->PCHSGeometry.cHeads = parallelsHeader.cHeads; 406 pImage->PCHSGeometry.cSectors = parallelsHeader.cSectorsPerTrack; 407 } 408 409 out: 410 LogFlowFunc(("returns %Rrc\n", rc)); 411 return rc; 412 } 413 399 414 400 415 /** @copydoc VBOXHDDBACKEND::pfnCheckIfValid */ 401 static int parallelsCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk) 402 { 403 RTFILE File; 416 static int parallelsCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk, 417 PVDINTERFACE pVDIfsImage) 418 { 419 int rc; 420 PVDIOSTORAGE pStorage; 404 421 ParallelsHeader parallelsHeader; 405 int rc; 406 407 rc = RTFileOpen(&File, pszFilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); 422 423 /* Get I/O interface. */ 424 PVDINTERFACE pInterfaceIO = VDInterfaceGet(pVDIfsImage, VDINTERFACETYPE_IO); 425 AssertPtrReturn(pInterfaceIO, VERR_INVALID_PARAMETER); 426 PVDINTERFACEIO pInterfaceIOCallbacks = VDGetInterfaceIO(pInterfaceIO); 427 AssertPtrReturn(pInterfaceIOCallbacks, VERR_INVALID_PARAMETER); 428 429 rc = pInterfaceIOCallbacks->pfnOpen(pInterfaceIO->pvUser, pszFilename, 430 VDOpenFlagsToFileOpenFlags(VD_OPEN_FLAGS_READONLY, 431 false /* fCreate */), 432 &pStorage); 408 433 if (RT_FAILURE(rc)) 409 return VERR_VD_GEN_INVALID_HEADER; 410 411 rc = RTFileReadAt(File, 0, ¶llelsHeader, sizeof(ParallelsHeader), NULL); 412 if (RT_FAILURE(rc)) 413 { 414 rc = VERR_VD_GEN_INVALID_HEADER; 415 } 416 else 434 return rc; 435 436 rc = pInterfaceIOCallbacks->pfnReadSync(pInterfaceIO->pvUser, pStorage, 437 0, ¶llelsHeader, 438 sizeof(ParallelsHeader), NULL); 439 if (RT_SUCCESS(rc)) 417 440 { 418 441 if ( !memcmp(parallelsHeader.HeaderIdentifier, PARALLELS_HEADER_MAGIC, 16) … … 432 455 char *pszExtension; 433 456 434 rc = RTFileGetSize(File, &cbFile); 457 rc = pInterfaceIOCallbacks->pfnGetSize(pInterfaceIO->pvUser, pStorage, 458 &cbFile); 435 459 if (RT_FAILURE(rc) || ((cbFile % 512) != 0)) 436 460 { 437 RTFileClose(File);438 return VERR_VD_ GEN_INVALID_HEADER;461 pInterfaceIOCallbacks->pfnClose(pInterfaceIO->pvUser, pStorage); 462 return VERR_VD_PARALLELS_INVALID_HEADER; 439 463 } 440 464 441 465 pszExtension = RTPathExt(pszFilename); 442 466 if (!pszExtension || strcmp(pszExtension, ".hdd")) 443 rc = VERR_VD_ GEN_INVALID_HEADER;467 rc = VERR_VD_PARALLELS_INVALID_HEADER; 444 468 else 445 469 rc = VINF_SUCCESS; … … 447 471 } 448 472 449 RTFileClose(File);473 pInterfaceIOCallbacks->pfnClose(pInterfaceIO->pvUser, pStorage); 450 474 return rc; 451 475 } … … 469 493 /* Check remaining arguments. */ 470 494 if ( !VALID_PTR(pszFilename) 471 || !*pszFilename 472 || strchr(pszFilename, '"')) 495 || !*pszFilename) 473 496 { 474 497 rc = VERR_INVALID_PARAMETER; … … 476 499 } 477 500 501 /** @todo r=klaus why this duplicate check, async is not claimed... */ 478 502 if (uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO) 479 503 { … … 489 513 } 490 514 491 #ifndef VBOX_WITH_NEW_IO_CODE 492 pImage->File = NIL_RTFILE; 493 #else 515 pImage->pszFilename = pszFilename; 494 516 pImage->pStorage = NULL; 495 #endif496 pImage->fAllocationBitmapChanged = false;497 pImage->pszFilename = pszFilename;498 517 pImage->pVDIfsDisk = pVDIfsDisk; 499 518 pImage->pVDIfsImage = pVDIfsImage; 519 pImage->fAllocationBitmapChanged = false; 500 520 501 521 rc = parallelsOpenImage(pImage, uOpenFlags); 502 522 if (RT_SUCCESS(rc)) 503 523 *ppBackendData = pImage; 524 else 525 RTMemFree(pImage); 504 526 505 527 out: … … 511 533 static int parallelsCreate(const char *pszFilename, uint64_t cbSize, 512 534 unsigned uImageFlags, const char *pszComment, 513 PC PDMMEDIAGEOMETRY pPCHSGeometry,514 PC PDMMEDIAGEOMETRY pLCHSGeometry, PCRTUUID pUuid,535 PCVDGEOMETRY pPCHSGeometry, 536 PCVDGEOMETRY pLCHSGeometry, PCRTUUID pUuid, 515 537 unsigned uOpenFlags, unsigned uPercentStart, 516 538 unsigned uPercentSpan, PVDINTERFACE pVDIfsDisk, 517 PVDINTERFACE pVDIfsImage, PVDINTERFACE pVDIfsOperation,518 void **ppBackendData)539 PVDINTERFACE pVDIfsImage, 540 PVDINTERFACE pVDIfsOperation, void **ppBackendData) 519 541 { 520 542 LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p ppBackendData=%#p", pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppBackendData)); 521 return VERR_NOT_IMPLEMENTED; 543 int rc = VERR_NOT_IMPLEMENTED; 544 545 LogFlowFunc(("returns %Rrc\n", rc)); 546 return rc; 522 547 } 523 548 … … 526 551 { 527 552 LogFlowFunc(("pBackendData=%#p pszFilename=%#p\n", pBackendData, pszFilename)); 528 return VERR_NOT_IMPLEMENTED; 553 int rc = VINF_SUCCESS; 554 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 555 556 /* Check arguments. */ 557 if ( !pImage 558 || !pszFilename 559 || !*pszFilename) 560 { 561 rc = VERR_INVALID_PARAMETER; 562 goto out; 563 } 564 565 /* Close the image. */ 566 rc = parallelsFreeImage(pImage, false); 567 if (RT_FAILURE(rc)) 568 goto out; 569 570 /* Rename the file. */ 571 rc = parallelsFileMove(pImage, pImage->pszFilename, pszFilename, 0); 572 if (RT_FAILURE(rc)) 573 { 574 /* The move failed, try to reopen the original image. */ 575 int rc2 = parallelsOpenImage(pImage, pImage->uOpenFlags); 576 if (RT_FAILURE(rc2)) 577 rc = rc2; 578 579 goto out; 580 } 581 582 /* Update pImage with the new information. */ 583 pImage->pszFilename = pszFilename; 584 585 /* Open the old image with new name. */ 586 rc = parallelsOpenImage(pImage, pImage->uOpenFlags); 587 if (RT_FAILURE(rc)) 588 goto out; 589 590 out: 591 LogFlowFunc(("returns %Rrc\n", rc)); 592 return rc; 529 593 } 530 594 … … 534 598 LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete)); 535 599 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 536 int rc = VINF_SUCCESS; 537 538 /* Freeing a never allocated image (e.g. because the open failed) is 539 * not signalled as an error. After all nothing bad happens. */ 540 if (pImage) 541 parallelsFreeImage(pImage, fDelete); 600 int rc; 601 602 rc = parallelsFreeImage(pImage, fDelete); 603 RTMemFree(pImage); 542 604 543 605 LogFlowFunc(("returns %Rrc\n", rc)); … … 547 609 /** @copydoc VBOXHDDBACKEND::pfnRead */ 548 610 static int parallelsRead(void *pBackendData, uint64_t uOffset, void *pvBuf, 549 size_t cbToRead, size_t *pcbActuallyRead) 550 { 551 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead)); 611 size_t cbBuf, size_t *pcbActuallyRead) 612 { 613 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbBuf=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbBuf, pcbActuallyRead)); 614 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 552 615 int rc = VINF_SUCCESS; 553 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;554 616 uint64_t uSector; 555 617 uint64_t uOffsetInFile; 556 618 uint32_t iIndexInAllocationTable; 557 619 558 Assert (pImage);620 AssertPtr(pImage); 559 621 Assert(uOffset % 512 == 0); 560 Assert(cb ToRead% 512 == 0);622 Assert(cbBuf % 512 == 0); 561 623 562 624 if (pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED) 563 625 { 564 rc = parallelsFileReadSync(pImage, uOffset, 565 pvBuf, cbToRead, NULL); 626 rc = parallelsFileReadSync(pImage, uOffset, pvBuf, cbBuf, NULL); 566 627 } 567 628 else … … 573 634 uSector = uSector % pImage->PCHSGeometry.cSectors; 574 635 575 cb ToRead = RT_MIN(cbToRead, (pImage->PCHSGeometry.cSectors - uSector)*512);636 cbBuf = RT_MIN(cbBuf, (pImage->PCHSGeometry.cSectors - uSector)*512); 576 637 577 638 if (pImage->pAllocationBitmap[iIndexInAllocationTable] == 0) … … 582 643 { 583 644 uOffsetInFile = (pImage->pAllocationBitmap[iIndexInAllocationTable] + uSector) * 512; 584 rc = parallelsFileReadSync(pImage, uOffsetInFile, 585 pvBuf, cbToRead, NULL); 586 } 587 } 588 589 *pcbActuallyRead = cbToRead; 590 645 rc = parallelsFileReadSync(pImage, uOffsetInFile, pvBuf, cbBuf, NULL); 646 } 647 } 648 649 if (RT_SUCCESS(rc)) 650 { 651 if (pcbActuallyRead) 652 *pcbActuallyRead = cbBuf; 653 654 Log2(("parallelsRead: off=%#llx pvBuf=%p cbBuf=%d\n" 655 "%.*Rhxd\n", 656 uOffset, pvBuf, cbBuf, cbBuf, pvBuf)); 657 } 658 659 out: 591 660 LogFlowFunc(("returns %Rrc\n", rc)); 592 661 return rc; … … 595 664 /** @copydoc VBOXHDDBACKEND::pfnWrite */ 596 665 static int parallelsWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf, 597 size_t cb ToWrite, size_t *pcbWriteProcess,666 size_t cbBuf, size_t *pcbWriteProcess, 598 667 size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite) 599 668 { 600 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p\n", pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess)); 669 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbBuf=%zu pcbWriteProcess=%#p\n", pBackendData, uOffset, pvBuf, cbBuf, pcbWriteProcess)); 670 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 601 671 int rc = VINF_SUCCESS; 602 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;603 672 uint64_t uSector; 604 673 uint64_t uOffsetInFile; 605 674 uint32_t iIndexInAllocationTable; 606 675 607 Assert (pImage);676 AssertPtr(pImage); 608 677 Assert(uOffset % 512 == 0); 609 Assert(cb ToWrite% 512 == 0);678 Assert(cbBuf % 512 == 0); 610 679 611 680 if (pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED) 612 681 { 613 rc = parallelsFileWriteSync(pImage, uOffset, 614 pvBuf, cbToWrite, NULL); 682 rc = parallelsFileWriteSync(pImage, uOffset, pvBuf, cbBuf, NULL); 615 683 } 616 684 else … … 622 690 uSector = uSector % pImage->PCHSGeometry.cSectors; 623 691 624 cb ToWrite = RT_MIN(cbToWrite, (pImage->PCHSGeometry.cSectors - uSector)*512);692 cbBuf = RT_MIN(cbBuf, (pImage->PCHSGeometry.cSectors - uSector)*512); 625 693 626 694 if (pImage->pAllocationBitmap[iIndexInAllocationTable] == 0) … … 635 703 636 704 if (!pNewBlock) 637 return VERR_NO_MEMORY; 705 { 706 rc = VERR_NO_MEMORY; 707 goto out; 708 } 638 709 639 710 uOffsetInFile = (uint64_t)pImage->pAllocationBitmap[iIndexInAllocationTable] * 512; 640 711 memcpy(pNewBlock + (uOffset - ((uint64_t)iIndexInAllocationTable * pImage->PCHSGeometry.cSectors * 512)), 641 pvBuf, cb ToWrite);712 pvBuf, cbBuf); 642 713 643 714 /* 644 715 * Write the new block at the current end of the file. 645 716 */ 646 rc = parallelsFileWriteSync(pImage, uOffsetInFile, 647 p NewBlock,648 pImage->PCHSGeometry.cSectors * 512,NULL);717 rc = parallelsFileWriteSync(pImage, uOffsetInFile, pNewBlock, 718 pImage->PCHSGeometry.cSectors * 512, 719 NULL); 649 720 650 721 RTMemFree(pNewBlock); … … 653 724 { 654 725 uOffsetInFile = (pImage->pAllocationBitmap[iIndexInAllocationTable] + uSector) * 512; 655 rc = parallelsFileWriteSync(pImage, uOffsetInFile, 656 pvBuf, cbToWrite, NULL); 657 } 658 } 659 660 *pcbWriteProcess = cbToWrite; 661 662 LogFlowFunc(("returns %Rrc\n", rc)); 663 return rc; 664 } 665 726 rc = parallelsFileWriteSync(pImage, uOffsetInFile, pvBuf, cbBuf, NULL); 727 } 728 } 729 730 if (pcbWriteProcess) 731 *pcbWriteProcess = cbBuf; 732 733 /* Stay on the safe side. Do not run the risk of confusing the higher 734 * level, as that can be pretty lethal to image consistency. */ 735 *pcbPreRead = 0; 736 *pcbPostRead = 0; 737 738 out: 739 LogFlowFunc(("returns %Rrc\n", rc)); 740 return rc; 741 } 742 743 /** @copydoc VBOXHDDBACKEND::pfnFlush */ 666 744 static int parallelsFlush(void *pBackendData) 667 745 { 668 746 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 669 747 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 670 int rc = VINF_SUCCESS;671 672 Assert (pImage);748 int rc; 749 750 AssertPtr(pImage); 673 751 674 752 rc = parallelsFlushImage(pImage); … … 684 762 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 685 763 686 Assert (pImage);764 AssertPtr(pImage); 687 765 688 766 if (pImage) … … 697 775 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 698 776 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 699 700 Assert(pImage); 701 702 if (pImage) 703 return pImage->cbSize; 704 else 705 return 0; 777 uint64_t cb = 0; 778 779 AssertPtr(pImage); 780 781 if (pImage && pImage->pStorage) 782 cb = pImage->cbSize; 783 784 LogFlowFunc(("returns %llu\n", cb)); 785 return cb; 706 786 } 707 787 … … 713 793 uint64_t cb = 0; 714 794 715 Assert(pImage); 716 717 if (pImage) 718 { 719 if (parallelsFileOpened(pImage)) 720 cb = pImage->cbFileCurrent; 721 } 795 AssertPtr(pImage); 796 797 if (pImage && pImage->pStorage) 798 cb = pImage->cbFileCurrent; 722 799 723 800 LogFlowFunc(("returns %lld\n", cb)); … … 727 804 /** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */ 728 805 static int parallelsGetPCHSGeometry(void *pBackendData, 729 P PDMMEDIAGEOMETRY pPCHSGeometry)806 PVDGEOMETRY pPCHSGeometry) 730 807 { 731 808 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry)); … … 733 810 int rc; 734 811 735 Assert (pImage);812 AssertPtr(pImage); 736 813 737 814 if (pImage) … … 754 831 /** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */ 755 832 static int parallelsSetPCHSGeometry(void *pBackendData, 756 PC PDMMEDIAGEOMETRY pPCHSGeometry)833 PCVDGEOMETRY pPCHSGeometry) 757 834 { 758 835 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); … … 760 837 int rc; 761 838 762 Assert (pImage);839 AssertPtr(pImage); 763 840 764 841 if (pImage) … … 783 860 /** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */ 784 861 static int parallelsGetLCHSGeometry(void *pBackendData, 785 P PDMMEDIAGEOMETRY pLCHSGeometry)862 PVDGEOMETRY pLCHSGeometry) 786 863 { 787 864 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry)); … … 789 866 int rc; 790 867 791 Assert (pImage);868 AssertPtr(pImage); 792 869 793 870 if (pImage) … … 810 887 /** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */ 811 888 static int parallelsSetLCHSGeometry(void *pBackendData, 812 PC PDMMEDIAGEOMETRY pLCHSGeometry)889 PCVDGEOMETRY pLCHSGeometry) 813 890 { 814 891 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); … … 816 893 int rc; 817 894 818 Assert (pImage);895 AssertPtr(pImage); 819 896 820 897 if (pImage) … … 844 921 unsigned uImageFlags; 845 922 846 Assert (pImage);923 AssertPtr(pImage); 847 924 848 925 if (pImage) … … 862 939 unsigned uOpenFlags; 863 940 864 Assert (pImage);941 AssertPtr(pImage); 865 942 866 943 if (pImage) … … 882 959 /* Image must be opened and the new flags must be valid. Just readonly and 883 960 * info flags are supported. */ 961 /** @todo r=klaus add VD_OPEN_FLAGS_ASYNC_IO when async io has been tested */ 884 962 if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_SHAREABLE))) 885 963 { … … 889 967 890 968 /* Implement this operation via reopening the image. */ 891 parallelsFreeImage(pImage, false);969 parallelsFreeImage(pImage, true); 892 970 rc = parallelsOpenImage(pImage, uOpenFlags); 893 971 … … 905 983 int rc; 906 984 907 Assert(pImage); 908 909 if (pImage) 910 { 985 AssertPtr(pImage); 986 987 if (pImage) 911 988 rc = VERR_NOT_SUPPORTED; 912 }913 989 else 914 990 rc = VERR_VD_NOT_OPENED; … … 925 1001 int rc; 926 1002 927 Assert (pImage);1003 AssertPtr(pImage); 928 1004 929 1005 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) … … 934 1010 935 1011 if (pImage) 936 rc = V INF_SUCCESS;1012 rc = VERR_NOT_SUPPORTED; 937 1013 else 938 1014 rc = VERR_VD_NOT_OPENED; … … 950 1026 int rc; 951 1027 952 Assert(pImage); 953 954 if (pImage) 955 { 1028 AssertPtr(pImage); 1029 1030 if (pImage) 956 1031 rc = VERR_NOT_SUPPORTED; 957 }958 1032 else 959 1033 rc = VERR_VD_NOT_OPENED; … … 970 1044 int rc; 971 1045 972 LogFlowFunc(("%RTuuid\n", pUuid)); 973 Assert(pImage); 1046 AssertPtr(pImage); 974 1047 975 1048 if (pImage) 976 1049 { 977 1050 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 978 {979 1051 rc = VERR_NOT_SUPPORTED; 980 }981 1052 else 982 1053 rc = VERR_VD_IMAGE_READ_ONLY; … … 996 1067 int rc; 997 1068 998 Assert(pImage); 999 1000 if (pImage) 1001 { 1069 AssertPtr(pImage); 1070 1071 if (pImage) 1002 1072 rc = VERR_NOT_SUPPORTED; 1003 }1004 1073 else 1005 1074 rc = VERR_VD_NOT_OPENED; … … 1016 1085 int rc; 1017 1086 1018 Assert (pImage);1087 AssertPtr(pImage); 1019 1088 1020 1089 if (pImage) 1021 1090 { 1022 1091 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 1023 {1024 1092 rc = VERR_NOT_SUPPORTED; 1025 }1026 1093 else 1027 1094 rc = VERR_VD_IMAGE_READ_ONLY; … … 1041 1108 int rc; 1042 1109 1043 Assert(pImage); 1044 1045 if (pImage) 1046 { 1047 rc = VINF_SUCCESS; 1048 } 1110 AssertPtr(pImage); 1111 1112 if (pImage) 1113 rc = VERR_NOT_SUPPORTED; 1049 1114 else 1050 1115 rc = VERR_VD_NOT_OPENED; … … 1061 1126 int rc; 1062 1127 1063 Assert (pImage);1128 AssertPtr(pImage); 1064 1129 1065 1130 if (pImage) 1066 1131 { 1067 1132 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 1068 {1069 1133 rc = VERR_NOT_SUPPORTED; 1070 }1071 1134 else 1072 1135 rc = VERR_VD_IMAGE_READ_ONLY; … … 1086 1149 int rc; 1087 1150 1088 Assert(pImage); 1089 1090 if (pImage) 1091 { 1151 AssertPtr(pImage); 1152 1153 if (pImage) 1092 1154 rc = VERR_NOT_SUPPORTED; 1093 }1094 1155 else 1095 1156 rc = VERR_VD_NOT_OPENED; … … 1106 1167 int rc; 1107 1168 1108 Assert (pImage);1169 AssertPtr(pImage); 1109 1170 1110 1171 if (pImage) 1111 1172 { 1112 1173 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 1113 {1114 1174 rc = VERR_NOT_SUPPORTED; 1115 }1116 1175 else 1117 1176 rc = VERR_VD_IMAGE_READ_ONLY; … … 1129 1188 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 1130 1189 1131 Assert (pImage);1132 if (pImage) 1133 { 1134 p Image->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u\n",1190 AssertPtr(pImage); 1191 if (pImage) 1192 { 1193 parallelsMessage(pImage, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u\n", 1135 1194 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors, 1136 1195 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors); … … 1138 1197 } 1139 1198 1140 1141 static int parallelsGetTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp) 1142 { 1143 int rc = VERR_NOT_IMPLEMENTED; 1144 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc)); 1145 return rc; 1146 } 1147 1148 static int parallelsGetParentTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp) 1149 { 1150 int rc = VERR_NOT_IMPLEMENTED; 1151 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc)); 1152 return rc; 1153 } 1154 1155 static int parallelsSetParentTimeStamp(void *pvBackendData, PCRTTIMESPEC pTimeStamp) 1156 { 1157 int rc = VERR_NOT_IMPLEMENTED; 1158 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc)); 1159 return rc; 1160 } 1161 1162 static int parallelsGetParentFilename(void *pvBackendData, char **ppszParentFilename) 1163 { 1164 int rc = VERR_NOT_IMPLEMENTED; 1165 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc)); 1166 return rc; 1167 } 1168 1169 static int parallelsSetParentFilename(void *pvBackendData, const char *pszParentFilename) 1170 { 1171 int rc = VERR_NOT_IMPLEMENTED; 1172 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc)); 1173 return rc; 1174 } 1175 1176 static bool parallelsIsAsyncIOSupported(void *pvBackendData) 1199 /** @copydoc VBOXHDDBACKEND::pfnIsAsyncIOSupported */ 1200 static bool parallelsIsAsyncIOSupported(void *pBackendData) 1177 1201 { 1178 1202 #if 0 /** @todo: Remove when tested */ … … 1183 1207 } 1184 1208 1185 static int parallelsAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbToRead, 1209 /** @copydoc VBOXHDDBACKEND::pfnAsyncRead */ 1210 static int parallelsAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbToRead, 1186 1211 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 1187 1212 { 1188 LogFlowFunc(("p vBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n",1189 p vBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));1213 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n", 1214 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead)); 1190 1215 int rc = VINF_SUCCESS; 1191 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)p vBackendData;1216 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 1192 1217 uint64_t uSector; 1193 1218 uint64_t uOffsetInFile; 1194 1219 uint32_t iIndexInAllocationTable; 1195 1220 1196 Assert (pImage);1221 AssertPtr(pImage); 1197 1222 Assert(uOffset % 512 == 0); 1198 1223 Assert(cbToRead % 512 == 0); … … 1200 1225 if (pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED) 1201 1226 { 1202 rc = pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser, 1203 pImage->pStorage, 1204 uOffset, pIoCtx, cbToRead); 1227 rc = parallelsFileReadUserAsync(pImage, uOffset, pIoCtx, cbToRead); 1205 1228 } 1206 1229 else … … 1221 1244 { 1222 1245 uOffsetInFile = (pImage->pAllocationBitmap[iIndexInAllocationTable] + uSector) * 512; 1223 rc = pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser, 1224 pImage->pStorage, 1225 uOffsetInFile, pIoCtx, cbToRead); 1246 rc = parallelsFileReadUserAsync(pImage, uOffsetInFile, pIoCtx, cbToRead); 1226 1247 } 1227 1248 } … … 1233 1254 } 1234 1255 1235 static int parallelsAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbToWrite, 1256 /** @copydoc VBOXHDDBACKEND::pfnAsyncWrite */ 1257 static int parallelsAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite, 1236 1258 PVDIOCTX pIoCtx, 1237 1259 size_t *pcbWriteProcess, size_t *pcbPreRead, 1238 1260 size_t *pcbPostRead, unsigned fWrite) 1239 1261 { 1240 LogFlowFunc(("p vBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p\n",1241 p vBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess));1262 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p\n", 1263 pBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess)); 1242 1264 int rc = VINF_SUCCESS; 1243 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)p vBackendData;1265 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 1244 1266 uint64_t uSector; 1245 1267 uint64_t uOffsetInFile; 1246 1268 uint32_t iIndexInAllocationTable; 1247 1269 1248 Assert (pImage);1270 AssertPtr(pImage); 1249 1271 Assert(uOffset % 512 == 0); 1250 1272 Assert(cbToWrite % 512 == 0); … … 1252 1274 if (pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED) 1253 1275 { 1254 rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser, 1255 pImage->pStorage, 1256 uOffset, pIoCtx, cbToWrite, 1257 NULL, NULL); 1276 rc = parallelsFileWriteUserAsync(pImage, uOffset, pIoCtx, cbToWrite, NULL, NULL); 1258 1277 } 1259 1278 else … … 1290 1309 * Write the new block at the current end of the file. 1291 1310 */ 1292 rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser, 1293 pImage->pStorage, 1294 uOffsetInFile, pIoCtx, cbToWrite, 1295 NULL, NULL); 1311 rc = parallelsFileWriteUserAsync(pImage, uOffsetInFile, pIoCtx, cbToWrite, NULL, NULL); 1296 1312 if (RT_SUCCESS(rc) || (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)) 1297 1313 { 1298 1314 /* Write the changed allocation bitmap entry. */ 1299 1315 /** @todo: Error handling. */ 1300 rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pImage->pInterfaceIO->pvUser, 1301 pImage->pStorage, 1302 sizeof(ParallelsHeader) + iIndexInAllocationTable * sizeof(uint32_t), 1303 &pImage->pAllocationBitmap[iIndexInAllocationTable], 1304 sizeof(uint32_t), 1305 pIoCtx, 1306 NULL, NULL); 1316 rc = parallelsFileWriteMetaAsync(pImage, 1317 sizeof(ParallelsHeader) + iIndexInAllocationTable * sizeof(uint32_t), 1318 &pImage->pAllocationBitmap[iIndexInAllocationTable], 1319 sizeof(uint32_t), pIoCtx, 1320 NULL, NULL); 1307 1321 } 1308 1322 } … … 1310 1324 { 1311 1325 uOffsetInFile = (pImage->pAllocationBitmap[iIndexInAllocationTable] + uSector) * 512; 1312 rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser, 1313 pImage->pStorage, 1314 uOffsetInFile, pIoCtx, cbToWrite, 1315 NULL, NULL); 1326 rc = parallelsFileWriteUserAsync(pImage, uOffsetInFile, pIoCtx, cbToWrite, NULL, NULL); 1316 1327 } 1317 1328 } … … 1324 1335 } 1325 1336 1326 static int parallelsAsyncFlush(void *pvBackendData, PVDIOCTX pIoCtx) 1337 /** @copydoc VBOXHDDBACKEND::pfnAsyncFlush */ 1338 static int parallelsAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx) 1327 1339 { 1328 1340 int rc = VINF_SUCCESS; 1329 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)p vBackendData;1341 PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData; 1330 1342 1331 1343 LogFlowFunc(("pImage=#%p\n", pImage)); 1332 1344 1333 1345 /* Flush the file, everything is up to date already. */ 1334 rc = pImage->pInterfaceIOCallbacks->pfnFlushAsync(pImage->pInterfaceIO->pvUser, 1335 pImage->pStorage, pIoCtx, 1336 NULL, NULL); 1337 1338 LogFlowFunc(("returns %Rrc\n", rc)); 1339 return rc; 1340 } 1346 rc = parallelsFileFlushAsync(pImage, pIoCtx, NULL, NULL); 1347 1348 LogFlowFunc(("returns %Rrc\n", rc)); 1349 return rc; 1350 } 1351 1341 1352 1342 1353 VBOXHDDBACKEND g_ParallelsBackend = … … 1347 1358 sizeof(VBOXHDDBACKEND), 1348 1359 /* uBackendCaps */ 1349 VD_CAP_FILE | VD_CAP_ASYNC ,1360 VD_CAP_FILE | VD_CAP_ASYNC | VD_CAP_VFS, 1350 1361 /* papszFileExtensions */ 1351 1362 s_apszParallelsFileExtensions, … … 1413 1424 parallelsDump, 1414 1425 /* pfnGetTimeStamp */ 1415 parallelsGetTimeStamp,1426 NULL, 1416 1427 /* pfnGetParentTimeStamp */ 1417 parallelsGetParentTimeStamp,1428 NULL, 1418 1429 /* pfnSetParentTimeStamp */ 1419 parallelsSetParentTimeStamp,1430 NULL, 1420 1431 /* pfnGetParentFilename */ 1421 parallelsGetParentFilename,1432 NULL, 1422 1433 /* pfnSetParentFilename */ 1423 parallelsSetParentFilename,1434 NULL, 1424 1435 /* pfnIsAsyncIOSupported */ 1425 1436 parallelsIsAsyncIOSupported, … … 1439 1450 NULL 1440 1451 }; 1441 -
trunk/src/VBox/Devices/Storage/RawHDDCore.cpp
r31776 r32536 26 26 #include <iprt/assert.h> 27 27 #include <iprt/alloc.h> 28 #include <iprt/file.h>29 28 30 29 … … 38 37 typedef struct RAWIMAGE 39 38 { 40 /** Base image name. */39 /** Image name. */ 41 40 const char *pszFilename; 42 #ifndef VBOX_WITH_NEW_IO_CODE43 /** File descriptor. */44 RTFILE File;45 #else46 41 /** Storage handle. */ 47 42 PVDIOSTORAGE pStorage; … … 50 45 /** Async I/O interface callbacks. */ 51 46 PVDINTERFACEIO pInterfaceIOCallbacks; 52 #endif53 47 54 48 /** Pointer to the per-disk VD interface list. */ … … 69 63 uint64_t cbSize; 70 64 /** Physical geometry of this image. */ 71 PDMMEDIAGEOMETRYPCHSGeometry;65 VDGEOMETRY PCHSGeometry; 72 66 /** Logical geometry of this image. */ 73 PDMMEDIAGEOMETRYLCHSGeometry;67 VDGEOMETRY LCHSGeometry; 74 68 75 69 } RAWIMAGE, *PRAWIMAGE; … … 82 76 static const char *const s_apszRawFileExtensions[] = 83 77 { 84 /** @todo At the mo nment this backend doesn't claim any extensions, but it might78 /** @todo At the moment this backend doesn't claim any extensions, but it might 85 79 * be useful to add a few later. However this needs careful testing, as the 86 80 * CheckIfValid function never returns success. */ … … 91 85 * Internal Functions * 92 86 *******************************************************************************/ 93 94 static int rawFlushImage(PRAWIMAGE pImage);95 static void rawFreeImage(PRAWIMAGE pImage, bool fDelete);96 97 87 98 88 /** … … 111 101 } 112 102 113 static int rawFileOpen(PRAWIMAGE pImage, bool fReadonly, bool fCreate) 103 /** 104 * Internal: signal an informational message to the frontend. 105 */ 106 DECLINLINE(int) rawMessage(PRAWIMAGE pImage, const char *pszFormat, ...) 114 107 { 115 108 int rc = VINF_SUCCESS; 116 117 AssertMsg(!(fReadonly && fCreate), ("Image can't be opened readonly while being created\n")); 118 119 #ifndef VBOX_WITH_NEW_IO_CODE 120 uint32_t fOpen = fReadonly ? RTFILE_O_READ | RTFILE_O_DENY_NONE 121 : RTFILE_O_READWRITE | RTFILE_O_DENY_WRITE; 122 123 if (fCreate) 124 fOpen |= RTFILE_O_CREATE; 125 else 126 fOpen |= RTFILE_O_OPEN; 127 128 rc = RTFileOpen(&pImage->File, pImage->pszFilename, fOpen); 129 #else 130 unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0; 131 132 if (fCreate) 133 uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE; 134 135 rc = pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser, 136 pImage->pszFilename, 137 uOpenFlags, 138 &pImage->pStorage); 139 #endif 140 141 return rc; 142 } 143 144 static int rawFileClose(PRAWIMAGE pImage) 109 va_list va; 110 va_start(va, pszFormat); 111 if (pImage->pInterfaceError) 112 rc = pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, 113 pszFormat, va); 114 va_end(va); 115 return rc; 116 } 117 118 119 DECLINLINE(int) rawFileOpen(PRAWIMAGE pImage, const char *pszFilename, 120 uint32_t fOpen) 121 { 122 return pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser, 123 pszFilename, fOpen, 124 &pImage->pStorage); 125 } 126 127 DECLINLINE(int) rawFileClose(PRAWIMAGE pImage) 128 { 129 return pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser, 130 pImage->pStorage); 131 } 132 133 DECLINLINE(int) rawFileDelete(PRAWIMAGE pImage, const char *pszFilename) 134 { 135 return pImage->pInterfaceIOCallbacks->pfnDelete(pImage->pInterfaceIO->pvUser, 136 pszFilename); 137 } 138 139 DECLINLINE(int) rawFileMove(PRAWIMAGE pImage, const char *pszSrc, 140 const char *pszDst, unsigned fMove) 141 { 142 return pImage->pInterfaceIOCallbacks->pfnMove(pImage->pInterfaceIO->pvUser, 143 pszSrc, pszDst, fMove); 144 } 145 146 DECLINLINE(int) rawFileGetFreeSpace(PRAWIMAGE pImage, const char *pszFilename, 147 int64_t *pcbFree) 148 { 149 return pImage->pInterfaceIOCallbacks->pfnGetFreeSpace(pImage->pInterfaceIO->pvUser, 150 pszFilename, pcbFree); 151 } 152 153 DECLINLINE(int) rawFileGetSize(PRAWIMAGE pImage, uint64_t *pcbSize) 154 { 155 return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser, 156 pImage->pStorage, pcbSize); 157 } 158 159 DECLINLINE(int) rawFileSetSize(PRAWIMAGE pImage, uint64_t cbSize) 160 { 161 return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser, 162 pImage->pStorage, cbSize); 163 } 164 165 DECLINLINE(int) rawFileWriteSync(PRAWIMAGE pImage, uint64_t uOffset, 166 const void *pvBuffer, size_t cbBuffer, 167 size_t *pcbWritten) 168 { 169 return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser, 170 pImage->pStorage, uOffset, 171 pvBuffer, cbBuffer, pcbWritten); 172 } 173 174 DECLINLINE(int) rawFileReadSync(PRAWIMAGE pImage, uint64_t uOffset, 175 void *pvBuffer, size_t cbBuffer, size_t *pcbRead) 176 { 177 return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser, 178 pImage->pStorage, uOffset, 179 pvBuffer, cbBuffer, pcbRead); 180 } 181 182 DECLINLINE(int) rawFileFlushSync(PRAWIMAGE pImage) 183 { 184 return pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser, 185 pImage->pStorage); 186 } 187 188 DECLINLINE(int) rawFileReadUserAsync(PRAWIMAGE pImage, uint64_t uOffset, 189 PVDIOCTX pIoCtx, size_t cbRead) 190 { 191 return pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser, 192 pImage->pStorage, 193 uOffset, pIoCtx, 194 cbRead); 195 } 196 197 DECLINLINE(int) rawFileWriteUserAsync(PRAWIMAGE pImage, uint64_t uOffset, 198 PVDIOCTX pIoCtx, size_t cbWrite, 199 PFNVDXFERCOMPLETED pfnComplete, 200 void *pvCompleteUser) 201 { 202 return pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser, 203 pImage->pStorage, 204 uOffset, pIoCtx, 205 cbWrite, 206 pfnComplete, 207 pvCompleteUser); 208 } 209 210 DECLINLINE(int) rawFileFlushAsync(PRAWIMAGE pImage, PVDIOCTX pIoCtx, 211 PFNVDXFERCOMPLETED pfnComplete, 212 void *pvCompleteUser) 213 { 214 return pImage->pInterfaceIOCallbacks->pfnFlushAsync(pImage->pInterfaceIO->pvUser, 215 pImage->pStorage, 216 pIoCtx, pfnComplete, 217 pvCompleteUser); 218 } 219 220 221 /** 222 * Internal. Flush image data to disk. 223 */ 224 static int rawFlushImage(PRAWIMAGE pImage) 145 225 { 146 226 int rc = VINF_SUCCESS; 147 227 148 #ifndef VBOX_WITH_NEW_IO_CODE 149 if (pImage->File != NIL_RTFILE) 150 rc = RTFileClose(pImage->File); 151 152 pImage->File = NIL_RTFILE; 153 #else 154 if (pImage->pStorage) 155 rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser, 156 pImage->pStorage); 157 158 pImage->pStorage = NULL; 159 #endif 160 161 return rc; 162 } 163 164 static int rawFileFlushSync(PRAWIMAGE pImage) 228 if ( pImage->pStorage 229 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 230 rc = rawFileFlushSync(pImage); 231 232 return rc; 233 } 234 235 /** 236 * Internal. Free all allocated space for representing an image except pImage, 237 * and optionally delete the image from disk. 238 */ 239 static int rawFreeImage(PRAWIMAGE pImage, bool fDelete) 165 240 { 166 241 int rc = VINF_SUCCESS; 167 242 168 #ifndef VBOX_WITH_NEW_IO_CODE 169 rc = RTFileFlush(pImage->File); 170 #else 171 rc = pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser, 172 pImage->pStorage); 173 #endif 174 175 return rc; 176 } 177 178 static int rawFileGetSize(PRAWIMAGE pImage, uint64_t *pcbSize) 179 { 180 int rc = VINF_SUCCESS; 181 182 #ifndef VBOX_WITH_NEW_IO_CODE 183 rc = RTFileGetSize(pImage->File, pcbSize); 184 #else 185 rc = pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser, 186 pImage->pStorage, 187 pcbSize); 188 #endif 189 190 return rc; 191 192 } 193 194 static int rawFileSetSize(PRAWIMAGE pImage, uint64_t cbSize) 195 { 196 int rc = VINF_SUCCESS; 197 198 #ifndef VBOX_WITH_NEW_IO_CODE 199 rc = RTFileSetSize(pImage->File, cbSize); 200 #else 201 rc = pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser, 202 pImage->pStorage, 203 cbSize); 204 #endif 205 206 return rc; 207 } 208 209 210 static int rawFileWriteSync(PRAWIMAGE pImage, uint64_t off, const void *pcvBuf, size_t cbWrite, size_t *pcbWritten) 211 { 212 int rc = VINF_SUCCESS; 213 214 #ifndef VBOX_WITH_NEW_IO_CODE 215 rc = RTFileWriteAt(pImage->File, off, pcvBuf, cbWrite, pcbWritten); 216 #else 217 rc = pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser, 218 pImage->pStorage, 219 off, cbWrite, pcvBuf, 220 pcbWritten); 221 #endif 222 223 return rc; 224 } 225 226 static int rawFileReadSync(PRAWIMAGE pImage, uint64_t off, void *pvBuf, size_t cbRead, size_t *pcbRead) 227 { 228 int rc = VINF_SUCCESS; 229 230 #ifndef VBOX_WITH_NEW_IO_CODE 231 rc = RTFileReadAt(pImage->File, off, pvBuf, cbRead, pcbRead); 232 #else 233 rc = pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser, 234 pImage->pStorage, 235 off, cbRead, pvBuf, 236 pcbRead); 237 #endif 238 239 return rc; 240 } 241 242 static bool rawFileOpened(PRAWIMAGE pImage) 243 { 244 #ifndef VBOX_WITH_NEW_IO_CODE 245 return pImage->File != NIL_RTFILE; 246 #else 247 return pImage->pStorage != NULL; 248 #endif 243 /* Freeing a never allocated image (e.g. because the open failed) is 244 * not signalled as an error. After all nothing bad happens. */ 245 if (pImage) 246 { 247 if (pImage->pStorage) 248 { 249 /* No point updating the file that is deleted anyway. */ 250 if (!fDelete) 251 rawFlushImage(pImage); 252 253 rawFileClose(pImage); 254 pImage->pStorage = NULL; 255 } 256 257 if (fDelete && pImage->pszFilename) 258 rawFileDelete(pImage, pImage->pszFilename); 259 } 260 261 LogFlowFunc(("returns %Rrc\n", rc)); 262 return rc; 249 263 } 250 264 … … 256 270 int rc; 257 271 258 if (uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO)259 return VERR_NOT_SUPPORTED;260 261 272 pImage->uOpenFlags = uOpenFlags; 262 273 … … 265 276 pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError); 266 277 267 #ifdef VBOX_WITH_NEW_IO_CODE 268 /* Try to get I/O interface. */ 278 /* Get I/O interface. */ 269 279 pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IO); 270 AssertPtr (pImage->pInterfaceIO);280 AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER); 271 281 pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO); 272 AssertPtr(pImage->pInterfaceIOCallbacks); 273 #endif 282 AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER); 274 283 275 284 /* 276 285 * Open the image. 277 286 */ 278 rc = rawFileOpen(pImage, !!(uOpenFlags & VD_OPEN_FLAGS_READONLY), false); 287 rc = rawFileOpen(pImage, pImage->pszFilename, 288 VDOpenFlagsToFileOpenFlags(uOpenFlags, 289 false /* fCreate */)); 279 290 if (RT_FAILURE(rc)) 280 291 { … … 305 316 static int rawCreateImage(PRAWIMAGE pImage, uint64_t cbSize, 306 317 unsigned uImageFlags, const char *pszComment, 307 PC PDMMEDIAGEOMETRY pPCHSGeometry,308 PC PDMMEDIAGEOMETRY pLCHSGeometry,318 PCVDGEOMETRY pPCHSGeometry, 319 PCVDGEOMETRY pLCHSGeometry, unsigned uOpenFlags, 309 320 PFNVDPROGRESS pfnProgress, void *pvUser, 310 321 unsigned uPercentStart, unsigned uPercentSpan) … … 324 335 325 336 pImage->uImageFlags = uImageFlags; 337 338 pImage->uOpenFlags = uOpenFlags & ~VD_OPEN_FLAGS_READONLY; 339 340 pImage->uImageFlags = uImageFlags; 326 341 pImage->PCHSGeometry = *pPCHSGeometry; 327 342 pImage->LCHSGeometry = *pLCHSGeometry; … … 331 346 pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError); 332 347 333 #ifdef VBOX_WITH_NEW_IO_CODE 334 /* Try to get async I/O interface. */ 348 /* Get I/O interface. */ 335 349 pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IO); 336 AssertPtr (pImage->pInterfaceIO);350 AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER); 337 351 pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO); 338 AssertPtr(pImage->pInterfaceIOCallbacks); 339 #endif 352 AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER); 340 353 341 354 /* Create image file. */ 342 rc = rawFileOpen(pImage, false, true); 355 rc = rawFileOpen(pImage, pImage->pszFilename, 356 VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags, 357 true /* fCreate */)); 343 358 if (RT_FAILURE(rc)) 344 359 { … … 349 364 /* Check the free space on the disk and leave early if there is not 350 365 * sufficient space available. */ 351 rc = RTFsQuerySizes(pImage->pszFilename, NULL, &cbFree, NULL, NULL);366 rc = rawFileGetFreeSpace(pImage, pImage->pszFilename, &cbFree); 352 367 if (RT_SUCCESS(rc) /* ignore errors */ && ((uint64_t)cbFree < cbSize)) 353 368 { … … 417 432 } 418 433 419 /**420 * Internal. Free all allocated space for representing an image, and optionally421 * delete the image from disk.422 */423 static void rawFreeImage(PRAWIMAGE pImage, bool fDelete)424 {425 Assert(pImage);426 427 if (rawFileOpened(pImage))428 {429 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))430 rawFlushImage(pImage);431 rawFileClose(pImage);432 }433 if (fDelete && pImage->pszFilename)434 RTFileDelete(pImage->pszFilename);435 }436 437 /**438 * Internal. Flush image data to disk.439 */440 static int rawFlushImage(PRAWIMAGE pImage)441 {442 int rc = VINF_SUCCESS;443 444 if ( rawFileOpened(pImage)445 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))446 rc = rawFileFlushSync(pImage);447 448 return rc;449 }450 451 434 452 435 /** @copydoc VBOXHDDBACKEND::pfnCheckIfValid */ 453 static int rawCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk) 436 static int rawCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk, 437 PVDINTERFACE pVDIfsImage) 454 438 { 455 439 LogFlowFunc(("pszFilename=\"%s\"\n", pszFilename)); … … 464 448 465 449 /* Always return failure, to avoid opening everything as a raw image. */ 466 rc = VERR_ VD_RAW_INVALID_HEADER;450 rc = VERR_NOT_SUPPORTED; 467 451 468 452 out: … … 503 487 } 504 488 pImage->pszFilename = pszFilename; 505 #ifndef VBOX_WITH_NEW_IO_CODE506 pImage->File = NIL_RTFILE;507 #else508 489 pImage->pStorage = NULL; 509 #endif510 490 pImage->pVDIfsDisk = pVDIfsDisk; 511 491 pImage->pVDIfsImage = pVDIfsImage; … … 525 505 static int rawCreate(const char *pszFilename, uint64_t cbSize, 526 506 unsigned uImageFlags, const char *pszComment, 527 PCPDMMEDIAGEOMETRY pPCHSGeometry, 528 PCPDMMEDIAGEOMETRY pLCHSGeometry, PCRTUUID pUuid, 529 unsigned uOpenFlags, unsigned uPercentStart, 530 unsigned uPercentSpan, PVDINTERFACE pVDIfsDisk, 531 PVDINTERFACE pVDIfsImage, PVDINTERFACE pVDIfsOperation, 532 void **ppBackendData) 507 PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry, 508 PCRTUUID pUuid, unsigned uOpenFlags, 509 unsigned uPercentStart, unsigned uPercentSpan, 510 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage, 511 PVDINTERFACE pVDIfsOperation, void **ppBackendData) 533 512 { 534 513 LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p ppBackendData=%#p", pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppBackendData)); … … 573 552 } 574 553 pImage->pszFilename = pszFilename; 575 #ifndef VBOX_WITH_NEW_IO_CODE576 pImage->File = NIL_RTFILE;577 #else578 554 pImage->pStorage = NULL; 579 #endif580 555 pImage->pVDIfsDisk = pVDIfsDisk; 581 556 pImage->pVDIfsImage = pVDIfsImage; 582 557 583 558 rc = rawCreateImage(pImage, cbSize, uImageFlags, pszComment, 584 pPCHSGeometry, pLCHSGeometry, 559 pPCHSGeometry, pLCHSGeometry, uOpenFlags, 585 560 pfnProgress, pvUser, uPercentStart, uPercentSpan); 586 561 if (RT_SUCCESS(rc)) … … 612 587 { 613 588 LogFlowFunc(("pBackendData=%#p pszFilename=%#p\n", pBackendData, pszFilename)); 614 int rc = VERR_NOT_IMPLEMENTED; 615 589 int rc = VINF_SUCCESS; 590 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData; 591 592 /* Check arguments. */ 593 if ( !pImage 594 || !pszFilename 595 || !*pszFilename) 596 { 597 rc = VERR_INVALID_PARAMETER; 598 goto out; 599 } 600 601 /* Close the image. */ 602 rc = rawFreeImage(pImage, false); 603 if (RT_FAILURE(rc)) 604 goto out; 605 606 /* Rename the file. */ 607 rc = rawFileMove(pImage, pImage->pszFilename, pszFilename, 0); 608 if (RT_FAILURE(rc)) 609 { 610 /* The move failed, try to reopen the original image. */ 611 int rc2 = rawOpenImage(pImage, pImage->uOpenFlags); 612 if (RT_FAILURE(rc2)) 613 rc = rc2; 614 615 goto out; 616 } 617 618 /* Update pImage with the new information. */ 619 pImage->pszFilename = pszFilename; 620 621 /* Open the old image with new name. */ 622 rc = rawOpenImage(pImage, pImage->uOpenFlags); 623 if (RT_FAILURE(rc)) 624 goto out; 625 626 out: 616 627 LogFlowFunc(("returns %Rrc\n", rc)); 617 628 return rc; … … 623 634 LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete)); 624 635 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData; 625 int rc = VINF_SUCCESS; 626 627 /* Freeing a never allocated image (e.g. because the open failed) is 628 * not signalled as an error. After all nothing bad happens. */ 629 if (pImage) 630 { 631 rawFreeImage(pImage, fDelete); 632 RTMemFree(pImage); 633 } 636 int rc; 637 638 rc = rawFreeImage(pImage, fDelete); 639 RTMemFree(pImage); 634 640 635 641 LogFlowFunc(("returns %Rrc\n", rc)); … … 645 651 int rc; 646 652 647 Assert (pImage);653 AssertPtr(pImage); 648 654 Assert(uOffset % 512 == 0); 649 655 Assert(cbToRead % 512 == 0); … … 673 679 int rc; 674 680 675 Assert (pImage);681 AssertPtr(pImage); 676 682 Assert(uOffset % 512 == 0); 677 683 Assert(cbToWrite % 512 == 0); … … 717 723 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData; 718 724 719 Assert (pImage);725 AssertPtr(pImage); 720 726 721 727 if (pImage) … … 730 736 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 731 737 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData; 732 733 Assert(pImage); 734 735 if (pImage) 736 return pImage->cbSize; 737 else 738 return 0; 738 uint64_t cb = 0; 739 740 AssertPtr(pImage); 741 742 if (pImage && pImage->pStorage) 743 cb = pImage->cbSize; 744 745 LogFlowFunc(("returns %llu\n", cb)); 746 return cb; 739 747 } 740 748 … … 746 754 uint64_t cb = 0; 747 755 748 Assert (pImage);756 AssertPtr(pImage); 749 757 750 758 if (pImage) 751 759 { 752 760 uint64_t cbFile; 753 if ( rawFileOpened(pImage))761 if (pImage->pStorage) 754 762 { 755 763 int rc = rawFileGetSize(pImage, &cbFile); … … 765 773 /** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */ 766 774 static int rawGetPCHSGeometry(void *pBackendData, 767 P PDMMEDIAGEOMETRY pPCHSGeometry)775 PVDGEOMETRY pPCHSGeometry) 768 776 { 769 777 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry)); … … 771 779 int rc; 772 780 773 Assert (pImage);781 AssertPtr(pImage); 774 782 775 783 if (pImage) … … 792 800 /** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */ 793 801 static int rawSetPCHSGeometry(void *pBackendData, 794 PC PDMMEDIAGEOMETRY pPCHSGeometry)802 PCVDGEOMETRY pPCHSGeometry) 795 803 { 796 804 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); … … 798 806 int rc; 799 807 800 Assert (pImage);808 AssertPtr(pImage); 801 809 802 810 if (pImage) … … 821 829 /** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */ 822 830 static int rawGetLCHSGeometry(void *pBackendData, 823 P PDMMEDIAGEOMETRY pLCHSGeometry)831 PVDGEOMETRY pLCHSGeometry) 824 832 { 825 833 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry)); … … 827 835 int rc; 828 836 829 Assert (pImage);837 AssertPtr(pImage); 830 838 831 839 if (pImage) … … 848 856 /** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */ 849 857 static int rawSetLCHSGeometry(void *pBackendData, 850 PC PDMMEDIAGEOMETRY pLCHSGeometry)858 PCVDGEOMETRY pLCHSGeometry) 851 859 { 852 860 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); … … 854 862 int rc; 855 863 856 Assert (pImage);864 AssertPtr(pImage); 857 865 858 866 if (pImage) … … 882 890 unsigned uImageFlags; 883 891 884 Assert (pImage);892 AssertPtr(pImage); 885 893 886 894 if (pImage) … … 900 908 unsigned uOpenFlags; 901 909 902 Assert (pImage);910 AssertPtr(pImage); 903 911 904 912 if (pImage) … … 920 928 /* Image must be opened and the new flags must be valid. Just readonly and 921 929 * info flags are supported. */ 922 if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO )))930 if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE))) 923 931 { 924 932 rc = VERR_INVALID_PARAMETER; … … 927 935 928 936 /* Implement this operation via reopening the image. */ 929 rawFreeImage(pImage, false); 937 rc = rawFreeImage(pImage, false); 938 if (RT_FAILURE(rc)) 939 goto out; 930 940 rc = rawOpenImage(pImage, uOpenFlags); 931 941 … … 943 953 int rc; 944 954 945 Assert(pImage); 946 947 if (pImage) 948 { 949 if (pszComment) 950 *pszComment = '\0'; 951 rc = VINF_SUCCESS; 952 } 955 AssertPtr(pImage); 956 957 if (pImage) 958 rc = VERR_NOT_SUPPORTED; 953 959 else 954 960 rc = VERR_VD_NOT_OPENED; … … 965 971 int rc; 966 972 967 Assert (pImage);973 AssertPtr(pImage); 968 974 969 975 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) … … 990 996 int rc; 991 997 992 Assert (pImage);998 AssertPtr(pImage); 993 999 994 1000 if (pImage) … … 1009 1015 1010 1016 LogFlowFunc(("%RTuuid\n", pUuid)); 1011 Assert (pImage);1017 AssertPtr(pImage); 1012 1018 1013 1019 if (pImage) … … 1032 1038 int rc; 1033 1039 1034 Assert (pImage);1040 AssertPtr(pImage); 1035 1041 1036 1042 if (pImage) … … 1050 1056 int rc; 1051 1057 1052 Assert (pImage);1058 AssertPtr(pImage); 1053 1059 1054 1060 if (pImage) … … 1073 1079 int rc; 1074 1080 1075 Assert (pImage);1081 AssertPtr(pImage); 1076 1082 1077 1083 if (pImage) … … 1091 1097 int rc; 1092 1098 1093 Assert (pImage);1099 AssertPtr(pImage); 1094 1100 1095 1101 if (pImage) … … 1114 1120 int rc; 1115 1121 1116 Assert (pImage);1122 AssertPtr(pImage); 1117 1123 1118 1124 if (pImage) … … 1132 1138 int rc; 1133 1139 1134 Assert (pImage);1140 AssertPtr(pImage); 1135 1141 1136 1142 if (pImage) … … 1153 1159 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData; 1154 1160 1155 Assert (pImage);1156 if (pImage) 1157 { 1158 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",1161 AssertPtr(pImage); 1162 if (pImage) 1163 { 1164 rawMessage(pImage, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n", 1159 1165 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors, 1160 1166 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors, … … 1163 1169 } 1164 1170 1165 static int rawGetTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp) 1166 { 1167 int rc = VERR_NOT_IMPLEMENTED; 1168 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc)); 1169 return rc; 1170 } 1171 1172 static int rawGetParentTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp) 1173 { 1174 int rc = VERR_NOT_IMPLEMENTED; 1175 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc)); 1176 return rc; 1177 } 1178 1179 static int rawSetParentTimeStamp(void *pvBackendData, PCRTTIMESPEC pTimeStamp) 1180 { 1181 int rc = VERR_NOT_IMPLEMENTED; 1182 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc)); 1183 return rc; 1184 } 1185 1186 static int rawGetParentFilename(void *pvBackendData, char **ppszParentFilename) 1187 { 1188 int rc = VERR_NOT_IMPLEMENTED; 1189 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc)); 1190 return rc; 1191 } 1192 1193 static int rawSetParentFilename(void *pvBackendData, const char *pszParentFilename) 1194 { 1195 int rc = VERR_NOT_IMPLEMENTED; 1196 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc)); 1197 return rc; 1198 } 1199 1200 static bool rawIsAsyncIOSupported(void *pvBackendData) 1171 /** @copydoc VBOXHDDBACKEND::pfnIsAsyncIOSupported */ 1172 static bool rawIsAsyncIOSupported(void *pBackendData) 1201 1173 { 1202 1174 return true; 1203 1175 } 1204 1176 1205 static int rawAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbRead, 1177 /** @copydoc VBOXHDDBACKEND::pfnAsyncRead */ 1178 static int rawAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbRead, 1206 1179 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 1207 1180 { 1208 1181 int rc = VINF_SUCCESS; 1209 PRAWIMAGE pImage = (PRAWIMAGE)pvBackendData; 1210 1211 rc = pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser, 1212 pImage->pStorage, 1213 uOffset, pIoCtx, cbRead); 1182 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData; 1183 1184 rc = rawFileReadUserAsync(pImage, uOffset, pIoCtx, cbRead); 1214 1185 if (RT_SUCCESS(rc)) 1215 1186 *pcbActuallyRead = cbRead; … … 1218 1189 } 1219 1190 1220 static int rawAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbWrite, 1191 /** @copydoc VBOXHDDBACKEND::pfnAsyncWrite */ 1192 static int rawAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbWrite, 1221 1193 PVDIOCTX pIoCtx, 1222 1194 size_t *pcbWriteProcess, size_t *pcbPreRead, … … 1224 1196 { 1225 1197 int rc = VINF_SUCCESS; 1226 PRAWIMAGE pImage = (PRAWIMAGE)pvBackendData; 1227 1228 rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser, 1229 pImage->pStorage, 1230 uOffset, pIoCtx, cbWrite, 1231 NULL, NULL); 1232 1198 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData; 1199 1200 rc = rawFileWriteUserAsync(pImage, uOffset, pIoCtx, cbWrite, NULL, NULL); 1233 1201 if (RT_SUCCESS(rc)) 1234 1202 { … … 1241 1209 } 1242 1210 1243 static int rawAsyncFlush(void *pvBackendData, PVDIOCTX pIoCtx) 1244 { 1245 int rc = VERR_NOT_IMPLEMENTED; 1246 LogFlowFunc(("returns %Rrc\n", rc)); 1247 return rc; 1248 } 1211 /** @copydoc VBOXHDDBACKEND::pfnAsyncFlush */ 1212 static int rawAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx) 1213 { 1214 int rc = VINF_SUCCESS; 1215 PRAWIMAGE pImage = (PRAWIMAGE)pBackendData; 1216 1217 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 1218 rc = rawFileFlushAsync(pImage, pIoCtx, NULL, NULL); 1219 1220 return rc; 1221 } 1222 1249 1223 1250 1224 VBOXHDDBACKEND g_RawBackend = … … 1255 1229 sizeof(VBOXHDDBACKEND), 1256 1230 /* uBackendCaps */ 1257 VD_CAP_CREATE_FIXED | VD_CAP_FILE | VD_CAP_ASYNC ,1231 VD_CAP_CREATE_FIXED | VD_CAP_FILE | VD_CAP_ASYNC | VD_CAP_VFS, 1258 1232 /* papszFileExtensions */ 1259 1233 s_apszRawFileExtensions, … … 1321 1295 rawDump, 1322 1296 /* pfnGetTimeStamp */ 1323 rawGetTimeStamp,1297 NULL, 1324 1298 /* pfnGetParentTimeStamp */ 1325 rawGetParentTimeStamp,1299 NULL, 1326 1300 /* pfnSetParentTimeStamp */ 1327 rawSetParentTimeStamp,1301 NULL, 1328 1302 /* pfnGetParentFilename */ 1329 rawGetParentFilename,1303 NULL, 1330 1304 /* pfnSetParentFilename */ 1331 rawSetParentFilename,1305 NULL, 1332 1306 /* pfnIsAsyncIOSupported */ 1333 1307 rawIsAsyncIOSupported, … … 1347 1321 NULL 1348 1322 }; 1349 -
trunk/src/VBox/Devices/Storage/VBoxHDD.cpp
r32520 r32536 77 77 char *pszFilename; 78 78 /** Data managed by the backend which keeps the actual info. */ 79 void *p vBackendData;79 void *pBackendData; 80 80 /** Cached sanitized image flags. */ 81 81 unsigned uImageFlags; … … 110 110 char *pszFilename; 111 111 /** Data managed by the backend which keeps the actual info. */ 112 void *p vBackendData;112 void *pBackendData; 113 113 /** Cached sanitized image flags. */ 114 114 unsigned uImageFlags; … … 151 151 uint64_t cbSize; 152 152 /** Cached PCHS geometry for this disk. */ 153 PDMMEDIAGEOMETRYPCHSGeometry;153 VDGEOMETRY PCHSGeometry; 154 154 /** Cached LCHS geometry for this disk. */ 155 PDMMEDIAGEOMETRYLCHSGeometry;155 VDGEOMETRY LCHSGeometry; 156 156 157 157 /** Pointer to list of VD interfaces, per-disk. */ … … 167 167 PVDINTERFACETHREADSYNC pInterfaceThreadSyncCallbacks; 168 168 169 /** I/O interface for the disk. */ 170 VDINTERFACE VDIIO; 171 /** I/O interface callback table for the images. */ 169 /** I/O interface callback table for the images (self-provided default 170 * implementation supporting both sync and async file operations). */ 172 171 VDINTERFACEIO VDIIOCallbacks; 173 172 … … 707 706 AssertPtr(pcbRead); 708 707 709 rc = pCache->Backend->pfnRead(pCache->p vBackendData, uOffset, pvBuf,708 rc = pCache->Backend->pfnRead(pCache->pBackendData, uOffset, pvBuf, 710 709 cbRead, pcbRead); 711 710 … … 737 736 738 737 if (pcbWritten) 739 rc = pCache->Backend->pfnWrite(pCache->p vBackendData, uOffset, pcvBuf,738 rc = pCache->Backend->pfnWrite(pCache->pBackendData, uOffset, pcvBuf, 740 739 cbWrite, pcbWritten); 741 740 else … … 745 744 do 746 745 { 747 rc = pCache->Backend->pfnWrite(pCache->p vBackendData, uOffset, pcvBuf,746 rc = pCache->Backend->pfnWrite(pCache->pBackendData, uOffset, pcvBuf, 748 747 cbWrite, &cbWritten); 749 748 uOffset += cbWritten; … … 776 775 * If the block is not allocated read from override chain if present. 777 776 */ 778 rc = pImage->Backend->pfnRead(pImage->p vBackendData,777 rc = pImage->Backend->pfnRead(pImage->pBackendData, 779 778 uOffset, pvBuf, cbThisRead, 780 779 &cbThisRead); … … 786 785 pCurrImage = pCurrImage->pPrev) 787 786 { 788 rc = pCurrImage->Backend->pfnRead(pCurrImage->p vBackendData,787 rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData, 789 788 uOffset, pvBuf, cbThisRead, 790 789 &cbThisRead); … … 848 847 * If the block is not allocated read from override chain if present. 849 848 */ 850 rc = pImage->Backend->pfnRead(pImage->p vBackendData,849 rc = pImage->Backend->pfnRead(pImage->pBackendData, 851 850 uOffset, pvBuf, cbThisRead, 852 851 &cbThisRead); … … 858 857 pCurrImage = pCurrImage->pPrev) 859 858 { 860 rc = pCurrImage->Backend->pfnRead(pCurrImage->p vBackendData,859 rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData, 861 860 uOffset, pvBuf, cbThisRead, 862 861 &cbThisRead); … … 1198 1197 * If the block is not allocated read from override chain if present. 1199 1198 */ 1200 rc = pCurrImage->Backend->pfnAsyncRead(pCurrImage->p vBackendData,1199 rc = pCurrImage->Backend->pfnAsyncRead(pCurrImage->pBackendData, 1201 1200 uOffset, cbThisRead, 1202 1201 pIoCtx, &cbThisRead); … … 1208 1207 pCurrImage = pCurrImage->pPrev) 1209 1208 { 1210 rc = pCurrImage->Backend->pfnAsyncRead(pCurrImage->p vBackendData,1209 rc = pCurrImage->Backend->pfnAsyncRead(pCurrImage->pBackendData, 1211 1210 uOffset, cbThisRead, 1212 1211 pIoCtx, &cbThisRead); … … 1275 1274 1276 1275 RTUuidCreate(&Uuid); 1277 pDisk->pLast->Backend->pfnSetModificationUuid(pDisk->pLast->p vBackendData,1276 pDisk->pLast->Backend->pfnSetModificationUuid(pDisk->pLast->pBackendData, 1278 1277 &Uuid); 1279 1278 1280 1279 if (pDisk->pCache) 1281 pDisk->pCache->Backend->pfnSetModificationUuid(pDisk->pCache->p vBackendData,1280 pDisk->pCache->Backend->pfnSetModificationUuid(pDisk->pCache->pBackendData, 1282 1281 &Uuid); 1283 1282 } … … 1301 1300 1302 1301 if (!(pDisk->uModified & VD_IMAGE_MODIFIED_DISABLE_UUID_UPDATE)) 1303 pDisk->pLast->Backend->pfnFlush(pDisk->pLast->p vBackendData);1302 pDisk->pLast->Backend->pfnFlush(pDisk->pLast->pBackendData); 1304 1303 } 1305 1304 } … … 1379 1378 1380 1379 /* Write the full block to the virtual disk. */ 1381 rc = pImage->Backend->pfnWrite(pImage->p vBackendData,1380 rc = pImage->Backend->pfnWrite(pImage->pBackendData, 1382 1381 uOffset - cbPreRead, pvTmp, 1383 1382 cbPreRead + cbThisWrite + cbPostRead, … … 1461 1460 1462 1461 /* Write the full block to the virtual disk. */ 1463 rc = pImage->Backend->pfnWrite(pImage->p vBackendData,1462 rc = pImage->Backend->pfnWrite(pImage->pBackendData, 1464 1463 uOffset - cbPreRead, pvTmp, 1465 1464 cbPreRead + cbThisWrite + cbPostRead, … … 1500 1499 fWrite = (pImage->uOpenFlags & VD_OPEN_FLAGS_HONOR_SAME) 1501 1500 ? 0 : VD_WRITE_NO_ALLOC; 1502 rc = pImage->Backend->pfnWrite(pImage->p vBackendData, uOffsetCur, pcvBufCur,1501 rc = pImage->Backend->pfnWrite(pImage->pBackendData, uOffsetCur, pcvBufCur, 1503 1502 cbThisWrite, &cbThisWrite, &cbPreRead, 1504 1503 &cbPostRead, fWrite); … … 1619 1618 /* Write the full block to the virtual disk. */ 1620 1619 vdIoCtxChildReset(pIoCtxDst); 1621 rc = pImage->Backend->pfnAsyncWrite(pImage->p vBackendData,1620 rc = pImage->Backend->pfnAsyncWrite(pImage->pBackendData, 1622 1621 uOffset - cbPreRead, 1623 1622 cbPreRead + cbThisWrite + cbPostRead, … … 1714 1713 /* Write the full block to the virtual disk. */ 1715 1714 RTSgBufReset(&pIoCtx->SgBuf); 1716 rc = pImage->Backend->pfnAsyncWrite(pImage->p vBackendData,1715 rc = pImage->Backend->pfnAsyncWrite(pImage->pBackendData, 1717 1716 pIoCtx->uOffset - cbPreRead, 1718 1717 cbPreRead + cbThisWrite + cbPostRead, … … 1833 1832 fWrite = (pImage->uOpenFlags & VD_OPEN_FLAGS_HONOR_SAME) 1834 1833 ? 0 : VD_WRITE_NO_ALLOC; 1835 rc = pImage->Backend->pfnAsyncWrite(pImage->p vBackendData, uOffset,1834 rc = pImage->Backend->pfnAsyncWrite(pImage->pBackendData, uOffset, 1836 1835 cbThisWrite, pIoCtx, 1837 1836 &cbThisWrite, &cbPreRead, … … 1970 1969 1971 1970 vdResetModifiedFlag(pDisk); 1972 rc = pImage->Backend->pfnAsyncFlush(pImage->p vBackendData, pIoCtx);1971 rc = pImage->Backend->pfnAsyncFlush(pImage->pBackendData, pIoCtx); 1973 1972 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 1974 1973 rc = VINF_SUCCESS; … … 2221 2220 * VD async I/O interface open callback. 2222 2221 */ 2223 static int vdAsyncIOOpen(void *pvUser, const char *pszLocation, u nsigned uOpenFlags,2222 static int vdAsyncIOOpen(void *pvUser, const char *pszLocation, uint32_t fOpen, 2224 2223 PFNVDCOMPLETED pfnCompleted, PVDINTERFACE pVDIfsDisk, 2225 2224 void **ppStorage) … … 2231 2230 2232 2231 pStorage->pfnCompleted = pfnCompleted; 2233 2234 uint32_t fOpen = 0;2235 2236 if (uOpenFlags & VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY)2237 fOpen |= RTFILE_O_READ | RTFILE_O_DENY_NONE;2238 else2239 {2240 fOpen |= RTFILE_O_READWRITE;2241 2242 if (uOpenFlags & VD_INTERFACEASYNCIO_OPEN_FLAGS_DONT_LOCK)2243 fOpen |= RTFILE_O_DENY_NONE;2244 else2245 fOpen |= RTFILE_O_DENY_WRITE;2246 }2247 2248 if (uOpenFlags & VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE)2249 fOpen |= RTFILE_O_CREATE;2250 else2251 fOpen |= RTFILE_O_OPEN;2252 2232 2253 2233 /* Open the file. */ … … 2299 2279 */ 2300 2280 static int vdAsyncIOWriteSync(void *pvUser, void *pvStorage, uint64_t uOffset, 2301 size_t cbWrite, const void *pvBuf, size_t *pcbWritten)2281 const void *pvBuf, size_t cbWrite, size_t *pcbWritten) 2302 2282 { 2303 2283 PVDIASYNCIOSTORAGE pStorage = (PVDIASYNCIOSTORAGE)pvStorage; … … 2310 2290 */ 2311 2291 static int vdAsyncIOReadSync(void *pvUser, void *pvStorage, uint64_t uOffset, 2312 size_t cbRead, void *pvBuf, size_t *pcbRead)2292 void *pvBuf, size_t cbRead, size_t *pcbRead) 2313 2293 { 2314 2294 PVDIASYNCIOSTORAGE pStorage = (PVDIASYNCIOSTORAGE)pvStorage; … … 2513 2493 { 2514 2494 RTCritSectEnter(&pDisk->CritSect); 2515 rc = pfnComplete(pIoStorage->pImage->p vBackendData, pIoCtx, pvUser, rcReq);2495 rc = pfnComplete(pIoStorage->pImage->pBackendData, pIoCtx, pvUser, rcReq); 2516 2496 RTCritSectLeave(&pDisk->CritSect); 2517 2497 } … … 2579 2559 { 2580 2560 RTCritSectEnter(&pDisk->CritSect); 2581 rc = pfnComplete(pIoStorage->pImage->p vBackendData, pIoCtx, pvUser, rcReq);2561 rc = pfnComplete(pIoStorage->pImage->pBackendData, pIoCtx, pvUser, rcReq); 2582 2562 RTCritSectLeave(&pDisk->CritSect); 2583 2563 } … … 2697 2677 } 2698 2678 2679 static int vdIODelete(void *pvUser, const char *pcszFilename) 2680 { 2681 return RTFileDelete(pcszFilename); 2682 } 2683 2684 static int vdIOMove(void *pvUser, const char *pcszSrc, const char *pcszDst, unsigned fMove) 2685 { 2686 return RTFileMove(pcszSrc, pcszDst, fMove); 2687 } 2688 2689 static int vdIOGetFreeSpace(void *pvUser, const char *pcszFilename, int64_t *pcbFreeSpace) 2690 { 2691 return RTFsQuerySizes(pcszFilename, NULL, pcbFreeSpace, NULL, NULL); 2692 } 2693 2694 static int vdIOGetModificationTime(void *pvUser, const char *pcszFilename, PRTTIMESPEC pModificationTime) 2695 { 2696 RTFSOBJINFO info; 2697 int rc = RTPathQueryInfo(pcszFilename, &info, RTFSOBJATTRADD_NOTHING); 2698 if (RT_SUCCESS(rc)) 2699 *pModificationTime = info.ModificationTime; 2700 return rc; 2701 } 2702 2699 2703 static int vdIOGetSize(void *pvUser, PVDIOSTORAGE pIoStorage, 2700 2704 uint64_t *pcbSize) … … 2720 2724 2721 2725 static int vdIOWriteSync(void *pvUser, PVDIOSTORAGE pIoStorage, uint64_t uOffset, 2722 size_t cbWrite, const void *pvBuf, size_t *pcbWritten)2726 const void *pvBuf, size_t cbWrite, size_t *pcbWritten) 2723 2727 { 2724 2728 PVDIMAGE pImage = (PVDIMAGE)pvUser; … … 2727 2731 return pDisk->pInterfaceAsyncIOCallbacks->pfnWriteSync(pDisk->pInterfaceAsyncIO->pvUser, 2728 2732 pIoStorage->u.pStorage, 2729 uOffset, cbWrite, pvBuf,2733 uOffset, pvBuf, cbWrite, 2730 2734 pcbWritten); 2731 2735 } 2732 2736 2733 2737 static int vdIOReadSync(void *pvUser, PVDIOSTORAGE pIoStorage, uint64_t uOffset, 2734 size_t cbRead, void *pvBuf, size_t *pcbRead)2738 void *pvBuf, size_t cbRead, size_t *pcbRead) 2735 2739 { 2736 2740 PVDIMAGE pImage = (PVDIMAGE)pvUser; … … 2739 2743 return pDisk->pInterfaceAsyncIOCallbacks->pfnReadSync(pDisk->pInterfaceAsyncIO->pvUser, 2740 2744 pIoStorage->u.pStorage, 2741 uOffset, cbRead, pvBuf,2745 uOffset, pvBuf, cbRead, 2742 2746 pcbRead); 2743 2747 } … … 3247 3251 */ 3248 3252 static int vdIOOpenLimited(void *pvUser, const char *pszLocation, 3249 u nsigned uOpenFlags, PPVDIOSTORAGE ppIoStorage)3253 uint32_t fOpen, PPVDIOSTORAGE ppIoStorage) 3250 3254 { 3251 3255 int rc = VINF_SUCCESS; … … 3254 3258 if (!pIoStorage) 3255 3259 return VERR_NO_MEMORY; 3256 3257 uint32_t fOpen = 0;3258 3259 if (uOpenFlags & VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY)3260 fOpen |= RTFILE_O_READ | RTFILE_O_DENY_NONE;3261 else3262 fOpen |= RTFILE_O_READWRITE | RTFILE_O_DENY_WRITE;3263 3264 if (uOpenFlags & VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE)3265 fOpen |= RTFILE_O_CREATE;3266 else3267 fOpen |= RTFILE_O_OPEN;3268 3260 3269 3261 rc = RTFileOpen(&pIoStorage->u.hFile, pszLocation, fOpen); … … 3285 3277 } 3286 3278 3279 static int vdIODeleteLimited(void *pvUser, const char *pcszFilename) 3280 { 3281 return RTFileDelete(pcszFilename); 3282 } 3283 3284 static int vdIOMoveLimited(void *pvUser, const char *pcszSrc, const char *pcszDst, unsigned fMove) 3285 { 3286 return RTFileMove(pcszSrc, pcszDst, fMove); 3287 } 3288 3289 static int vdIOGetFreeSpaceLimited(void *pvUser, const char *pcszFilename, int64_t *pcbFreeSpace) 3290 { 3291 return RTFsQuerySizes(pcszFilename, NULL, pcbFreeSpace, NULL, NULL); 3292 } 3293 3294 static int vdIOGetModificationTimeLimited(void *pvUser, const char *pcszFilename, PRTTIMESPEC pModificationTime) 3295 { 3296 RTFSOBJINFO info; 3297 int rc = RTPathQueryInfo(pcszFilename, &info, RTFSOBJATTRADD_NOTHING); 3298 if (RT_SUCCESS(rc)) 3299 *pModificationTime = info.ModificationTime; 3300 return rc; 3301 } 3302 3287 3303 static int vdIOGetSizeLimited(void *pvUser, PVDIOSTORAGE pIoStorage, 3288 3304 uint64_t *pcbSize) … … 3298 3314 3299 3315 static int vdIOWriteSyncLimited(void *pvUser, PVDIOSTORAGE pIoStorage, uint64_t uOffset, 3300 size_t cbWrite, const void *pvBuf, size_t *pcbWritten)3316 const void *pvBuf, size_t cbWrite, size_t *pcbWritten) 3301 3317 { 3302 3318 return RTFileWriteAt(pIoStorage->u.hFile, uOffset, pvBuf, cbWrite, pcbWritten); … … 3304 3320 3305 3321 static int vdIOReadSyncLimited(void *pvUser, PVDIOSTORAGE pIoStorage, uint64_t uOffset, 3306 size_t cbRead, void *pvBuf, size_t *pcbRead)3322 void *pvBuf, size_t cbRead, size_t *pcbRead) 3307 3323 { 3308 3324 return RTFileReadAt(pIoStorage->u.hFile, uOffset, pvBuf, cbRead, pcbRead); … … 3318 3334 * internal: send output to the log (unconditionally). 3319 3335 */ 3320 int vdLogMessage(void *pvUser, const char *pszFormat, ...)3336 int vdLogMessage(void *pvUser, const char *pszFormat, va_list args) 3321 3337 { 3322 3338 NOREF(pvUser); 3323 va_list args; 3324 va_start(args, pszFormat); 3325 RTLogPrintf(pszFormat, args); 3326 va_end(args); 3339 RTLogPrintfV(pszFormat, args); 3327 3340 return VINF_SUCCESS; 3341 } 3342 3343 DECLINLINE(int) vdMessageWrapper(PVBOXHDD pDisk, const char *pszFormat, ...) 3344 { 3345 va_list va; 3346 va_start(va, pszFormat); 3347 int rc = pDisk->pInterfaceErrorCallbacks->pfnMessage(pDisk->pInterfaceError->pvUser, 3348 pszFormat, va); 3349 va_end(va); 3350 return rc; 3328 3351 } 3329 3352 … … 3592 3615 pDisk->VDIIOCallbacks.pfnOpen = vdIOOpen; 3593 3616 pDisk->VDIIOCallbacks.pfnClose = vdIOClose; 3617 pDisk->VDIIOCallbacks.pfnDelete = vdIODelete; 3618 pDisk->VDIIOCallbacks.pfnMove = vdIOMove; 3619 pDisk->VDIIOCallbacks.pfnGetFreeSpace = vdIOGetFreeSpace; 3620 pDisk->VDIIOCallbacks.pfnGetModificationTime = vdIOGetModificationTime; 3594 3621 pDisk->VDIIOCallbacks.pfnGetSize = vdIOGetSize; 3595 3622 pDisk->VDIIOCallbacks.pfnSetSize = vdIOSetSize; … … 3652 3679 * VERR_NOT_SUPPORTED if no backend was found. 3653 3680 * @param pVDIfsDisk Pointer to the per-disk VD interface list. 3681 * @param pVDIfsImage Pointer to the per-image VD interface list. 3654 3682 * @param pszFilename Name of the image file for which the backend is queried. 3655 3683 * @param ppszFormat Receives pointer of the UTF-8 string which contains the format name. 3656 3684 * The returned pointer must be freed using RTStrFree(). 3657 3685 */ 3658 VBOXDDU_DECL(int) VDGetFormat(PVDINTERFACE pVDIfsDisk, const char *pszFilename, char **ppszFormat) 3686 VBOXDDU_DECL(int) VDGetFormat(PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage, 3687 const char *pszFilename, char **ppszFormat) 3659 3688 { 3660 3689 int rc = VERR_NOT_SUPPORTED; … … 3674 3703 VDInit(); 3675 3704 3676 VDIIOCallbacks.cbSize = sizeof(VDINTERFACEIO); 3677 VDIIOCallbacks.enmInterface = VDINTERFACETYPE_IO; 3678 VDIIOCallbacks.pfnOpen = vdIOOpenLimited; 3679 VDIIOCallbacks.pfnClose = vdIOCloseLimited; 3680 VDIIOCallbacks.pfnGetSize = vdIOGetSizeLimited; 3681 VDIIOCallbacks.pfnSetSize = vdIOSetSizeLimited; 3682 VDIIOCallbacks.pfnReadSync = vdIOReadSyncLimited; 3683 VDIIOCallbacks.pfnWriteSync = vdIOWriteSyncLimited; 3684 VDIIOCallbacks.pfnFlushSync = vdIOFlushSyncLimited; 3685 VDIIOCallbacks.pfnReadUserAsync = NULL; 3686 VDIIOCallbacks.pfnWriteUserAsync = NULL; 3687 VDIIOCallbacks.pfnReadMetaAsync = NULL; 3688 VDIIOCallbacks.pfnWriteMetaAsync = NULL; 3689 VDIIOCallbacks.pfnFlushAsync = NULL; 3690 rc = VDInterfaceAdd(&VDIIO, "VD_IO", VDINTERFACETYPE_IO, 3691 &VDIIOCallbacks, NULL, &pVDIfsDisk); 3692 AssertRC(rc); 3705 if (!VDInterfaceGet(pVDIfsImage, VDINTERFACETYPE_IO)) 3706 { 3707 VDIIOCallbacks.cbSize = sizeof(VDINTERFACEIO); 3708 VDIIOCallbacks.enmInterface = VDINTERFACETYPE_IO; 3709 VDIIOCallbacks.pfnOpen = vdIOOpenLimited; 3710 VDIIOCallbacks.pfnClose = vdIOCloseLimited; 3711 VDIIOCallbacks.pfnDelete = vdIODeleteLimited; 3712 VDIIOCallbacks.pfnMove = vdIOMoveLimited; 3713 VDIIOCallbacks.pfnGetFreeSpace = vdIOGetFreeSpaceLimited; 3714 VDIIOCallbacks.pfnGetModificationTime = vdIOGetModificationTimeLimited; 3715 VDIIOCallbacks.pfnGetSize = vdIOGetSizeLimited; 3716 VDIIOCallbacks.pfnSetSize = vdIOSetSizeLimited; 3717 VDIIOCallbacks.pfnReadSync = vdIOReadSyncLimited; 3718 VDIIOCallbacks.pfnWriteSync = vdIOWriteSyncLimited; 3719 VDIIOCallbacks.pfnFlushSync = vdIOFlushSyncLimited; 3720 VDIIOCallbacks.pfnReadUserAsync = NULL; 3721 VDIIOCallbacks.pfnWriteUserAsync = NULL; 3722 VDIIOCallbacks.pfnReadMetaAsync = NULL; 3723 VDIIOCallbacks.pfnWriteMetaAsync = NULL; 3724 VDIIOCallbacks.pfnFlushAsync = NULL; 3725 rc = VDInterfaceAdd(&VDIIO, "VD_IO", VDINTERFACETYPE_IO, 3726 &VDIIOCallbacks, NULL, &pVDIfsImage); 3727 AssertRC(rc); 3728 } 3693 3729 3694 3730 /* Find the backend supporting this file format. */ … … 3697 3733 if (g_apBackends[i]->pfnCheckIfValid) 3698 3734 { 3699 rc = g_apBackends[i]->pfnCheckIfValid(pszFilename, pVDIfsDisk); 3735 rc = g_apBackends[i]->pfnCheckIfValid(pszFilename, pVDIfsDisk, 3736 pVDIfsImage); 3700 3737 if ( RT_SUCCESS(rc) 3701 3738 /* The correct backend has been found, but there is a small … … 3708 3745 && rc != VERR_VD_ISCSI_INVALID_HEADER 3709 3746 && rc != VERR_VD_VHD_INVALID_HEADER 3710 && rc != VERR_VD_RAW_INVALID_HEADER)) 3747 && rc != VERR_VD_RAW_INVALID_HEADER 3748 && rc != VERR_VD_DMG_INVALID_HEADER)) 3711 3749 { 3712 3750 /* Copy the name into the new string. */ … … 3732 3770 if (g_apCacheBackends[i]->pfnProbe) 3733 3771 { 3734 rc = g_apCacheBackends[i]->pfnProbe(pszFilename, pVDIfsDisk); 3772 rc = g_apCacheBackends[i]->pfnProbe(pszFilename, pVDIfsDisk, 3773 pVDIfsImage); 3735 3774 if ( RT_SUCCESS(rc) 3736 3775 || (rc != VERR_VD_GEN_INVALID_HEADER)) … … 3832 3871 } 3833 3872 3834 /* Set up the I/O interface. */ 3835 rc = VDInterfaceAdd(&pImage->VDIIO, "VD_IO", VDINTERFACETYPE_IO, 3836 &pDisk->VDIIOCallbacks, pImage, &pImage->pVDIfsImage); 3837 AssertRC(rc); 3873 /* Set up the I/O interface if necessary. */ 3874 if (!VDInterfaceGet(pVDIfsImage, VDINTERFACETYPE_IO)) 3875 { 3876 rc = VDInterfaceAdd(&pImage->VDIIO, "VD_IO", VDINTERFACETYPE_IO, 3877 &pDisk->VDIIOCallbacks, pImage, 3878 &pImage->pVDIfsImage); 3879 AssertRC(rc); 3880 } 3838 3881 3839 3882 pImage->uOpenFlags = uOpenFlags & VD_OPEN_FLAGS_HONOR_SAME; … … 3842 3885 pDisk->pVDIfsDisk, 3843 3886 pImage->pVDIfsImage, 3844 &pImage->p vBackendData);3887 &pImage->pBackendData); 3845 3888 /* If the open in read-write mode failed, retry in read-only mode. */ 3846 3889 if (RT_FAILURE(rc)) … … 3857 3900 pDisk->pVDIfsDisk, 3858 3901 pImage->pVDIfsImage, 3859 &pImage->p vBackendData);3902 &pImage->pBackendData); 3860 3903 if (RT_FAILURE(rc)) 3861 3904 { … … 3877 3920 * and diff images, so this must be corrected here. */ 3878 3921 unsigned uImageFlags; 3879 uImageFlags = pImage->Backend->pfnGetImageFlags(pImage->p vBackendData);3922 uImageFlags = pImage->Backend->pfnGetImageFlags(pImage->pBackendData); 3880 3923 if (RT_FAILURE(rc)) 3881 3924 uImageFlags = VD_IMAGE_FLAGS_NONE; … … 3906 3949 RTUUID parentUuid; 3907 3950 RTUuidClear(&parentUuid); 3908 rc2 = pImage->Backend->pfnGetParentUuid(pImage->p vBackendData, &parentUuid);3951 rc2 = pImage->Backend->pfnGetParentUuid(pImage->pBackendData, &parentUuid); 3909 3952 if (RT_SUCCESS(rc2) && !RTUuidIsNull(&parentUuid)) 3910 3953 uImageFlags |= VD_IMAGE_FLAGS_DIFF; … … 3920 3963 3921 3964 /* Cache disk information. */ 3922 pDisk->cbSize = pImage->Backend->pfnGetSize(pImage->p vBackendData);3965 pDisk->cbSize = pImage->Backend->pfnGetSize(pImage->pBackendData); 3923 3966 3924 3967 /* Cache PCHS geometry. */ 3925 rc2 = pImage->Backend->pfnGetPCHSGeometry(pImage->p vBackendData,3968 rc2 = pImage->Backend->pfnGetPCHSGeometry(pImage->pBackendData, 3926 3969 &pDisk->PCHSGeometry); 3927 3970 if (RT_FAILURE(rc2)) … … 3940 3983 3941 3984 /* Cache LCHS geometry. */ 3942 rc2 = pImage->Backend->pfnGetLCHSGeometry(pImage->p vBackendData,3985 rc2 = pImage->Backend->pfnGetLCHSGeometry(pImage->pBackendData, 3943 3986 &pDisk->LCHSGeometry); 3944 3987 if (RT_FAILURE(rc2)) … … 3959 4002 /* Switch previous image to read-only mode. */ 3960 4003 unsigned uOpenFlagsPrevImg; 3961 uOpenFlagsPrevImg = pDisk->pLast->Backend->pfnGetOpenFlags(pDisk->pLast->p vBackendData);4004 uOpenFlagsPrevImg = pDisk->pLast->Backend->pfnGetOpenFlags(pDisk->pLast->pBackendData); 3962 4005 if (!(uOpenFlagsPrevImg & VD_OPEN_FLAGS_READONLY)) 3963 4006 { 3964 4007 uOpenFlagsPrevImg |= VD_OPEN_FLAGS_READONLY; 3965 rc = pDisk->pLast->Backend->pfnSetOpenFlags(pDisk->pLast->p vBackendData, uOpenFlagsPrevImg);4008 rc = pDisk->pLast->Backend->pfnSetOpenFlags(pDisk->pLast->pBackendData, uOpenFlagsPrevImg); 3966 4009 } 3967 4010 } … … 3977 4020 { 3978 4021 /* Error detected, but image opened. Close image. */ 3979 rc2 = pImage->Backend->pfnClose(pImage->p vBackendData, false);4022 rc2 = pImage->Backend->pfnClose(pImage->pBackendData, false); 3980 4023 AssertRC(rc2); 3981 pImage->p vBackendData = NULL;4024 pImage->pBackendData = NULL; 3982 4025 } 3983 4026 } while (0); … … 4079 4122 pDisk->pVDIfsDisk, 4080 4123 pCache->pVDIfsCache, 4081 &pCache->p vBackendData);4124 &pCache->pBackendData); 4082 4125 /* If the open in read-write mode failed, retry in read-only mode. */ 4083 4126 if (RT_FAILURE(rc)) … … 4094 4137 pDisk->pVDIfsDisk, 4095 4138 pCache->pVDIfsCache, 4096 &pCache->p vBackendData);4139 &pCache->pBackendData); 4097 4140 if (RT_FAILURE(rc)) 4098 4141 { … … 4115 4158 RTUUID UuidImage, UuidCache; 4116 4159 4117 rc = pCache->Backend->pfnGetModificationUuid(pCache->p vBackendData,4160 rc = pCache->Backend->pfnGetModificationUuid(pCache->pBackendData, 4118 4161 &UuidCache); 4119 4162 if (RT_SUCCESS(rc)) 4120 4163 { 4121 rc = pDisk->pLast->Backend->pfnGetModificationUuid(pDisk->pLast->p vBackendData,4164 rc = pDisk->pLast->Backend->pfnGetModificationUuid(pDisk->pLast->pBackendData, 4122 4165 &UuidImage); 4123 4166 if (RT_SUCCESS(rc)) … … 4147 4190 { 4148 4191 /* Error detected, but image opened. Close image. */ 4149 rc2 = pCache->Backend->pfnClose(pCache->p vBackendData, false);4192 rc2 = pCache->Backend->pfnClose(pCache->pBackendData, false); 4150 4193 AssertRC(rc2); 4151 pCache->p vBackendData = NULL;4194 pCache->pBackendData = NULL; 4152 4195 } 4153 4196 } while (0); … … 4193 4236 const char *pszFilename, uint64_t cbSize, 4194 4237 unsigned uImageFlags, const char *pszComment, 4195 PC PDMMEDIAGEOMETRY pPCHSGeometry,4196 PC PDMMEDIAGEOMETRY pLCHSGeometry,4238 PCVDGEOMETRY pPCHSGeometry, 4239 PCVDGEOMETRY pLCHSGeometry, 4197 4240 PCRTUUID pUuid, unsigned uOpenFlags, 4198 4241 PVDINTERFACE pVDIfsImage, … … 4290 4333 pImage->pVDIfsImage = pVDIfsImage; 4291 4334 4292 /* Set up the I/O interface. */ 4293 rc = VDInterfaceAdd(&pImage->VDIIO, "VD_IO", VDINTERFACETYPE_IO, 4294 &pDisk->VDIIOCallbacks, pImage, &pImage->pVDIfsImage); 4295 AssertRC(rc); 4335 /* Set up the I/O interface if necessary. */ 4336 if (!VDInterfaceGet(pVDIfsImage, VDINTERFACETYPE_IO)) 4337 { 4338 rc = VDInterfaceAdd(&pImage->VDIIO, "VD_IO", VDINTERFACETYPE_IO, 4339 &pDisk->VDIIOCallbacks, pImage, 4340 &pImage->pVDIfsImage); 4341 AssertRC(rc); 4342 } 4296 4343 4297 4344 rc = vdFindBackend(pszBackend, &pImage->Backend); … … 4329 4376 pImage->pVDIfsImage, 4330 4377 pVDIfsOperation, 4331 &pImage->p vBackendData);4378 &pImage->pBackendData); 4332 4379 4333 4380 if (RT_SUCCESS(rc)) … … 4357 4404 { 4358 4405 /* Cache disk information. */ 4359 pDisk->cbSize = pImage->Backend->pfnGetSize(pImage->p vBackendData);4406 pDisk->cbSize = pImage->Backend->pfnGetSize(pImage->pBackendData); 4360 4407 4361 4408 /* Cache PCHS geometry. */ 4362 rc2 = pImage->Backend->pfnGetPCHSGeometry(pImage->p vBackendData,4409 rc2 = pImage->Backend->pfnGetPCHSGeometry(pImage->pBackendData, 4363 4410 &pDisk->PCHSGeometry); 4364 4411 if (RT_FAILURE(rc2)) … … 4377 4424 4378 4425 /* Cache LCHS geometry. */ 4379 rc2 = pImage->Backend->pfnGetLCHSGeometry(pImage->p vBackendData,4426 rc2 = pImage->Backend->pfnGetLCHSGeometry(pImage->pBackendData, 4380 4427 &pDisk->LCHSGeometry); 4381 4428 if (RT_FAILURE(rc2)) … … 4400 4447 { 4401 4448 /* Error detected, but image opened. Close and delete image. */ 4402 rc2 = pImage->Backend->pfnClose(pImage->p vBackendData, true);4449 rc2 = pImage->Backend->pfnClose(pImage->pBackendData, true); 4403 4450 AssertRC(rc2); 4404 pImage->p vBackendData = NULL;4451 pImage->pBackendData = NULL; 4405 4452 } 4406 4453 } while (0); … … 4539 4586 pImage->pVDIfsImage = pVDIfsImage; 4540 4587 4541 /* Set up the I/O interface. */ 4542 rc = VDInterfaceAdd(&pImage->VDIIO, "VD_IO", VDINTERFACETYPE_IO, 4543 &pDisk->VDIIOCallbacks, pImage, &pImage->pVDIfsImage); 4544 AssertRC(rc); 4588 /* Set up the I/O interface if necessary. */ 4589 if (!VDInterfaceGet(pVDIfsImage, VDINTERFACETYPE_IO)) 4590 { 4591 rc = VDInterfaceAdd(&pImage->VDIIO, "VD_IO", VDINTERFACETYPE_IO, 4592 &pDisk->VDIIOCallbacks, pImage, 4593 &pImage->pVDIfsImage); 4594 AssertRC(rc); 4595 } 4545 4596 4546 4597 /* Create UUID if the caller didn't specify one. */ … … 4569 4620 pImage->pVDIfsImage, 4570 4621 pVDIfsOperation, 4571 &pImage->p vBackendData);4622 &pImage->pBackendData); 4572 4623 4573 4624 if (RT_SUCCESS(rc)) … … 4582 4633 /* Switch previous image to read-only mode. */ 4583 4634 unsigned uOpenFlagsPrevImg; 4584 uOpenFlagsPrevImg = pDisk->pLast->Backend->pfnGetOpenFlags(pDisk->pLast->p vBackendData);4635 uOpenFlagsPrevImg = pDisk->pLast->Backend->pfnGetOpenFlags(pDisk->pLast->pBackendData); 4585 4636 if (!(uOpenFlagsPrevImg & VD_OPEN_FLAGS_READONLY)) 4586 4637 { 4587 4638 uOpenFlagsPrevImg |= VD_OPEN_FLAGS_READONLY; 4588 rc = pDisk->pLast->Backend->pfnSetOpenFlags(pDisk->pLast->p vBackendData, uOpenFlagsPrevImg);4639 rc = pDisk->pLast->Backend->pfnSetOpenFlags(pDisk->pLast->pBackendData, uOpenFlagsPrevImg); 4589 4640 } 4590 4641 … … 4606 4657 { 4607 4658 Uuid = *pParentUuid; 4608 pImage->Backend->pfnSetParentUuid(pImage->p vBackendData, &Uuid);4659 pImage->Backend->pfnSetParentUuid(pImage->pBackendData, &Uuid); 4609 4660 } 4610 4661 else 4611 4662 { 4612 rc2 = pDisk->pLast->Backend->pfnGetUuid(pDisk->pLast->p vBackendData,4663 rc2 = pDisk->pLast->Backend->pfnGetUuid(pDisk->pLast->pBackendData, 4613 4664 &Uuid); 4614 4665 if (RT_SUCCESS(rc2)) 4615 pImage->Backend->pfnSetParentUuid(pImage->p vBackendData, &Uuid);4666 pImage->Backend->pfnSetParentUuid(pImage->pBackendData, &Uuid); 4616 4667 } 4617 rc2 = pDisk->pLast->Backend->pfnGetModificationUuid(pDisk->pLast->p vBackendData,4668 rc2 = pDisk->pLast->Backend->pfnGetModificationUuid(pDisk->pLast->pBackendData, 4618 4669 &Uuid); 4619 4670 if (RT_SUCCESS(rc2)) 4620 pImage->Backend->pfnSetParentModificationUuid(pImage->p vBackendData,4671 pImage->Backend->pfnSetParentModificationUuid(pImage->pBackendData, 4621 4672 &Uuid); 4622 rc2 = pDisk->pLast->Backend->pfnGetTimeStamp(pDisk->pLast->pvBackendData, 4623 &ts); 4624 if (RT_SUCCESS(rc2)) 4625 pImage->Backend->pfnSetParentTimeStamp(pImage->pvBackendData, &ts); 4626 4627 rc2 = pImage->Backend->pfnSetParentFilename(pImage->pvBackendData, pDisk->pLast->pszFilename); 4673 if (pDisk->pLast->Backend->pfnGetTimeStamp) 4674 rc2 = pDisk->pLast->Backend->pfnGetTimeStamp(pDisk->pLast->pBackendData, 4675 &ts); 4676 else 4677 rc = VERR_NOT_IMPLEMENTED; 4678 if (RT_SUCCESS(rc2) && pImage->Backend->pfnSetParentTimeStamp) 4679 pImage->Backend->pfnSetParentTimeStamp(pImage->pBackendData, &ts); 4680 4681 if (pImage->Backend->pfnSetParentFilename) 4682 rc2 = pImage->Backend->pfnSetParentFilename(pImage->pBackendData, pDisk->pLast->pszFilename); 4628 4683 } 4629 4684 … … 4638 4693 { 4639 4694 /* Error detected, but image opened. Close and delete image. */ 4640 rc2 = pImage->Backend->pfnClose(pImage->p vBackendData, true);4695 rc2 = pImage->Backend->pfnClose(pImage->pBackendData, true); 4641 4696 AssertRC(rc2); 4642 pImage->p vBackendData = NULL;4697 pImage->pBackendData = NULL; 4643 4698 } 4644 4699 } while (0); … … 4805 4860 pCache->pVDIfsCache, 4806 4861 pVDIfsOperation, 4807 &pCache->p vBackendData);4862 &pCache->pBackendData); 4808 4863 4809 4864 if (RT_SUCCESS(rc)) … … 4826 4881 4827 4882 /* Set same modification Uuid as the last image. */ 4828 rc = pDisk->pLast->Backend->pfnGetModificationUuid(pDisk->pLast->p vBackendData,4883 rc = pDisk->pLast->Backend->pfnGetModificationUuid(pDisk->pLast->pBackendData, 4829 4884 &UuidModification); 4830 4885 if (RT_SUCCESS(rc)) 4831 4886 { 4832 rc = pCache->Backend->pfnSetModificationUuid(pCache->p vBackendData,4887 rc = pCache->Backend->pfnSetModificationUuid(pCache->pBackendData, 4833 4888 &UuidModification); 4834 4889 } … … 4846 4901 { 4847 4902 /* Error detected, but image opened. Close and delete image. */ 4848 rc2 = pCache->Backend->pfnClose(pCache->p vBackendData, true);4903 rc2 = pCache->Backend->pfnClose(pCache->pBackendData, true); 4849 4904 AssertRC(rc2); 4850 pCache->p vBackendData = NULL;4905 pCache->pBackendData = NULL; 4851 4906 } 4852 4907 } while (0); … … 4931 4986 4932 4987 /* Make sure destination image is writable. */ 4933 unsigned uOpenFlags = pImageTo->Backend->pfnGetOpenFlags(pImageTo->p vBackendData);4988 unsigned uOpenFlags = pImageTo->Backend->pfnGetOpenFlags(pImageTo->pBackendData); 4934 4989 if (uOpenFlags & VD_OPEN_FLAGS_READONLY) 4935 4990 { 4936 4991 uOpenFlags &= ~VD_OPEN_FLAGS_READONLY; 4937 rc = pImageTo->Backend->pfnSetOpenFlags(pImageTo->p vBackendData,4992 rc = pImageTo->Backend->pfnSetOpenFlags(pImageTo->pBackendData, 4938 4993 uOpenFlags); 4939 4994 if (RT_FAILURE(rc)) … … 4942 4997 4943 4998 /* Get size of destination image. */ 4944 uint64_t cbSize = pImageTo->Backend->pfnGetSize(pImageTo->p vBackendData);4999 uint64_t cbSize = pImageTo->Backend->pfnGetSize(pImageTo->pBackendData); 4945 5000 rc2 = vdThreadFinishWrite(pDisk); 4946 5001 AssertRC(rc2); … … 4973 5028 fLockWrite = true; 4974 5029 4975 rc = pImageTo->Backend->pfnRead(pImageTo->p vBackendData,5030 rc = pImageTo->Backend->pfnRead(pImageTo->pBackendData, 4976 5031 uOffset, pvBuf, cbThisRead, 4977 5032 &cbThisRead); … … 4986 5041 pCurrImage = pCurrImage->pPrev) 4987 5042 { 4988 rc = pCurrImage->Backend->pfnRead(pCurrImage->p vBackendData,5043 rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData, 4989 5044 uOffset, pvBuf, 4990 5045 cbThisRead, … … 5047 5102 5048 5103 /* We need to open the image in read/write mode. */ 5049 uOpenFlags = pImageChild->Backend->pfnGetOpenFlags(pImageChild->p vBackendData);5104 uOpenFlags = pImageChild->Backend->pfnGetOpenFlags(pImageChild->pBackendData); 5050 5105 5051 5106 if (uOpenFlags & VD_OPEN_FLAGS_READONLY) 5052 5107 { 5053 5108 uOpenFlags &= ~VD_OPEN_FLAGS_READONLY; 5054 rc = pImageChild->Backend->pfnSetOpenFlags(pImageChild->p vBackendData,5109 rc = pImageChild->Backend->pfnSetOpenFlags(pImageChild->pBackendData, 5055 5110 uOpenFlags); 5056 5111 if (RT_FAILURE(rc)) … … 5086 5141 pCurrImage = pCurrImage->pPrev) 5087 5142 { 5088 rc = pCurrImage->Backend->pfnRead(pCurrImage->p vBackendData,5143 rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData, 5089 5144 uOffset, pvBuf, 5090 5145 cbThisRead, &cbThisRead); … … 5142 5197 if (pImageFrom->pPrev) 5143 5198 { 5144 rc = pImageFrom->pPrev->Backend->pfnGetUuid(pImageFrom->pPrev->p vBackendData,5199 rc = pImageFrom->pPrev->Backend->pfnGetUuid(pImageFrom->pPrev->pBackendData, 5145 5200 &Uuid); 5146 5201 AssertRC(rc); … … 5148 5203 else 5149 5204 RTUuidClear(&Uuid); 5150 rc = pImageTo->Backend->pfnSetParentUuid(pImageTo->p vBackendData,5205 rc = pImageTo->Backend->pfnSetParentUuid(pImageTo->pBackendData, 5151 5206 &Uuid); 5152 5207 AssertRC(rc); … … 5157 5212 if (pImageFrom->pNext) 5158 5213 { 5159 rc = pImageTo->Backend->pfnGetUuid(pImageTo->p vBackendData,5214 rc = pImageTo->Backend->pfnGetUuid(pImageTo->pBackendData, 5160 5215 &Uuid); 5161 5216 AssertRC(rc); 5162 5217 5163 rc = pImageFrom->Backend->pfnSetParentUuid(pImageFrom->pNext->p vBackendData,5218 rc = pImageFrom->Backend->pfnSetParentUuid(pImageFrom->pNext->pBackendData, 5164 5219 &Uuid); 5165 5220 AssertRC(rc); … … 5178 5233 pTmp = pImg->pPrev; 5179 5234 vdRemoveImageFromList(pDisk, pImg); 5180 pImg->Backend->pfnClose(pImg->p vBackendData, true);5235 pImg->Backend->pfnClose(pImg->pBackendData, true); 5181 5236 RTMemFree(pImg->pszFilename); 5182 5237 RTMemFree(pImg); … … 5187 5242 if (pImageTo != pDisk->pLast) 5188 5243 { 5189 uOpenFlags = pImageTo->Backend->pfnGetOpenFlags(pImageTo->p vBackendData);5244 uOpenFlags = pImageTo->Backend->pfnGetOpenFlags(pImageTo->pBackendData); 5190 5245 uOpenFlags |= VD_OPEN_FLAGS_READONLY; 5191 rc = pImageTo->Backend->pfnSetOpenFlags(pImageTo->p vBackendData,5246 rc = pImageTo->Backend->pfnSetOpenFlags(pImageTo->pBackendData, 5192 5247 uOpenFlags); 5193 5248 if (RT_FAILURE(rc)) … … 5204 5259 && pImageChild != pDisk->pLast) 5205 5260 { 5206 uOpenFlags = pImageChild->Backend->pfnGetOpenFlags(pImageChild->p vBackendData);5261 uOpenFlags = pImageChild->Backend->pfnGetOpenFlags(pImageChild->pBackendData); 5207 5262 uOpenFlags |= VD_OPEN_FLAGS_READONLY; 5208 rc = pImageChild->Backend->pfnSetOpenFlags(pImageChild->p vBackendData,5263 rc = pImageChild->Backend->pfnSetOpenFlags(pImageChild->pBackendData, 5209 5264 uOpenFlags); 5210 5265 if (RT_FAILURE(rc)) … … 5312 5367 if (pDiskFrom == pDiskTo) 5313 5368 { 5314 /* Rename only works when backends are the same. */ 5369 /* Rename only works when backends are the same, are file based 5370 * and the rename method is implemented. */ 5315 5371 if ( fMoveByRename 5316 && !RTStrICmp(pszBackend, pImageFrom->Backend->pszBackendName)) 5372 && !RTStrICmp(pszBackend, pImageFrom->Backend->pszBackendName) 5373 && pImageFrom->Backend->uBackendCaps & VD_CAP_FILE 5374 && pImageFrom->Backend->pfnRename) 5317 5375 { 5318 5376 rc2 = vdThreadFinishRead(pDiskFrom); … … 5323 5381 AssertRC(rc2); 5324 5382 fLockWriteFrom = true; 5325 rc = pImageFrom->Backend->pfnRename(pImageFrom->p vBackendData, pszFilename ? pszFilename : pImageFrom->pszFilename);5383 rc = pImageFrom->Backend->pfnRename(pImageFrom->pBackendData, pszFilename ? pszFilename : pImageFrom->pszFilename); 5326 5384 break; 5327 5385 } … … 5339 5397 5340 5398 uint64_t cbSizeFrom; 5341 cbSizeFrom = pImageFrom->Backend->pfnGetSize(pImageFrom->p vBackendData);5399 cbSizeFrom = pImageFrom->Backend->pfnGetSize(pImageFrom->pBackendData); 5342 5400 if (cbSizeFrom == 0) 5343 5401 { … … 5346 5404 } 5347 5405 5348 PDMMEDIAGEOMETRY PCHSGeometryFrom = {0, 0, 0};5349 PDMMEDIAGEOMETRY LCHSGeometryFrom = {0, 0, 0};5350 pImageFrom->Backend->pfnGetPCHSGeometry(pImageFrom->p vBackendData, &PCHSGeometryFrom);5351 pImageFrom->Backend->pfnGetLCHSGeometry(pImageFrom->p vBackendData, &LCHSGeometryFrom);5406 VDGEOMETRY PCHSGeometryFrom = {0, 0, 0}; 5407 VDGEOMETRY LCHSGeometryFrom = {0, 0, 0}; 5408 pImageFrom->Backend->pfnGetPCHSGeometry(pImageFrom->pBackendData, &PCHSGeometryFrom); 5409 pImageFrom->Backend->pfnGetLCHSGeometry(pImageFrom->pBackendData, &LCHSGeometryFrom); 5352 5410 5353 5411 RTUUID ImageUuid, ImageModificationUuid; … … 5361 5419 else 5362 5420 { 5363 rc = pImageFrom->Backend->pfnGetUuid(pImageFrom->p vBackendData, &ImageUuid);5421 rc = pImageFrom->Backend->pfnGetUuid(pImageFrom->pBackendData, &ImageUuid); 5364 5422 if (RT_FAILURE(rc)) 5365 5423 RTUuidCreate(&ImageUuid); 5366 5424 } 5367 rc = pImageFrom->Backend->pfnGetModificationUuid(pImageFrom->p vBackendData, &ImageModificationUuid);5425 rc = pImageFrom->Backend->pfnGetModificationUuid(pImageFrom->pBackendData, &ImageModificationUuid); 5368 5426 if (RT_FAILURE(rc)) 5369 5427 RTUuidClear(&ImageModificationUuid); 5370 5428 5371 5429 char szComment[1024]; 5372 rc = pImageFrom->Backend->pfnGetComment(pImageFrom->p vBackendData, szComment, sizeof(szComment));5430 rc = pImageFrom->Backend->pfnGetComment(pImageFrom->pBackendData, szComment, sizeof(szComment)); 5373 5431 if (RT_FAILURE(rc)) 5374 5432 szComment[0] = '\0'; … … 5377 5435 5378 5436 unsigned uOpenFlagsFrom; 5379 uOpenFlagsFrom = pImageFrom->Backend->pfnGetOpenFlags(pImageFrom->p vBackendData);5437 uOpenFlagsFrom = pImageFrom->Backend->pfnGetOpenFlags(pImageFrom->pBackendData); 5380 5438 5381 5439 rc2 = vdThreadFinishRead(pDiskFrom); … … 5440 5498 5441 5499 if (RT_SUCCESS(rc) && !RTUuidIsNull(&ImageUuid)) 5442 pDiskTo->pLast->Backend->pfnSetUuid(pDiskTo->pLast->p vBackendData, &ImageUuid);5500 pDiskTo->pLast->Backend->pfnSetUuid(pDiskTo->pLast->pBackendData, &ImageUuid); 5443 5501 } 5444 5502 if (RT_FAILURE(rc)) … … 5456 5514 5457 5515 uint64_t cbSizeTo; 5458 cbSizeTo = pImageTo->Backend->pfnGetSize(pImageTo->p vBackendData);5516 cbSizeTo = pImageTo->Backend->pfnGetSize(pImageTo->pBackendData); 5459 5517 if (cbSizeTo == 0) 5460 5518 { … … 5566 5624 * backend might not provide a valid modification UUID. */ 5567 5625 if (!RTUuidIsNull(&ImageModificationUuid)) 5568 pImageTo->Backend->pfnSetModificationUuid(pImageTo->p vBackendData, &ImageModificationUuid);5626 pImageTo->Backend->pfnSetModificationUuid(pImageTo->pBackendData, &ImageModificationUuid); 5569 5627 } 5570 5628 } while (0); … … 5584 5642 5585 5643 /* Close and delete image. */ 5586 rc2 = pImageTo->Backend->pfnClose(pImageTo->p vBackendData, true);5587 AssertRC(rc2); 5588 pImageTo->p vBackendData = NULL;5644 rc2 = pImageTo->Backend->pfnClose(pImageTo->pBackendData, true); 5645 AssertRC(rc2); 5646 pImageTo->pBackendData = NULL; 5589 5647 5590 5648 /* Free remaining resources. */ … … 5711 5769 fLockWrite = true; 5712 5770 5713 rc = pImage->Backend->pfnCompact(pImage->p vBackendData,5771 rc = pImage->Backend->pfnCompact(pImage->pBackendData, 5714 5772 0, 99, 5715 5773 pDisk->pVDIfsDisk, … … 5758 5816 */ 5759 5817 VBOXDDU_DECL(int) VDResize(PVBOXHDD pDisk, uint64_t cbSize, 5760 PC PDMMEDIAGEOMETRY pPCHSGeometry,5761 PC PDMMEDIAGEOMETRY pLCHSGeometry,5818 PCVDGEOMETRY pPCHSGeometry, 5819 PCVDGEOMETRY pLCHSGeometry, 5762 5820 PVDINTERFACE pVDIfsOperation) 5763 5821 { 5822 /** @todo r=klaus resizing was designed to be part of VDCopy, so having a separate function is not desirable. */ 5764 5823 int rc = VINF_SUCCESS; 5765 5824 int rc2; … … 5812 5871 fLockWrite = true; 5813 5872 5814 PDMMEDIAGEOMETRY PCHSGeometryOld;5815 PDMMEDIAGEOMETRY LCHSGeometryOld;5816 PC PDMMEDIAGEOMETRY pPCHSGeometryNew;5817 PC PDMMEDIAGEOMETRY pLCHSGeometryNew;5873 VDGEOMETRY PCHSGeometryOld; 5874 VDGEOMETRY LCHSGeometryOld; 5875 PCVDGEOMETRY pPCHSGeometryNew; 5876 PCVDGEOMETRY pLCHSGeometryNew; 5818 5877 5819 5878 if (pPCHSGeometry->cCylinders == 0) 5820 5879 { 5821 5880 /* Auto-detect marker, calculate new value ourself. */ 5822 rc = pImage->Backend->pfnGetPCHSGeometry(pImage->p vBackendData, &PCHSGeometryOld);5881 rc = pImage->Backend->pfnGetPCHSGeometry(pImage->pBackendData, &PCHSGeometryOld); 5823 5882 if (RT_SUCCESS(rc) && (PCHSGeometryOld.cCylinders != 0)) 5824 5883 PCHSGeometryOld.cCylinders = RT_MIN(cbSize / 512 / PCHSGeometryOld.cHeads / PCHSGeometryOld.cSectors, 16383); … … 5834 5893 { 5835 5894 /* Auto-detect marker, calculate new value ourself. */ 5836 rc = pImage->Backend->pfnGetLCHSGeometry(pImage->p vBackendData, &LCHSGeometryOld);5895 rc = pImage->Backend->pfnGetLCHSGeometry(pImage->pBackendData, &LCHSGeometryOld); 5837 5896 if (RT_SUCCESS(rc) && (LCHSGeometryOld.cCylinders != 0)) 5838 5897 LCHSGeometryOld.cCylinders = cbSize / 512 / LCHSGeometryOld.cHeads / LCHSGeometryOld.cSectors; … … 5846 5905 5847 5906 if (RT_SUCCESS(rc)) 5848 rc = pImage->Backend->pfnResize(pImage->p vBackendData,5849 cbSize * _1M,5907 rc = pImage->Backend->pfnResize(pImage->pBackendData, 5908 cbSize, 5850 5909 pPCHSGeometryNew, 5851 5910 pLCHSGeometryNew, … … 5914 5973 break; 5915 5974 } 5916 unsigned uOpenFlags = pImage->Backend->pfnGetOpenFlags(pImage->p vBackendData);5975 unsigned uOpenFlags = pImage->Backend->pfnGetOpenFlags(pImage->pBackendData); 5917 5976 /* Remove image from list of opened images. */ 5918 5977 vdRemoveImageFromList(pDisk, pImage); 5919 5978 /* Close (and optionally delete) image. */ 5920 rc = pImage->Backend->pfnClose(pImage->p vBackendData, fDelete);5979 rc = pImage->Backend->pfnClose(pImage->pBackendData, fDelete); 5921 5980 /* Free remaining resources related to the image. */ 5922 5981 RTStrFree(pImage->pszFilename); … … 5932 5991 if (!(uOpenFlags & VD_OPEN_FLAGS_READONLY)) 5933 5992 { 5934 uOpenFlags = pImage->Backend->pfnGetOpenFlags(pImage->p vBackendData);5993 uOpenFlags = pImage->Backend->pfnGetOpenFlags(pImage->pBackendData); 5935 5994 uOpenFlags &= ~ VD_OPEN_FLAGS_READONLY; 5936 rc = pImage->Backend->pfnSetOpenFlags(pImage->p vBackendData, uOpenFlags);5995 rc = pImage->Backend->pfnSetOpenFlags(pImage->pBackendData, uOpenFlags); 5937 5996 } 5938 5997 5939 5998 /* Cache disk information. */ 5940 pDisk->cbSize = pImage->Backend->pfnGetSize(pImage->p vBackendData);5999 pDisk->cbSize = pImage->Backend->pfnGetSize(pImage->pBackendData); 5941 6000 5942 6001 /* Cache PCHS geometry. */ 5943 rc2 = pImage->Backend->pfnGetPCHSGeometry(pImage->p vBackendData,6002 rc2 = pImage->Backend->pfnGetPCHSGeometry(pImage->pBackendData, 5944 6003 &pDisk->PCHSGeometry); 5945 6004 if (RT_FAILURE(rc2)) … … 5958 6017 5959 6018 /* Cache LCHS geometry. */ 5960 rc2 = pImage->Backend->pfnGetLCHSGeometry(pImage->p vBackendData,6019 rc2 = pImage->Backend->pfnGetLCHSGeometry(pImage->pBackendData, 5961 6020 &pDisk->LCHSGeometry); 5962 6021 if (RT_FAILURE(rc2)) … … 6016 6075 pDisk->pCache = NULL; 6017 6076 6018 pCache->Backend->pfnClose(pCache->p vBackendData, fDelete);6077 pCache->Backend->pfnClose(pCache->pBackendData, fDelete); 6019 6078 if (pCache->pszFilename) 6020 6079 RTStrFree(pCache->pszFilename); … … 6059 6118 if (pCache) 6060 6119 { 6061 rc2 = pCache->Backend->pfnClose(pCache->p vBackendData, false);6120 rc2 = pCache->Backend->pfnClose(pCache->pBackendData, false); 6062 6121 if (RT_FAILURE(rc2) && RT_SUCCESS(rc)) 6063 6122 rc = rc2; … … 6075 6134 vdRemoveImageFromList(pDisk, pImage); 6076 6135 /* Close image. */ 6077 rc2 = pImage->Backend->pfnClose(pImage->p vBackendData, false);6136 rc2 = pImage->Backend->pfnClose(pImage->pBackendData, false); 6078 6137 if (RT_FAILURE(rc2) && RT_SUCCESS(rc)) 6079 6138 rc = rc2; … … 6245 6304 6246 6305 vdResetModifiedFlag(pDisk); 6247 rc = pImage->Backend->pfnFlush(pImage->p vBackendData);6306 rc = pImage->Backend->pfnFlush(pImage->pBackendData); 6248 6307 6249 6308 if ( RT_SUCCESS(rc) 6250 6309 && pDisk->pCache) 6251 rc = pDisk->pCache->Backend->pfnFlush(pDisk->pCache->p vBackendData);6310 rc = pDisk->pCache->Backend->pfnFlush(pDisk->pCache->pBackendData); 6252 6311 } while (0); 6253 6312 … … 6326 6385 6327 6386 unsigned uOpenFlags; 6328 uOpenFlags = pDisk->pLast->Backend->pfnGetOpenFlags(pDisk->pLast->p vBackendData);6387 uOpenFlags = pDisk->pLast->Backend->pfnGetOpenFlags(pDisk->pLast->pBackendData); 6329 6388 fReadOnly = !!(uOpenFlags & VD_OPEN_FLAGS_READONLY); 6330 6389 } while (0); … … 6367 6426 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 6368 6427 AssertPtrBreakStmt(pImage, cbSize = 0); 6369 cbSize = pImage->Backend->pfnGetSize(pImage->p vBackendData);6428 cbSize = pImage->Backend->pfnGetSize(pImage->pBackendData); 6370 6429 } while (0); 6371 6430 … … 6407 6466 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 6408 6467 AssertPtrBreakStmt(pImage, cbSize = 0); 6409 cbSize = pImage->Backend->pfnGetFileSize(pImage->p vBackendData);6468 cbSize = pImage->Backend->pfnGetFileSize(pImage->pBackendData); 6410 6469 } while (0); 6411 6470 … … 6431 6490 */ 6432 6491 VBOXDDU_DECL(int) VDGetPCHSGeometry(PVBOXHDD pDisk, unsigned nImage, 6433 P PDMMEDIAGEOMETRY pPCHSGeometry)6492 PVDGEOMETRY pPCHSGeometry) 6434 6493 { 6435 6494 int rc = VINF_SUCCESS; … … 6466 6525 } 6467 6526 else 6468 rc = pImage->Backend->pfnGetPCHSGeometry(pImage->p vBackendData,6527 rc = pImage->Backend->pfnGetPCHSGeometry(pImage->pBackendData, 6469 6528 pPCHSGeometry); 6470 6529 } while (0); … … 6476 6535 } 6477 6536 6478 LogFlowFunc(("% s: %Rrc (PCHS=%u/%u/%u)\n", __FUNCTION__, rc,6537 LogFlowFunc(("%Rrc (PCHS=%u/%u/%u)\n", rc, 6479 6538 pDisk->PCHSGeometry.cCylinders, pDisk->PCHSGeometry.cHeads, 6480 6539 pDisk->PCHSGeometry.cSectors)); … … 6495 6554 */ 6496 6555 VBOXDDU_DECL(int) VDSetPCHSGeometry(PVBOXHDD pDisk, unsigned nImage, 6497 PC PDMMEDIAGEOMETRY pPCHSGeometry)6556 PCVDGEOMETRY pPCHSGeometry) 6498 6557 { 6499 6558 int rc = VINF_SUCCESS; … … 6537 6596 * of updating an image which could be opened in read-only mode 6538 6597 * right now. */ 6539 rc = pImage->Backend->pfnSetPCHSGeometry(pImage->p vBackendData,6598 rc = pImage->Backend->pfnSetPCHSGeometry(pImage->pBackendData, 6540 6599 pPCHSGeometry); 6541 6600 6542 6601 /* Cache new geometry values in any case. */ 6543 rc2 = pImage->Backend->pfnGetPCHSGeometry(pImage->p vBackendData,6602 rc2 = pImage->Backend->pfnGetPCHSGeometry(pImage->pBackendData, 6544 6603 &pDisk->PCHSGeometry); 6545 6604 if (RT_FAILURE(rc2)) … … 6559 6618 else 6560 6619 { 6561 PDMMEDIAGEOMETRY PCHS;6562 rc = pImage->Backend->pfnGetPCHSGeometry(pImage->p vBackendData,6620 VDGEOMETRY PCHS; 6621 rc = pImage->Backend->pfnGetPCHSGeometry(pImage->pBackendData, 6563 6622 &PCHS); 6564 6623 if ( RT_FAILURE(rc) … … 6572 6631 * of updating an image which could be opened in read-only mode 6573 6632 * right now. */ 6574 rc = pImage->Backend->pfnSetPCHSGeometry(pImage->p vBackendData,6633 rc = pImage->Backend->pfnSetPCHSGeometry(pImage->pBackendData, 6575 6634 pPCHSGeometry); 6576 6635 } … … 6599 6658 */ 6600 6659 VBOXDDU_DECL(int) VDGetLCHSGeometry(PVBOXHDD pDisk, unsigned nImage, 6601 P PDMMEDIAGEOMETRY pLCHSGeometry)6660 PVDGEOMETRY pLCHSGeometry) 6602 6661 { 6603 6662 int rc = VINF_SUCCESS; … … 6634 6693 } 6635 6694 else 6636 rc = pImage->Backend->pfnGetLCHSGeometry(pImage->p vBackendData,6695 rc = pImage->Backend->pfnGetLCHSGeometry(pImage->pBackendData, 6637 6696 pLCHSGeometry); 6638 6697 } while (0); … … 6663 6722 */ 6664 6723 VBOXDDU_DECL(int) VDSetLCHSGeometry(PVBOXHDD pDisk, unsigned nImage, 6665 PC PDMMEDIAGEOMETRY pLCHSGeometry)6724 PCVDGEOMETRY pLCHSGeometry) 6666 6725 { 6667 6726 int rc = VINF_SUCCESS; … … 6705 6764 * of updating an image which could be opened in read-only mode 6706 6765 * right now. */ 6707 rc = pImage->Backend->pfnSetLCHSGeometry(pImage->p vBackendData,6766 rc = pImage->Backend->pfnSetLCHSGeometry(pImage->pBackendData, 6708 6767 pLCHSGeometry); 6709 6768 6710 6769 /* Cache new geometry values in any case. */ 6711 rc2 = pImage->Backend->pfnGetLCHSGeometry(pImage->p vBackendData,6770 rc2 = pImage->Backend->pfnGetLCHSGeometry(pImage->pBackendData, 6712 6771 &pDisk->LCHSGeometry); 6713 6772 if (RT_FAILURE(rc2)) … … 6727 6786 else 6728 6787 { 6729 PDMMEDIAGEOMETRY LCHS;6730 rc = pImage->Backend->pfnGetLCHSGeometry(pImage->p vBackendData,6788 VDGEOMETRY LCHS; 6789 rc = pImage->Backend->pfnGetLCHSGeometry(pImage->pBackendData, 6731 6790 &LCHS); 6732 6791 if ( RT_FAILURE(rc) … … 6740 6799 * of updating an image which could be opened in read-only mode 6741 6800 * right now. */ 6742 rc = pImage->Backend->pfnSetLCHSGeometry(pImage->p vBackendData,6801 rc = pImage->Backend->pfnSetLCHSGeometry(pImage->pBackendData, 6743 6802 pLCHSGeometry); 6744 6803 } … … 6792 6851 AssertPtrBreakStmt(pImage, rc = VERR_VD_IMAGE_NOT_FOUND); 6793 6852 6794 *puVersion = pImage->Backend->pfnGetVersion(pImage->p vBackendData);6853 *puVersion = pImage->Backend->pfnGetVersion(pImage->pBackendData); 6795 6854 } while (0); 6796 6855 … … 6942 7001 AssertPtrBreakStmt(pImage, rc = VERR_VD_IMAGE_NOT_FOUND); 6943 7002 6944 *puOpenFlags = pImage->Backend->pfnGetOpenFlags(pImage->p vBackendData);7003 *puOpenFlags = pImage->Backend->pfnGetOpenFlags(pImage->pBackendData); 6945 7004 } while (0); 6946 7005 … … 6992 7051 AssertPtrBreakStmt(pImage, rc = VERR_VD_IMAGE_NOT_FOUND); 6993 7052 6994 rc = pImage->Backend->pfnSetOpenFlags(pImage->p vBackendData,7053 rc = pImage->Backend->pfnSetOpenFlags(pImage->pBackendData, 6995 7054 uOpenFlags); 6996 7055 } while (0); … … 7114 7173 AssertPtrBreakStmt(pImage, rc = VERR_VD_IMAGE_NOT_FOUND); 7115 7174 7116 rc = pImage->Backend->pfnGetComment(pImage->p vBackendData, pszComment,7175 rc = pImage->Backend->pfnGetComment(pImage->pBackendData, pszComment, 7117 7176 cbComment); 7118 7177 } while (0); … … 7164 7223 AssertPtrBreakStmt(pImage, rc = VERR_VD_IMAGE_NOT_FOUND); 7165 7224 7166 rc = pImage->Backend->pfnSetComment(pImage->p vBackendData, pszComment);7225 rc = pImage->Backend->pfnSetComment(pImage->pBackendData, pszComment); 7167 7226 } while (0); 7168 7227 … … 7212 7271 AssertPtrBreakStmt(pImage, rc = VERR_VD_IMAGE_NOT_FOUND); 7213 7272 7214 rc = pImage->Backend->pfnGetUuid(pImage->p vBackendData, pUuid);7273 rc = pImage->Backend->pfnGetUuid(pImage->pBackendData, pUuid); 7215 7274 } while (0); 7216 7275 … … 7265 7324 pUuid = &Uuid; 7266 7325 } 7267 rc = pImage->Backend->pfnSetUuid(pImage->p vBackendData, pUuid);7326 rc = pImage->Backend->pfnSetUuid(pImage->pBackendData, pUuid); 7268 7327 } while (0); 7269 7328 … … 7312 7371 AssertPtrBreakStmt(pImage, rc = VERR_VD_IMAGE_NOT_FOUND); 7313 7372 7314 rc = pImage->Backend->pfnGetModificationUuid(pImage->p vBackendData,7373 rc = pImage->Backend->pfnGetModificationUuid(pImage->pBackendData, 7315 7374 pUuid); 7316 7375 } while (0); … … 7367 7426 pUuid = &Uuid; 7368 7427 } 7369 rc = pImage->Backend->pfnSetModificationUuid(pImage->p vBackendData,7428 rc = pImage->Backend->pfnSetModificationUuid(pImage->pBackendData, 7370 7429 pUuid); 7371 7430 } while (0); … … 7416 7475 AssertPtrBreakStmt(pImage, rc = VERR_VD_IMAGE_NOT_FOUND); 7417 7476 7418 rc = pImage->Backend->pfnGetParentUuid(pImage->p vBackendData, pUuid);7477 rc = pImage->Backend->pfnGetParentUuid(pImage->pBackendData, pUuid); 7419 7478 } while (0); 7420 7479 … … 7470 7529 pUuid = &Uuid; 7471 7530 } 7472 rc = pImage->Backend->pfnSetParentUuid(pImage->p vBackendData, pUuid);7531 rc = pImage->Backend->pfnSetParentUuid(pImage->pBackendData, pUuid); 7473 7532 } while (0); 7474 7533 … … 7500 7559 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 7501 7560 7502 int (*pfnMessage)(void *, const char *, ...) = NULL; 7503 void *pvUser = pDisk->pInterfaceError->pvUser; 7504 7505 if (pDisk->pInterfaceErrorCallbacks && VALID_PTR(pDisk->pInterfaceErrorCallbacks->pfnMessage)) 7506 pfnMessage = pDisk->pInterfaceErrorCallbacks->pfnMessage; 7507 else 7508 { 7561 if (!pDisk->pInterfaceErrorCallbacks || !VALID_PTR(pDisk->pInterfaceErrorCallbacks->pfnMessage)) 7509 7562 pDisk->pInterfaceErrorCallbacks->pfnMessage = vdLogMessage; 7510 pfnMessage = vdLogMessage;7511 }7512 7563 7513 7564 rc2 = vdThreadStartRead(pDisk); … … 7515 7566 fLockRead = true; 7516 7567 7517 pfnMessage(pvUser, "--- Dumping VD Disk, Images=%u\n", pDisk->cImages);7568 vdMessageWrapper(pDisk, "--- Dumping VD Disk, Images=%u\n", pDisk->cImages); 7518 7569 for (PVDIMAGE pImage = pDisk->pBase; pImage; pImage = pImage->pNext) 7519 7570 { 7520 pfnMessage(pvUser, "Dumping VD image \"%s\" (Backend=%s)\n",7521 pImage->pszFilename, pImage->Backend->pszBackendName);7522 pImage->Backend->pfnDump(pImage->p vBackendData);7571 vdMessageWrapper(pDisk, "Dumping VD image \"%s\" (Backend=%s)\n", 7572 pImage->pszFilename, pImage->Backend->pszBackendName); 7573 pImage->Backend->pfnDump(pImage->pBackendData); 7523 7574 } 7524 7575 } while (0); … … 7566 7617 7567 7618 if (pImage->Backend->uBackendCaps & VD_CAP_ASYNC) 7568 *pfAIOSupported = pImage->Backend->pfnIsAsyncIOSupported(pImage->p vBackendData);7619 *pfAIOSupported = pImage->Backend->pfnIsAsyncIOSupported(pImage->pBackendData); 7569 7620 else 7570 7621 *pfAIOSupported = false; -
trunk/src/VBox/Devices/Storage/VCICacheCore.cpp
r32370 r32536 34 34 35 35 /** 36 * Rawimage data structure.36 * VCI image data structure. 37 37 */ 38 38 typedef struct VCICACHE … … 81 81 *******************************************************************************/ 82 82 83 static int vciFlushImage(PVCICACHE pImage);84 static void vciFreeImage(PVCICACHE pImage, bool fDelete);85 86 87 83 /** 88 84 * Internal: signal an error to the frontend. … … 100 96 } 101 97 102 static int vciFileOpen(PVCICACHE pImage, bool fReadonly, bool fCreate) 98 /** 99 * Internal: signal an informational message to the frontend. 100 */ 101 DECLINLINE(int) vciMessage(PVCICACHE pImage, const char *pszFormat, ...) 103 102 { 104 103 int rc = VINF_SUCCESS; 105 106 AssertMsg(!(fReadonly && fCreate), ("Image can't be opened readonly while being created\n")); 107 108 unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0; 109 110 if (fCreate) 111 uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE; 112 113 rc = pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser, 114 pImage->pszFilename, 115 uOpenFlags, 116 &pImage->pStorage); 117 118 return rc; 119 } 120 121 static int vciFileClose(PVCICACHE pImage) 122 { 123 int rc = VINF_SUCCESS; 124 125 if (pImage->pStorage) 126 rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser, 127 pImage->pStorage); 128 129 pImage->pStorage = NULL; 130 131 return rc; 132 } 133 134 static int vciFileFlushSync(PVCICACHE pImage) 104 va_list va; 105 va_start(va, pszFormat); 106 if (pImage->pInterfaceError) 107 rc = pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, 108 pszFormat, va); 109 va_end(va); 110 return rc; 111 } 112 113 114 DECLINLINE(int) vciFileOpen(PVCICACHE pImage, const char *pszFilename, 115 uint32_t fOpen) 116 { 117 return pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser, 118 pszFilename, fOpen, 119 &pImage->pStorage); 120 } 121 122 DECLINLINE(int) vciFileClose(PVCICACHE pImage) 123 { 124 return pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser, 125 pImage->pStorage); 126 } 127 128 DECLINLINE(int) vciFileDelete(PVCICACHE pImage, const char *pszFilename) 129 { 130 return pImage->pInterfaceIOCallbacks->pfnDelete(pImage->pInterfaceIO->pvUser, 131 pszFilename); 132 } 133 134 DECLINLINE(int) vciFileMove(PVCICACHE pImage, const char *pszSrc, 135 const char *pszDst, unsigned fMove) 136 { 137 return pImage->pInterfaceIOCallbacks->pfnMove(pImage->pInterfaceIO->pvUser, 138 pszSrc, pszDst, fMove); 139 } 140 141 DECLINLINE(int) vciFileGetFreeSpace(PVCICACHE pImage, const char *pszFilename, 142 int64_t *pcbFree) 143 { 144 return pImage->pInterfaceIOCallbacks->pfnGetFreeSpace(pImage->pInterfaceIO->pvUser, 145 pszFilename, pcbFree); 146 } 147 148 DECLINLINE(int) vciFileGetSize(PVCICACHE pImage, uint64_t *pcbSize) 149 { 150 return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser, 151 pImage->pStorage, pcbSize); 152 } 153 154 DECLINLINE(int) vciFileSetSize(PVCICACHE pImage, uint64_t cbSize) 155 { 156 return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser, 157 pImage->pStorage, cbSize); 158 } 159 160 DECLINLINE(int) vciFileWriteSync(PVCICACHE pImage, uint64_t uOffset, 161 const void *pvBuffer, size_t cbBuffer, 162 size_t *pcbWritten) 163 { 164 return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser, 165 pImage->pStorage, uOffset, 166 pvBuffer, cbBuffer, pcbWritten); 167 } 168 169 DECLINLINE(int) vciFileReadSync(PVCICACHE pImage, uint64_t uOffset, 170 void *pvBuffer, size_t cbBuffer, size_t *pcbRead) 171 { 172 return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser, 173 pImage->pStorage, uOffset, 174 pvBuffer, cbBuffer, pcbRead); 175 } 176 177 DECLINLINE(int) vciFileFlushSync(PVCICACHE pImage) 135 178 { 136 179 return pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser, … … 138 181 } 139 182 140 static int vciFileGetSize(PVCICACHE pImage, uint64_t *pcbSize) 141 { 142 return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser, 143 pImage->pStorage, 144 pcbSize); 145 } 146 147 static int vciFileSetSize(PVCICACHE pImage, uint64_t cbSize) 148 { 149 return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser, 150 pImage->pStorage, 151 cbSize); 152 } 153 154 155 static int vciFileWriteSync(PVCICACHE pImage, uint64_t off, const void *pcvBuf, size_t cbWrite, size_t *pcbWritten) 156 { 157 return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser, 158 pImage->pStorage, 159 off, cbWrite, pcvBuf, 160 pcbWritten); 161 } 162 163 static int vciFileReadSync(PVCICACHE pImage, uint64_t off, void *pvBuf, size_t cbRead, size_t *pcbRead) 164 { 165 return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser, 166 pImage->pStorage, 167 off, cbRead, pvBuf, 168 pcbRead); 169 } 170 171 static bool vciFileOpened(PVCICACHE pImage) 172 { 173 return pImage->pStorage != NULL; 183 DECLINLINE(int) vciFileReadUserAsync(PVCICACHE pImage, uint64_t uOffset, 184 PVDIOCTX pIoCtx, size_t cbRead) 185 { 186 return pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser, 187 pImage->pStorage, 188 uOffset, pIoCtx, 189 cbRead); 190 } 191 192 DECLINLINE(int) vciFileWriteUserAsync(PVCICACHE pImage, uint64_t uOffset, 193 PVDIOCTX pIoCtx, size_t cbWrite, 194 PFNVDXFERCOMPLETED pfnComplete, 195 void *pvCompleteUser) 196 { 197 return pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser, 198 pImage->pStorage, 199 uOffset, pIoCtx, 200 cbWrite, 201 pfnComplete, 202 pvCompleteUser); 203 } 204 205 DECLINLINE(int) vciFileFlushAsync(PVCICACHE pImage, PVDIOCTX pIoCtx, 206 PFNVDXFERCOMPLETED pfnComplete, 207 void *pvCompleteUser) 208 { 209 return pImage->pInterfaceIOCallbacks->pfnFlushAsync(pImage->pInterfaceIO->pvUser, 210 pImage->pStorage, 211 pIoCtx, pfnComplete, 212 pvCompleteUser); 213 } 214 215 216 /** 217 * Internal. Flush image data to disk. 218 */ 219 static int vciFlushImage(PVCICACHE pImage) 220 { 221 int rc = VINF_SUCCESS; 222 223 if ( pImage->pStorage 224 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 225 rc = vciFileFlushSync(pImage); 226 227 return rc; 228 } 229 230 /** 231 * Internal. Free all allocated space for representing an image except pImage, 232 * and optionally delete the image from disk. 233 */ 234 static int vciFreeImage(PVCICACHE pImage, bool fDelete) 235 { 236 int rc = VINF_SUCCESS; 237 238 /* Freeing a never allocated image (e.g. because the open failed) is 239 * not signalled as an error. After all nothing bad happens. */ 240 if (pImage) 241 { 242 if (pImage->pStorage) 243 { 244 /* No point updating the file that is deleted anyway. */ 245 if (!fDelete) 246 vciFlushImage(pImage); 247 248 vciFileClose(pImage); 249 pImage->pStorage = NULL; 250 } 251 252 if (fDelete && pImage->pszFilename) 253 vciFileDelete(pImage, pImage->pszFilename); 254 } 255 256 LogFlowFunc(("returns %Rrc\n", rc)); 257 return rc; 174 258 } 175 259 … … 181 265 int rc; 182 266 183 if (uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO)184 return VERR_NOT_SUPPORTED;185 186 267 pImage->uOpenFlags = uOpenFlags; 187 268 … … 190 271 pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError); 191 272 192 #ifdef VBOX_WITH_NEW_IO_CODE 193 /* Try to get I/O interface. */ 273 /* Get I/O interface. */ 194 274 pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IO); 195 AssertPtr (pImage->pInterfaceIO);275 AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER); 196 276 pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO); 197 AssertPtr(pImage->pInterfaceIOCallbacks); 198 #endif 277 AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER); 199 278 200 279 /* 201 280 * Open the image. 202 281 */ 203 rc = vciFileOpen(pImage, !!(uOpenFlags & VD_OPEN_FLAGS_READONLY), false); 282 rc = vciFileOpen(pImage, pImage->pszFilename, 283 VDOpenFlagsToFileOpenFlags(uOpenFlags, 284 false /* fCreate */)); 204 285 if (RT_FAILURE(rc)) 205 286 { … … 230 311 static int vciCreateImage(PVCICACHE pImage, uint64_t cbSize, 231 312 unsigned uImageFlags, const char *pszComment, 232 PFNVDPROGRESS pfnProgress, void *pvUser, 233 unsigned uPercentStart, unsigned uPercentSpan) 313 unsigned uOpenFlags, PFNVDPROGRESS pfnProgress, 314 void *pvUser, unsigned uPercentStart, 315 unsigned uPercentSpan) 234 316 { 235 317 int rc; … … 241 323 if (uImageFlags & VD_IMAGE_FLAGS_DIFF) 242 324 { 243 rc = vciError(pImage, VERR_VD_RAW_INVALID_TYPE, RT_SRC_POS, N_(" Raw: cannot create diff image '%s'"), pImage->pszFilename);325 rc = vciError(pImage, VERR_VD_RAW_INVALID_TYPE, RT_SRC_POS, N_("VCI: cannot create diff image '%s'"), pImage->pszFilename); 244 326 goto out; 245 327 } … … 247 329 248 330 pImage->uImageFlags = uImageFlags; 331 332 pImage->uOpenFlags = uOpenFlags & ~VD_OPEN_FLAGS_READONLY; 249 333 250 334 pImage->pInterfaceError = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ERROR); … … 252 336 pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError); 253 337 254 #ifdef VBOX_WITH_NEW_IO_CODE 255 /* Try to get async I/O interface. */ 338 /* Get I/O interface. */ 256 339 pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IO); 257 AssertPtr (pImage->pInterfaceIO);340 AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER); 258 341 pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO); 259 AssertPtr(pImage->pInterfaceIOCallbacks); 260 #endif 342 AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER); 261 343 262 344 /* Create image file. */ 263 rc = vciFileOpen(pImage, false, true); 345 rc = vciFileOpen(pImage, pImage->pszFilename, 346 VDOpenFlagsToFileOpenFlags(uOpenFlags & ~VD_OPEN_FLAGS_READONLY, 347 true /* fCreate */)); 264 348 if (RT_FAILURE(rc)) 265 349 { 266 rc = vciError(pImage, rc, RT_SRC_POS, N_(" Raw: cannot create image '%s'"), pImage->pszFilename);350 rc = vciError(pImage, rc, RT_SRC_POS, N_("VCI: cannot create image '%s'"), pImage->pszFilename); 267 351 goto out; 268 352 } … … 270 354 /* Check the free space on the disk and leave early if there is not 271 355 * sufficient space available. */ 272 rc = RTFsQuerySizes(pImage->pszFilename, NULL, &cbFree, NULL, NULL);356 rc = vciFileGetFreeSpace(pImage, pImage->pszFilename, &cbFree); 273 357 if (RT_SUCCESS(rc) /* ignore errors */ && ((uint64_t)cbFree < cbSize)) 274 358 { 275 rc = vciError(pImage, VERR_DISK_FULL, RT_SRC_POS, N_(" Raw: disk would overflow creating image '%s'"), pImage->pszFilename);359 rc = vciError(pImage, VERR_DISK_FULL, RT_SRC_POS, N_("VCI: disk would overflow creating image '%s'"), pImage->pszFilename); 276 360 goto out; 277 361 } … … 282 366 if (RT_FAILURE(rc)) 283 367 { 284 rc = vciError(pImage, rc, RT_SRC_POS, N_(" Raw: setting image size failed for '%s'"), pImage->pszFilename);368 rc = vciError(pImage, rc, RT_SRC_POS, N_("VCI: setting image size failed for '%s'"), pImage->pszFilename); 285 369 goto out; 286 370 } … … 306 390 if (RT_FAILURE(rc)) 307 391 { 308 rc = vciError(pImage, rc, RT_SRC_POS, N_(" Raw: writing block failed for '%s'"), pImage->pszFilename);392 rc = vciError(pImage, rc, RT_SRC_POS, N_("VCI: writing block failed for '%s'"), pImage->pszFilename); 309 393 goto out; 310 394 } … … 338 422 } 339 423 340 /**341 * Internal. Free all allocated space for representing an image, and optionally342 * delete the image from disk.343 */344 static void vciFreeImage(PVCICACHE pImage, bool fDelete)345 {346 Assert(pImage);347 348 if (vciFileOpened(pImage))349 {350 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))351 vciFlushImage(pImage);352 vciFileClose(pImage);353 }354 if (fDelete && pImage->pszFilename)355 RTFileDelete(pImage->pszFilename);356 }357 358 /**359 * Internal. Flush image data to disk.360 */361 static int vciFlushImage(PVCICACHE pImage)362 {363 int rc = VINF_SUCCESS;364 365 if ( vciFileOpened(pImage)366 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))367 rc = vciFileFlushSync(pImage);368 369 return rc;370 }371 372 424 373 425 /** @copydoc VDCACHEBACKEND::pfnProbe */ 374 static int vciProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk) 426 static int vciProbe(const char *pszFilename, PVDINTERFACE pVDIfsCache, 427 PVDINTERFACE pVDIfsImage) 375 428 { 376 429 LogFlowFunc(("pszFilename=\"%s\"\n", pszFilename)); … … 395 448 static int vciOpen(const char *pszFilename, unsigned uOpenFlags, 396 449 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage, 397 void **pp vBackendData)398 { 399 LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p pp vBackendData=%#p\n", pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, ppvBackendData));450 void **ppBackendData) 451 { 452 LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p ppBackendData=%#p\n", pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, ppBackendData)); 400 453 int rc; 401 454 PVCICACHE pImage; … … 424 477 } 425 478 pImage->pszFilename = pszFilename; 426 pImage->pStorage 427 pImage->pVDIfsDisk 479 pImage->pStorage = NULL; 480 pImage->pVDIfsDisk = pVDIfsDisk; 428 481 pImage->pVDIfsImage = pVDIfsImage; 429 482 430 483 rc = vciOpenImage(pImage, uOpenFlags); 431 484 if (RT_SUCCESS(rc)) 432 *pp vBackendData = pImage;485 *ppBackendData = pImage; 433 486 else 434 487 RTMemFree(pImage); 435 488 436 489 out: 437 LogFlowFunc(("returns %Rrc (p vBackendData=%#p)\n", rc, *ppvBackendData));490 LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData)); 438 491 return rc; 439 492 } … … 442 495 static int vciCreate(const char *pszFilename, uint64_t cbSize, 443 496 unsigned uImageFlags, const char *pszComment, 444 PCRTUUID pUuid, 445 unsigned uOpenFlags, unsigned uPercentStart, 446 unsigned uPercentSpan, PVDINTERFACE pVDIfsDisk, 447 PVDINTERFACE pVDIfsImage, PVDINTERFACE pVDIfsOperation, 448 void **ppvBackendData) 449 { 450 LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p ppvBackendData=%#p", 451 pszFilename, cbSize, uImageFlags, pszComment, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppvBackendData)); 497 PCRTUUID pUuid, unsigned uOpenFlags, 498 unsigned uPercentStart, unsigned uPercentSpan, 499 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage, 500 PVDINTERFACE pVDIfsOperation, void **ppBackendData) 501 { 502 LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p ppBackendData=%#p", 503 pszFilename, cbSize, uImageFlags, pszComment, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppBackendData)); 452 504 int rc; 453 505 PVCICACHE pImage; … … 488 540 } 489 541 pImage->pszFilename = pszFilename; 490 pImage->pStorage 491 pImage->pVDIfsDisk 542 pImage->pStorage = NULL; 543 pImage->pVDIfsDisk = pVDIfsDisk; 492 544 pImage->pVDIfsImage = pVDIfsImage; 493 545 494 rc = vciCreateImage(pImage, cbSize, uImageFlags, pszComment, 546 rc = vciCreateImage(pImage, cbSize, uImageFlags, pszComment, uOpenFlags, 495 547 pfnProgress, pvUser, uPercentStart, uPercentSpan); 496 548 if (RT_SUCCESS(rc)) … … 508 560 } 509 561 } 510 *pp vBackendData = pImage;562 *ppBackendData = pImage; 511 563 } 512 564 else … … 514 566 515 567 out: 516 LogFlowFunc(("returns %Rrc (p vBackendData=%#p)\n", rc, *ppvBackendData));568 LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData)); 517 569 return rc; 518 570 } 519 571 520 572 /** @copydoc VDCACHEBACKEND::pfnClose */ 521 static int vciClose(void *pvBackendData, bool fDelete) 522 { 523 LogFlowFunc(("pvBackendData=%#p fDelete=%d\n", pvBackendData, fDelete)); 524 PVCICACHE pImage = (PVCICACHE)pvBackendData; 525 int rc = VINF_SUCCESS; 526 527 /* Freeing a never allocated image (e.g. because the open failed) is 528 * not signalled as an error. After all nothing bad happens. */ 529 if (pImage) 530 { 531 vciFreeImage(pImage, fDelete); 532 RTMemFree(pImage); 533 } 573 static int vciClose(void *pBackendData, bool fDelete) 574 { 575 LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete)); 576 PVCICACHE pImage = (PVCICACHE)pBackendData; 577 int rc; 578 579 rc = vciFreeImage(pImage, fDelete); 580 RTMemFree(pImage); 534 581 535 582 LogFlowFunc(("returns %Rrc\n", rc)); … … 538 585 539 586 /** @copydoc VDCACHEBACKEND::pfnRead */ 540 static int vciRead(void *p vBackendData, uint64_t uOffset, void *pvBuf,587 static int vciRead(void *pBackendData, uint64_t uOffset, void *pvBuf, 541 588 size_t cbToRead, size_t *pcbActuallyRead) 542 589 { 543 LogFlowFunc(("p vBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pvBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));544 PVCICACHE pImage = (PVCICACHE)p vBackendData;545 int rc; 546 547 Assert (pImage);590 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead)); 591 PVCICACHE pImage = (PVCICACHE)pBackendData; 592 int rc; 593 594 AssertPtr(pImage); 548 595 Assert(uOffset % 512 == 0); 549 596 Assert(cbToRead % 512 == 0); … … 565 612 566 613 /** @copydoc VDCACHEBACKEND::pfnWrite */ 567 static int vciWrite(void *p vBackendData, uint64_t uOffset, const void *pvBuf,614 static int vciWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf, 568 615 size_t cbToWrite, size_t *pcbWriteProcess) 569 616 { 570 LogFlowFunc(("p vBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p\n",571 p vBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess));572 PVCICACHE pImage = (PVCICACHE)p vBackendData;573 int rc; 574 575 Assert (pImage);617 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p\n", 618 pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess)); 619 PVCICACHE pImage = (PVCICACHE)pBackendData; 620 int rc; 621 622 AssertPtr(pImage); 576 623 Assert(uOffset % 512 == 0); 577 624 Assert(cbToWrite % 512 == 0); … … 600 647 601 648 /** @copydoc VDCACHEBACKEND::pfnFlush */ 602 static int vciFlush(void *p vBackendData)603 { 604 LogFlowFunc(("p vBackendData=%#p\n", pvBackendData));605 PVCICACHE pImage = (PVCICACHE)p vBackendData;649 static int vciFlush(void *pBackendData) 650 { 651 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 652 PVCICACHE pImage = (PVCICACHE)pBackendData; 606 653 int rc; 607 654 … … 612 659 613 660 /** @copydoc VDCACHEBACKEND::pfnGetVersion */ 614 static unsigned vciGetVersion(void *p vBackendData)615 { 616 LogFlowFunc(("p vBackendData=%#p\n", pvBackendData));617 PVCICACHE pImage = (PVCICACHE)p vBackendData;618 619 Assert (pImage);661 static unsigned vciGetVersion(void *pBackendData) 662 { 663 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 664 PVCICACHE pImage = (PVCICACHE)pBackendData; 665 666 AssertPtr(pImage); 620 667 621 668 if (pImage) … … 626 673 627 674 /** @copydoc VDCACHEBACKEND::pfnGetSize */ 628 static uint64_t vciGetSize(void *pvBackendData) 629 { 630 LogFlowFunc(("pvBackendData=%#p\n", pvBackendData)); 631 PVCICACHE pImage = (PVCICACHE)pvBackendData; 632 633 Assert(pImage); 675 static uint64_t vciGetSize(void *pBackendData) 676 { 677 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 678 PVCICACHE pImage = (PVCICACHE)pBackendData; 679 uint64_t cb = 0; 680 681 AssertPtr(pImage); 682 683 if (pImage && pImage->pStorage) 684 cb = pImage->cbSize; 685 686 LogFlowFunc(("returns %llu\n", cb)); 687 return cb; 688 } 689 690 /** @copydoc VDCACHEBACKEND::pfnGetFileSize */ 691 static uint64_t vciGetFileSize(void *pBackendData) 692 { 693 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 694 PVCICACHE pImage = (PVCICACHE)pBackendData; 695 uint64_t cb = 0; 696 697 AssertPtr(pImage); 634 698 635 699 if (pImage) 636 return pImage->cbSize;637 else638 return 0;639 }640 641 /** @copydoc VDCACHEBACKEND::pfnGetFileSize */642 static uint64_t vciGetFileSize(void *pvBackendData)643 {644 LogFlowFunc(("pvBackendData=%#p\n", pvBackendData));645 PVCICACHE pImage = (PVCICACHE)pvBackendData;646 uint64_t cb = 0;647 648 Assert(pImage);649 650 if (pImage)651 700 { 652 701 uint64_t cbFile; 653 if ( vciFileOpened(pImage))702 if (pImage->pStorage) 654 703 { 655 704 int rc = vciFileGetSize(pImage, &cbFile); 656 705 if (RT_SUCCESS(rc)) 657 cb += cbFile;706 cb = cbFile; 658 707 } 659 708 } … … 664 713 665 714 /** @copydoc VDCACHEBACKEND::pfnGetImageFlags */ 666 static unsigned vciGetImageFlags(void *p vBackendData)667 { 668 LogFlowFunc(("p vBackendData=%#p\n", pvBackendData));669 PVCICACHE pImage = (PVCICACHE)p vBackendData;715 static unsigned vciGetImageFlags(void *pBackendData) 716 { 717 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 718 PVCICACHE pImage = (PVCICACHE)pBackendData; 670 719 unsigned uImageFlags; 671 720 672 Assert (pImage);721 AssertPtr(pImage); 673 722 674 723 if (pImage) … … 682 731 683 732 /** @copydoc VDCACHEBACKEND::pfnGetOpenFlags */ 684 static unsigned vciGetOpenFlags(void *p vBackendData)685 { 686 LogFlowFunc(("p vBackendData=%#p\n", pvBackendData));687 PVCICACHE pImage = (PVCICACHE)p vBackendData;733 static unsigned vciGetOpenFlags(void *pBackendData) 734 { 735 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 736 PVCICACHE pImage = (PVCICACHE)pBackendData; 688 737 unsigned uOpenFlags; 689 738 690 Assert (pImage);739 AssertPtr(pImage); 691 740 692 741 if (pImage) … … 700 749 701 750 /** @copydoc VDCACHEBACKEND::pfnSetOpenFlags */ 702 static int vciSetOpenFlags(void *p vBackendData, unsigned uOpenFlags)703 { 704 LogFlowFunc(("p vBackendData=%#p\n uOpenFlags=%#x", pvBackendData, uOpenFlags));705 PVCICACHE pImage = (PVCICACHE)p vBackendData;751 static int vciSetOpenFlags(void *pBackendData, unsigned uOpenFlags) 752 { 753 LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags)); 754 PVCICACHE pImage = (PVCICACHE)pBackendData; 706 755 int rc; 707 756 … … 715 764 716 765 /* Implement this operation via reopening the image. */ 717 vciFreeImage(pImage, false); 766 rc = vciFreeImage(pImage, false); 767 if (RT_FAILURE(rc)) 768 goto out; 718 769 rc = vciOpenImage(pImage, uOpenFlags); 719 770 … … 724 775 725 776 /** @copydoc VDCACHEBACKEND::pfnGetComment */ 726 static int vciGetComment(void *p vBackendData, char *pszComment,777 static int vciGetComment(void *pBackendData, char *pszComment, 727 778 size_t cbComment) 728 779 { 729 LogFlowFunc(("pvBackendData=%#p pszComment=%#p cbComment=%zu\n", pvBackendData, pszComment, cbComment)); 730 PVCICACHE pImage = (PVCICACHE)pvBackendData; 731 int rc; 732 733 Assert(pImage); 734 735 if (pImage) 736 { 737 if (pszComment) 738 *pszComment = '\0'; 739 rc = VINF_SUCCESS; 740 } 741 else 742 rc = VERR_VD_NOT_OPENED; 743 744 LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment)); 745 return rc; 746 } 747 748 /** @copydoc VDCACHEBACKEND::pfnSetComment */ 749 static int vciSetComment(void *pvBackendData, const char *pszComment) 750 { 751 LogFlowFunc(("pvBackendData=%#p pszComment=\"%s\"\n", pvBackendData, pszComment)); 752 PVCICACHE pImage = (PVCICACHE)pvBackendData; 753 int rc; 754 755 Assert(pImage); 756 757 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 758 { 759 rc = VERR_VD_IMAGE_READ_ONLY; 760 goto out; 761 } 780 LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment)); 781 PVCICACHE pImage = (PVCICACHE)pBackendData; 782 int rc; 783 784 AssertPtr(pImage); 762 785 763 786 if (pImage) … … 766 789 rc = VERR_VD_NOT_OPENED; 767 790 768 out: 769 LogFlowFunc(("returns %Rrc\n", rc)); 770 return rc; 771 } 772 773 /** @copydoc VDCACHEBACKEND::pfnGetUuid */ 774 static int vciGetUuid(void *pvBackendData, PRTUUID pUuid) 775 { 776 LogFlowFunc(("pvBackendData=%#p pUuid=%#p\n", pvBackendData, pUuid)); 777 PVCICACHE pImage = (PVCICACHE)pvBackendData; 778 int rc; 779 780 Assert(pImage); 791 LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment)); 792 return rc; 793 } 794 795 /** @copydoc VDCACHEBACKEND::pfnSetComment */ 796 static int vciSetComment(void *pBackendData, const char *pszComment) 797 { 798 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment)); 799 PVCICACHE pImage = (PVCICACHE)pBackendData; 800 int rc; 801 802 AssertPtr(pImage); 803 804 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 805 { 806 rc = VERR_VD_IMAGE_READ_ONLY; 807 goto out; 808 } 781 809 782 810 if (pImage) … … 785 813 rc = VERR_VD_NOT_OPENED; 786 814 815 out: 816 LogFlowFunc(("returns %Rrc\n", rc)); 817 return rc; 818 } 819 820 /** @copydoc VDCACHEBACKEND::pfnGetUuid */ 821 static int vciGetUuid(void *pBackendData, PRTUUID pUuid) 822 { 823 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 824 PVCICACHE pImage = (PVCICACHE)pBackendData; 825 int rc; 826 827 AssertPtr(pImage); 828 829 if (pImage) 830 rc = VERR_NOT_SUPPORTED; 831 else 832 rc = VERR_VD_NOT_OPENED; 833 787 834 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 788 835 return rc; … … 790 837 791 838 /** @copydoc VDCACHEBACKEND::pfnSetUuid */ 792 static int vciSetUuid(void *p vBackendData, PCRTUUID pUuid)793 { 794 LogFlowFunc(("p vBackendData=%#p Uuid=%RTuuid\n", pvBackendData, pUuid));795 PVCICACHE pImage = (PVCICACHE)p vBackendData;839 static int vciSetUuid(void *pBackendData, PCRTUUID pUuid) 840 { 841 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 842 PVCICACHE pImage = (PVCICACHE)pBackendData; 796 843 int rc; 797 844 798 845 LogFlowFunc(("%RTuuid\n", pUuid)); 799 Assert (pImage);846 AssertPtr(pImage); 800 847 801 848 if (pImage) … … 814 861 815 862 /** @copydoc VDCACHEBACKEND::pfnGetModificationUuid */ 816 static int vciGetModificationUuid(void *p vBackendData, PRTUUID pUuid)817 { 818 LogFlowFunc(("p vBackendData=%#p pUuid=%#p\n", pvBackendData, pUuid));819 PVCICACHE pImage = (PVCICACHE)p vBackendData;820 int rc; 821 822 Assert (pImage);863 static int vciGetModificationUuid(void *pBackendData, PRTUUID pUuid) 864 { 865 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 866 PVCICACHE pImage = (PVCICACHE)pBackendData; 867 int rc; 868 869 AssertPtr(pImage); 823 870 824 871 if (pImage) … … 832 879 833 880 /** @copydoc VDCACHEBACKEND::pfnSetModificationUuid */ 834 static int vciSetModificationUuid(void *p vBackendData, PCRTUUID pUuid)835 { 836 LogFlowFunc(("p vBackendData=%#p Uuid=%RTuuid\n", pvBackendData, pUuid));837 PVCICACHE pImage = (PVCICACHE)p vBackendData;838 int rc; 839 840 Assert (pImage);881 static int vciSetModificationUuid(void *pBackendData, PCRTUUID pUuid) 882 { 883 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 884 PVCICACHE pImage = (PVCICACHE)pBackendData; 885 int rc; 886 887 AssertPtr(pImage); 841 888 842 889 if (pImage) … … 855 902 856 903 /** @copydoc VDCACHEBACKEND::pfnDump */ 857 static void vciDump(void *pvBackendData) 858 { 859 NOREF(pvBackendData); 860 } 861 862 static int vciAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbRead, 904 static void vciDump(void *pBackendData) 905 { 906 NOREF(pBackendData); 907 } 908 909 /** @copydoc VDCACHEBACKEND::pfnAsyncRead */ 910 static int vciAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbRead, 863 911 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 864 912 { 865 913 int rc = VINF_SUCCESS; 866 PVCICACHE pImage = (PVCICACHE)pvBackendData; 867 868 rc = pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser, 869 pImage->pStorage, 870 uOffset, pIoCtx, cbRead); 914 PVCICACHE pImage = (PVCICACHE)pBackendData; 915 916 rc = vciFileReadUserAsync(pImage, uOffset, pIoCtx, cbRead); 871 917 if (RT_SUCCESS(rc)) 872 918 *pcbActuallyRead = cbRead; … … 875 921 } 876 922 877 static int vciAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbWrite, 923 /** @copydoc VDCACHEBACKEND::pfnAsyncWrite */ 924 static int vciAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbWrite, 878 925 PVDIOCTX pIoCtx, size_t *pcbWriteProcess) 879 926 { 880 927 int rc = VINF_SUCCESS; 881 PVCICACHE pImage = (PVCICACHE)pvBackendData; 882 883 rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser, 884 pImage->pStorage, 885 uOffset, pIoCtx, cbWrite, 886 NULL, NULL); 887 928 PVCICACHE pImage = (PVCICACHE)pBackendData; 929 930 rc = vciFileWriteUserAsync(pImage, uOffset, pIoCtx, cbWrite, NULL, NULL); 888 931 if (RT_SUCCESS(rc)) 889 932 *pcbWriteProcess = cbWrite; … … 892 935 } 893 936 894 static int vciAsyncFlush(void *pvBackendData, PVDIOCTX pIoCtx) 895 { 896 int rc = VERR_NOT_IMPLEMENTED; 897 LogFlowFunc(("returns %Rrc\n", rc)); 898 return rc; 899 } 937 /** @copydoc VDCACHEBACKEND::pfnAsyncFlush */ 938 static int vciAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx) 939 { 940 int rc = VINF_SUCCESS; 941 PVCICACHE pImage = (PVCICACHE)pBackendData; 942 943 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 944 rc = vciFileFlushAsync(pImage, pIoCtx, NULL, NULL); 945 946 return rc; 947 } 948 900 949 901 950 VDCACHEBACKEND g_VciCacheBackend = -
trunk/src/VBox/Devices/Storage/VDICore.h
r32388 r32536 5 5 6 6 /* 7 * Copyright (C) 2006-20 09Oracle Corporation7 * Copyright (C) 2006-2010 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 22 22 * Header Files * 23 23 *******************************************************************************/ 24 #ifndef VBOX_VDICORE_VD25 24 #include <VBox/VBoxHDD.h> 26 #else /* VBOX_VDICORE_VD */ 27 #include <VBox/VBoxHDD.h> 28 #endif /* VBOX_VDICORE_VD */ 25 #ifndef VBOX_VDICORE_VD 29 26 #include <VBox/pdm.h> 27 #endif /* !VBOX_VDICORE_VD */ 30 28 #include <VBox/mm.h> 31 29 #include <VBox/err.h> … … 35 33 #include <iprt/assert.h> 36 34 #include <iprt/uuid.h> 37 #include <iprt/file.h>38 35 #include <iprt/string.h> 39 36 #include <iprt/asm.h> … … 192 189 /** Image comment. (UTF-8) */ 193 190 char szComment[VDI_IMAGE_COMMENT_SIZE]; 194 /** Offset of Blocks array from the begining of image file.191 /** Offset of blocks array from the begining of image file. 195 192 * Should be sector-aligned for HDD access optimization. */ 196 193 uint32_t offBlocks; … … 241 238 } VDIHEADER, *PVDIHEADER; 242 239 240 /** 241 * File alignment boundary for both the block array and data area. Should be 242 * at least the size of a physical sector on disk for performance reasons. 243 * With the growing market share of disks with 4K sectors this needs to be 244 * bumped, and maybe again later. */ 245 #define VDI_DATA_ALIGN _4K 246 243 247 /** Block 'pointer'. */ 244 248 typedef uint32_t VDIIMAGEBLOCKPOINTER; … … 555 559 struct VDIIMAGEDESC *pNext; 556 560 #endif /* !VBOX_VDICORE_VD */ 557 #ifndef VBOX_WITH_NEW_IO_CODE558 /** File handle. */559 RTFILE File;560 #else561 561 /** Opaque storage handle. */ 562 562 PVDIOSTORAGE pStorage; 563 #endif564 563 #ifndef VBOX_VDICORE_VD 565 564 /** True if the image is operating in readonly mode. */ … … 568 567 unsigned fOpen; 569 568 #else /* VBOX_VDICORE_VD */ 570 /** Image open flags, VD_ _OPEN_FLAGS_*. */569 /** Image open flags, VD_OPEN_FLAGS_*. */ 571 570 unsigned uOpenFlags; 572 571 #endif /* VBOX_VDICORE_VD */ … … 610 609 const char *pszFilename; 611 610 /** Physical geometry of this image (never actually stored). */ 612 PDMMEDIAGEOMETRYPCHSGeometry;611 VDGEOMETRY PCHSGeometry; 613 612 /** Pointer to the per-disk VD interface list. */ 614 613 PVDINTERFACE pVDIfsDisk; … … 619 618 /** Error interface callback table. */ 620 619 PVDINTERFACEERROR pInterfaceErrorCallbacks; 621 # ifdef VBOX_WITH_NEW_IO_CODE622 620 /** I/O interface. */ 623 621 PVDINTERFACE pInterfaceIO; 624 622 /** I/O interface callbacks. */ 625 623 PVDINTERFACEIO pInterfaceIOCallbacks; 626 # endif627 624 #endif /* VBOX_VDICORE_VD */ 628 625 } VDIIMAGEDESC, *PVDIIMAGEDESC; … … 673 670 bool fHonorZeroWrites; 674 671 672 #ifndef VBOX_VDICORE_VD 675 673 /** The media interface. */ 676 674 PDMIMEDIA IMedia; 677 675 /** Pointer to the driver instance. */ 678 676 PPDMDRVINS pDrvIns; 677 #endif /* !VBOX_VDICORE_VD */ 679 678 }; 680 679 -
trunk/src/VBox/Devices/Storage/VDIHDDCore.cpp
r32431 r32536 28 28 #include <iprt/assert.h> 29 29 #include <iprt/uuid.h> 30 #include <iprt/file.h>31 30 #include <iprt/string.h> 32 31 #include <iprt/asm.h> … … 58 57 static int vdiUpdateHeader(PVDIIMAGEDESC pImage); 59 58 static int vdiUpdateBlockInfo(PVDIIMAGEDESC pImage, unsigned uBlock); 60 static void vdiFreeImage(PVDIIMAGEDESC pImage, bool fDelete);61 59 static int vdiUpdateHeaderAsync(PVDIIMAGEDESC pImage, PVDIOCTX pIoCtx); 62 60 static int vdiUpdateBlockInfoAsync(PVDIIMAGEDESC pImage, unsigned uBlock, PVDIOCTX pIoCtx); … … 78 76 } 79 77 80 81 static int vdiFileOpen(PVDIIMAGEDESC pImage, bool fReadonly, bool fShareable, 82 bool fCreate) 78 /** 79 * Internal: signal an informational message to the frontend. 80 */ 81 DECLINLINE(int) vdiMessage(PVDIIMAGEDESC pImage, const char *pszFormat, ...) 83 82 { 84 83 int rc = VINF_SUCCESS; 85 86 AssertMsg(!(fReadonly && fCreate), ("Image can't be opened readonly while being created\n")); 87 88 #ifndef VBOX_WITH_NEW_IO_CODE 89 uint32_t fDeny = fReadonly | fShareable ? RTFILE_O_DENY_NONE : RTFILE_O_DENY_WRITE; 90 uint32_t fOpen = fReadonly ? RTFILE_O_READ : RTFILE_O_READWRITE; 91 fOpen |= fDeny; 92 93 if (fCreate) 94 fOpen |= RTFILE_O_CREATE; 95 else 96 fOpen |= RTFILE_O_OPEN; 97 98 rc = RTFileOpen(&pImage->File, pImage->pszFilename, fOpen); 99 #else 100 unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0; 101 102 if (fCreate) 103 uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE; 104 105 if (fShareable) 106 uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_DONT_LOCK; 107 108 rc = pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser, 109 pImage->pszFilename, 110 uOpenFlags, 111 &pImage->pStorage); 112 #endif 113 114 return rc; 115 } 116 117 static int vdiFileClose(PVDIIMAGEDESC pImage) 118 { 119 int rc = VINF_SUCCESS; 120 121 #ifndef VBOX_WITH_NEW_IO_CODE 122 if (pImage->File != NIL_RTFILE) 123 rc = RTFileClose(pImage->File); 124 125 pImage->File = NIL_RTFILE; 126 #else 127 rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser, 128 pImage->pStorage); 129 130 pImage->pStorage = NULL; 131 #endif 132 133 return rc; 134 } 135 136 static int vdiFileFlushSync(PVDIIMAGEDESC pImage) 137 { 138 int rc = VINF_SUCCESS; 139 140 #ifndef VBOX_WITH_NEW_IO_CODE 141 rc = RTFileFlush(pImage->File); 142 #else 143 rc = pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser, 144 pImage->pStorage); 145 #endif 146 147 return rc; 148 } 149 150 static int vdiFileGetSize(PVDIIMAGEDESC pImage, uint64_t *pcbSize) 151 { 152 int rc = VINF_SUCCESS; 153 154 #ifndef VBOX_WITH_NEW_IO_CODE 155 rc = RTFileGetSize(pImage->File, pcbSize); 156 #else 157 rc = pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser, 158 pImage->pStorage, 159 pcbSize); 160 #endif 161 162 return rc; 163 } 164 165 static int vdiFileSetSize(PVDIIMAGEDESC pImage, uint64_t cbSize) 166 { 167 int rc = VINF_SUCCESS; 168 169 #ifndef VBOX_WITH_NEW_IO_CODE 170 rc = RTFileSetSize(pImage->File, cbSize); 171 #else 172 rc = pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser, 173 pImage->pStorage, 174 cbSize); 175 #endif 176 177 return rc; 178 } 179 180 static int vdiFileWriteSync(PVDIIMAGEDESC pImage, uint64_t off, const void *pcvBuf, size_t cbWrite, size_t *pcbWritten) 181 { 182 int rc = VINF_SUCCESS; 183 184 #ifndef VBOX_WITH_NEW_IO_CODE 185 rc = RTFileWriteAt(pImage->File, off, pcvBuf, cbWrite, pcbWritten); 186 #else 187 rc = pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser, 188 pImage->pStorage, 189 off, cbWrite, pcvBuf, 190 pcbWritten); 191 #endif 192 193 return rc; 194 } 195 196 static int vdiFileReadSync(PVDIIMAGEDESC pImage, uint64_t off, void *pvBuf, size_t cbRead, size_t *pcbRead) 197 { 198 int rc = VINF_SUCCESS; 199 200 #ifndef VBOX_WITH_NEW_IO_CODE 201 rc = RTFileReadAt(pImage->File, off, pvBuf, cbRead, pcbRead); 202 #else 203 rc = pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser, 204 pImage->pStorage, 205 off, cbRead, pvBuf, 206 pcbRead); 207 #endif 208 209 return rc; 210 } 211 212 static int vdiFileWriteMetaAsync(PVDIIMAGEDESC pImage, uint64_t off, void *pcvBuf, size_t cbWrite, 213 PVDIOCTX pIoCtx) 84 va_list va; 85 va_start(va, pszFormat); 86 if (pImage->pInterfaceError && pImage->pInterfaceErrorCallbacks) 87 rc = pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, 88 pszFormat, va); 89 va_end(va); 90 return rc; 91 } 92 93 94 DECLINLINE(int) vdiFileOpen(PVDIIMAGEDESC pImage, const char *pszFilename, 95 uint32_t fOpen) 96 { 97 return pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser, 98 pszFilename, fOpen, 99 &pImage->pStorage); 100 } 101 102 DECLINLINE(int) vdiFileClose(PVDIIMAGEDESC pImage) 103 { 104 return pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser, 105 pImage->pStorage); 106 } 107 108 DECLINLINE(int) vdiFileDelete(PVDIIMAGEDESC pImage, const char *pszFilename) 109 { 110 return pImage->pInterfaceIOCallbacks->pfnDelete(pImage->pInterfaceIO->pvUser, 111 pszFilename); 112 } 113 114 DECLINLINE(int) vdiFileMove(PVDIIMAGEDESC pImage, const char *pszSrc, 115 const char *pszDst, unsigned fMove) 116 { 117 return pImage->pInterfaceIOCallbacks->pfnMove(pImage->pInterfaceIO->pvUser, 118 pszSrc, pszDst, fMove); 119 } 120 121 DECLINLINE(int) vdiFileGetFreeSpace(PVDIIMAGEDESC pImage, const char *pszFilename, 122 int64_t *pcbFree) 123 { 124 return pImage->pInterfaceIOCallbacks->pfnGetFreeSpace(pImage->pInterfaceIO->pvUser, 125 pszFilename, pcbFree); 126 } 127 128 DECLINLINE(int) vdiFileGetSize(PVDIIMAGEDESC pImage, uint64_t *pcbSize) 129 { 130 return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser, 131 pImage->pStorage, pcbSize); 132 } 133 134 DECLINLINE(int) vdiFileSetSize(PVDIIMAGEDESC pImage, uint64_t cbSize) 135 { 136 return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser, 137 pImage->pStorage, cbSize); 138 } 139 140 DECLINLINE(int) vdiFileWriteSync(PVDIIMAGEDESC pImage, uint64_t uOffset, 141 const void *pvBuffer, size_t cbBuffer, 142 size_t *pcbWritten) 143 { 144 return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser, 145 pImage->pStorage, uOffset, 146 pvBuffer, cbBuffer, pcbWritten); 147 } 148 149 DECLINLINE(int) vdiFileReadSync(PVDIIMAGEDESC pImage, uint64_t uOffset, 150 void *pvBuffer, size_t cbBuffer, size_t *pcbRead) 151 { 152 return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser, 153 pImage->pStorage, uOffset, 154 pvBuffer, cbBuffer, pcbRead); 155 } 156 157 DECLINLINE(int) vdiFileFlushSync(PVDIIMAGEDESC pImage) 158 { 159 return pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser, 160 pImage->pStorage); 161 } 162 163 DECLINLINE(int) vdiFileReadUserAsync(PVDIIMAGEDESC pImage, uint64_t uOffset, 164 PVDIOCTX pIoCtx, size_t cbRead) 165 { 166 return pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser, 167 pImage->pStorage, 168 uOffset, pIoCtx, 169 cbRead); 170 } 171 172 DECLINLINE(int) vdiFileWriteUserAsync(PVDIIMAGEDESC pImage, uint64_t uOffset, 173 PVDIOCTX pIoCtx, size_t cbWrite, 174 PFNVDXFERCOMPLETED pfnComplete, 175 void *pvCompleteUser) 176 { 177 return pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser, 178 pImage->pStorage, 179 uOffset, pIoCtx, 180 cbWrite, 181 pfnComplete, 182 pvCompleteUser); 183 } 184 185 DECLINLINE(int) vdiFileWriteMetaAsync(PVDIIMAGEDESC pImage, uint64_t uOffset, 186 void *pvBuffer, size_t cbBuffer, 187 PVDIOCTX pIoCtx, 188 PFNVDXFERCOMPLETED pfnComplete, 189 void *pvCompleteUser) 214 190 { 215 191 return pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pImage->pInterfaceIO->pvUser, 216 192 pImage->pStorage, 217 off, pcvBuf, cbWrite, pIoCtx, 218 NULL, NULL); 219 } 220 221 static int vdiFileReadMetaAsync(PVDIIMAGEDESC pImage, uint64_t off, void *pvBuf, size_t cbRead, 222 PVDIOCTX pIoCtx) 223 { 224 return pImage->pInterfaceIOCallbacks->pfnReadMetaAsync(pImage->pInterfaceIO->pvUser, 225 pImage->pStorage, 226 off, pvBuf, cbRead, pIoCtx, 227 NULL, NULL, NULL); 228 } 229 230 static bool vdiFileOpened(PVDIIMAGEDESC pImage) 231 { 232 #ifndef VBOX_WITH_NEW_IO_CODE 233 return pImage->File != NIL_RTFILE; 234 #else 235 return pImage->pStorage != NULL; 236 #endif 237 } 238 239 static int vdiFileFlushAsync(PVDIIMAGEDESC pImage, PVDIOCTX pIoCtx) 193 uOffset, pvBuffer, 194 cbBuffer, pIoCtx, 195 pfnComplete, 196 pvCompleteUser); 197 } 198 199 DECLINLINE(int) vdiFileFlushAsync(PVDIIMAGEDESC pImage, PVDIOCTX pIoCtx, 200 PFNVDXFERCOMPLETED pfnComplete, 201 void *pvCompleteUser) 240 202 { 241 203 return pImage->pInterfaceIOCallbacks->pfnFlushAsync(pImage->pInterfaceIO->pvUser, 242 pImage->pStorage, pIoCtx, 243 NULL, NULL); 244 } 245 204 pImage->pStorage, 205 pIoCtx, pfnComplete, 206 pvCompleteUser); 207 } 208 209 DECLINLINE(size_t) vdiFileIoCtxSet(PVDIIMAGEDESC pImage, PVDIOCTX pIoCtx, 210 int ch, size_t cbSet) 211 { 212 return pImage->pInterfaceIOCallbacks->pfnIoCtxSet(pImage->pInterfaceIO->pvUser, 213 pIoCtx, ch, cbSet); 214 } 215 216 217 /** 218 * Internal: Flush the image file to disk. 219 */ 220 static void vdiFlushImage(PVDIIMAGEDESC pImage) 221 { 222 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 223 { 224 /* Save header. */ 225 int rc = vdiUpdateHeader(pImage); 226 AssertMsgRC(rc, ("vdiUpdateHeader() failed, filename=\"%s\", rc=%Rrc\n", 227 pImage->pszFilename, rc)); 228 vdiFileFlushSync(pImage); 229 } 230 } 231 232 /** 233 * Internal: Free all allocated space for representing an image, and optionally 234 * delete the image from disk. 235 */ 236 static int vdiFreeImage(PVDIIMAGEDESC pImage, bool fDelete) 237 { 238 int rc = VINF_SUCCESS; 239 240 /* Freeing a never allocated image (e.g. because the open failed) is 241 * not signalled as an error. After all nothing bad happens. */ 242 if (pImage) 243 { 244 if (pImage->pStorage) 245 { 246 /* No point updating the file that is deleted anyway. */ 247 if (!fDelete) 248 vdiFlushImage(pImage); 249 250 vdiFileClose(pImage); 251 pImage->pStorage = NULL; 252 } 253 254 if (pImage->paBlocks) 255 { 256 RTMemFree(pImage->paBlocks); 257 pImage->paBlocks = NULL; 258 } 259 260 if (fDelete && pImage->pszFilename) 261 vdiFileDelete(pImage, pImage->pszFilename); 262 } 263 264 LogFlowFunc(("returns %Rrc\n", rc)); 265 return rc; 266 } 246 267 247 268 /** … … 260 281 return uNumber == 1 ? uPower2 : 0; 261 282 } 262 263 283 264 284 /** … … 360 380 361 381 /* Init offsets. */ 362 pHeader->u.v1.offBlocks = RT_ALIGN_32(sizeof(VDIPREHEADER) + sizeof(VDIHEADER1), VDI_ GEOMETRY_SECTOR_SIZE);363 pHeader->u.v1.offData = RT_ALIGN_32(pHeader->u.v1.offBlocks + (pHeader->u.v1.cBlocks * sizeof(VDIIMAGEBLOCKPOINTER)), VDI_ GEOMETRY_SECTOR_SIZE);382 pHeader->u.v1.offBlocks = RT_ALIGN_32(sizeof(VDIPREHEADER) + sizeof(VDIHEADER1), VDI_DATA_ALIGN); 383 pHeader->u.v1.offData = RT_ALIGN_32(pHeader->u.v1.offBlocks + (pHeader->u.v1.cBlocks * sizeof(VDIIMAGEBLOCKPOINTER)), VDI_DATA_ALIGN); 364 384 365 385 /* Init uuids. */ … … 517 537 static int vdiCreateImage(PVDIIMAGEDESC pImage, uint64_t cbSize, 518 538 unsigned uImageFlags, const char *pszComment, 519 PC PDMMEDIAGEOMETRY pPCHSGeometry,520 PC PDMMEDIAGEOMETRY pLCHSGeometry, PCRTUUID pUuid,539 PCVDGEOMETRY pPCHSGeometry, 540 PCVDGEOMETRY pLCHSGeometry, PCRTUUID pUuid, 521 541 unsigned uOpenFlags, PFNVDPROGRESS pfnProgress, 522 542 void *pvUser, unsigned uPercentStart, … … 542 562 pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError); 543 563 544 #ifdef VBOX_WITH_NEW_IO_CODE 545 /* Try to get I/O interface. */ 564 /* Get I/O interface. */ 546 565 pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IO); 547 AssertPtr (pImage->pInterfaceIO);566 AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER); 548 567 pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO); 549 AssertPtr(pImage->pInterfaceIOCallbacks); 550 #endif 568 AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER); 551 569 552 570 vdiInitPreHeader(&pImage->PreHeader); … … 586 604 587 605 /* Create image file. */ 588 rc = vdiFileOpen(pImage, false /* fReadonly */,589 !!(uOpenFlags & VD_OPEN_FLAGS_SHAREABLE),590 true /* fCreate */);606 rc = vdiFileOpen(pImage, pImage->pszFilename, 607 VDOpenFlagsToFileOpenFlags(uOpenFlags & ~VD_OPEN_FLAGS_READONLY, 608 true /* fCreate */)); 591 609 if (RT_FAILURE(rc)) 592 610 { … … 602 620 /* Check the free space on the disk and leave early if there is not 603 621 * sufficient space available. */ 604 RTFOFFcbFree = 0;605 rc = RTFsQuerySizes(pImage->pszFilename, NULL, &cbFree, NULL, NULL);622 int64_t cbFree = 0; 623 rc = vdiFileGetFreeSpace(pImage, pImage->pszFilename, &cbFree); 606 624 if (RT_SUCCESS(rc) /* ignore errors */ && ((uint64_t)cbFree < cbTotal)) 607 625 { … … 645 663 646 664 /* Write header. */ 647 rc = vdiFileWriteSync(pImage, sizeof(pImage->PreHeader), &pImage->Header.u.v1plus, sizeof(pImage->Header.u.v1plus), NULL); 665 rc = vdiFileWriteSync(pImage, sizeof(pImage->PreHeader), 666 &pImage->Header.u.v1plus, 667 sizeof(pImage->Header.u.v1plus), NULL); 648 668 if (RT_FAILURE(rc)) 649 669 { … … 652 672 } 653 673 654 rc = vdiFileWriteSync(pImage, pImage->offStartBlocks, 655 pImage->paBlocks, 674 rc = vdiFileWriteSync(pImage, pImage->offStartBlocks, pImage->paBlocks, 656 675 getImageBlocks(&pImage->Header) * sizeof(VDIIMAGEBLOCKPOINTER), 657 676 NULL); … … 730 749 pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError); 731 750 732 #ifdef VBOX_WITH_NEW_IO_CODE 733 /* Try to get I/O interface. */ 751 /* Get I/O interface. */ 734 752 pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IO); 735 AssertPtr (pImage->pInterfaceIO);753 AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER); 736 754 pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO); 737 AssertPtr(pImage->pInterfaceIOCallbacks); 738 #endif 755 AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER); 739 756 740 757 /* 741 758 * Open the image. 742 759 */ 743 rc = vdiFileOpen(pImage, 744 !!(uOpenFlags & VD_OPEN_FLAGS_READONLY), 745 !!(uOpenFlags & VD_OPEN_FLAGS_SHAREABLE), 746 false /* fCreate */); 760 rc = vdiFileOpen(pImage, pImage->pszFilename, 761 VDOpenFlagsToFileOpenFlags(uOpenFlags, false /* fCreate */)); 747 762 if (RT_FAILURE(rc)) 748 763 { … … 753 768 754 769 /* Read pre-header. */ 755 rc = vdiFileReadSync(pImage, 0, &pImage->PreHeader, sizeof(pImage->PreHeader), 756 NULL); 770 rc = vdiFileReadSync(pImage, 0, &pImage->PreHeader, sizeof(pImage->PreHeader), NULL); 757 771 if (RT_FAILURE(rc)) 758 772 { … … 807 821 { 808 822 /* Read the actual VDI 1.1+ header completely. */ 809 rc = vdiFileReadSync(pImage, sizeof(pImage->PreHeader), &pImage->Header.u.v1plus, sizeof(pImage->Header.u.v1plus), NULL); 823 rc = vdiFileReadSync(pImage, sizeof(pImage->PreHeader), 824 &pImage->Header.u.v1plus, 825 sizeof(pImage->Header.u.v1plus), NULL); 810 826 if (RT_FAILURE(rc)) 811 827 { … … 858 874 { 859 875 case 0: 860 rc = vdiFileWriteSync(pImage, sizeof(VDIPREHEADER), &pImage->Header.u.v0, sizeof(pImage->Header.u.v0), NULL); 876 rc = vdiFileWriteSync(pImage, sizeof(VDIPREHEADER), 877 &pImage->Header.u.v0, sizeof(pImage->Header.u.v0), 878 NULL); 861 879 break; 862 880 case 1: 863 881 if (pImage->Header.u.v1plus.cbHeader < sizeof(pImage->Header.u.v1plus)) 864 rc = vdiFileWriteSync(pImage, sizeof(VDIPREHEADER), &pImage->Header.u.v1, sizeof(pImage->Header.u.v1), NULL); 882 rc = vdiFileWriteSync(pImage, sizeof(VDIPREHEADER), 883 &pImage->Header.u.v1, sizeof(pImage->Header.u.v1), 884 NULL); 865 885 else 866 rc = vdiFileWriteSync(pImage, sizeof(VDIPREHEADER), &pImage->Header.u.v1plus, sizeof(pImage->Header.u.v1plus), NULL); 886 rc = vdiFileWriteSync(pImage, sizeof(VDIPREHEADER), 887 &pImage->Header.u.v1plus, sizeof(pImage->Header.u.v1plus), 888 NULL); 867 889 break; 868 890 default: … … 884 906 case 0: 885 907 rc = vdiFileWriteMetaAsync(pImage, sizeof(VDIPREHEADER), 886 &pImage->Header.u.v0, sizeof(pImage->Header.u.v0),887 pIoCtx);888 908 &pImage->Header.u.v0, 909 sizeof(pImage->Header.u.v0), 910 pIoCtx, NULL, NULL); 889 911 break; 890 912 case 1: 891 913 if (pImage->Header.u.v1plus.cbHeader < sizeof(pImage->Header.u.v1plus)) 892 914 rc = vdiFileWriteMetaAsync(pImage, sizeof(VDIPREHEADER), 893 &pImage->Header.u.v1, sizeof(pImage->Header.u.v1), 894 pIoCtx); 915 &pImage->Header.u.v1, 916 sizeof(pImage->Header.u.v1), 917 pIoCtx, NULL, NULL); 895 918 else 896 919 rc = vdiFileWriteMetaAsync(pImage, sizeof(VDIPREHEADER), 897 &pImage->Header.u.v1plus, sizeof(pImage->Header.u.v1plus), 898 pIoCtx); 920 &pImage->Header.u.v1plus, 921 sizeof(pImage->Header.u.v1plus), 922 pIoCtx, NULL, NULL); 899 923 break; 900 924 default: … … 917 941 { 918 942 /* write only one block pointer. */ 919 rc = vdiFileWriteSync(pImage, 920 pImage->offStartBlocks + uBlock * sizeof(VDIIMAGEBLOCKPOINTER), 921 &pImage->paBlocks[uBlock], 922 sizeof(VDIIMAGEBLOCKPOINTER), 943 rc = vdiFileWriteSync(pImage, pImage->offStartBlocks + uBlock * sizeof(VDIIMAGEBLOCKPOINTER), 944 &pImage->paBlocks[uBlock], sizeof(VDIIMAGEBLOCKPOINTER), 923 945 NULL); 924 946 AssertMsgRC(rc, ("vdiUpdateBlockInfo failed to update block=%u, filename=\"%s\", rc=%Rrc\n", … … 943 965 &pImage->paBlocks[uBlock], 944 966 sizeof(VDIIMAGEBLOCKPOINTER), 945 pIoCtx );967 pIoCtx, NULL, NULL); 946 968 AssertMsg(RT_SUCCESS(rc) || rc == VERR_VD_ASYNC_IO_IN_PROGRESS, 947 969 ("vdiUpdateBlockInfo failed to update block=%u, filename=\"%s\", rc=%Rrc\n", … … 949 971 } 950 972 return rc; 951 }952 953 /**954 * Internal: Flush the image file to disk.955 */956 static void vdiFlushImage(PVDIIMAGEDESC pImage)957 {958 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))959 {960 /* Save header. */961 int rc = vdiUpdateHeader(pImage);962 AssertMsgRC(rc, ("vdiUpdateHeader() failed, filename=\"%s\", rc=%Rrc\n",963 pImage->pszFilename, rc));964 vdiFileFlushSync(pImage);965 }966 973 } 967 974 … … 980 987 ("vdiUpdateHeaderAsync() failed, filename=\"%s\", rc=%Rrc\n", 981 988 pImage->pszFilename, rc)); 982 rc = vdiFileFlushAsync(pImage, pIoCtx );989 rc = vdiFileFlushAsync(pImage, pIoCtx, NULL, NULL); 983 990 AssertMsg(RT_SUCCESS(rc) || rc == VERR_VD_ASYNC_IO_IN_PROGRESS, 984 991 ("Flushing data to disk failed rc=%Rrc\n", rc)); … … 988 995 } 989 996 990 /**991 * Internal: Free all allocated space for representing an image, and optionally992 * delete the image from disk.993 */994 static void vdiFreeImage(PVDIIMAGEDESC pImage, bool fDelete)995 {996 AssertPtr(pImage);997 998 if (vdiFileOpened(pImage))999 {1000 vdiFlushImage(pImage);1001 vdiFileClose(pImage);1002 }1003 if (pImage->paBlocks)1004 {1005 RTMemFree(pImage->paBlocks);1006 pImage->paBlocks = NULL;1007 }1008 if (fDelete && pImage->pszFilename)1009 RTFileDelete(pImage->pszFilename);1010 }1011 1012 997 1013 998 /** @copydoc VBOXHDDBACKEND::pfnCheckIfValid */ 1014 static int vdiCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk) 999 static int vdiCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk, 1000 PVDINTERFACE pVDIfsImage) 1015 1001 { 1016 1002 LogFlowFunc(("pszFilename=\"%s\"\n", pszFilename)); … … 1032 1018 } 1033 1019 pImage->pszFilename = pszFilename; 1034 #ifndef VBOX_WITH_NEW_IO_CODE1035 pImage->File = NIL_RTFILE;1036 #else1037 1020 pImage->pStorage = NULL; 1038 #endif1039 1021 pImage->paBlocks = NULL; 1040 1022 pImage->pVDIfsDisk = pVDIfsDisk; 1041 /* For the async I/O interface which is normally retrieved from the image interface list. */ 1042 pImage->pVDIfsImage = pVDIfsDisk; 1023 pImage->pVDIfsImage = pVDIfsImage; 1043 1024 1044 1025 rc = vdiOpenImage(pImage, VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_READONLY); … … 1082 1063 } 1083 1064 pImage->pszFilename = pszFilename; 1084 #ifndef VBOX_WITH_NEW_IO_CODE1085 pImage->File = NIL_RTFILE;1086 #else1087 1065 pImage->pStorage = NULL; 1088 #endif1089 1066 pImage->paBlocks = NULL; 1090 1067 pImage->pVDIfsDisk = pVDIfsDisk; … … 1103 1080 static int vdiCreate(const char *pszFilename, uint64_t cbSize, 1104 1081 unsigned uImageFlags, const char *pszComment, 1105 PCPDMMEDIAGEOMETRY pPCHSGeometry, 1106 PCPDMMEDIAGEOMETRY pLCHSGeometry, PCRTUUID pUuid, 1107 unsigned uOpenFlags, unsigned uPercentStart, 1108 unsigned uPercentSpan, PVDINTERFACE pVDIfsDisk, 1109 PVDINTERFACE pVDIfsImage, PVDINTERFACE pVDIfsOperation, 1110 void **ppBackendData) 1082 PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry, 1083 PCRTUUID pUuid, unsigned uOpenFlags, 1084 unsigned uPercentStart, unsigned uPercentSpan, 1085 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage, 1086 PVDINTERFACE pVDIfsOperation, void **ppBackendData) 1111 1087 { 1112 1088 LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p ppBackendData=%#p", pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppBackendData)); … … 1134 1110 } 1135 1111 1136 /* Check size. Maximum 2PB-3M (to be on the safe side). No tricks with 1137 * adjusting the 1M block size so far, which would extend the size. */ 1112 /* Check size. Maximum 4PB-3M. No tricks with adjusting the 1M block size 1113 * so far, which would extend the size. */ 1114 cbSize = RT_ALIGN_64(cbSize, _1M); 1138 1115 if ( !cbSize 1139 1116 || cbSize >= _1P * 2 - _1M * 3) … … 1161 1138 } 1162 1139 pImage->pszFilename = pszFilename; 1163 #ifndef VBOX_WITH_NEW_IO_CODE1164 pImage->File = NIL_RTFILE;1165 #else1166 1140 pImage->pStorage = NULL; 1167 #endif1168 1141 pImage->paBlocks = NULL; 1169 1142 pImage->pVDIfsDisk = pVDIfsDisk; … … 1182 1155 rc = vdiOpenImage(pImage, uOpenFlags); 1183 1156 if (RT_FAILURE(rc)) 1157 { 1158 RTMemFree(pImage); 1184 1159 goto out; 1160 } 1185 1161 } 1186 1162 *ppBackendData = pImage; … … 1215 1191 1216 1192 /* Rename the file. */ 1217 rc = RTFileMove(pImage->pszFilename, pszFilename, 0);1193 rc = vdiFileMove(pImage, pImage->pszFilename, pszFilename, 0); 1218 1194 if (RT_FAILURE(rc)) 1219 1195 { … … 1244 1220 LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete)); 1245 1221 PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData; 1246 int rc = VINF_SUCCESS; 1247 1248 /* Freeing a never allocated image (e.g. because the open failed) is 1249 * not signalled as an error. After all nothing bad happens. */ 1250 if (pImage) 1251 { 1252 vdiFreeImage(pImage, fDelete); 1253 RTMemFree(pImage); 1254 } 1222 int rc; 1223 1224 rc = vdiFreeImage(pImage, fDelete); 1225 RTMemFree(pImage); 1255 1226 1256 1227 LogFlowFunc(("returns %Rrc\n", rc)); … … 1340 1311 /* No size check here, will do that later. For dynamic images which are 1341 1312 * not multiples of the block size in length, this would prevent writing to 1342 * the last grain. */1313 * the last block. */ 1343 1314 1344 1315 /* Calculate starting block number and offset inside it. */ … … 1481 1452 { 1482 1453 uint64_t cbFile; 1483 if ( vdiFileOpened(pImage))1454 if (pImage->pStorage) 1484 1455 { 1485 1456 int rc = vdiFileGetSize(pImage, &cbFile); … … 1494 1465 1495 1466 /** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */ 1496 static int vdiGetPCHSGeometry(void *pBackendData, 1497 PPDMMEDIAGEOMETRY pPCHSGeometry) 1467 static int vdiGetPCHSGeometry(void *pBackendData, PVDGEOMETRY pPCHSGeometry) 1498 1468 { 1499 1469 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry)); … … 1521 1491 1522 1492 /** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */ 1523 static int vdiSetPCHSGeometry(void *pBackendData, 1524 PCPDMMEDIAGEOMETRY pPCHSGeometry) 1493 static int vdiSetPCHSGeometry(void *pBackendData, PCVDGEOMETRY pPCHSGeometry) 1525 1494 { 1526 1495 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); … … 1550 1519 1551 1520 /** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */ 1552 static int vdiGetLCHSGeometry(void *pBackendData, 1553 PPDMMEDIAGEOMETRY pLCHSGeometry) 1521 static int vdiGetLCHSGeometry(void *pBackendData, PVDGEOMETRY pLCHSGeometry) 1554 1522 { 1555 1523 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry)); … … 1586 1554 1587 1555 /** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */ 1588 static int vdiSetLCHSGeometry(void *pBackendData, 1589 PCPDMMEDIAGEOMETRY pLCHSGeometry) 1556 static int vdiSetLCHSGeometry(void *pBackendData, PCVDGEOMETRY pLCHSGeometry) 1590 1557 { 1591 1558 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); … … 1679 1646 /* Implement this operation via reopening the image. */ 1680 1647 pszFilename = pImage->pszFilename; 1681 vdiFreeImage(pImage, false); 1648 rc = vdiFreeImage(pImage, false); 1649 if (RT_FAILURE(rc)) 1650 goto out; 1682 1651 rc = vdiOpenImage(pImage, uOpenFlags); 1683 1652 … … 1986 1955 PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData; 1987 1956 1988 #ifndef VBOX_WITH_NEW_IO_CODE 1989 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Dumping VDI image \"%s\" mode=%s uOpenFlags=%X File=%08X\n", 1990 pImage->pszFilename, 1991 (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) ? "r/o" : "r/w", 1992 pImage->uOpenFlags, 1993 pImage->File); 1994 #else 1995 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Dumping VDI image \"%s\" mode=%s uOpenFlags=%X File=%#p\n", 1957 vdiMessage(pImage, "Dumping VDI image \"%s\" mode=%s uOpenFlags=%X File=%#p\n", 1996 1958 pImage->pszFilename, 1997 1959 (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) ? "r/o" : "r/w", 1998 1960 pImage->uOpenFlags, 1999 1961 pImage->pStorage); 2000 #endif 2001 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: Version=%08X Type=%X Flags=%X Size=%llu\n", 1962 vdiMessage(pImage, "Header: Version=%08X Type=%X Flags=%X Size=%llu\n", 2002 1963 pImage->PreHeader.u32Version, 2003 1964 getImageType(&pImage->Header), 2004 1965 getImageFlags(&pImage->Header), 2005 1966 getImageDiskSize(&pImage->Header)); 2006 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: cbBlock=%u cbBlockExtra=%u cBlocks=%u cBlocksAllocated=%u\n",1967 vdiMessage(pImage, "Header: cbBlock=%u cbBlockExtra=%u cBlocks=%u cBlocksAllocated=%u\n", 2007 1968 getImageBlockSize(&pImage->Header), 2008 1969 getImageExtraBlockSize(&pImage->Header), 2009 1970 getImageBlocks(&pImage->Header), 2010 1971 getImageBlocksAllocated(&pImage->Header)); 2011 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: offBlocks=%u offData=%u\n",1972 vdiMessage(pImage, "Header: offBlocks=%u offData=%u\n", 2012 1973 getImageBlocksOffset(&pImage->Header), 2013 1974 getImageDataOffset(&pImage->Header)); 2014 1975 PVDIDISKGEOMETRY pg = getImageLCHSGeometry(&pImage->Header); 2015 1976 if (pg) 2016 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: Geometry: C/H/S=%u/%u/%u cbSector=%u\n",1977 vdiMessage(pImage, "Header: Geometry: C/H/S=%u/%u/%u cbSector=%u\n", 2017 1978 pg->cCylinders, pg->cHeads, pg->cSectors, pg->cbSector); 2018 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: uuidCreation={%RTuuid}\n", getImageCreationUUID(&pImage->Header));2019 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: uuidModification={%RTuuid}\n", getImageModificationUUID(&pImage->Header));2020 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: uuidParent={%RTuuid}\n", getImageParentUUID(&pImage->Header));1979 vdiMessage(pImage, "Header: uuidCreation={%RTuuid}\n", getImageCreationUUID(&pImage->Header)); 1980 vdiMessage(pImage, "Header: uuidModification={%RTuuid}\n", getImageModificationUUID(&pImage->Header)); 1981 vdiMessage(pImage, "Header: uuidParent={%RTuuid}\n", getImageParentUUID(&pImage->Header)); 2021 1982 if (GET_MAJOR_HEADER_VERSION(&pImage->Header) >= 1) 2022 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: uuidParentModification={%RTuuid}\n", getImageParentModificationUUID(&pImage->Header));2023 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Image: fFlags=%08X offStartBlocks=%u offStartData=%u\n",1983 vdiMessage(pImage, "Header: uuidParentModification={%RTuuid}\n", getImageParentModificationUUID(&pImage->Header)); 1984 vdiMessage(pImage, "Image: fFlags=%08X offStartBlocks=%u offStartData=%u\n", 2024 1985 pImage->uImageFlags, pImage->offStartBlocks, pImage->offStartData); 2025 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Image: uBlockMask=%08X cbTotalBlockData=%u uShiftOffset2Index=%u offStartBlockData=%u\n",1986 vdiMessage(pImage, "Image: uBlockMask=%08X cbTotalBlockData=%u uShiftOffset2Index=%u offStartBlockData=%u\n", 2026 1987 pImage->uBlockMask, 2027 1988 pImage->cbTotalBlockData, … … 2041 2002 if (cBlocksNotFree != getImageBlocksAllocated(&pImage->Header)) 2042 2003 { 2043 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "!! WARNING: %u blocks actually allocated (cBlocksAllocated=%u) !!\n",2004 vdiMessage(pImage, "!! WARNING: %u blocks actually allocated (cBlocksAllocated=%u) !!\n", 2044 2005 cBlocksNotFree, getImageBlocksAllocated(&pImage->Header)); 2045 2006 } 2046 2007 if (cBadBlocks) 2047 2008 { 2048 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "!! WARNING: %u bad blocks found !!\n",2009 vdiMessage(pImage, "!! WARNING: %u bad blocks found !!\n", 2049 2010 cBadBlocks); 2050 2011 } 2051 2012 } 2052 2013 2053 static int vdiGetTimeStamp(void *pBackendData, PRTTIMESPEC pTimeStamp)2054 {2055 int rc = VERR_NOT_IMPLEMENTED;2056 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));2057 return rc;2058 }2059 2060 static int vdiGetParentTimeStamp(void *pBackendData, PRTTIMESPEC pTimeStamp)2061 {2062 int rc = VERR_NOT_IMPLEMENTED;2063 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));2064 return rc;2065 }2066 2067 static int vdiSetParentTimeStamp(void *pBackendData, PCRTTIMESPEC pTimeStamp)2068 {2069 int rc = VERR_NOT_IMPLEMENTED;2070 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));2071 return rc;2072 }2073 2074 static int vdiGetParentFilename(void *pBackendData, char **ppszParentFilename)2075 {2076 int rc = VERR_NOT_IMPLEMENTED;2077 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));2078 return rc;2079 }2080 2081 static int vdiSetParentFilename(void *pBackendData, const char *pszParentFilename)2082 {2083 int rc = VERR_NOT_IMPLEMENTED;2084 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));2085 return rc;2086 }2087 2088 2014 static bool vdiIsAsyncIOSupported(void *pBackendData) 2089 2015 { … … 2091 2017 } 2092 2018 2093 static int vdiAsyncRead(void *p vBackendData, uint64_t uOffset, size_t cbToRead,2019 static int vdiAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbToRead, 2094 2020 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 2095 2021 { 2096 LogFlowFunc(("p vBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n",2097 p vBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));2098 PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)p vBackendData;2022 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n", 2023 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead)); 2024 PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData; 2099 2025 unsigned uBlock; 2100 2026 unsigned offRead; … … 2127 2053 size_t cbSet; 2128 2054 2129 cbSet = pImage->pInterfaceIOCallbacks->pfnIoCtxSet(pImage->pInterfaceIO->pvUser, 2130 pIoCtx, 0, cbToRead); 2055 cbSet = vdiFileIoCtxSet(pImage, pIoCtx, 0, cbToRead); 2131 2056 Assert(cbSet == cbToRead); 2132 2057 … … 2138 2063 uint64_t u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData 2139 2064 + (pImage->offStartData + pImage->offStartBlockData + offRead); 2140 rc = pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser, 2141 pImage->pStorage, 2142 u64Offset, 2143 pIoCtx, cbToRead); 2065 rc = vdiFileReadUserAsync(pImage, u64Offset, pIoCtx, cbToRead); 2144 2066 } 2145 2067 … … 2152 2074 } 2153 2075 2154 static int vdiAsyncWrite(void *p vBackendData, uint64_t uOffset, size_t cbToWrite,2076 static int vdiAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite, 2155 2077 PVDIOCTX pIoCtx, 2156 2078 size_t *pcbWriteProcess, size_t *pcbPreRead, 2157 2079 size_t *pcbPostRead, unsigned fWrite) 2158 2080 { 2159 LogFlowFunc(("p vBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",2160 p vBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));2161 PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)p vBackendData;2081 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", 2082 pBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead)); 2083 PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData; 2162 2084 unsigned uBlock; 2163 2085 unsigned offWrite; … … 2182 2104 /* No size check here, will do that later. For dynamic images which are 2183 2105 * not multiples of the block size in length, this would prevent writing to 2184 * the last grain. */2106 * the last block. */ 2185 2107 2186 2108 /* Calculate starting block number and offset inside it. */ … … 2224 2146 uint64_t u64Offset = (uint64_t)cBlocksAllocated * pImage->cbTotalBlockData 2225 2147 + (pImage->offStartData + pImage->offStartBlockData); 2226 rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser, 2227 pImage->pStorage, 2228 u64Offset, 2229 pIoCtx, cbToWrite, 2230 NULL, NULL); 2148 rc = vdiFileWriteUserAsync(pImage, u64Offset, pIoCtx, cbToWrite, NULL, NULL); 2231 2149 if (RT_UNLIKELY(RT_FAILURE_NP(rc) && (rc != VERR_VD_ASYNC_IO_IN_PROGRESS))) 2232 2150 goto out; … … 2255 2173 uint64_t u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData 2256 2174 + (pImage->offStartData + pImage->offStartBlockData + offWrite); 2257 rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser, 2258 pImage->pStorage, 2259 u64Offset, 2260 pIoCtx, cbToWrite, 2261 NULL, NULL); 2175 rc = vdiFileWriteUserAsync(pImage, u64Offset, pIoCtx, cbToWrite, NULL, NULL); 2262 2176 } 2263 2177 } while (0); … … 2271 2185 } 2272 2186 2273 static int vdiAsyncFlush(void *p vBackendData, PVDIOCTX pIoCtx)2274 { 2275 LogFlowFunc(("pBackendData=%#p\n", p vBackendData));2276 PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)p vBackendData;2187 static int vdiAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx) 2188 { 2189 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 2190 PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData; 2277 2191 int rc = VINF_SUCCESS; 2278 2192 … … 2497 2411 /* Truncate the image to the proper size to finish compacting. */ 2498 2412 rc = vdiFileSetSize(pImage, 2499 (uint64_t)uBlockUsedPos * pImage->cbTotalBlockData2500 + (pImage->offStartData + pImage->offStartBlockData));2413 (uint64_t)uBlockUsedPos * pImage->cbTotalBlockData 2414 + pImage->offStartData + pImage->offStartBlockData); 2501 2415 } while (0); 2502 2416 … … 2521 2435 /** @copydoc VBOXHDDBACKEND::pfnResize */ 2522 2436 static int vdiResize(void *pBackendData, uint64_t cbSize, 2523 PC PDMMEDIAGEOMETRY pPCHSGeometry, PCPDMMEDIAGEOMETRY pLCHSGeometry,2437 PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry, 2524 2438 unsigned uPercentStart, unsigned uPercentSpan, 2525 2439 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage, … … 2547 2461 * very old images. 2548 2462 */ 2463 /** @todo implement making the image smaller, it is the responsibility of 2464 * the user to know what he's doing. */ 2549 2465 if ( cbSize < getImageDiskSize(&pImage->Header) 2550 2466 || GET_MAJOR_HEADER_VERSION(&pImage->Header) == 0 … … 2560 2476 uint32_t cBlocksOld = getImageBlocks(&pImage->Header); /** < Number of blocks before the resize. */ 2561 2477 uint64_t cbBlockspaceNew = cBlocksNew * sizeof(VDIIMAGEBLOCKPOINTER); /** < Required space for the block array after the resize. */ 2562 uint64_t offStartDataNew = RT_ALIGN_32(pImage->offStartBlocks + cbBlockspaceNew, VDI_ GEOMETRY_SECTOR_SIZE); /** < New start offset for block data after the resize */2478 uint64_t offStartDataNew = RT_ALIGN_32(pImage->offStartBlocks + cbBlockspaceNew, VDI_DATA_ALIGN); /** < New start offset for block data after the resize */ 2563 2479 2564 2480 if ( pImage->offStartData != offStartDataNew 2565 2481 && cBlocksAllocated > 0) 2566 2482 { 2567 /* Calculate how many sectors nee to be relocated. */2483 /* Calculate how many sectors need to be relocated. */ 2568 2484 uint64_t cbOverlapping = offStartDataNew - pImage->offStartData; 2569 2485 unsigned cBlocksReloc = cbOverlapping / getImageBlockSize(&pImage->Header); … … 2571 2487 cBlocksReloc++; 2572 2488 2489 /* Since only full blocks can be relocated the new data start is 2490 * determined by moving it block by block. */ 2573 2491 cBlocksReloc = RT_MIN(cBlocksReloc, cBlocksAllocated); 2574 2492 offStartDataNew = pImage->offStartData; … … 2730 2648 /* uBackendCaps */ 2731 2649 VD_CAP_UUID | VD_CAP_CREATE_FIXED | VD_CAP_CREATE_DYNAMIC 2732 | VD_CAP_DIFF | VD_CAP_FILE | VD_CAP_ASYNC ,2650 | VD_CAP_DIFF | VD_CAP_FILE | VD_CAP_ASYNC | VD_CAP_VFS, 2733 2651 /* papszFileExtensions */ 2734 2652 s_apszVdiFileExtensions, … … 2796 2714 vdiDump, 2797 2715 /* pfnGetTimeStamp */ 2798 vdiGetTimeStamp,2716 NULL, 2799 2717 /* pfnGetParentTimeStamp */ 2800 vdiGetParentTimeStamp,2718 NULL, 2801 2719 /* pfnSetParentTimeStamp */ 2802 vdiSetParentTimeStamp,2720 NULL, 2803 2721 /* pfnGetParentFilename */ 2804 vdiGetParentFilename,2722 NULL, 2805 2723 /* pfnSetParentFilename */ 2806 vdiSetParentFilename,2724 NULL, 2807 2725 /* pfnIsAsyncIOSupported */ 2808 2726 vdiIsAsyncIOSupported, -
trunk/src/VBox/Devices/Storage/VHDHDDCore.cpp
r31921 r32536 29 29 #include <iprt/mem.h> 30 30 #include <iprt/uuid.h> 31 #include <iprt/file.h>32 31 #include <iprt/path.h> 33 32 #include <iprt/string.h> 34 #include <iprt/rand.h>35 33 36 34 #define VHD_RELATIVE_MAX_PATH 512 … … 125 123 typedef struct VHDIMAGE 126 124 { 127 /** Base image name. */125 /** Image file name. */ 128 126 const char *pszFilename; 129 #ifndef VBOX_WITH_NEW_IO_CODE 130 /** Descriptor file if applicable. */ 131 RTFILE File; 132 #else 133 /** storage handle. */ 127 /** Opaque storage handle. */ 134 128 PVDIOSTORAGE pStorage; 129 135 130 /** I/O interface. */ 136 131 PVDINTERFACE pInterfaceIO; 137 132 /** I/O interface callbacks. */ 138 133 PVDINTERFACEIO pInterfaceIOCallbacks; 139 #endif140 134 141 135 /** Pointer to the per-disk VD interface list. */ … … 148 142 PVDINTERFACEERROR pInterfaceErrorCallbacks; 149 143 150 /** Open flags passed by VBoxHD layer. */144 /** Open flags passed by VBoxHDD layer. */ 151 145 unsigned uOpenFlags; 152 146 /** Image flags defined during creation or determined during open. */ … … 154 148 /** Total size of the image. */ 155 149 uint64_t cbSize; 156 /** Original size of the image. */ 157 uint64_t cbOrigSize; 150 158 151 /** Physical geometry of this image. */ 159 PDMMEDIAGEOMETRYPCHSGeometry;152 VDGEOMETRY PCHSGeometry; 160 153 /** Logical geometry of this image. */ 161 PDMMEDIAGEOMETRY LCHSGeometry; 154 VDGEOMETRY LCHSGeometry; 155 162 156 /** Image UUID. */ 163 157 RTUUID ImageUuid; 164 158 /** Parent image UUID. */ 165 159 RTUUID ParentUuid; 160 166 161 /** Parent's time stamp at the time of image creation. */ 167 162 uint32_t u32ParentTimeStamp; 168 163 /** Relative path to the parent image. */ 169 164 char *pszParentFilename; 170 /** File size on the host disk (including all headers). */ 171 uint64_t FileSize; 165 172 166 /** The Block Allocation Table. */ 173 167 uint32_t *pBlockAllocationTable; 174 168 /** Number of entries in the table. */ 175 169 uint32_t cBlockAllocationTableEntries; 170 176 171 /** Size of one data block. */ 177 172 uint32_t cbDataBlock; … … 256 251 *******************************************************************************/ 257 252 258 static int vhdFlush(void *pBackendData); 259 static int vhdLoadDynamicDisk(PVHDIMAGE pImage, uint64_t uDynamicDiskHeaderOffset); 260 261 static int vhdFileOpen(PVHDIMAGE pImage, bool fReadonly, bool fShareable, 262 bool fCreate) 253 /** 254 * Internal: signal an error to the frontend. 255 */ 256 DECLINLINE(int) vhdError(PVHDIMAGE pImage, int rc, RT_SRC_POS_DECL, 257 const char *pszFormat, ...) 258 { 259 va_list va; 260 va_start(va, pszFormat); 261 if (pImage->pInterfaceError && pImage->pInterfaceErrorCallbacks) 262 pImage->pInterfaceErrorCallbacks->pfnError(pImage->pInterfaceError->pvUser, rc, RT_SRC_POS_ARGS, 263 pszFormat, va); 264 va_end(va); 265 return rc; 266 } 267 268 /** 269 * Internal: signal an informational message to the frontend. 270 */ 271 DECLINLINE(int) vhdMessage(PVHDIMAGE pImage, const char *pszFormat, ...) 263 272 { 264 273 int rc = VINF_SUCCESS; 265 266 AssertMsg(!(fReadonly && fCreate), ("Image can't be opened readonly while being created\n")); 267 268 #ifndef VBOX_WITH_NEW_IO_CODE 269 uint32_t fDeny = fReadonly | fShareable ? RTFILE_O_DENY_NONE : RTFILE_O_DENY_WRITE; 270 uint32_t fOpen = fReadonly ? RTFILE_O_READ : RTFILE_O_READWRITE; 271 fOpen |= fDeny; 272 273 if (fCreate) 274 fOpen |= RTFILE_O_CREATE; 275 else 276 fOpen |= RTFILE_O_OPEN; 277 278 rc = RTFileOpen(&pImage->File, pImage->pszFilename, fOpen); 279 #else 280 unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0; 281 282 if (fCreate) 283 uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE; 284 285 if (fShareable) 286 uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_DONT_LOCK; 287 288 rc = pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser, 289 pImage->pszFilename, 290 uOpenFlags, 291 &pImage->pStorage); 292 #endif 293 294 return rc; 295 } 296 297 static int vhdFileClose(PVHDIMAGE pImage) 298 { 299 int rc = VINF_SUCCESS; 300 301 #ifndef VBOX_WITH_NEW_IO_CODE 302 if (pImage->File != NIL_RTFILE) 303 rc = RTFileClose(pImage->File); 304 305 pImage->File = NIL_RTFILE; 306 #else 307 rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser, 308 pImage->pStorage); 309 pImage->pStorage = NULL; 310 #endif 311 312 return rc; 313 } 314 315 static int vhdFileFlushSync(PVHDIMAGE pImage) 316 { 317 int rc = VINF_SUCCESS; 318 319 #ifndef VBOX_WITH_NEW_IO_CODE 320 rc = RTFileFlush(pImage->File); 321 #else 322 rc = pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser, 323 pImage->pStorage); 324 #endif 325 326 return rc; 327 } 328 329 static int vhdFileGetSize(PVHDIMAGE pImage, uint64_t *pcbSize) 330 { 331 int rc = VINF_SUCCESS; 332 333 #ifndef VBOX_WITH_NEW_IO_CODE 334 rc = RTFileGetSize(pImage->File, pcbSize); 335 #else 336 rc = pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser, 337 pImage->pStorage, 338 pcbSize); 339 #endif 340 341 return rc; 342 343 } 344 345 static int vhdFileSetSize(PVHDIMAGE pImage, uint64_t cbSize) 346 { 347 int rc = VINF_SUCCESS; 348 349 #ifndef VBOX_WITH_NEW_IO_CODE 350 rc = RTFileSetSize(pImage->File, cbSize); 351 #else 352 rc = pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser, 353 pImage->pStorage, 354 cbSize); 355 #endif 356 357 return rc; 358 } 359 360 361 static int vhdFileWriteSync(PVHDIMAGE pImage, uint64_t off, const void *pcvBuf, size_t cbWrite, size_t *pcbWritten) 362 { 363 int rc = VINF_SUCCESS; 364 365 #ifndef VBOX_WITH_NEW_IO_CODE 366 rc = RTFileWriteAt(pImage->File, off, pcvBuf, cbWrite, pcbWritten); 367 #else 368 rc = pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser, 369 pImage->pStorage, 370 off, cbWrite, pcvBuf, 371 pcbWritten); 372 #endif 373 374 return rc; 375 } 376 377 static int vhdFileReadSync(PVHDIMAGE pImage, uint64_t off, void *pvBuf, size_t cbRead, size_t *pcbRead) 378 { 379 int rc = VINF_SUCCESS; 380 381 #ifndef VBOX_WITH_NEW_IO_CODE 382 rc = RTFileReadAt(pImage->File, off, pvBuf, cbRead, pcbRead); 383 #else 384 rc = pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser, 385 pImage->pStorage, 386 off, cbRead, pvBuf, 387 pcbRead); 388 #endif 389 390 return rc; 391 } 392 393 static bool vhdFileOpened(PVHDIMAGE pImage) 394 { 395 #ifndef VBOX_WITH_NEW_IO_CODE 396 return pImage->File != NIL_RTFILE; 397 #else 398 return pImage->pStorage != NULL; 399 #endif 400 } 401 402 /* 946684800 is a number of seconds between 1/1/1970 and 1/1/2000 */ 403 #define VHD_TO_UNIX_EPOCH_SECONDS UINT64_C(946684800) 404 405 static uint32_t vhdRtTime2VhdTime(PCRTTIMESPEC pRtTimeStamp) 406 { 407 uint64_t u64Seconds = RTTimeSpecGetSeconds(pRtTimeStamp); 408 return (uint32_t)(u64Seconds - VHD_TO_UNIX_EPOCH_SECONDS); 409 } 410 411 static void vhdTime2RtTime(PRTTIMESPEC pRtTimeStamp, uint32_t u32VhdTimeStamp) 412 { 413 RTTimeSpecSetSeconds(pRtTimeStamp, VHD_TO_UNIX_EPOCH_SECONDS + u32VhdTimeStamp); 414 } 415 416 /** 417 * Internal: Allocates the block bitmap rounding up to the next 32bit or 64bit boundary. 418 * Can be freed with RTMemFree. The memory is zeroed. 419 */ 420 DECLINLINE(uint8_t *)vhdBlockBitmapAllocate(PVHDIMAGE pImage) 421 { 422 #ifdef RT_ARCH_AMD64 423 return (uint8_t *)RTMemAllocZ(pImage->cbDataBlockBitmap + 8); 424 #else 425 return (uint8_t *)RTMemAllocZ(pImage->cbDataBlockBitmap + 4); 426 #endif 427 } 274 va_list va; 275 va_start(va, pszFormat); 276 if (pImage->pInterfaceError && pImage->pInterfaceErrorCallbacks) 277 rc = pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, 278 pszFormat, va); 279 va_end(va); 280 return rc; 281 } 282 283 284 DECLINLINE(int) vhdFileOpen(PVHDIMAGE pImage, const char *pszFilename, 285 uint32_t fOpen) 286 { 287 return pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser, 288 pszFilename, fOpen, 289 &pImage->pStorage); 290 } 291 292 DECLINLINE(int) vhdFileClose(PVHDIMAGE pImage) 293 { 294 return pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser, 295 pImage->pStorage); 296 } 297 298 DECLINLINE(int) vhdFileDelete(PVHDIMAGE pImage, const char *pszFilename) 299 { 300 return pImage->pInterfaceIOCallbacks->pfnDelete(pImage->pInterfaceIO->pvUser, 301 pszFilename); 302 } 303 304 DECLINLINE(int) vhdFileMove(PVHDIMAGE pImage, const char *pszSrc, 305 const char *pszDst, unsigned fMove) 306 { 307 return pImage->pInterfaceIOCallbacks->pfnMove(pImage->pInterfaceIO->pvUser, 308 pszSrc, pszDst, fMove); 309 } 310 311 DECLINLINE(int) vhdFileGetFreeSpace(PVHDIMAGE pImage, const char *pszFilename, 312 int64_t *pcbFree) 313 { 314 return pImage->pInterfaceIOCallbacks->pfnGetFreeSpace(pImage->pInterfaceIO->pvUser, 315 pszFilename, pcbFree); 316 } 317 318 DECLINLINE(int) vhdFileGetModificationTime(PVHDIMAGE pImage, 319 const char *pszFilename, 320 PRTTIMESPEC pModificationTime) 321 { 322 return pImage->pInterfaceIOCallbacks->pfnGetModificationTime(pImage->pInterfaceIO->pvUser, 323 pszFilename, 324 pModificationTime); 325 } 326 327 DECLINLINE(int) vhdFileGetSize(PVHDIMAGE pImage, uint64_t *pcbSize) 328 { 329 return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser, 330 pImage->pStorage, pcbSize); 331 } 332 333 DECLINLINE(int) vhdFileSetSize(PVHDIMAGE pImage, uint64_t cbSize) 334 { 335 return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser, 336 pImage->pStorage, cbSize); 337 } 338 339 DECLINLINE(int) vhdFileWriteSync(PVHDIMAGE pImage, uint64_t uOffset, 340 const void *pvBuffer, size_t cbBuffer, 341 size_t *pcbWritten) 342 { 343 return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser, 344 pImage->pStorage, uOffset, 345 pvBuffer, cbBuffer, pcbWritten); 346 } 347 348 DECLINLINE(int) vhdFileReadSync(PVHDIMAGE pImage, uint64_t uOffset, 349 void *pvBuffer, size_t cbBuffer, size_t *pcbRead) 350 { 351 return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser, 352 pImage->pStorage, uOffset, 353 pvBuffer, cbBuffer, pcbRead); 354 } 355 356 DECLINLINE(int) vhdFileFlushSync(PVHDIMAGE pImage) 357 { 358 return pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser, 359 pImage->pStorage); 360 } 361 362 DECLINLINE(int) vhdFileReadUserAsync(PVHDIMAGE pImage, uint64_t uOffset, 363 PVDIOCTX pIoCtx, size_t cbRead) 364 { 365 return pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser, 366 pImage->pStorage, 367 uOffset, pIoCtx, 368 cbRead); 369 } 370 371 DECLINLINE(int) vhdFileWriteUserAsync(PVHDIMAGE pImage, uint64_t uOffset, 372 PVDIOCTX pIoCtx, size_t cbWrite, 373 PFNVDXFERCOMPLETED pfnComplete, 374 void *pvCompleteUser) 375 { 376 return pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser, 377 pImage->pStorage, 378 uOffset, pIoCtx, 379 cbWrite, 380 pfnComplete, 381 pvCompleteUser); 382 } 383 384 DECLINLINE(int) vhdFileReadMetaAsync(PVHDIMAGE pImage, uint64_t uOffset, 385 void *pvBuffer, size_t cbBuffer, 386 PVDIOCTX pIoCtx, PPVDMETAXFER ppMetaXfer, 387 PFNVDXFERCOMPLETED pfnComplete, 388 void *pvCompleteUser) 389 { 390 return pImage->pInterfaceIOCallbacks->pfnReadMetaAsync(pImage->pInterfaceIO->pvUser, 391 pImage->pStorage, 392 uOffset, pvBuffer, 393 cbBuffer, pIoCtx, 394 ppMetaXfer, 395 pfnComplete, 396 pvCompleteUser); 397 } 398 399 DECLINLINE(int) vhdFileWriteMetaAsync(PVHDIMAGE pImage, uint64_t uOffset, 400 void *pvBuffer, size_t cbBuffer, 401 PVDIOCTX pIoCtx, 402 PFNVDXFERCOMPLETED pfnComplete, 403 void *pvCompleteUser) 404 { 405 return pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pImage->pInterfaceIO->pvUser, 406 pImage->pStorage, 407 uOffset, pvBuffer, 408 cbBuffer, pIoCtx, 409 pfnComplete, 410 pvCompleteUser); 411 } 412 413 DECLINLINE(int) vhdFileFlushAsync(PVHDIMAGE pImage, PVDIOCTX pIoCtx, 414 PFNVDXFERCOMPLETED pfnComplete, 415 void *pvCompleteUser) 416 { 417 return pImage->pInterfaceIOCallbacks->pfnFlushAsync(pImage->pInterfaceIO->pvUser, 418 pImage->pStorage, 419 pIoCtx, pfnComplete, 420 pvCompleteUser); 421 } 422 423 DECLINLINE(void) vhdFileMetaXferRelease(PVHDIMAGE pImage, PVDMETAXFER pMetaXfer) 424 { 425 pImage->pInterfaceIOCallbacks->pfnMetaXferRelease(pImage->pInterfaceIO->pvUser, 426 pMetaXfer); 427 } 428 428 429 429 430 /** … … 438 439 } 439 440 440 static int vhdFilenameToUtf16(const char *pszFilename, uint16_t *pu16Buf, uint32_t cbBufSize, uint32_t *pcbActualSize, bool fBigEndian) 441 /** 442 * Internal: Convert filename to UTF16 with appropriate endianness. 443 */ 444 static int vhdFilenameToUtf16(const char *pszFilename, uint16_t *pu16Buf, 445 uint32_t cbBufSize, uint32_t *pcbActualSize, 446 bool fBigEndian) 441 447 { 442 448 int rc; … … 535 541 goto out; 536 542 } 537 rc = vhdFileWriteSync(pImage, RT_BE2H_U64(pLocator->u64DataOffset), pvBuf, 538 RT_BE2H_U32(pLocator->u32DataSpace) * VHD_SECTOR_SIZE, NULL); 543 rc = vhdFileWriteSync(pImage, RT_BE2H_U64(pLocator->u64DataOffset), 544 pvBuf, RT_BE2H_U32(pLocator->u32DataSpace) * VHD_SECTOR_SIZE, 545 NULL); 539 546 540 547 out: 541 548 if (pvBuf) 542 549 RTMemTmpFree(pvBuf); 543 return rc;544 }545 546 /**547 * Internal: Update the VHD footer.548 */549 static int vhdUpdateFooter(PVHDIMAGE pImage)550 {551 int rc = VINF_SUCCESS;552 553 /* Update fields which can change. */554 pImage->vhdFooterCopy.CurSize = RT_H2BE_U64(pImage->cbSize);555 pImage->vhdFooterCopy.DiskGeometryCylinder = RT_H2BE_U16(pImage->PCHSGeometry.cCylinders);556 pImage->vhdFooterCopy.DiskGeometryHeads = pImage->PCHSGeometry.cHeads;557 pImage->vhdFooterCopy.DiskGeometrySectors = pImage->PCHSGeometry.cSectors;558 559 pImage->vhdFooterCopy.Checksum = 0;560 pImage->vhdFooterCopy.Checksum = RT_H2BE_U32(vhdChecksum(&pImage->vhdFooterCopy, sizeof(VHDFooter)));561 562 if (pImage->pBlockAllocationTable)563 rc = vhdFileWriteSync(pImage, 0, &pImage->vhdFooterCopy, sizeof(VHDFooter), NULL);564 565 if (RT_SUCCESS(rc))566 rc = vhdFileWriteSync(pImage, pImage->uCurrentEndOfFile, &pImage->vhdFooterCopy, sizeof(VHDFooter), NULL);567 568 550 return rc; 569 551 } … … 612 594 rc = vhdLocatorUpdate(pImage, &ddh.ParentLocatorEntry[i], pImage->pszParentFilename); 613 595 if (RT_FAILURE(rc)) 614 goto out;596 return rc; 615 597 } 616 598 else … … 630 612 ddh.Checksum = RT_H2BE_U32(vhdChecksum(&ddh, sizeof(ddh))); 631 613 rc = vhdFileWriteSync(pImage, pImage->u64DataOffset, &ddh, sizeof(ddh), NULL); 632 if (RT_FAILURE(rc)) 633 return rc; 634 635 /* Update the VHD footer. */ 636 rc = vhdUpdateFooter(pImage); 637 638 out: 639 return rc; 614 return rc; 615 } 616 617 /** 618 * Internal: Update the VHD footer. 619 */ 620 static int vhdUpdateFooter(PVHDIMAGE pImage) 621 { 622 int rc = VINF_SUCCESS; 623 624 /* Update fields which can change. */ 625 pImage->vhdFooterCopy.CurSize = RT_H2BE_U64(pImage->cbSize); 626 pImage->vhdFooterCopy.DiskGeometryCylinder = RT_H2BE_U16(pImage->PCHSGeometry.cCylinders); 627 pImage->vhdFooterCopy.DiskGeometryHeads = pImage->PCHSGeometry.cHeads; 628 pImage->vhdFooterCopy.DiskGeometrySectors = pImage->PCHSGeometry.cSectors; 629 630 pImage->vhdFooterCopy.Checksum = 0; 631 pImage->vhdFooterCopy.Checksum = RT_H2BE_U32(vhdChecksum(&pImage->vhdFooterCopy, sizeof(VHDFooter))); 632 633 if (pImage->pBlockAllocationTable) 634 rc = vhdFileWriteSync(pImage, 0, &pImage->vhdFooterCopy, 635 sizeof(VHDFooter), NULL); 636 637 if (RT_SUCCESS(rc)) 638 rc = vhdFileWriteSync(pImage, pImage->uCurrentEndOfFile, 639 &pImage->vhdFooterCopy, sizeof(VHDFooter), NULL); 640 641 return rc; 642 } 643 644 /** 645 * Internal. Flush image data to disk. 646 */ 647 static int vhdFlushImage(PVHDIMAGE pImage) 648 { 649 int rc = VINF_SUCCESS; 650 651 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 652 return VINF_SUCCESS; 653 654 if (pImage->pBlockAllocationTable) 655 { 656 /* 657 * This is an expanding image. Write the BAT and copy of the disk footer. 658 */ 659 size_t cbBlockAllocationTableToWrite = pImage->cBlockAllocationTableEntries * sizeof(uint32_t); 660 uint32_t *pBlockAllocationTableToWrite = (uint32_t *)RTMemAllocZ(cbBlockAllocationTableToWrite); 661 662 if (!pBlockAllocationTableToWrite) 663 return VERR_NO_MEMORY; 664 665 /* 666 * The BAT entries have to be stored in big endian format. 667 */ 668 for (unsigned i = 0; i < pImage->cBlockAllocationTableEntries; i++) 669 pBlockAllocationTableToWrite[i] = RT_H2BE_U32(pImage->pBlockAllocationTable[i]); 670 671 /* 672 * Write the block allocation table after the copy of the disk footer and the dynamic disk header. 673 */ 674 vhdFileWriteSync(pImage, pImage->uBlockAllocationTableOffset, 675 pBlockAllocationTableToWrite, 676 cbBlockAllocationTableToWrite, NULL); 677 if (pImage->fDynHdrNeedsUpdate) 678 rc = vhdDynamicHeaderUpdate(pImage); 679 RTMemFree(pBlockAllocationTableToWrite); 680 } 681 682 if (RT_SUCCESS(rc)) 683 rc = vhdUpdateFooter(pImage); 684 685 if (RT_SUCCESS(rc)) 686 rc = vhdFileFlushSync(pImage); 687 688 return rc; 689 } 690 691 /** 692 * Internal. Free all allocated space for representing an image except pImage, 693 * and optionally delete the image from disk. 694 */ 695 static int vhdFreeImage(PVHDIMAGE pImage, bool fDelete) 696 { 697 int rc = VINF_SUCCESS; 698 699 /* Freeing a never allocated image (e.g. because the open failed) is 700 * not signalled as an error. After all nothing bad happens. */ 701 if (pImage) 702 { 703 if (pImage->pStorage) 704 { 705 /* No point updating the file that is deleted anyway. */ 706 if (!fDelete) 707 vhdFlushImage(pImage); 708 709 vhdFileClose(pImage); 710 pImage->pStorage = NULL; 711 } 712 713 if (pImage->pszParentFilename) 714 { 715 RTStrFree(pImage->pszParentFilename); 716 pImage->pszParentFilename = NULL; 717 } 718 if (pImage->pBlockAllocationTable) 719 { 720 RTMemFree(pImage->pBlockAllocationTable); 721 pImage->pBlockAllocationTable = NULL; 722 } 723 if (pImage->pu8Bitmap) 724 { 725 RTMemFree(pImage->pu8Bitmap); 726 pImage->pu8Bitmap = NULL; 727 } 728 729 if (fDelete && pImage->pszFilename) 730 rc = vhdFileDelete(pImage, pImage->pszFilename); 731 } 732 733 LogFlowFunc(("returns %Rrc\n", rc)); 734 return rc; 735 } 736 737 /* 946684800 is the number of seconds between 1/1/1970 and 1/1/2000 */ 738 #define VHD_TO_UNIX_EPOCH_SECONDS UINT64_C(946684800) 739 740 static uint32_t vhdRtTime2VhdTime(PCRTTIMESPEC pRtTimeStamp) 741 { 742 uint64_t u64Seconds = RTTimeSpecGetSeconds(pRtTimeStamp); 743 return (uint32_t)(u64Seconds - VHD_TO_UNIX_EPOCH_SECONDS); 744 } 745 746 static void vhdTime2RtTime(PRTTIMESPEC pRtTimeStamp, uint32_t u32VhdTimeStamp) 747 { 748 RTTimeSpecSetSeconds(pRtTimeStamp, VHD_TO_UNIX_EPOCH_SECONDS + u32VhdTimeStamp); 749 } 750 751 /** 752 * Internal: Allocates the block bitmap rounding up to the next 32bit or 64bit boundary. 753 * Can be freed with RTMemFree. The memory is zeroed. 754 */ 755 DECLINLINE(uint8_t *)vhdBlockBitmapAllocate(PVHDIMAGE pImage) 756 { 757 #ifdef RT_ARCH_AMD64 758 return (uint8_t *)RTMemAllocZ(pImage->cbDataBlockBitmap + 8); 759 #else 760 return (uint8_t *)RTMemAllocZ(pImage->cbDataBlockBitmap + 4); 761 #endif 640 762 } 641 763 … … 671 793 if (uStatus == VHDIMAGEEXPAND_STEP_SUCCESS) 672 794 { 673 rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pImage->pInterfaceIO->pvUser,674 pImage->pStorage,675 pImage->uBlockAllocationTableOffset+ pExpand->idxBatAllocated * sizeof(uint32_t),676 &pImage->pBlockAllocationTable[pExpand->idxBatAllocated], sizeof(uint32_t), pIoCtx,677 795 rc = vhdFileWriteMetaAsync(pImage, 796 pImage->uBlockAllocationTableOffset 797 + pExpand->idxBatAllocated * sizeof(uint32_t), 798 &pImage->pBlockAllocationTable[pExpand->idxBatAllocated], 799 sizeof(uint32_t), pIoCtx, NULL, NULL); 678 800 fIoInProgress |= rc == VERR_VD_ASYNC_IO_IN_PROGRESS; 679 801 } … … 683 805 * fill up the free space making it impossible to add the footer) 684 806 * and add the footer at the right place again. */ 685 rc = pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser, 686 pImage->pStorage, 687 pExpand->cbEofOld + sizeof(VHDFooter)); 807 rc = vhdFileSetSize(pImage, pExpand->cbEofOld + sizeof(VHDFooter)); 688 808 AssertRC(rc); 689 809 690 810 pImage->uCurrentEndOfFile = pExpand->cbEofOld; 691 rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pImage->pInterfaceIO->pvUser, 692 pImage->pStorage, 693 pImage->uCurrentEndOfFile, 694 &pImage->vhdFooterCopy, sizeof(VHDFooter), pIoCtx, 695 NULL, NULL); 811 rc = vhdFileWriteMetaAsync(pImage, pImage->uCurrentEndOfFile, 812 &pImage->vhdFooterCopy, sizeof(VHDFooter), 813 pIoCtx, NULL, NULL); 696 814 fIoInProgress |= rc == VERR_VD_ASYNC_IO_IN_PROGRESS; 697 815 } … … 700 818 } 701 819 702 static int vhdAsyncExpansionStepCompleted(void *p vBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq, unsigned iStep)703 { 704 PVHDIMAGE pImage = (PVHDIMAGE)p vBackendData;820 static int vhdAsyncExpansionStepCompleted(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq, unsigned iStep) 821 { 822 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 705 823 PVHDIMAGEEXPAND pExpand = (PVHDIMAGEEXPAND)pvUser; 706 824 707 LogFlowFunc(("p vBackendData=%#p pIoCtx=%#p pvUser=%#p rcReq=%Rrc iStep=%u\n",708 p vBackendData, pIoCtx, pvUser, rcReq, iStep));825 LogFlowFunc(("pBackendData=%#p pIoCtx=%#p pvUser=%#p rcReq=%Rrc iStep=%u\n", 826 pBackendData, pIoCtx, pvUser, rcReq, iStep)); 709 827 710 828 if (RT_SUCCESS(rcReq)) … … 719 837 } 720 838 721 static int vhdAsyncExpansionDataBlockBitmapComplete(void *pvBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq) 722 { 723 return vhdAsyncExpansionStepCompleted(pvBackendData, pIoCtx, pvUser, rcReq, VHDIMAGEEXPAND_BLOCKBITMAP_STATUS_SHIFT); 724 } 725 726 static int vhdAsyncExpansionDataComplete(void *pvBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq) 727 { 728 return vhdAsyncExpansionStepCompleted(pvBackendData, pIoCtx, pvUser, rcReq, VHDIMAGEEXPAND_USERBLOCK_STATUS_SHIFT); 729 } 730 731 static int vhdAsyncExpansionBatUpdateComplete(void *pvBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq) 732 { 733 return vhdAsyncExpansionStepCompleted(pvBackendData, pIoCtx, pvUser, rcReq, VHDIMAGEEXPAND_BAT_STATUS_SHIFT); 734 } 735 736 static int vhdAsyncExpansionFooterUpdateComplete(void *pvBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq) 737 { 738 return vhdAsyncExpansionStepCompleted(pvBackendData, pIoCtx, pvUser, rcReq, VHDIMAGEEXPAND_FOOTER_STATUS_SHIFT); 839 static int vhdAsyncExpansionDataBlockBitmapComplete(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq) 840 { 841 return vhdAsyncExpansionStepCompleted(pBackendData, pIoCtx, pvUser, rcReq, VHDIMAGEEXPAND_BLOCKBITMAP_STATUS_SHIFT); 842 } 843 844 static int vhdAsyncExpansionDataComplete(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq) 845 { 846 return vhdAsyncExpansionStepCompleted(pBackendData, pIoCtx, pvUser, rcReq, VHDIMAGEEXPAND_USERBLOCK_STATUS_SHIFT); 847 } 848 849 static int vhdAsyncExpansionBatUpdateComplete(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq) 850 { 851 return vhdAsyncExpansionStepCompleted(pBackendData, pIoCtx, pvUser, rcReq, VHDIMAGEEXPAND_BAT_STATUS_SHIFT); 852 } 853 854 static int vhdAsyncExpansionFooterUpdateComplete(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq) 855 { 856 return vhdAsyncExpansionStepCompleted(pBackendData, pIoCtx, pvUser, rcReq, VHDIMAGEEXPAND_FOOTER_STATUS_SHIFT); 857 } 858 859 static int vhdLoadDynamicDisk(PVHDIMAGE pImage, uint64_t uDynamicDiskHeaderOffset) 860 { 861 VHDDynamicDiskHeader vhdDynamicDiskHeader; 862 int rc = VINF_SUCCESS; 863 uint32_t *pBlockAllocationTable; 864 uint64_t uBlockAllocationTableOffset; 865 unsigned i = 0; 866 867 Log(("Open a dynamic disk.\n")); 868 869 /* 870 * Read the dynamic disk header. 871 */ 872 rc = vhdFileReadSync(pImage, uDynamicDiskHeaderOffset, 873 &vhdDynamicDiskHeader, sizeof(VHDDynamicDiskHeader), 874 NULL); 875 if (!memcmp(vhdDynamicDiskHeader.Cookie, VHD_DYNAMIC_DISK_HEADER_COOKIE, VHD_DYNAMIC_DISK_HEADER_COOKIE_SIZE)) 876 return VERR_INVALID_PARAMETER; 877 878 pImage->cbDataBlock = RT_BE2H_U32(vhdDynamicDiskHeader.BlockSize); 879 LogFlowFunc(("BlockSize=%u\n", pImage->cbDataBlock)); 880 pImage->cBlockAllocationTableEntries = RT_BE2H_U32(vhdDynamicDiskHeader.MaxTableEntries); 881 LogFlowFunc(("MaxTableEntries=%lu\n", pImage->cBlockAllocationTableEntries)); 882 AssertMsg(!(pImage->cbDataBlock % VHD_SECTOR_SIZE), ("%s: Data block size is not a multiple of %!\n", __FUNCTION__, VHD_SECTOR_SIZE)); 883 884 pImage->cSectorsPerDataBlock = pImage->cbDataBlock / VHD_SECTOR_SIZE; 885 LogFlowFunc(("SectorsPerDataBlock=%u\n", pImage->cSectorsPerDataBlock)); 886 887 /* 888 * Every block starts with a bitmap indicating which sectors are valid and which are not. 889 * We store the size of it to be able to calculate the real offset. 890 */ 891 pImage->cbDataBlockBitmap = pImage->cSectorsPerDataBlock / 8; 892 pImage->cDataBlockBitmapSectors = pImage->cbDataBlockBitmap / VHD_SECTOR_SIZE; 893 /* Round up to full sector size */ 894 if (pImage->cbDataBlockBitmap % VHD_SECTOR_SIZE > 0) 895 pImage->cDataBlockBitmapSectors++; 896 LogFlowFunc(("cbDataBlockBitmap=%u\n", pImage->cbDataBlockBitmap)); 897 LogFlowFunc(("cDataBlockBitmapSectors=%u\n", pImage->cDataBlockBitmapSectors)); 898 899 pImage->pu8Bitmap = vhdBlockBitmapAllocate(pImage); 900 if (!pImage->pu8Bitmap) 901 return VERR_NO_MEMORY; 902 903 pBlockAllocationTable = (uint32_t *)RTMemAllocZ(pImage->cBlockAllocationTableEntries * sizeof(uint32_t)); 904 if (!pBlockAllocationTable) 905 return VERR_NO_MEMORY; 906 907 /* 908 * Read the table. 909 */ 910 uBlockAllocationTableOffset = RT_BE2H_U64(vhdDynamicDiskHeader.TableOffset); 911 LogFlowFunc(("uBlockAllocationTableOffset=%llu\n", uBlockAllocationTableOffset)); 912 pImage->uBlockAllocationTableOffset = uBlockAllocationTableOffset; 913 rc = vhdFileReadSync(pImage, uBlockAllocationTableOffset, 914 pBlockAllocationTable, 915 pImage->cBlockAllocationTableEntries * sizeof(uint32_t), 916 NULL); 917 918 /* 919 * Because the offset entries inside the allocation table are stored big endian 920 * we need to convert them into host endian. 921 */ 922 pImage->pBlockAllocationTable = (uint32_t *)RTMemAllocZ(pImage->cBlockAllocationTableEntries * sizeof(uint32_t)); 923 if (!pImage->pBlockAllocationTable) 924 return VERR_NO_MEMORY; 925 926 for (i = 0; i < pImage->cBlockAllocationTableEntries; i++) 927 pImage->pBlockAllocationTable[i] = RT_BE2H_U32(pBlockAllocationTable[i]); 928 929 RTMemFree(pBlockAllocationTable); 930 931 if (pImage->uImageFlags & VD_IMAGE_FLAGS_DIFF) 932 memcpy(pImage->ParentUuid.au8, vhdDynamicDiskHeader.ParentUuid, sizeof(pImage->ParentUuid)); 933 934 return rc; 739 935 } 740 936 … … 750 946 pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError); 751 947 752 #ifdef VBOX_WITH_NEW_IO_CODE 753 /* Try to get async I/O interface. */ 948 /* Get I/O interface. */ 754 949 pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IO); 755 AssertPtr (pImage->pInterfaceIO);950 AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER); 756 951 pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO); 757 AssertPtr(pImage->pInterfaceIOCallbacks); 758 #endif 952 AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER); 759 953 760 954 /* 761 955 * Open the image. 762 956 */ 763 int rc = vhdFileOpen(pImage, !!(uOpenFlags & VD_OPEN_FLAGS_READONLY), 764 !!(uOpenFlags & VD_OPEN_FLAGS_SHAREABLE), false); 957 int rc = vhdFileOpen(pImage, pImage->pszFilename, 958 VDOpenFlagsToFileOpenFlags(uOpenFlags, 959 false /* fCreate */)); 765 960 if (RT_FAILURE(rc)) 766 961 { … … 771 966 772 967 rc = vhdFileGetSize(pImage, &FileSize); 773 pImage->FileSize = FileSize;774 968 pImage->uCurrentEndOfFile = FileSize - sizeof(VHDFooter); 775 969 776 rc = vhdFileReadSync(pImage, pImage->uCurrentEndOfFile, &vhdFooter, sizeof(VHDFooter), NULL); 970 rc = vhdFileReadSync(pImage, pImage->uCurrentEndOfFile, 971 &vhdFooter, sizeof(VHDFooter), NULL); 777 972 if (memcmp(vhdFooter.Cookie, VHD_FOOTER_COOKIE, VHD_FOOTER_COOKIE_SIZE) != 0) 778 973 return VERR_VD_VHD_INVALID_HEADER; … … 826 1021 rc = vhdLoadDynamicDisk(pImage, pImage->u64DataOffset); 827 1022 828 return rc;829 }830 831 static int vhdOpen(const char *pszFilename, unsigned uOpenFlags,832 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,833 void **ppvBackendData)834 {835 int rc = VINF_SUCCESS;836 PVHDIMAGE pImage;837 838 /* Check open flags. All valid flags are supported. */839 if (uOpenFlags & ~VD_OPEN_FLAGS_MASK)840 {841 rc = VERR_INVALID_PARAMETER;842 return rc;843 }844 845 pImage = (PVHDIMAGE)RTMemAllocZ(sizeof(VHDIMAGE));846 if (!pImage)847 {848 rc = VERR_NO_MEMORY;849 return rc;850 }851 pImage->pszFilename = pszFilename;852 #ifndef VBOX_WITH_NEW_IO_CODE853 pImage->File = NIL_RTFILE;854 #else855 pImage->pStorage = NULL;856 #endif857 pImage->pVDIfsDisk = pVDIfsDisk;858 pImage->pVDIfsImage = pVDIfsImage;859 860 rc = vhdOpenImage(pImage, uOpenFlags);861 if (RT_SUCCESS(rc))862 *ppvBackendData = pImage;863 return rc;864 }865 866 static int vhdLoadDynamicDisk(PVHDIMAGE pImage, uint64_t uDynamicDiskHeaderOffset)867 {868 VHDDynamicDiskHeader vhdDynamicDiskHeader;869 int rc = VINF_SUCCESS;870 uint32_t *pBlockAllocationTable;871 uint64_t uBlockAllocationTableOffset;872 unsigned i = 0;873 874 Log(("Open a dynamic disk.\n"));875 876 /*877 * Read the dynamic disk header.878 */879 rc = vhdFileReadSync(pImage, uDynamicDiskHeaderOffset, &vhdDynamicDiskHeader, sizeof(VHDDynamicDiskHeader), NULL);880 if (memcmp(vhdDynamicDiskHeader.Cookie, VHD_DYNAMIC_DISK_HEADER_COOKIE, VHD_DYNAMIC_DISK_HEADER_COOKIE_SIZE) != 0)881 return VERR_INVALID_PARAMETER;882 883 pImage->cbDataBlock = RT_BE2H_U32(vhdDynamicDiskHeader.BlockSize);884 LogFlowFunc(("BlockSize=%u\n", pImage->cbDataBlock));885 pImage->cBlockAllocationTableEntries = RT_BE2H_U32(vhdDynamicDiskHeader.MaxTableEntries);886 LogFlowFunc(("MaxTableEntries=%lu\n", pImage->cBlockAllocationTableEntries));887 AssertMsg(!(pImage->cbDataBlock % VHD_SECTOR_SIZE), ("%s: Data block size is not a multiple of %!\n", __FUNCTION__, VHD_SECTOR_SIZE));888 889 pImage->cSectorsPerDataBlock = pImage->cbDataBlock / VHD_SECTOR_SIZE;890 LogFlowFunc(("SectorsPerDataBlock=%u\n", pImage->cSectorsPerDataBlock));891 892 /*893 * Every block starts with a bitmap indicating which sectors are valid and which are not.894 * We store the size of it to be able to calculate the real offset.895 */896 pImage->cbDataBlockBitmap = pImage->cSectorsPerDataBlock / 8;897 pImage->cDataBlockBitmapSectors = pImage->cbDataBlockBitmap / VHD_SECTOR_SIZE;898 /* Round up to full sector size */899 if (pImage->cbDataBlockBitmap % VHD_SECTOR_SIZE > 0)900 pImage->cDataBlockBitmapSectors++;901 LogFlowFunc(("cbDataBlockBitmap=%u\n", pImage->cbDataBlockBitmap));902 LogFlowFunc(("cDataBlockBitmapSectors=%u\n", pImage->cDataBlockBitmapSectors));903 904 pImage->pu8Bitmap = vhdBlockBitmapAllocate(pImage);905 if (!pImage->pu8Bitmap)906 return VERR_NO_MEMORY;907 908 pBlockAllocationTable = (uint32_t *)RTMemAllocZ(pImage->cBlockAllocationTableEntries * sizeof(uint32_t));909 if (!pBlockAllocationTable)910 return VERR_NO_MEMORY;911 912 /*913 * Read the table.914 */915 uBlockAllocationTableOffset = RT_BE2H_U64(vhdDynamicDiskHeader.TableOffset);916 LogFlowFunc(("uBlockAllocationTableOffset=%llu\n", uBlockAllocationTableOffset));917 pImage->uBlockAllocationTableOffset = uBlockAllocationTableOffset;918 rc = vhdFileReadSync(pImage, uBlockAllocationTableOffset, pBlockAllocationTable, pImage->cBlockAllocationTableEntries * sizeof(uint32_t), NULL);919 920 /*921 * Because the offset entries inside the allocation table are stored big endian922 * we need to convert them into host endian.923 */924 pImage->pBlockAllocationTable = (uint32_t *)RTMemAllocZ(pImage->cBlockAllocationTableEntries * sizeof(uint32_t));925 if (!pImage->pBlockAllocationTable)926 return VERR_NO_MEMORY;927 928 for (i = 0; i < pImage->cBlockAllocationTableEntries; i++)929 pImage->pBlockAllocationTable[i] = RT_BE2H_U32(pBlockAllocationTable[i]);930 931 RTMemFree(pBlockAllocationTable);932 933 if (pImage->uImageFlags & VD_IMAGE_FLAGS_DIFF)934 memcpy(pImage->ParentUuid.au8, vhdDynamicDiskHeader.ParentUuid, sizeof(pImage->ParentUuid));935 936 return rc;937 }938 939 static int vhdCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk)940 {941 int rc = VINF_SUCCESS;942 RTFILE File;943 uint64_t cbFile;944 VHDFooter vhdFooter;945 946 rc = RTFileOpen(&File, pszFilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);947 1023 if (RT_FAILURE(rc)) 948 return VERR_VD_VHD_INVALID_HEADER; 949 950 rc = RTFileGetSize(File, &cbFile); 951 if (RT_FAILURE(rc)) 952 { 953 RTFileClose(File); 954 return VERR_VD_VHD_INVALID_HEADER; 955 } 956 957 rc = RTFileReadAt(File, cbFile - sizeof(VHDFooter), &vhdFooter, sizeof(VHDFooter), NULL); 958 if (RT_FAILURE(rc) || (memcmp(vhdFooter.Cookie, VHD_FOOTER_COOKIE, VHD_FOOTER_COOKIE_SIZE) != 0)) 959 rc = VERR_VD_VHD_INVALID_HEADER; 960 else 961 rc = VINF_SUCCESS; 962 963 RTFileClose(File); 964 965 return rc; 966 } 967 968 static unsigned vhdGetVersion(void *pBackendData) 969 { 970 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 971 972 AssertPtr(pImage); 973 974 if (pImage) 975 return 1; /**< @todo use correct version */ 976 else 977 return 0; 978 } 979 980 static int vhdGetPCHSGeometry(void *pBackendData, PPDMMEDIAGEOMETRY pPCHSGeometry) 981 { 982 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 983 int rc; 984 985 AssertPtr(pImage); 986 987 if (pImage) 988 { 989 if (pImage->PCHSGeometry.cCylinders) 990 { 991 *pPCHSGeometry = pImage->PCHSGeometry; 992 rc = VINF_SUCCESS; 993 } 994 else 995 rc = VERR_VD_GEOMETRY_NOT_SET; 996 } 997 else 998 rc = VERR_VD_NOT_OPENED; 999 1000 LogFlowFunc(("returned %Rrc (CHS=%u/%u/%u)\n", rc, pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors)); 1001 return rc; 1002 } 1003 1004 static int vhdSetPCHSGeometry(void *pBackendData, PCPDMMEDIAGEOMETRY pPCHSGeometry) 1005 { 1006 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1007 int rc; 1008 1009 AssertPtr(pImage); 1010 1011 if (pImage) 1012 { 1013 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 1014 { 1015 rc = VERR_VD_IMAGE_READ_ONLY; 1016 goto out; 1017 } 1018 1019 pImage->PCHSGeometry = *pPCHSGeometry; 1020 rc = VINF_SUCCESS; 1021 } 1022 else 1023 rc = VERR_VD_NOT_OPENED; 1024 1025 out: 1026 LogFlowFunc(("returned %Rrc\n", rc)); 1027 return rc; 1028 } 1029 1030 static int vhdGetLCHSGeometry(void *pBackendData, PPDMMEDIAGEOMETRY pLCHSGeometry) 1031 { 1032 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1033 int rc; 1034 1035 AssertPtr(pImage); 1036 1037 if (pImage) 1038 { 1039 if (pImage->LCHSGeometry.cCylinders) 1040 { 1041 *pLCHSGeometry = pImage->LCHSGeometry; 1042 rc = VINF_SUCCESS; 1043 } 1044 else 1045 rc = VERR_VD_GEOMETRY_NOT_SET; 1046 } 1047 else 1048 rc = VERR_VD_NOT_OPENED; 1049 1050 LogFlowFunc(("returned %Rrc (CHS=%u/%u/%u)\n", rc, pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors)); 1051 return rc; 1052 } 1053 1054 static int vhdSetLCHSGeometry(void *pBackendData, PCPDMMEDIAGEOMETRY pLCHSGeometry) 1055 { 1056 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1057 int rc; 1058 1059 AssertPtr(pImage); 1060 1061 if (pImage) 1062 { 1063 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 1064 { 1065 rc = VERR_VD_IMAGE_READ_ONLY; 1066 goto out; 1067 } 1068 1069 pImage->LCHSGeometry = *pLCHSGeometry; 1070 rc = VINF_SUCCESS; 1071 } 1072 else 1073 rc = VERR_VD_NOT_OPENED; 1074 1075 out: 1076 LogFlowFunc(("returned %Rrc\n", rc)); 1077 return rc; 1078 } 1079 1080 static unsigned vhdGetImageFlags(void *pBackendData) 1081 { 1082 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1083 unsigned uImageFlags; 1084 1085 AssertPtr(pImage); 1086 1087 if (pImage) 1088 uImageFlags = pImage->uImageFlags; 1089 else 1090 uImageFlags = 0; 1091 1092 LogFlowFunc(("returned %#x\n", uImageFlags)); 1093 return uImageFlags; 1094 } 1095 1096 static unsigned vhdGetOpenFlags(void *pBackendData) 1097 { 1098 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1099 unsigned uOpenFlags; 1100 1101 AssertPtr(pImage); 1102 1103 if (pImage) 1104 uOpenFlags = pImage->uOpenFlags; 1105 else 1106 uOpenFlags = 0; 1107 1108 LogFlowFunc(("returned %#x\n", uOpenFlags)); 1109 return uOpenFlags; 1110 } 1111 1112 static int vhdSetOpenFlags(void *pBackendData, unsigned uOpenFlags) 1113 { 1114 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1115 int rc; 1116 1117 /* Image must be opened and the new flags must be valid. Just readonly and 1118 * info flags are supported. */ 1119 if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_ASYNC_IO))) 1120 { 1121 rc = VERR_INVALID_PARAMETER; 1122 goto out; 1123 } 1124 1125 rc = vhdFlush(pImage); 1126 if (RT_FAILURE(rc)) 1127 goto out; 1128 vhdFileClose(pImage); 1129 pImage->uOpenFlags = uOpenFlags; 1130 rc = vhdFileOpen(pImage, !!(uOpenFlags & VD_OPEN_FLAGS_READONLY), 1131 !!(uOpenFlags & VD_OPEN_FLAGS_SHAREABLE), false); 1132 1133 out: 1134 LogFlowFunc(("returned %Rrc\n", rc)); 1135 return rc; 1136 } 1137 1138 static int vhdRename(void *pBackendData, const char *pszFilename) 1139 { 1140 LogFlowFunc(("pBackendData=%#p pszFilename=%#p\n", pBackendData, pszFilename)); 1141 1142 int rc = VINF_SUCCESS; 1143 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1144 1145 /* Check arguments. */ 1146 if ( !pImage 1147 || !pszFilename 1148 || !*pszFilename) 1149 { 1150 rc = VERR_INVALID_PARAMETER; 1151 goto out; 1152 } 1153 1154 /* Close the file. vhdFreeImage would additionally free pImage. */ 1155 vhdFlush(pImage); 1156 vhdFileClose(pImage); 1157 1158 /* Rename the file. */ 1159 rc = RTFileMove(pImage->pszFilename, pszFilename, 0); 1160 if (RT_FAILURE(rc)) 1161 { 1162 /* The move failed, try to reopen the original image. */ 1163 int rc2 = vhdOpenImage(pImage, pImage->uOpenFlags); 1164 if (RT_FAILURE(rc2)) 1165 rc = rc2; 1166 1167 goto out; 1168 } 1169 1170 /* Update pImage with the new information. */ 1171 pImage->pszFilename = pszFilename; 1172 1173 /* Open the new image. */ 1174 rc = vhdOpenImage(pImage, pImage->uOpenFlags); 1175 if (RT_FAILURE(rc)) 1176 goto out; 1177 1178 out: 1179 LogFlowFunc(("returns %Rrc\n", rc)); 1180 return rc; 1181 } 1182 1183 static void vhdFreeImageMemory(PVHDIMAGE pImage) 1184 { 1185 if (pImage->pszParentFilename) 1186 { 1187 RTStrFree(pImage->pszParentFilename); 1188 pImage->pszParentFilename = NULL; 1189 } 1190 if (pImage->pBlockAllocationTable) 1191 { 1192 RTMemFree(pImage->pBlockAllocationTable); 1193 pImage->pBlockAllocationTable = NULL; 1194 } 1195 if (pImage->pu8Bitmap) 1196 { 1197 RTMemFree(pImage->pu8Bitmap); 1198 pImage->pu8Bitmap = NULL; 1199 } 1200 RTMemFree(pImage); 1201 } 1202 1203 static int vhdFreeImage(PVHDIMAGE pImage) 1204 { 1205 int rc = VINF_SUCCESS; 1206 1207 /* Freeing a never allocated image (e.g. because the open failed) is 1208 * not signalled as an error. After all nothing bad happens. */ 1209 if (pImage) 1210 { 1211 vhdFlush(pImage); 1212 vhdFileClose(pImage); 1213 vhdFreeImageMemory(pImage); 1214 } 1215 1216 LogFlowFunc(("returned %Rrc\n", rc)); 1217 return rc; 1218 } 1219 1220 static int vhdClose(void *pBackendData, bool fDelete) 1221 { 1222 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1223 int rc = VINF_SUCCESS; 1224 1225 /* Freeing a never allocated image (e.g. because the open failed) is 1226 * not signalled as an error. After all nothing bad happens. */ 1227 if (pImage) 1228 { 1229 if (fDelete) 1230 { 1231 /* No point in updating the file that is deleted anyway. */ 1232 vhdFileClose(pImage); 1233 RTFileDelete(pImage->pszFilename); 1234 vhdFreeImageMemory(pImage); 1235 } 1236 else 1237 rc = vhdFreeImage(pImage); 1238 } 1239 1240 LogFlowFunc(("returned %Rrc\n", rc)); 1024 vhdFreeImage(pImage, false); 1241 1025 return rc; 1242 1026 } … … 1280 1064 1281 1065 return !ASMBitTestAndSet(puBitmap, iBitInByte); 1282 }1283 1284 static int vhdRead(void *pBackendData, uint64_t uOffset, void *pvBuf, size_t cbRead, size_t *pcbActuallyRead)1285 {1286 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;1287 int rc = VINF_SUCCESS;1288 1289 LogFlowFunc(("pBackendData=%p uOffset=%#llx pvBuf=%p cbRead=%u pcbActuallyRead=%p\n", pBackendData, uOffset, pvBuf, cbRead, pcbActuallyRead));1290 1291 if (uOffset + cbRead > pImage->cbSize)1292 return VERR_INVALID_PARAMETER;1293 1294 /*1295 * If we have a dynamic disk image, we need to find the data block and sector to read.1296 */1297 if (pImage->pBlockAllocationTable)1298 {1299 /*1300 * Get the data block first.1301 */1302 uint32_t cBlockAllocationTableEntry = (uOffset / VHD_SECTOR_SIZE) / pImage->cSectorsPerDataBlock;1303 uint32_t cBATEntryIndex = (uOffset / VHD_SECTOR_SIZE) % pImage->cSectorsPerDataBlock;1304 uint64_t uVhdOffset;1305 1306 LogFlowFunc(("cBlockAllocationTableEntry=%u cBatEntryIndex=%u\n", cBlockAllocationTableEntry, cBATEntryIndex));1307 LogFlowFunc(("BlockAllocationEntry=%u\n", pImage->pBlockAllocationTable[cBlockAllocationTableEntry]));1308 1309 /*1310 * If the block is not allocated the content of the entry is ~01311 */1312 if (pImage->pBlockAllocationTable[cBlockAllocationTableEntry] == ~0U)1313 {1314 /* Return block size as read. */1315 *pcbActuallyRead = RT_MIN(cbRead, pImage->cSectorsPerDataBlock * VHD_SECTOR_SIZE);1316 return VERR_VD_BLOCK_FREE;1317 }1318 1319 uVhdOffset = ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry] + pImage->cDataBlockBitmapSectors + cBATEntryIndex) * VHD_SECTOR_SIZE;1320 LogFlowFunc(("uVhdOffset=%llu cbRead=%u\n", uVhdOffset, cbRead));1321 1322 /*1323 * Clip read range to remain in this data block.1324 */1325 cbRead = RT_MIN(cbRead, (pImage->cbDataBlock - (cBATEntryIndex * VHD_SECTOR_SIZE)));1326 1327 /* Read in the block's bitmap. */1328 rc = vhdFileReadSync(pImage,1329 ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,1330 pImage->pu8Bitmap, pImage->cbDataBlockBitmap, NULL);1331 if (RT_SUCCESS(rc))1332 {1333 uint32_t cSectors = 0;1334 1335 if (vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex))1336 {1337 cBATEntryIndex++;1338 cSectors = 1;1339 1340 /*1341 * The first sector being read is marked dirty, read as much as we1342 * can from child. Note that only sectors that are marked dirty1343 * must be read from child.1344 */1345 while ( (cSectors < (cbRead / VHD_SECTOR_SIZE))1346 && vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex))1347 {1348 cBATEntryIndex++;1349 cSectors++;1350 }1351 1352 cbRead = cSectors * VHD_SECTOR_SIZE;1353 1354 LogFlowFunc(("uVhdOffset=%llu cbRead=%u\n", uVhdOffset, cbRead));1355 rc = vhdFileReadSync(pImage, uVhdOffset, pvBuf, cbRead, NULL);1356 }1357 else1358 {1359 /*1360 * The first sector being read is marked clean, so we should read from1361 * our parent instead, but only as much as there are the following1362 * clean sectors, because the block may still contain dirty sectors1363 * further on. We just need to compute the number of clean sectors1364 * and pass it to our caller along with the notification that they1365 * should be read from the parent.1366 */1367 cBATEntryIndex++;1368 cSectors = 1;1369 1370 while ( (cSectors < (cbRead / VHD_SECTOR_SIZE))1371 && !vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex))1372 {1373 cBATEntryIndex++;1374 cSectors++;1375 }1376 1377 cbRead = cSectors * VHD_SECTOR_SIZE;1378 Log(("%s: Sectors free: uVhdOffset=%llu cbRead=%u\n", __FUNCTION__, uVhdOffset, cbRead));1379 rc = VERR_VD_BLOCK_FREE;1380 }1381 }1382 else1383 AssertMsgFailed(("Reading block bitmap failed rc=%Rrc\n", rc));1384 }1385 else1386 {1387 rc = vhdFileReadSync(pImage, uOffset, pvBuf, cbRead, NULL);1388 }1389 1390 if (pcbActuallyRead)1391 *pcbActuallyRead = cbRead;1392 1393 Log2(("vhdRead: off=%#llx pvBuf=%p cbRead=%d\n"1394 "%.*Rhxd\n",1395 uOffset, pvBuf, cbRead, cbRead, pvBuf));1396 1397 return rc;1398 }1399 1400 static int vhdWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf, size_t cbToWrite, size_t *pcbWriteProcess, size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite)1401 {1402 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;1403 int rc = VINF_SUCCESS;1404 1405 LogFlowFunc(("pBackendData=%p uOffset=%llu pvBuf=%p cbToWrite=%u pcbWriteProcess=%p pcbPreRead=%p pcbPostRead=%p fWrite=%u\n",1406 pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead, fWrite));1407 1408 AssertPtr(pImage);1409 Assert(uOffset % VHD_SECTOR_SIZE == 0);1410 Assert(cbToWrite % VHD_SECTOR_SIZE == 0);1411 1412 if (pImage->pBlockAllocationTable)1413 {1414 /*1415 * Get the data block first.1416 */1417 uint32_t cSector = uOffset / VHD_SECTOR_SIZE;1418 uint32_t cBlockAllocationTableEntry = cSector / pImage->cSectorsPerDataBlock;1419 uint32_t cBATEntryIndex = cSector % pImage->cSectorsPerDataBlock;1420 uint64_t uVhdOffset;1421 1422 /*1423 * Clip write range.1424 */1425 cbToWrite = RT_MIN(cbToWrite, (pImage->cbDataBlock - (cBATEntryIndex * VHD_SECTOR_SIZE)));1426 1427 /*1428 * If the block is not allocated the content of the entry is ~01429 * and we need to allocate a new block. Note that while blocks are1430 * allocated with a relatively big granularity, each sector has its1431 * own bitmap entry, indicating whether it has been written or not.1432 * So that means for the purposes of the higher level that the1433 * granularity is invisible. This means there's no need to return1434 * VERR_VD_BLOCK_FREE unless the block hasn't been allocated yet.1435 */1436 if (pImage->pBlockAllocationTable[cBlockAllocationTableEntry] == ~0U)1437 {1438 /* Check if the block allocation should be suppressed. */1439 if (fWrite & VD_WRITE_NO_ALLOC)1440 {1441 *pcbPreRead = cBATEntryIndex * VHD_SECTOR_SIZE;1442 *pcbPostRead = pImage->cSectorsPerDataBlock * VHD_SECTOR_SIZE - cbToWrite - *pcbPreRead;1443 1444 if (pcbWriteProcess)1445 *pcbWriteProcess = cbToWrite;1446 return VERR_VD_BLOCK_FREE;1447 }1448 1449 size_t cbNewBlock = pImage->cbDataBlock + (pImage->cDataBlockBitmapSectors * VHD_SECTOR_SIZE);1450 uint8_t *pNewBlock = (uint8_t *)RTMemAllocZ(cbNewBlock);1451 1452 if (!pNewBlock)1453 return VERR_NO_MEMORY;1454 1455 /*1456 * Write the new block at the current end of the file.1457 */1458 rc = vhdFileWriteSync(pImage, pImage->uCurrentEndOfFile, pNewBlock, cbNewBlock, NULL);1459 AssertRC(rc);1460 1461 /*1462 * Set the new end of the file and link the new block into the BAT.1463 */1464 pImage->pBlockAllocationTable[cBlockAllocationTableEntry] = pImage->uCurrentEndOfFile / VHD_SECTOR_SIZE;1465 pImage->uCurrentEndOfFile += cbNewBlock;1466 RTMemFree(pNewBlock);1467 1468 /* Write the updated BAT and the footer to remain in a consistent state. */1469 rc = vhdFlush(pImage);1470 AssertRC(rc);1471 }1472 1473 /*1474 * Calculate the real offset in the file.1475 */1476 uVhdOffset = ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry] + pImage->cDataBlockBitmapSectors + cBATEntryIndex) * VHD_SECTOR_SIZE;1477 1478 /* Write data. */1479 vhdFileWriteSync(pImage, uVhdOffset, pvBuf, cbToWrite, NULL);1480 1481 /* Read in the block's bitmap. */1482 rc = vhdFileReadSync(pImage,1483 ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,1484 pImage->pu8Bitmap, pImage->cbDataBlockBitmap, NULL);1485 if (RT_SUCCESS(rc))1486 {1487 bool fChanged = false;1488 1489 /* Set the bits for all sectors having been written. */1490 for (uint32_t iSector = 0; iSector < (cbToWrite / VHD_SECTOR_SIZE); iSector++)1491 {1492 fChanged |= vhdBlockBitmapSectorSet(pImage, pImage->pu8Bitmap, cBATEntryIndex);1493 cBATEntryIndex++;1494 }1495 1496 if (fChanged)1497 {1498 /* Write the bitmap back. */1499 rc = vhdFileWriteSync(pImage,1500 ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,1501 pImage->pu8Bitmap, pImage->cbDataBlockBitmap, NULL);1502 }1503 }1504 }1505 else1506 {1507 rc = vhdFileWriteSync(pImage, uOffset, pvBuf, cbToWrite, NULL);1508 }1509 1510 if (pcbWriteProcess)1511 *pcbWriteProcess = cbToWrite;1512 1513 /* Stay on the safe side. Do not run the risk of confusing the higher1514 * level, as that can be pretty lethal to image consistency. */1515 *pcbPreRead = 0;1516 *pcbPostRead = 0;1517 1518 return rc;1519 }1520 1521 static int vhdFlush(void *pBackendData)1522 {1523 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;1524 1525 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)1526 return VINF_SUCCESS;1527 1528 if (pImage->pBlockAllocationTable)1529 {1530 /*1531 * This is an expanding image. Write the BAT and copy of the disk footer.1532 */1533 size_t cbBlockAllocationTableToWrite = pImage->cBlockAllocationTableEntries * sizeof(uint32_t);1534 uint32_t *pBlockAllocationTableToWrite = (uint32_t *)RTMemAllocZ(cbBlockAllocationTableToWrite);1535 1536 if (!pBlockAllocationTableToWrite)1537 return VERR_NO_MEMORY;1538 1539 /*1540 * The BAT entries have to be stored in big endian format.1541 */1542 for (unsigned i = 0; i < pImage->cBlockAllocationTableEntries; i++)1543 pBlockAllocationTableToWrite[i] = RT_H2BE_U32(pImage->pBlockAllocationTable[i]);1544 1545 /*1546 * Write the block allocation table after the copy of the disk footer and the dynamic disk header.1547 */1548 vhdFileWriteSync(pImage, pImage->uBlockAllocationTableOffset, pBlockAllocationTableToWrite, cbBlockAllocationTableToWrite, NULL);1549 if (pImage->fDynHdrNeedsUpdate)1550 vhdDynamicHeaderUpdate(pImage);1551 RTMemFree(pBlockAllocationTableToWrite);1552 }1553 1554 vhdUpdateFooter(pImage);1555 1556 int rc = vhdFileFlushSync(pImage);1557 1558 return rc;1559 }1560 1561 static uint64_t vhdGetSize(void *pBackendData)1562 {1563 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;1564 1565 AssertPtr(pImage);1566 1567 if (pImage)1568 {1569 Log(("%s: cbSize=%llu\n", __FUNCTION__, pImage->cbSize));1570 return pImage->cbSize;1571 }1572 else1573 return 0;1574 }1575 1576 static uint64_t vhdGetFileSize(void *pBackendData)1577 {1578 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;1579 1580 AssertPtr(pImage);1581 1582 if (pImage)1583 {1584 uint64_t cb;1585 int rc = vhdFileGetSize(pImage, &cb);1586 if (RT_SUCCESS(rc))1587 return cb;1588 else1589 return 0;1590 }1591 else1592 return 0;1593 }1594 1595 static int vhdGetUuid(void *pBackendData, PRTUUID pUuid)1596 {1597 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;1598 int rc;1599 1600 AssertPtr(pImage);1601 1602 if (pImage)1603 {1604 *pUuid = pImage->ImageUuid;1605 rc = VINF_SUCCESS;1606 }1607 else1608 rc = VERR_VD_NOT_OPENED;1609 LogFlowFunc(("returned %Rrc (%RTuuid)\n", rc, pUuid));1610 return rc;1611 }1612 1613 static int vhdSetUuid(void *pBackendData, PCRTUUID pUuid)1614 {1615 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;1616 int rc;1617 1618 LogFlowFunc(("Uuid=%RTuuid\n", pUuid));1619 AssertPtr(pImage);1620 1621 if (pImage)1622 {1623 pImage->ImageUuid = *pUuid;1624 /* Update the footer copy. It will get written to disk when the image is closed. */1625 memcpy(&pImage->vhdFooterCopy.UniqueID, pUuid, 16);1626 /* Update checksum. */1627 pImage->vhdFooterCopy.Checksum = 0;1628 pImage->vhdFooterCopy.Checksum = RT_H2BE_U32(vhdChecksum(&pImage->vhdFooterCopy, sizeof(VHDFooter)));1629 1630 /* Need to update the dynamic disk header to update the disk footer copy at the beginning. */1631 if (!(pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED))1632 pImage->fDynHdrNeedsUpdate = true;1633 rc = VINF_SUCCESS;1634 }1635 else1636 rc = VERR_VD_NOT_OPENED;1637 LogFlowFunc(("returned %Rrc\n", rc));1638 return rc;1639 }1640 1641 static int vhdGetComment(void *pBackendData, char *pszComment, size_t cbComment)1642 {1643 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;1644 int rc;1645 1646 AssertPtr(pImage);1647 1648 if (pImage)1649 {1650 rc = VERR_NOT_SUPPORTED;1651 }1652 else1653 rc = VERR_VD_NOT_OPENED;1654 1655 LogFlowFunc(("returned %Rrc comment='%s'\n", rc, pszComment));1656 return rc;1657 }1658 1659 static int vhdSetComment(void *pBackendData, const char *pszComment)1660 {1661 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;1662 int rc;1663 1664 LogFlowFunc(("pszComment='%s'\n", pszComment));1665 AssertPtr(pImage);1666 1667 if (pImage)1668 {1669 /**@todo: implement */1670 rc = VINF_SUCCESS;1671 }1672 else1673 rc = VERR_VD_NOT_OPENED;1674 1675 LogFlowFunc(("returned %Rrc\n", rc));1676 return rc;1677 }1678 1679 static int vhdGetModificationUuid(void *pBackendData, PRTUUID pUuid)1680 {1681 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;1682 int rc;1683 1684 AssertPtr(pImage);1685 1686 if (pImage)1687 {1688 rc = VERR_NOT_SUPPORTED;1689 }1690 else1691 rc = VERR_VD_NOT_OPENED;1692 LogFlowFunc(("returned %Rrc (%RTuuid)\n", rc, pUuid));1693 return rc;1694 }1695 1696 static int vhdSetModificationUuid(void *pBackendData, PCRTUUID pUuid)1697 {1698 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;1699 int rc;1700 1701 LogFlowFunc(("Uuid=%RTuuid\n", pUuid));1702 AssertPtr(pImage);1703 1704 if (pImage)1705 {1706 rc = VINF_SUCCESS;1707 }1708 else1709 rc = VERR_VD_NOT_OPENED;1710 LogFlowFunc(("returned %Rrc\n", rc));1711 return rc;1712 }1713 1714 static int vhdGetParentUuid(void *pBackendData, PRTUUID pUuid)1715 {1716 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;1717 int rc;1718 1719 AssertPtr(pImage);1720 1721 if (pImage)1722 {1723 *pUuid = pImage->ParentUuid;1724 rc = VINF_SUCCESS;1725 }1726 else1727 rc = VERR_VD_NOT_OPENED;1728 LogFlowFunc(("returned %Rrc (%RTuuid)\n", rc, pUuid));1729 return rc;1730 }1731 1732 static int vhdSetParentUuid(void *pBackendData, PCRTUUID pUuid)1733 {1734 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;1735 int rc = VINF_SUCCESS;1736 1737 LogFlowFunc((" %RTuuid\n", pUuid));1738 AssertPtr(pImage);1739 1740 if (pImage && vhdFileOpened(pImage))1741 {1742 if (!(pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED))1743 {1744 pImage->ParentUuid = *pUuid;1745 pImage->fDynHdrNeedsUpdate = true;1746 }1747 else1748 rc = VERR_NOT_SUPPORTED;1749 }1750 else1751 rc = VERR_VD_NOT_OPENED;1752 LogFlowFunc(("returned %Rrc\n", rc));1753 return rc;1754 }1755 1756 static int vhdGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)1757 {1758 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;1759 int rc;1760 1761 AssertPtr(pImage);1762 1763 if (pImage)1764 {1765 rc = VERR_NOT_SUPPORTED;1766 }1767 else1768 rc = VERR_VD_NOT_OPENED;1769 LogFlowFunc(("returned %Rrc (%RTuuid)\n", rc, pUuid));1770 return rc;1771 }1772 1773 static int vhdSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)1774 {1775 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;1776 int rc;1777 1778 LogFlowFunc(("%RTuuid\n", pUuid));1779 AssertPtr(pImage);1780 1781 if (pImage)1782 {1783 rc = VINF_SUCCESS;1784 }1785 else1786 rc = VERR_VD_NOT_OPENED;1787 LogFlowFunc(("returned %Rrc\n", rc));1788 return rc;1789 1066 } 1790 1067 … … 1841 1118 } 1842 1119 1843 1844 /**1845 * Internal: signal an error to the frontend.1846 */1847 DECLINLINE(int) vhdError(PVHDIMAGE pImage, int rc, RT_SRC_POS_DECL,1848 const char *pszFormat, ...)1849 {1850 va_list va;1851 va_start(va, pszFormat);1852 if (pImage->pInterfaceError && pImage->pInterfaceErrorCallbacks)1853 pImage->pInterfaceErrorCallbacks->pfnError(pImage->pInterfaceError->pvUser, rc, RT_SRC_POS_ARGS,1854 pszFormat, va);1855 va_end(va);1856 return rc;1857 }1858 1120 1859 1121 static uint32_t vhdAllocateParentLocators(PVHDIMAGE pImage, VHDDynamicDiskHeader *pDDH, uint64_t u64Offset) … … 1934 1196 return vhdError(pImage, VERR_NO_MEMORY, RT_SRC_POS, N_("VHD: cannot set the file size for '%s'"), pImage->pszFilename); 1935 1197 1936 rc = vhdFileWriteSync(pImage, 0, pvTmp, pImage->uCurrentEndOfFile + sizeof(VHDFooter), NULL); 1198 rc = vhdFileWriteSync(pImage, 0, pvTmp, 1199 pImage->uCurrentEndOfFile + sizeof(VHDFooter), NULL); 1937 1200 if (RT_FAILURE(rc)) 1938 1201 { … … 1954 1217 DynamicDiskHeader.Checksum = RT_H2BE_U32(vhdChecksum(&DynamicDiskHeader, sizeof(DynamicDiskHeader))); 1955 1218 1956 rc = vhdFileWriteSync(pImage, sizeof(VHDFooter), &DynamicDiskHeader, sizeof(DynamicDiskHeader), NULL); 1219 rc = vhdFileWriteSync(pImage, sizeof(VHDFooter), &DynamicDiskHeader, 1220 sizeof(DynamicDiskHeader), NULL); 1957 1221 if (RT_FAILURE(rc)) 1958 1222 return vhdError(pImage, rc, RT_SRC_POS, N_("VHD: cannot write dynamic disk header to image '%s'"), pImage->pszFilename); 1959 1223 1960 1224 /* Write BAT. */ 1961 rc = vhdFileWriteSync(pImage, pImage->uBlockAllocationTableOffset, pImage->pBlockAllocationTable, 1962 pImage->cBlockAllocationTableEntries * sizeof(uint32_t), NULL); 1225 rc = vhdFileWriteSync(pImage, pImage->uBlockAllocationTableOffset, 1226 pImage->pBlockAllocationTable, 1227 pImage->cBlockAllocationTableEntries * sizeof(uint32_t), 1228 NULL); 1963 1229 if (RT_FAILURE(rc)) 1964 1230 return vhdError(pImage, rc, RT_SRC_POS, N_("VHD: cannot write BAT to image '%s'"), pImage->pszFilename); … … 1972 1238 static int vhdCreateImage(PVHDIMAGE pImage, uint64_t cbSize, 1973 1239 unsigned uImageFlags, const char *pszComment, 1974 PC PDMMEDIAGEOMETRY pPCHSGeometry,1975 PC PDMMEDIAGEOMETRY pLCHSGeometry, PCRTUUID pUuid,1240 PCVDGEOMETRY pPCHSGeometry, 1241 PCVDGEOMETRY pLCHSGeometry, PCRTUUID pUuid, 1976 1242 unsigned uOpenFlags, 1977 1243 PFNVDPROGRESS pfnProgress, void *pvUser, … … 1989 1255 pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError); 1990 1256 1991 rc = vhdFileOpen(pImage, false /* fReadonly */,1992 !!(uOpenFlags & VD_OPEN_FLAGS_SHAREABLE),1993 true /* fCreate */);1257 rc = vhdFileOpen(pImage, pImage->pszFilename, 1258 VDOpenFlagsToFileOpenFlags(uOpenFlags & ~VD_OPEN_FLAGS_READONLY, 1259 true /* fCreate */)); 1994 1260 if (RT_FAILURE(rc)) 1995 1261 return vhdError(pImage, rc, RT_SRC_POS, N_("VHD: cannot create image '%s'"), pImage->pszFilename); … … 2079 1345 2080 1346 /* Store the footer */ 2081 rc = vhdFileWriteSync(pImage, pImage->uCurrentEndOfFile, &Footer, sizeof(Footer), NULL); 1347 rc = vhdFileWriteSync(pImage, pImage->uCurrentEndOfFile, &Footer, 1348 sizeof(Footer), NULL); 2082 1349 if (RT_FAILURE(rc)) 2083 1350 { … … 2098 1365 } 2099 1366 2100 if (pfnProgress) 1367 out: 1368 if (RT_SUCCESS(rc) && pfnProgress) 2101 1369 pfnProgress(pvUser, uPercentStart + uPercentSpan); 2102 1370 1371 if (RT_FAILURE(rc)) 1372 vhdFreeImage(pImage, rc != VERR_ALREADY_EXISTS); 1373 return rc; 1374 } 1375 1376 1377 /** @copydoc VBOXHDDBACKEND::pfnCheckIfValid */ 1378 static int vhdCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk, 1379 PVDINTERFACE pVDIfsImage) 1380 { 1381 LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p\n", pszFilename, pVDIfsDisk, pVDIfsImage)); 1382 int rc; 1383 PVDIOSTORAGE pStorage; 1384 uint64_t cbFile; 1385 VHDFooter vhdFooter; 1386 1387 /* Get I/O interface. */ 1388 PVDINTERFACE pInterfaceIO = VDInterfaceGet(pVDIfsImage, VDINTERFACETYPE_IO); 1389 AssertPtrReturn(pInterfaceIO, VERR_INVALID_PARAMETER); 1390 PVDINTERFACEIO pInterfaceIOCallbacks = VDGetInterfaceIO(pInterfaceIO); 1391 AssertPtrReturn(pInterfaceIOCallbacks, VERR_INVALID_PARAMETER); 1392 1393 rc = pInterfaceIOCallbacks->pfnOpen(pInterfaceIO->pvUser, pszFilename, 1394 VDOpenFlagsToFileOpenFlags(VD_OPEN_FLAGS_READONLY, 1395 false /* fCreate */), 1396 &pStorage); 1397 if (RT_FAILURE(rc)) 1398 goto out; 1399 1400 rc = pInterfaceIOCallbacks->pfnGetSize(pInterfaceIO->pvUser, pStorage, 1401 &cbFile); 1402 if (RT_FAILURE(rc)) 1403 { 1404 pInterfaceIOCallbacks->pfnClose(pInterfaceIO->pvUser, pStorage); 1405 rc = VERR_VD_VHD_INVALID_HEADER; 1406 goto out; 1407 } 1408 1409 rc = pInterfaceIOCallbacks->pfnReadSync(pInterfaceIO->pvUser, pStorage, 1410 cbFile - sizeof(VHDFooter), 1411 &vhdFooter, sizeof(VHDFooter), NULL); 1412 if (RT_FAILURE(rc) || (memcmp(vhdFooter.Cookie, VHD_FOOTER_COOKIE, VHD_FOOTER_COOKIE_SIZE) != 0)) 1413 rc = VERR_VD_VHD_INVALID_HEADER; 1414 else 1415 rc = VINF_SUCCESS; 1416 1417 pInterfaceIOCallbacks->pfnClose(pInterfaceIO->pvUser, pStorage); 1418 2103 1419 out: 2104 return rc; 2105 } 2106 1420 LogFlowFunc(("returns %Rrc\n", rc)); 1421 return rc; 1422 } 1423 1424 /** @copydoc VBOXHDDBACKEND::pfnOpen */ 1425 static int vhdOpen(const char *pszFilename, unsigned uOpenFlags, 1426 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage, 1427 void **ppBackendData) 1428 { 1429 LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p ppBackendData=%#p\n", pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, ppBackendData)); 1430 int rc = VINF_SUCCESS; 1431 PVHDIMAGE pImage; 1432 1433 /* Check open flags. All valid flags are supported. */ 1434 if (uOpenFlags & ~VD_OPEN_FLAGS_MASK) 1435 { 1436 rc = VERR_INVALID_PARAMETER; 1437 goto out; 1438 } 1439 1440 /* Check remaining arguments. */ 1441 if ( !VALID_PTR(pszFilename) 1442 || !*pszFilename) 1443 { 1444 rc = VERR_INVALID_PARAMETER; 1445 goto out; 1446 } 1447 1448 pImage = (PVHDIMAGE)RTMemAllocZ(sizeof(VHDIMAGE)); 1449 if (!pImage) 1450 { 1451 rc = VERR_NO_MEMORY; 1452 goto out; 1453 } 1454 1455 pImage->pszFilename = pszFilename; 1456 pImage->pStorage = NULL; 1457 pImage->pVDIfsDisk = pVDIfsDisk; 1458 pImage->pVDIfsImage = pVDIfsImage; 1459 1460 rc = vhdOpenImage(pImage, uOpenFlags); 1461 if (RT_SUCCESS(rc)) 1462 *ppBackendData = pImage; 1463 else 1464 RTMemFree(pImage); 1465 1466 out: 1467 LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData)); 1468 return rc; 1469 } 1470 1471 /** @copydoc VBOXHDDBACKEND::pfnCreate */ 2107 1472 static int vhdCreate(const char *pszFilename, uint64_t cbSize, 2108 1473 unsigned uImageFlags, const char *pszComment, 2109 PC PDMMEDIAGEOMETRY pPCHSGeometry,2110 PC PDMMEDIAGEOMETRY pLCHSGeometry, PCRTUUID pUuid,2111 unsigned u OpenFlags, unsigned uPercentStart,2112 unsigned uPercentSpan, PVDINTERFACE pVDIfsDisk,2113 PVDINTERFACE pVDIfs Image, PVDINTERFACE pVDIfsOperation,2114 void **ppvBackendData) 2115 { 1474 PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry, 1475 PCRTUUID pUuid, unsigned uOpenFlags, 1476 unsigned uPercentStart, unsigned uPercentSpan, 1477 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage, 1478 PVDINTERFACE pVDIfsOperation, void **ppBackendData) 1479 { 1480 LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p ppBackendData=%#p", pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppBackendData)); 2116 1481 int rc = VINF_SUCCESS; 2117 1482 PVHDIMAGE pImage; … … 2146 1511 } 2147 1512 pImage->pszFilename = pszFilename; 2148 #ifndef VBOX_WITH_NEW_IO_CODE2149 pImage->File = NIL_RTFILE;2150 #else2151 1513 pImage->pStorage = NULL; 2152 #endif2153 1514 pImage->pVDIfsDisk = pVDIfsDisk; 2154 1515 pImage->pVDIfsImage = pVDIfsImage; 2155 1516 2156 #ifdef VBOX_WITH_NEW_IO_CODE 2157 /* Try to get I/O interface. */ 1517 /* Get I/O interface. */ 2158 1518 pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IO); 2159 AssertPtr (pImage->pInterfaceIO);1519 AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER); 2160 1520 pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO); 2161 AssertPtr(pImage->pInterfaceIOCallbacks); 2162 #endif 1521 AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER); 2163 1522 2164 1523 rc = vhdCreateImage(pImage, cbSize, uImageFlags, pszComment, … … 2172 1531 if (uOpenFlags & VD_OPEN_FLAGS_READONLY) 2173 1532 { 2174 vhd Close(pImage, false);1533 vhdFreeImage(pImage, false); 2175 1534 rc = vhdOpenImage(pImage, uOpenFlags); 2176 1535 if (RT_FAILURE(rc)) 1536 { 1537 RTMemFree(pImage); 2177 1538 goto out; 1539 } 2178 1540 } 2179 *ppvBackendData = pImage; 2180 } 1541 *ppBackendData = pImage; 1542 } 1543 else 1544 RTMemFree(pImage); 1545 2181 1546 out: 2182 LogFlowFunc(("returned %Rrc\n", rc)); 2183 return rc; 2184 } 2185 2186 static void vhdDump(void *pBackendData) 2187 { 2188 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2189 2190 AssertPtr(pImage); 2191 if (pImage) 2192 { 2193 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n", 2194 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors, 2195 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors, 2196 VHD_SECTOR_SIZE); 2197 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: uuidCreation={%RTuuid}\n", &pImage->ImageUuid); 2198 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: uuidParent={%RTuuid}\n", &pImage->ParentUuid); 2199 } 2200 } 2201 2202 2203 static int vhdGetTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp) 2204 { 1547 LogFlowFunc(("returns %Rrc\n", rc)); 1548 return rc; 1549 } 1550 1551 /** @copydoc VBOXHDDBACKEND::pfnRename */ 1552 static int vhdRename(void *pBackendData, const char *pszFilename) 1553 { 1554 LogFlowFunc(("pBackendData=%#p pszFilename=%#p\n", pBackendData, pszFilename)); 2205 1555 int rc = VINF_SUCCESS; 2206 PVHDIMAGE pImage = (PVHDIMAGE)pvBackendData; 2207 2208 AssertPtr(pImage); 2209 if (pImage) 2210 { 2211 RTFSOBJINFO info; 2212 2213 #ifndef VBOX_WITH_NEW_IO_CODE 2214 rc = RTFileQueryInfo(pImage->File, &info, RTFSOBJATTRADD_NOTHING); 2215 #else 2216 /* Interface doesn't provide such a feature. */ 2217 RTFILE File; 2218 rc = RTFileOpen(&File, pImage->pszFilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); 2219 if (RT_SUCCESS(rc)) 2220 { 2221 rc = RTFileQueryInfo(File, &info, RTFSOBJATTRADD_NOTHING); 2222 RTFileClose(File); 2223 } 2224 #endif 2225 2226 *pTimeStamp = info.ModificationTime; 2227 } 2228 else 2229 rc = VERR_VD_NOT_OPENED; 2230 LogFlowFunc(("returned %Rrc\n", rc)); 2231 return rc; 2232 } 2233 2234 static int vhdGetParentTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp) 2235 { 1556 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1557 1558 /* Check arguments. */ 1559 if ( !pImage 1560 || !pszFilename 1561 || !*pszFilename) 1562 { 1563 rc = VERR_INVALID_PARAMETER; 1564 goto out; 1565 } 1566 1567 /* Close the image. */ 1568 rc = vhdFreeImage(pImage, false); 1569 if (RT_FAILURE(rc)) 1570 goto out; 1571 1572 /* Rename the file. */ 1573 rc = vhdFileMove(pImage, pImage->pszFilename, pszFilename, 0); 1574 if (RT_FAILURE(rc)) 1575 { 1576 /* The move failed, try to reopen the original image. */ 1577 int rc2 = vhdOpenImage(pImage, pImage->uOpenFlags); 1578 if (RT_FAILURE(rc2)) 1579 rc = rc2; 1580 1581 goto out; 1582 } 1583 1584 /* Update pImage with the new information. */ 1585 pImage->pszFilename = pszFilename; 1586 1587 /* Open the old file with new name. */ 1588 rc = vhdOpenImage(pImage, pImage->uOpenFlags); 1589 if (RT_FAILURE(rc)) 1590 goto out; 1591 1592 out: 1593 LogFlowFunc(("returns %Rrc\n", rc)); 1594 return rc; 1595 } 1596 1597 /** @copydoc VBOXHDDBACKEND::pfnClose */ 1598 static int vhdClose(void *pBackendData, bool fDelete) 1599 { 1600 LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete)); 1601 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1602 int rc; 1603 1604 rc = vhdFreeImage(pImage, fDelete); 1605 RTMemFree(pImage); 1606 1607 LogFlowFunc(("returns %Rrc\n", rc)); 1608 return rc; 1609 } 1610 1611 /** @copydoc VBOXHDDBACKEND::pfnRead */ 1612 static int vhdRead(void *pBackendData, uint64_t uOffset, void *pvBuf, 1613 size_t cbBuf, size_t *pcbActuallyRead) 1614 { 1615 LogFlowFunc(("pBackendData=%p uOffset=%#llx pvBuf=%p cbBuf=%u pcbActuallyRead=%p\n", pBackendData, uOffset, pvBuf, cbBuf, pcbActuallyRead)); 1616 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2236 1617 int rc = VINF_SUCCESS; 2237 PVHDIMAGE pImage = (PVHDIMAGE)pvBackendData; 2238 2239 AssertPtr(pImage); 2240 if (pImage) 2241 vhdTime2RtTime(pTimeStamp, pImage->u32ParentTimeStamp); 2242 else 2243 rc = VERR_VD_NOT_OPENED; 2244 LogFlowFunc(("returned %Rrc\n", rc)); 2245 return rc; 2246 } 2247 2248 static int vhdSetParentTimeStamp(void *pvBackendData, PCRTTIMESPEC pTimeStamp) 2249 { 2250 int rc = VINF_SUCCESS; 2251 PVHDIMAGE pImage = (PVHDIMAGE)pvBackendData; 2252 2253 AssertPtr(pImage); 2254 if (pImage) 2255 { 2256 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2257 rc = VERR_VD_IMAGE_READ_ONLY; 2258 else 2259 { 2260 pImage->u32ParentTimeStamp = vhdRtTime2VhdTime(pTimeStamp); 2261 pImage->fDynHdrNeedsUpdate = true; 2262 } 2263 } 2264 else 2265 rc = VERR_VD_NOT_OPENED; 2266 LogFlowFunc(("returned %Rrc\n", rc)); 2267 return rc; 2268 } 2269 2270 static int vhdGetParentFilename(void *pvBackendData, char **ppszParentFilename) 2271 { 2272 int rc = VINF_SUCCESS; 2273 PVHDIMAGE pImage = (PVHDIMAGE)pvBackendData; 2274 2275 AssertPtr(pImage); 2276 if (pImage) 2277 *ppszParentFilename = RTStrDup(pImage->pszParentFilename); 2278 else 2279 rc = VERR_VD_NOT_OPENED; 2280 LogFlowFunc(("returned %Rrc\n", rc)); 2281 return rc; 2282 } 2283 2284 static int vhdSetParentFilename(void *pvBackendData, const char *pszParentFilename) 2285 { 2286 int rc = VINF_SUCCESS; 2287 PVHDIMAGE pImage = (PVHDIMAGE)pvBackendData; 2288 2289 AssertPtr(pImage); 2290 if (pImage) 2291 { 2292 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2293 rc = VERR_VD_IMAGE_READ_ONLY; 2294 else 2295 { 2296 if (pImage->pszParentFilename) 2297 RTStrFree(pImage->pszParentFilename); 2298 pImage->pszParentFilename = RTStrDup(pszParentFilename); 2299 if (!pImage->pszParentFilename) 2300 rc = VERR_NO_MEMORY; 2301 else 2302 pImage->fDynHdrNeedsUpdate = true; 2303 } 2304 } 2305 else 2306 rc = VERR_VD_NOT_OPENED; 2307 LogFlowFunc(("returned %Rrc\n", rc)); 2308 return rc; 2309 } 2310 2311 static bool vhdIsAsyncIOSupported(void *pvBackendData) 2312 { 2313 return true; 2314 } 2315 2316 static int vhdAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbRead, 2317 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 2318 { 2319 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2320 int rc = VINF_SUCCESS; 2321 2322 LogFlowFunc(("pBackendData=%p uOffset=%#llx pIoCtx=%#p cbRead=%u pcbActuallyRead=%p\n", pBackendData, uOffset, pIoCtx, cbRead, pcbActuallyRead)); 2323 2324 if (uOffset + cbRead > pImage->cbSize) 2325 return VERR_INVALID_PARAMETER; 1618 1619 if (uOffset + cbBuf > pImage->cbSize) 1620 { 1621 rc = VERR_INVALID_PARAMETER; 1622 goto out; 1623 } 2326 1624 2327 1625 /* … … 2346 1644 { 2347 1645 /* Return block size as read. */ 2348 *pcbActuallyRead = RT_MIN(cbRead, pImage->cSectorsPerDataBlock * VHD_SECTOR_SIZE); 2349 return VERR_VD_BLOCK_FREE; 1646 *pcbActuallyRead = RT_MIN(cbBuf, pImage->cSectorsPerDataBlock * VHD_SECTOR_SIZE); 1647 rc = VERR_VD_BLOCK_FREE; 1648 goto out; 2350 1649 } 2351 1650 2352 1651 uVhdOffset = ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry] + pImage->cDataBlockBitmapSectors + cBATEntryIndex) * VHD_SECTOR_SIZE; 2353 LogFlowFunc(("uVhdOffset=%llu cb Read=%u\n", uVhdOffset, cbRead));1652 LogFlowFunc(("uVhdOffset=%llu cbBuf=%u\n", uVhdOffset, cbBuf)); 2354 1653 2355 1654 /* 2356 1655 * Clip read range to remain in this data block. 2357 1656 */ 2358 cb Read = RT_MIN(cbRead, (pImage->cbDataBlock - (cBATEntryIndex * VHD_SECTOR_SIZE)));1657 cbBuf = RT_MIN(cbBuf, (pImage->cbDataBlock - (cBATEntryIndex * VHD_SECTOR_SIZE))); 2359 1658 2360 1659 /* Read in the block's bitmap. */ 2361 PVDMETAXFER pMetaXfer; 2362 rc = pImage->pInterfaceIOCallbacks->pfnReadMetaAsync(pImage->pInterfaceIO->pvUser, 2363 pImage->pStorage, 2364 ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE, 2365 pImage->pu8Bitmap, pImage->cbDataBlockBitmap, pIoCtx, &pMetaXfer, 2366 NULL, NULL); 2367 1660 rc = vhdFileReadSync(pImage, 1661 ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE, 1662 pImage->pu8Bitmap, pImage->cbDataBlockBitmap, 1663 NULL); 2368 1664 if (RT_SUCCESS(rc)) 2369 1665 { 2370 1666 uint32_t cSectors = 0; 2371 1667 2372 pImage->pInterfaceIOCallbacks->pfnMetaXferRelease(pImage->pInterfaceIO->pvUser, pMetaXfer);2373 1668 if (vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex)) 2374 1669 { … … 2381 1676 * must be read from child. 2382 1677 */ 2383 while ( (cSectors < (cb Read/ VHD_SECTOR_SIZE))1678 while ( (cSectors < (cbBuf / VHD_SECTOR_SIZE)) 2384 1679 && vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex)) 2385 1680 { … … 2388 1683 } 2389 1684 2390 cbRead = cSectors * VHD_SECTOR_SIZE; 2391 2392 LogFlowFunc(("uVhdOffset=%llu cbRead=%u\n", uVhdOffset, cbRead)); 2393 rc = pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser, 2394 pImage->pStorage, 2395 uVhdOffset, pIoCtx, cbRead); 1685 cbBuf = cSectors * VHD_SECTOR_SIZE; 1686 1687 LogFlowFunc(("uVhdOffset=%llu cbBuf=%u\n", uVhdOffset, cbBuf)); 1688 rc = vhdFileReadSync(pImage, uVhdOffset, pvBuf, cbBuf, NULL); 2396 1689 } 2397 1690 else … … 2408 1701 cSectors = 1; 2409 1702 1703 while ( (cSectors < (cbBuf / VHD_SECTOR_SIZE)) 1704 && !vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex)) 1705 { 1706 cBATEntryIndex++; 1707 cSectors++; 1708 } 1709 1710 cbBuf = cSectors * VHD_SECTOR_SIZE; 1711 LogFunc(("Sectors free: uVhdOffset=%llu cbBuf=%u\n", uVhdOffset, cbBuf)); 1712 rc = VERR_VD_BLOCK_FREE; 1713 } 1714 } 1715 else 1716 AssertMsgFailed(("Reading block bitmap failed rc=%Rrc\n", rc)); 1717 } 1718 else 1719 { 1720 rc = vhdFileReadSync(pImage, uOffset, pvBuf, cbBuf, NULL); 1721 } 1722 1723 if (RT_SUCCESS(rc)) 1724 { 1725 if (pcbActuallyRead) 1726 *pcbActuallyRead = cbBuf; 1727 1728 Log2(("vhdRead: off=%#llx pvBuf=%p cbBuf=%d\n" 1729 "%.*Rhxd\n", 1730 uOffset, pvBuf, cbBuf, cbBuf, pvBuf)); 1731 } 1732 1733 out: 1734 LogFlowFunc(("returns %Rrc\n", rc)); 1735 return rc; 1736 } 1737 1738 /** @copydoc VBOXHDDBACKEND::pfnWrite */ 1739 static int vhdWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf, 1740 size_t cbBuf, size_t *pcbWriteProcess, 1741 size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite) 1742 { 1743 LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbBuf=%zu pcbWriteProcess=%#p\n", pBackendData, uOffset, pvBuf, cbBuf, pcbWriteProcess)); 1744 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1745 int rc = VINF_SUCCESS; 1746 1747 LogFlowFunc(("pBackendData=%p uOffset=%llu pvBuf=%p cbBuf=%u pcbWriteProcess=%p pcbPreRead=%p pcbPostRead=%p fWrite=%u\n", 1748 pBackendData, uOffset, pvBuf, cbBuf, pcbWriteProcess, pcbPreRead, pcbPostRead, fWrite)); 1749 1750 AssertPtr(pImage); 1751 Assert(uOffset % VHD_SECTOR_SIZE == 0); 1752 Assert(cbBuf % VHD_SECTOR_SIZE == 0); 1753 1754 if (pImage->pBlockAllocationTable) 1755 { 1756 /* 1757 * Get the data block first. 1758 */ 1759 uint32_t cSector = uOffset / VHD_SECTOR_SIZE; 1760 uint32_t cBlockAllocationTableEntry = cSector / pImage->cSectorsPerDataBlock; 1761 uint32_t cBATEntryIndex = cSector % pImage->cSectorsPerDataBlock; 1762 uint64_t uVhdOffset; 1763 1764 /* 1765 * Clip write range. 1766 */ 1767 cbBuf = RT_MIN(cbBuf, (pImage->cbDataBlock - (cBATEntryIndex * VHD_SECTOR_SIZE))); 1768 1769 /* 1770 * If the block is not allocated the content of the entry is ~0 1771 * and we need to allocate a new block. Note that while blocks are 1772 * allocated with a relatively big granularity, each sector has its 1773 * own bitmap entry, indicating whether it has been written or not. 1774 * So that means for the purposes of the higher level that the 1775 * granularity is invisible. This means there's no need to return 1776 * VERR_VD_BLOCK_FREE unless the block hasn't been allocated yet. 1777 */ 1778 if (pImage->pBlockAllocationTable[cBlockAllocationTableEntry] == ~0U) 1779 { 1780 /* Check if the block allocation should be suppressed. */ 1781 if (fWrite & VD_WRITE_NO_ALLOC) 1782 { 1783 *pcbPreRead = cBATEntryIndex * VHD_SECTOR_SIZE; 1784 *pcbPostRead = pImage->cSectorsPerDataBlock * VHD_SECTOR_SIZE - cbBuf - *pcbPreRead; 1785 1786 if (pcbWriteProcess) 1787 *pcbWriteProcess = cbBuf; 1788 rc = VERR_VD_BLOCK_FREE; 1789 goto out; 1790 } 1791 1792 size_t cbNewBlock = pImage->cbDataBlock + (pImage->cDataBlockBitmapSectors * VHD_SECTOR_SIZE); 1793 uint8_t *pNewBlock = (uint8_t *)RTMemAllocZ(cbNewBlock); 1794 1795 if (!pNewBlock) 1796 { 1797 rc = VERR_NO_MEMORY; 1798 goto out; 1799 } 1800 1801 /* 1802 * Write the new block at the current end of the file. 1803 */ 1804 rc = vhdFileWriteSync(pImage, pImage->uCurrentEndOfFile, 1805 pNewBlock, cbNewBlock, NULL); 1806 AssertRC(rc); 1807 1808 /* 1809 * Set the new end of the file and link the new block into the BAT. 1810 */ 1811 pImage->pBlockAllocationTable[cBlockAllocationTableEntry] = pImage->uCurrentEndOfFile / VHD_SECTOR_SIZE; 1812 pImage->uCurrentEndOfFile += cbNewBlock; 1813 RTMemFree(pNewBlock); 1814 1815 /* Write the updated BAT and the footer to remain in a consistent state. */ 1816 rc = vhdFlushImage(pImage); 1817 AssertRC(rc); 1818 } 1819 1820 /* 1821 * Calculate the real offset in the file. 1822 */ 1823 uVhdOffset = ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry] + pImage->cDataBlockBitmapSectors + cBATEntryIndex) * VHD_SECTOR_SIZE; 1824 1825 /* Write data. */ 1826 vhdFileWriteSync(pImage, uVhdOffset, pvBuf, cbBuf, NULL); 1827 1828 /* Read in the block's bitmap. */ 1829 rc = vhdFileReadSync(pImage, 1830 ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE, 1831 pImage->pu8Bitmap, pImage->cbDataBlockBitmap, 1832 NULL); 1833 if (RT_SUCCESS(rc)) 1834 { 1835 bool fChanged = false; 1836 1837 /* Set the bits for all sectors having been written. */ 1838 for (uint32_t iSector = 0; iSector < (cbBuf / VHD_SECTOR_SIZE); iSector++) 1839 { 1840 fChanged |= vhdBlockBitmapSectorSet(pImage, pImage->pu8Bitmap, cBATEntryIndex); 1841 cBATEntryIndex++; 1842 } 1843 1844 if (fChanged) 1845 { 1846 /* Write the bitmap back. */ 1847 rc = vhdFileWriteSync(pImage, 1848 ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE, 1849 pImage->pu8Bitmap, pImage->cbDataBlockBitmap, 1850 NULL); 1851 } 1852 } 1853 } 1854 else 1855 { 1856 rc = vhdFileWriteSync(pImage, uOffset, pvBuf, cbBuf, NULL); 1857 } 1858 1859 if (pcbWriteProcess) 1860 *pcbWriteProcess = cbBuf; 1861 1862 /* Stay on the safe side. Do not run the risk of confusing the higher 1863 * level, as that can be pretty lethal to image consistency. */ 1864 *pcbPreRead = 0; 1865 *pcbPostRead = 0; 1866 1867 out: 1868 LogFlowFunc(("returns %Rrc\n", rc)); 1869 return rc; 1870 } 1871 1872 /** @copydoc VBOXHDDBACKEND::pfnFlush */ 1873 static int vhdFlush(void *pBackendData) 1874 { 1875 LogFlowFunc(("pBackendData=%#p", pBackendData)); 1876 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1877 int rc; 1878 1879 rc = vhdFlushImage(pImage); 1880 LogFlowFunc(("returns %Rrc\n", rc)); 1881 return rc; 1882 } 1883 1884 /** @copydoc VBOXHDDBACKEND::pfnGetVersion */ 1885 static unsigned vhdGetVersion(void *pBackendData) 1886 { 1887 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1888 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1889 unsigned ver = 0; 1890 1891 AssertPtr(pImage); 1892 1893 if (pImage) 1894 ver = 1; /**< @todo use correct version */ 1895 1896 LogFlowFunc(("returns %u\n", ver)); 1897 return ver; 1898 } 1899 1900 /** @copydoc VBOXHDDBACKEND::pfnGetSize */ 1901 static uint64_t vhdGetSize(void *pBackendData) 1902 { 1903 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1904 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1905 uint64_t cb = 0; 1906 1907 AssertPtr(pImage); 1908 1909 if (pImage && pImage->pStorage) 1910 cb = pImage->cbSize; 1911 1912 LogFlowFunc(("returns %llu\n", cb)); 1913 return cb; 1914 } 1915 1916 /** @copydoc VBOXHDDBACKEND::pfnGetFileSize */ 1917 static uint64_t vhdGetFileSize(void *pBackendData) 1918 { 1919 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1920 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1921 uint64_t cb = 0; 1922 1923 AssertPtr(pImage); 1924 1925 if (pImage && pImage->pStorage) 1926 cb = pImage->uCurrentEndOfFile + sizeof(VHDFooter); 1927 1928 LogFlowFunc(("returns %lld\n", cb)); 1929 return cb; 1930 } 1931 1932 /** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */ 1933 static int vhdGetPCHSGeometry(void *pBackendData, PVDGEOMETRY pPCHSGeometry) 1934 { 1935 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry)); 1936 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1937 int rc; 1938 1939 AssertPtr(pImage); 1940 1941 if (pImage) 1942 { 1943 if (pImage->PCHSGeometry.cCylinders) 1944 { 1945 *pPCHSGeometry = pImage->PCHSGeometry; 1946 rc = VINF_SUCCESS; 1947 } 1948 else 1949 rc = VERR_VD_GEOMETRY_NOT_SET; 1950 } 1951 else 1952 rc = VERR_VD_NOT_OPENED; 1953 1954 LogFlowFunc(("returns %Rrc (CHS=%u/%u/%u)\n", rc, pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors)); 1955 return rc; 1956 } 1957 1958 /** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */ 1959 static int vhdSetPCHSGeometry(void *pBackendData, PCVDGEOMETRY pPCHSGeometry) 1960 { 1961 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 1962 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1963 int rc; 1964 1965 AssertPtr(pImage); 1966 1967 if (pImage) 1968 { 1969 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 1970 { 1971 rc = VERR_VD_IMAGE_READ_ONLY; 1972 goto out; 1973 } 1974 1975 pImage->PCHSGeometry = *pPCHSGeometry; 1976 rc = VINF_SUCCESS; 1977 } 1978 else 1979 rc = VERR_VD_NOT_OPENED; 1980 1981 out: 1982 LogFlowFunc(("returns %Rrc\n", rc)); 1983 return rc; 1984 } 1985 1986 /** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */ 1987 static int vhdGetLCHSGeometry(void *pBackendData, PVDGEOMETRY pLCHSGeometry) 1988 { 1989 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry)); 1990 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 1991 int rc; 1992 1993 AssertPtr(pImage); 1994 1995 if (pImage) 1996 { 1997 if (pImage->LCHSGeometry.cCylinders) 1998 { 1999 *pLCHSGeometry = pImage->LCHSGeometry; 2000 rc = VINF_SUCCESS; 2001 } 2002 else 2003 rc = VERR_VD_GEOMETRY_NOT_SET; 2004 } 2005 else 2006 rc = VERR_VD_NOT_OPENED; 2007 2008 LogFlowFunc(("returns %Rrc (CHS=%u/%u/%u)\n", rc, pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors)); 2009 return rc; 2010 } 2011 2012 /** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */ 2013 static int vhdSetLCHSGeometry(void *pBackendData, PCVDGEOMETRY pLCHSGeometry) 2014 { 2015 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2016 int rc; 2017 2018 AssertPtr(pImage); 2019 2020 if (pImage) 2021 { 2022 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2023 { 2024 rc = VERR_VD_IMAGE_READ_ONLY; 2025 goto out; 2026 } 2027 2028 pImage->LCHSGeometry = *pLCHSGeometry; 2029 rc = VINF_SUCCESS; 2030 } 2031 else 2032 rc = VERR_VD_NOT_OPENED; 2033 2034 out: 2035 LogFlowFunc(("returns %Rrc\n", rc)); 2036 return rc; 2037 } 2038 2039 /** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */ 2040 static unsigned vhdGetImageFlags(void *pBackendData) 2041 { 2042 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 2043 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2044 unsigned uImageFlags; 2045 2046 AssertPtr(pImage); 2047 2048 if (pImage) 2049 uImageFlags = pImage->uImageFlags; 2050 else 2051 uImageFlags = 0; 2052 2053 LogFlowFunc(("returns %#x\n", uImageFlags)); 2054 return uImageFlags; 2055 } 2056 2057 /** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */ 2058 static unsigned vhdGetOpenFlags(void *pBackendData) 2059 { 2060 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 2061 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2062 unsigned uOpenFlags; 2063 2064 AssertPtr(pImage); 2065 2066 if (pImage) 2067 uOpenFlags = pImage->uOpenFlags; 2068 else 2069 uOpenFlags = 0; 2070 2071 LogFlowFunc(("returns %#x\n", uOpenFlags)); 2072 return uOpenFlags; 2073 } 2074 2075 /** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */ 2076 static int vhdSetOpenFlags(void *pBackendData, unsigned uOpenFlags) 2077 { 2078 LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags)); 2079 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2080 int rc; 2081 2082 /* Image must be opened and the new flags must be valid. Just readonly and 2083 * info flags are supported. */ 2084 if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE))) 2085 { 2086 rc = VERR_INVALID_PARAMETER; 2087 goto out; 2088 } 2089 2090 /* Implement this operation via reopening the image. */ 2091 rc = vhdFreeImage(pImage, false); 2092 if (RT_FAILURE(rc)) 2093 goto out; 2094 rc = vhdOpenImage(pImage, uOpenFlags); 2095 2096 out: 2097 LogFlowFunc(("returns %Rrc\n", rc)); 2098 return rc; 2099 } 2100 2101 /** @copydoc VBOXHDDBACKEND::pfnGetComment */ 2102 static int vhdGetComment(void *pBackendData, char *pszComment, 2103 size_t cbComment) 2104 { 2105 LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment)); 2106 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2107 int rc; 2108 2109 AssertPtr(pImage); 2110 2111 if (pImage) 2112 rc = VERR_NOT_SUPPORTED; 2113 else 2114 rc = VERR_VD_NOT_OPENED; 2115 2116 LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment)); 2117 return rc; 2118 } 2119 2120 /** @copydoc VBOXHDDBACKEND::pfnSetComment */ 2121 static int vhdSetComment(void *pBackendData, const char *pszComment) 2122 { 2123 LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment)); 2124 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2125 int rc; 2126 2127 AssertPtr(pImage); 2128 2129 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2130 { 2131 rc = VERR_VD_IMAGE_READ_ONLY; 2132 goto out; 2133 } 2134 2135 if (pImage) 2136 rc = VERR_NOT_SUPPORTED; 2137 else 2138 rc = VERR_VD_NOT_OPENED; 2139 2140 out: 2141 LogFlowFunc(("returns %Rrc\n", rc)); 2142 return rc; 2143 } 2144 2145 /** @copydoc VBOXHDDBACKEND::pfnGetUuid */ 2146 static int vhdGetUuid(void *pBackendData, PRTUUID pUuid) 2147 { 2148 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2149 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2150 int rc; 2151 2152 AssertPtr(pImage); 2153 2154 if (pImage) 2155 { 2156 *pUuid = pImage->ImageUuid; 2157 rc = VINF_SUCCESS; 2158 } 2159 else 2160 rc = VERR_VD_NOT_OPENED; 2161 2162 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2163 return rc; 2164 } 2165 2166 /** @copydoc VBOXHDDBACKEND::pfnSetUuid */ 2167 static int vhdSetUuid(void *pBackendData, PCRTUUID pUuid) 2168 { 2169 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2170 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2171 int rc; 2172 2173 AssertPtr(pImage); 2174 2175 if (pImage) 2176 { 2177 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2178 { 2179 pImage->ImageUuid = *pUuid; 2180 /* Update the footer copy. It will get written to disk when the image is closed. */ 2181 memcpy(&pImage->vhdFooterCopy.UniqueID, pUuid, 16); 2182 /* Update checksum. */ 2183 pImage->vhdFooterCopy.Checksum = 0; 2184 pImage->vhdFooterCopy.Checksum = RT_H2BE_U32(vhdChecksum(&pImage->vhdFooterCopy, sizeof(VHDFooter))); 2185 2186 /* Need to update the dynamic disk header to update the disk footer copy at the beginning. */ 2187 if (!(pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED)) 2188 pImage->fDynHdrNeedsUpdate = true; 2189 rc = VINF_SUCCESS; 2190 } 2191 else 2192 rc = VERR_VD_IMAGE_READ_ONLY; 2193 } 2194 else 2195 rc = VERR_VD_NOT_OPENED; 2196 2197 LogFlowFunc(("returns %Rrc\n", rc)); 2198 return rc; 2199 } 2200 2201 /** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */ 2202 static int vhdGetModificationUuid(void *pBackendData, PRTUUID pUuid) 2203 { 2204 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2205 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2206 int rc; 2207 2208 AssertPtr(pImage); 2209 2210 if (pImage) 2211 rc = VERR_NOT_SUPPORTED; 2212 else 2213 rc = VERR_VD_NOT_OPENED; 2214 2215 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2216 return rc; 2217 } 2218 2219 /** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */ 2220 static int vhdSetModificationUuid(void *pBackendData, PCRTUUID pUuid) 2221 { 2222 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2223 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2224 int rc; 2225 2226 AssertPtr(pImage); 2227 2228 if (pImage) 2229 { 2230 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2231 rc = VERR_NOT_SUPPORTED; 2232 else 2233 rc = VERR_VD_IMAGE_READ_ONLY; 2234 } 2235 else 2236 rc = VERR_VD_NOT_OPENED; 2237 2238 LogFlowFunc(("returns %Rrc\n", rc)); 2239 return rc; 2240 } 2241 2242 /** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */ 2243 static int vhdGetParentUuid(void *pBackendData, PRTUUID pUuid) 2244 { 2245 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2246 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2247 int rc; 2248 2249 AssertPtr(pImage); 2250 2251 if (pImage) 2252 { 2253 *pUuid = pImage->ParentUuid; 2254 rc = VINF_SUCCESS; 2255 } 2256 else 2257 rc = VERR_VD_NOT_OPENED; 2258 2259 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2260 return rc; 2261 } 2262 2263 /** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */ 2264 static int vhdSetParentUuid(void *pBackendData, PCRTUUID pUuid) 2265 { 2266 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2267 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2268 int rc = VINF_SUCCESS; 2269 2270 AssertPtr(pImage); 2271 2272 if (pImage && pImage->pStorage) 2273 { 2274 if (!(pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED)) 2275 { 2276 pImage->ParentUuid = *pUuid; 2277 pImage->fDynHdrNeedsUpdate = true; 2278 } 2279 else 2280 rc = VERR_VD_IMAGE_READ_ONLY; 2281 } 2282 else 2283 rc = VERR_VD_NOT_OPENED; 2284 2285 LogFlowFunc(("returns %Rrc\n", rc)); 2286 return rc; 2287 } 2288 2289 /** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */ 2290 static int vhdGetParentModificationUuid(void *pBackendData, PRTUUID pUuid) 2291 { 2292 LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid)); 2293 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2294 int rc; 2295 2296 AssertPtr(pImage); 2297 2298 if (pImage) 2299 rc = VERR_NOT_SUPPORTED; 2300 else 2301 rc = VERR_VD_NOT_OPENED; 2302 2303 LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid)); 2304 return rc; 2305 } 2306 2307 /** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */ 2308 static int vhdSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid) 2309 { 2310 LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid)); 2311 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2312 int rc; 2313 2314 AssertPtr(pImage); 2315 2316 if (pImage) 2317 { 2318 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2319 rc = VERR_NOT_SUPPORTED; 2320 else 2321 rc = VERR_VD_IMAGE_READ_ONLY; 2322 } 2323 else 2324 rc = VERR_VD_NOT_OPENED; 2325 2326 LogFlowFunc(("returns %Rrc\n", rc)); 2327 return rc; 2328 } 2329 2330 /** @copydoc VBOXHDDBACKEND::pfnDump */ 2331 static void vhdDump(void *pBackendData) 2332 { 2333 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2334 2335 AssertPtr(pImage); 2336 if (pImage) 2337 { 2338 vhdMessage(pImage, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n", 2339 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors, 2340 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors, 2341 VHD_SECTOR_SIZE); 2342 vhdMessage(pImage, "Header: uuidCreation={%RTuuid}\n", &pImage->ImageUuid); 2343 vhdMessage(pImage, "Header: uuidParent={%RTuuid}\n", &pImage->ParentUuid); 2344 } 2345 } 2346 2347 /** @copydoc VBOXHDDBACKEND::pfnGetTimestamp */ 2348 static int vhdGetTimeStamp(void *pBackendData, PRTTIMESPEC pTimeStamp) 2349 { 2350 int rc = VINF_SUCCESS; 2351 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2352 2353 AssertPtr(pImage); 2354 2355 if (pImage) 2356 rc = vhdFileGetModificationTime(pImage, pImage->pszFilename, pTimeStamp); 2357 else 2358 rc = VERR_VD_NOT_OPENED; 2359 2360 LogFlowFunc(("returns %Rrc\n", rc)); 2361 return rc; 2362 } 2363 2364 /** @copydoc VBOXHDDBACKEND::pfnGetParentTimeStamp */ 2365 static int vhdGetParentTimeStamp(void *pBackendData, PRTTIMESPEC pTimeStamp) 2366 { 2367 int rc = VINF_SUCCESS; 2368 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2369 2370 AssertPtr(pImage); 2371 2372 if (pImage) 2373 vhdTime2RtTime(pTimeStamp, pImage->u32ParentTimeStamp); 2374 else 2375 rc = VERR_VD_NOT_OPENED; 2376 2377 LogFlowFunc(("returns %Rrc\n", rc)); 2378 return rc; 2379 } 2380 2381 /** @copydoc VBOXHDDBACKEND::pfnSetParentTimeStamp */ 2382 static int vhdSetParentTimeStamp(void *pBackendData, PCRTTIMESPEC pTimeStamp) 2383 { 2384 int rc = VINF_SUCCESS; 2385 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2386 2387 AssertPtr(pImage); 2388 if (pImage) 2389 { 2390 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2391 rc = VERR_VD_IMAGE_READ_ONLY; 2392 else 2393 { 2394 pImage->u32ParentTimeStamp = vhdRtTime2VhdTime(pTimeStamp); 2395 pImage->fDynHdrNeedsUpdate = true; 2396 } 2397 } 2398 else 2399 rc = VERR_VD_NOT_OPENED; 2400 2401 LogFlowFunc(("returns %Rrc\n", rc)); 2402 return rc; 2403 } 2404 2405 /** @copydoc VBOXHDDBACKEND::pfnGetParentFilename */ 2406 static int vhdGetParentFilename(void *pBackendData, char **ppszParentFilename) 2407 { 2408 int rc = VINF_SUCCESS; 2409 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2410 2411 AssertPtr(pImage); 2412 if (pImage) 2413 *ppszParentFilename = RTStrDup(pImage->pszParentFilename); 2414 else 2415 rc = VERR_VD_NOT_OPENED; 2416 2417 LogFlowFunc(("returns %Rrc\n", rc)); 2418 return rc; 2419 } 2420 2421 /** @copydoc VBOXHDDBACKEND::pfnSetParentFilename */ 2422 static int vhdSetParentFilename(void *pBackendData, const char *pszParentFilename) 2423 { 2424 int rc = VINF_SUCCESS; 2425 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2426 2427 AssertPtr(pImage); 2428 if (pImage) 2429 { 2430 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2431 rc = VERR_VD_IMAGE_READ_ONLY; 2432 else 2433 { 2434 if (pImage->pszParentFilename) 2435 RTStrFree(pImage->pszParentFilename); 2436 pImage->pszParentFilename = RTStrDup(pszParentFilename); 2437 if (!pImage->pszParentFilename) 2438 rc = VERR_NO_MEMORY; 2439 else 2440 pImage->fDynHdrNeedsUpdate = true; 2441 } 2442 } 2443 else 2444 rc = VERR_VD_NOT_OPENED; 2445 2446 LogFlowFunc(("returns %Rrc\n", rc)); 2447 return rc; 2448 } 2449 2450 /** @copydoc VBOXHDDBACKEND::pfnIsAsyncIOSupported */ 2451 static bool vhdIsAsyncIOSupported(void *pBackendData) 2452 { 2453 return true; 2454 } 2455 2456 /** @copydoc VBOXHDDBACKEND::pfnAsyncRead */ 2457 static int vhdAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbRead, 2458 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 2459 { 2460 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2461 int rc = VINF_SUCCESS; 2462 2463 LogFlowFunc(("pBackendData=%p uOffset=%#llx pIoCtx=%#p cbRead=%u pcbActuallyRead=%p\n", pBackendData, uOffset, pIoCtx, cbRead, pcbActuallyRead)); 2464 2465 if (uOffset + cbRead > pImage->cbSize) 2466 return VERR_INVALID_PARAMETER; 2467 2468 /* 2469 * If we have a dynamic disk image, we need to find the data block and sector to read. 2470 */ 2471 if (pImage->pBlockAllocationTable) 2472 { 2473 /* 2474 * Get the data block first. 2475 */ 2476 uint32_t cBlockAllocationTableEntry = (uOffset / VHD_SECTOR_SIZE) / pImage->cSectorsPerDataBlock; 2477 uint32_t cBATEntryIndex = (uOffset / VHD_SECTOR_SIZE) % pImage->cSectorsPerDataBlock; 2478 uint64_t uVhdOffset; 2479 2480 LogFlowFunc(("cBlockAllocationTableEntry=%u cBatEntryIndex=%u\n", cBlockAllocationTableEntry, cBATEntryIndex)); 2481 LogFlowFunc(("BlockAllocationEntry=%u\n", pImage->pBlockAllocationTable[cBlockAllocationTableEntry])); 2482 2483 /* 2484 * If the block is not allocated the content of the entry is ~0 2485 */ 2486 if (pImage->pBlockAllocationTable[cBlockAllocationTableEntry] == ~0U) 2487 { 2488 /* Return block size as read. */ 2489 *pcbActuallyRead = RT_MIN(cbRead, pImage->cSectorsPerDataBlock * VHD_SECTOR_SIZE); 2490 return VERR_VD_BLOCK_FREE; 2491 } 2492 2493 uVhdOffset = ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry] + pImage->cDataBlockBitmapSectors + cBATEntryIndex) * VHD_SECTOR_SIZE; 2494 LogFlowFunc(("uVhdOffset=%llu cbRead=%u\n", uVhdOffset, cbRead)); 2495 2496 /* 2497 * Clip read range to remain in this data block. 2498 */ 2499 cbRead = RT_MIN(cbRead, (pImage->cbDataBlock - (cBATEntryIndex * VHD_SECTOR_SIZE))); 2500 2501 /* Read in the block's bitmap. */ 2502 PVDMETAXFER pMetaXfer; 2503 rc = vhdFileReadMetaAsync(pImage, 2504 ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE, 2505 pImage->pu8Bitmap, pImage->cbDataBlockBitmap, 2506 pIoCtx, &pMetaXfer, NULL, NULL); 2507 2508 if (RT_SUCCESS(rc)) 2509 { 2510 uint32_t cSectors = 0; 2511 2512 vhdFileMetaXferRelease(pImage, pMetaXfer); 2513 if (vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex)) 2514 { 2515 cBATEntryIndex++; 2516 cSectors = 1; 2517 2518 /* 2519 * The first sector being read is marked dirty, read as much as we 2520 * can from child. Note that only sectors that are marked dirty 2521 * must be read from child. 2522 */ 2523 while ( (cSectors < (cbRead / VHD_SECTOR_SIZE)) 2524 && vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex)) 2525 { 2526 cBATEntryIndex++; 2527 cSectors++; 2528 } 2529 2530 cbRead = cSectors * VHD_SECTOR_SIZE; 2531 2532 LogFlowFunc(("uVhdOffset=%llu cbRead=%u\n", uVhdOffset, cbRead)); 2533 rc = vhdFileReadUserAsync(pImage, uVhdOffset, pIoCtx, cbRead); 2534 } 2535 else 2536 { 2537 /* 2538 * The first sector being read is marked clean, so we should read from 2539 * our parent instead, but only as much as there are the following 2540 * clean sectors, because the block may still contain dirty sectors 2541 * further on. We just need to compute the number of clean sectors 2542 * and pass it to our caller along with the notification that they 2543 * should be read from the parent. 2544 */ 2545 cBATEntryIndex++; 2546 cSectors = 1; 2547 2410 2548 while ( (cSectors < (cbRead / VHD_SECTOR_SIZE)) 2411 2549 && !vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex)) … … 2416 2554 2417 2555 cbRead = cSectors * VHD_SECTOR_SIZE; 2418 Log (("%s: Sectors free: uVhdOffset=%llu cbRead=%u\n", __FUNCTION__, uVhdOffset, cbRead));2556 LogFunc(("Sectors free: uVhdOffset=%llu cbRead=%u\n", uVhdOffset, cbRead)); 2419 2557 rc = VERR_VD_BLOCK_FREE; 2420 2558 } … … 2425 2563 else 2426 2564 { 2427 rc = pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser, 2428 pImage->pStorage, 2429 uOffset, pIoCtx, cbRead); 2565 rc = vhdFileReadUserAsync(pImage, uOffset, pIoCtx, cbRead); 2430 2566 } 2431 2567 … … 2437 2573 } 2438 2574 2575 /** @copydoc VBOXHDDBACKEND::pfnAsyncWrite */ 2439 2576 static int vhdAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbWrite, 2440 2577 PVDIOCTX pIoCtx, … … 2512 2649 * Start with the sector bitmap. 2513 2650 */ 2514 rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pImage->pInterfaceIO->pvUser,2515 pImage->pStorage,2516 pImage->uCurrentEndOfFile,2517 pExpand->au8Bitmap, pImage->cbDataBlockBitmap, pIoCtx,2518 vhdAsyncExpansionDataBlockBitmapComplete,pExpand);2651 rc = vhdFileWriteMetaAsync(pImage, pImage->uCurrentEndOfFile, 2652 pExpand->au8Bitmap, 2653 pImage->cbDataBlockBitmap, pIoCtx, 2654 vhdAsyncExpansionDataBlockBitmapComplete, 2655 pExpand); 2519 2656 if (RT_SUCCESS(rc)) 2520 2657 VHDIMAGEEXPAND_STATUS_SET(pExpand->fFlags, VHDIMAGEEXPAND_BLOCKBITMAP_STATUS_SHIFT, VHDIMAGEEXPAND_STEP_SUCCESS); … … 2534 2671 * Write the new block at the current end of the file. 2535 2672 */ 2536 rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser,2537 pImage->pStorage,2538 pImage->uCurrentEndOfFile + pImage->cbDataBlockBitmap,2539 pIoCtx, cbWrite,2540 vhdAsyncExpansionDataComplete,pExpand);2673 rc = vhdFileWriteUserAsync(pImage, 2674 pImage->uCurrentEndOfFile + pImage->cbDataBlockBitmap, 2675 pIoCtx, cbWrite, 2676 vhdAsyncExpansionDataComplete, 2677 pExpand); 2541 2678 if (RT_SUCCESS(rc)) 2542 2679 VHDIMAGEEXPAND_STATUS_SET(pExpand->fFlags, VHDIMAGEEXPAND_USERBLOCK_STATUS_SHIFT, VHDIMAGEEXPAND_STEP_SUCCESS); … … 2554 2691 * Write entry in the BAT. 2555 2692 */ 2556 rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pImage->pInterfaceIO->pvUser, 2557 pImage->pStorage, 2558 pImage->uBlockAllocationTableOffset + cBlockAllocationTableEntry * sizeof(uint32_t), 2559 &pExpand->idxBlockBe, sizeof(uint32_t), pIoCtx, 2560 vhdAsyncExpansionBatUpdateComplete, pExpand); 2693 rc = vhdFileWriteMetaAsync(pImage, 2694 pImage->uBlockAllocationTableOffset + cBlockAllocationTableEntry * sizeof(uint32_t), 2695 &pExpand->idxBlockBe, 2696 sizeof(uint32_t), pIoCtx, 2697 vhdAsyncExpansionBatUpdateComplete, 2698 pExpand); 2561 2699 if (RT_SUCCESS(rc)) 2562 2700 VHDIMAGEEXPAND_STATUS_SET(pExpand->fFlags, VHDIMAGEEXPAND_BAT_STATUS_SHIFT, VHDIMAGEEXPAND_STEP_SUCCESS); … … 2577 2715 2578 2716 /* Update the footer. */ 2579 rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pImage->pInterfaceIO->pvUser,2580 pImage->pStorage,2581 pImage->uCurrentEndOfFile,2582 &pImage->vhdFooterCopy, sizeof(VHDFooter), pIoCtx,2583 vhdAsyncExpansionFooterUpdateComplete,pExpand);2717 rc = vhdFileWriteMetaAsync(pImage, pImage->uCurrentEndOfFile, 2718 &pImage->vhdFooterCopy, 2719 sizeof(VHDFooter), pIoCtx, 2720 vhdAsyncExpansionFooterUpdateComplete, 2721 pExpand); 2584 2722 if (RT_SUCCESS(rc)) 2585 2723 VHDIMAGEEXPAND_STATUS_SET(pExpand->fFlags, VHDIMAGEEXPAND_FOOTER_STATUS_SHIFT, VHDIMAGEEXPAND_STEP_SUCCESS); … … 2608 2746 /* Read in the block's bitmap. */ 2609 2747 PVDMETAXFER pMetaXfer; 2610 rc = pImage->pInterfaceIOCallbacks->pfnReadMetaAsync(pImage->pInterfaceIO->pvUser,2611 pImage->pStorage,2612 ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,2613 pImage->pu8Bitmap, pImage->cbDataBlockBitmap, pIoCtx, &pMetaXfer,2614 2748 rc = vhdFileReadMetaAsync(pImage, 2749 ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE, 2750 pImage->pu8Bitmap, 2751 pImage->cbDataBlockBitmap, pIoCtx, 2752 &pMetaXfer, NULL, NULL); 2615 2753 if (RT_SUCCESS(rc)) 2616 2754 { 2617 pImage->pInterfaceIOCallbacks->pfnMetaXferRelease(pImage->pInterfaceIO->pvUser, pMetaXfer);2755 vhdFileMetaXferRelease(pImage, pMetaXfer); 2618 2756 2619 2757 /* Write data. */ 2620 rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser, 2621 pImage->pStorage, 2622 uVhdOffset, pIoCtx, cbWrite, 2623 NULL, NULL); 2758 rc = vhdFileWriteUserAsync(pImage, uVhdOffset, pIoCtx, cbWrite, 2759 NULL, NULL); 2624 2760 if (RT_SUCCESS(rc) || rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 2625 2761 { … … 2645 2781 * to rollback anything here. 2646 2782 */ 2647 rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pImage->pInterfaceIO->pvUser,2648 pImage->pStorage,2649 ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,2650 pImage->pu8Bitmap, pImage->cbDataBlockBitmap, pIoCtx,2651 2783 rc = vhdFileWriteMetaAsync(pImage, 2784 ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE, 2785 pImage->pu8Bitmap, 2786 pImage->cbDataBlockBitmap, 2787 pIoCtx, NULL, NULL); 2652 2788 } 2653 2789 } … … 2657 2793 else 2658 2794 { 2659 rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser, 2660 pImage->pStorage, 2661 uOffset, pIoCtx, cbWrite, 2662 NULL, NULL); 2795 rc = vhdFileWriteUserAsync(pImage, uOffset, pIoCtx, cbWrite, NULL, NULL); 2663 2796 } 2664 2797 … … 2674 2807 } 2675 2808 2676 static int vhdAsyncFlush(void *pvBackendData, PVDIOCTX pIoCtx) 2677 { 2678 PVHDIMAGE pImage = (PVHDIMAGE)pvBackendData; 2809 /** @copydoc VBOXHDDBACKEND::pfnAsyncFlush */ 2810 static int vhdAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx) 2811 { 2812 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2679 2813 2680 2814 /* No need to write anything here. Data is always updated on a write. */ 2681 return pImage->pInterfaceIOCallbacks->pfnFlushAsync(pImage->pInterfaceIO->pvUser, 2682 pImage->pStorage, pIoCtx, 2683 NULL, NULL); 2684 } 2685 2815 return vhdFileFlushAsync(pImage, pIoCtx, NULL, NULL); 2816 } 2686 2817 2687 2818 /** @copydoc VBOXHDDBACKEND::pfnResize */ 2688 static int vhdResize(void *p vBackendData, uint64_t cbSize,2689 PC PDMMEDIAGEOMETRY pPCHSGeometry, PCPDMMEDIAGEOMETRY pLCHSGeometry,2819 static int vhdResize(void *pBackendData, uint64_t cbSize, 2820 PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry, 2690 2821 unsigned uPercentStart, unsigned uPercentSpan, 2691 2822 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage, 2692 2823 PVDINTERFACE pVDIfsOperation) 2693 2824 { 2694 PVHDIMAGE pImage = (PVHDIMAGE)p vBackendData;2825 PVHDIMAGE pImage = (PVHDIMAGE)pBackendData; 2695 2826 int rc = VINF_SUCCESS; 2696 2827 … … 2878 3009 VD_CAP_UUID | VD_CAP_DIFF | VD_CAP_FILE | 2879 3010 VD_CAP_CREATE_FIXED | VD_CAP_CREATE_DYNAMIC | 2880 VD_CAP_ASYNC ,3011 VD_CAP_ASYNC | VD_CAP_VFS, 2881 3012 /* papszFileExtensions */ 2882 3013 s_apszVhdFileExtensions, -
trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp
r32195 r32536 1 1 /* $Id$ */ 2 2 /** @file 3 * VMDK Disk image, Core Code.3 * VMDK disk image, core code. 4 4 */ 5 5 … … 27 27 #include <iprt/alloc.h> 28 28 #include <iprt/uuid.h> 29 #include <iprt/file.h>30 29 #include <iprt/path.h> 31 30 #include <iprt/string.h> … … 142 141 uint32_t cbSize; 143 142 uint32_t uType; 144 } VMDKMARKER ;143 } VMDKMARKER, *PVMDKMARKER; 145 144 #pragma pack() 146 145 … … 229 228 /** File open flags for consistency checking. */ 230 229 unsigned fOpen; 231 /** F ile handle. */232 RTFILE File;233 /** Handle for asnychronous access if requested.*/230 /** Flag whether this file has been opened for async I/O. */ 231 bool fAsyncIO; 232 /** Handle for sync/async file abstraction.*/ 234 233 PVDIOSTORAGE pStorage; 235 /** Flag whether to use File or pStorage. */236 bool fAsyncIO;237 234 /** Reference counter. */ 238 235 unsigned uReferences; 239 236 /** Flag whether the file should be deleted on last close. */ 240 237 bool fDelete; 241 /** Pointer to the image we belong to . */238 /** Pointer to the image we belong to (for debugging purposes). */ 242 239 PVMDKIMAGE pImage; 243 240 /** Pointer to next file descriptor. */ … … 404 401 typedef struct VMDKIMAGE 405 402 { 403 /** Image name. */ 404 const char *pszFilename; 405 /** Descriptor file if applicable. */ 406 PVMDKFILE pFile; 407 /** I/O interface. */ 408 PVDINTERFACE pInterfaceIO; 409 /** I/O interface callbacks. */ 410 PVDINTERFACEIO pInterfaceIOCallbacks; 411 412 /** Pointer to the per-disk VD interface list. */ 413 PVDINTERFACE pVDIfsDisk; 414 /** Pointer to the per-image VD interface list. */ 415 PVDINTERFACE pVDIfsImage; 416 417 /** Error interface. */ 418 PVDINTERFACE pInterfaceError; 419 /** Error interface callbacks. */ 420 PVDINTERFACEERROR pInterfaceErrorCallbacks; 421 406 422 /** Pointer to the image extents. */ 407 423 PVMDKEXTENT pExtents; … … 412 428 PVMDKFILE pFiles; 413 429 414 /** Base image name. */415 const char *pszFilename;416 /** Descriptor file if applicable. */417 PVMDKFILE pFile;418 419 /** Pointer to the per-disk VD interface list. */420 PVDINTERFACE pVDIfsDisk;421 /** Pointer to the per-image VD interface list. */422 PVDINTERFACE pVDIfsImage;423 424 /** Error interface. */425 PVDINTERFACE pInterfaceError;426 /** Error interface callbacks. */427 PVDINTERFACEERROR pInterfaceErrorCallbacks;428 429 /** I/O interface. */430 PVDINTERFACE pInterfaceIO;431 /** I/O interface callbacks. */432 PVDINTERFACEIO pInterfaceIOCallbacks;433 430 /** 434 431 * Pointer to an array of segment entries for async I/O. … … 448 445 uint64_t cbSize; 449 446 /** Physical geometry of this image. */ 450 PDMMEDIAGEOMETRYPCHSGeometry;447 VDGEOMETRY PCHSGeometry; 451 448 /** Logical geometry of this image. */ 452 PDMMEDIAGEOMETRYLCHSGeometry;449 VDGEOMETRY LCHSGeometry; 453 450 /** Image UUID. */ 454 451 RTUUID ImageUuid; … … 474 471 typedef struct VMDKINFLATESTATE 475 472 { 473 /* Image this operation relates to. */ 474 PVMDKIMAGE pImage; 476 475 /* File where the data is stored. */ 477 PVMDKFILE File;476 PVMDKFILE pFile; 478 477 /* Total size of the data to read. */ 479 478 size_t cbSize; … … 487 486 typedef struct VMDKDEFLATESTATE 488 487 { 488 /* Image this operation relates to. */ 489 PVMDKIMAGE pImage; 489 490 /* File where the data is to be stored. */ 490 PVMDKFILE File;491 PVMDKFILE pFile; 491 492 /* Offset in the file to write at. */ 492 493 uint64_t uFileOffset; … … 520 521 521 522 /******************************************************************************* 522 523 523 * Static Variables * 524 *******************************************************************************/ 524 525 525 526 /** NULL-terminated array of supported file extensions. */ … … 542 543 static int vmdkFlushImage(PVMDKIMAGE pImage); 543 544 static int vmdkSetImageComment(PVMDKIMAGE pImage, const char *pszComment); 544 static voidvmdkFreeImage(PVMDKIMAGE pImage, bool fDelete);545 546 static int vmdkAllocGrainAsyncComplete(void *p vBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq);545 static int vmdkFreeImage(PVMDKIMAGE pImage, bool fDelete); 546 547 static int vmdkAllocGrainAsyncComplete(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq); 547 548 548 549 /** … … 562 563 563 564 /** 565 * Internal: signal an informational message to the frontend. 566 */ 567 DECLINLINE(int) vmdkMessage(PVMDKIMAGE pImage, const char *pszFormat, ...) 568 { 569 int rc = VINF_SUCCESS; 570 va_list va; 571 va_start(va, pszFormat); 572 if (pImage->pInterfaceError && pImage->pInterfaceErrorCallbacks) 573 rc = pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, 574 pszFormat, va); 575 va_end(va); 576 return rc; 577 } 578 579 /** 564 580 * Internal: open a file (using a file descriptor cache to ensure each file 565 581 * is only opened once - anything else can cause locking problems). 566 582 */ 567 583 static int vmdkFileOpen(PVMDKIMAGE pImage, PVMDKFILE *ppVmdkFile, 568 const char *pszFilename, u nsignedfOpen, bool fAsyncIO)584 const char *pszFilename, uint32_t fOpen, bool fAsyncIO) 569 585 { 570 586 int rc = VINF_SUCCESS; … … 602 618 } 603 619 pVmdkFile->fOpen = fOpen; 604 605 #ifndef VBOX_WITH_NEW_IO_CODE 606 if ((pImage->uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO) && (fAsyncIO)) 607 { 608 rc = pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser, 609 pszFilename, 610 pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY 611 ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY 612 : 0, 613 NULL, 614 pImage->pVDIfsDisk, 615 &pVmdkFile->pStorage); 616 pVmdkFile->fAsyncIO = true; 617 } 618 else 619 { 620 rc = RTFileOpen(&pVmdkFile->File, pszFilename, fOpen); 621 pVmdkFile->fAsyncIO = false; 622 } 623 #else 624 unsigned uOpenFlags = 0; 625 626 if ((fOpen & RTFILE_O_ACCESS_MASK) == RTFILE_O_READ) 627 uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY; 628 if ((fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_CREATE) 629 uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE; 630 if ((fOpen & RTFILE_O_DENY_MASK) == RTFILE_O_DENY_NONE) 631 uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_DONT_LOCK; 620 pVmdkFile->fAsyncIO = fAsyncIO; 632 621 633 622 rc = pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser, 634 pszFilename, 635 uOpenFlags, 623 pszFilename, fOpen, 636 624 &pVmdkFile->pStorage); 637 #endif638 625 if (RT_SUCCESS(rc)) 639 626 { … … 685 672 pImage->pFiles = pNext; 686 673 687 #ifndef VBOX_WITH_NEW_IO_CODE688 if (pVmdkFile->fAsyncIO)689 {690 rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,691 pVmdkFile->pStorage);692 }693 else694 {695 rc = RTFileClose(pVmdkFile->File);696 }697 #else698 674 rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser, 699 675 pVmdkFile->pStorage); 700 #endif701 676 if (RT_SUCCESS(rc) && pVmdkFile->fDelete) 702 rc = RTFileDelete(pVmdkFile->pszFilename); 677 rc = pImage->pInterfaceIOCallbacks->pfnDelete(pImage->pInterfaceIO->pvUser, 678 pVmdkFile->pszFilename); 703 679 RTStrFree((char *)(void *)pVmdkFile->pszFilename); 704 680 RTMemFree(pVmdkFile); … … 710 686 711 687 /** 712 * Internal: re ad from a file distinguishing between async and normal operation688 * Internal: rename a file (sync) 713 689 */ 714 DECLINLINE(int) vmdkFileReadAt(PVMDKFILE pVmdkFile, 715 uint64_t uOffset, void *pvBuf, 716 size_t cbToRead, size_t *pcbRead) 717 { 718 PVMDKIMAGE pImage = pVmdkFile->pImage; 719 720 #ifndef VBOX_WITH_NEW_IO_CODE 721 if (pVmdkFile->fAsyncIO) 722 return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser, 723 pVmdkFile->pStorage, uOffset, 724 cbToRead, pvBuf, pcbRead); 725 else 726 return RTFileReadAt(pVmdkFile->File, uOffset, pvBuf, cbToRead, pcbRead); 727 #else 690 DECLINLINE(int) vmdkFileMove(PVMDKIMAGE pImage, const char *pszSrc, 691 const char *pszDst, unsigned fMove) 692 { 693 return pImage->pInterfaceIOCallbacks->pfnMove(pImage->pInterfaceIO->pvUser, 694 pszSrc, pszDst, fMove); 695 } 696 697 /** 698 * Internal: get the size of a file (sync/async) 699 */ 700 DECLINLINE(int) vmdkFileGetSize(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile, 701 uint64_t *pcbSize) 702 { 703 return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser, 704 pVmdkFile->pStorage, 705 pcbSize); 706 } 707 708 /** 709 * Internal: set the size of a file (sync/async) 710 */ 711 DECLINLINE(int) vmdkFileSetSize(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile, 712 uint64_t cbSize) 713 { 714 return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser, 715 pVmdkFile->pStorage, 716 cbSize); 717 } 718 719 /** 720 * Internal: read from a file (sync) 721 */ 722 DECLINLINE(int) vmdkFileReadSync(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile, 723 uint64_t uOffset, void *pvBuf, 724 size_t cbToRead, size_t *pcbRead) 725 { 728 726 return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser, 729 727 pVmdkFile->pStorage, uOffset, 730 cbToRead, pvBuf, pcbRead); 731 #endif 728 pvBuf, cbToRead, pcbRead); 732 729 } 733 730 734 731 /** 735 * Internal: write to a file distinguishing between async and normal operation732 * Internal: write to a file (sync) 736 733 */ 737 DECLINLINE(int) vmdkFileWriteAt(PVMDKFILE pVmdkFile, 738 uint64_t uOffset, const void *pvBuf, 739 size_t cbToWrite, size_t *pcbWritten) 740 { 741 PVMDKIMAGE pImage = pVmdkFile->pImage; 742 743 #ifndef VBOX_WITH_NEW_IO_CODE 744 if (pVmdkFile->fAsyncIO) 745 return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser, 746 pVmdkFile->pStorage, uOffset, 747 cbToWrite, pvBuf, pcbWritten); 748 else 749 return RTFileWriteAt(pVmdkFile->File, uOffset, pvBuf, cbToWrite, pcbWritten); 750 #else 751 return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser, 752 pVmdkFile->pStorage, uOffset, 753 cbToWrite, pvBuf, pcbWritten); 754 #endif 734 DECLINLINE(int) vmdkFileWriteSync(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile, 735 uint64_t uOffset, const void *pvBuf, 736 size_t cbToWrite, size_t *pcbWritten) 737 { 738 return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser, 739 pVmdkFile->pStorage, uOffset, 740 pvBuf, cbToWrite, pcbWritten); 755 741 } 756 742 757 743 /** 758 * Internal: get the size of a file distinguishing beween async and normal operation744 * Internal: flush a file (sync) 759 745 */ 760 DECLINLINE(int) vmdkFileGetSize(PVMDKFILE pVmdkFile, uint64_t *pcbSize) 761 { 762 PVMDKIMAGE pImage = pVmdkFile->pImage; 763 764 #ifndef VBOX_WITH_NEW_IO_CODE 765 if (pVmdkFile->fAsyncIO) 766 { 767 return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser, 768 pVmdkFile->pStorage, 769 pcbSize); 770 } 771 else 772 return RTFileGetSize(pVmdkFile->File, pcbSize); 773 #else 774 return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser, 775 pVmdkFile->pStorage, 776 pcbSize); 777 #endif 778 } 779 780 /** 781 * Internal: set the size of a file distinguishing beween async and normal operation 782 */ 783 DECLINLINE(int) vmdkFileSetSize(PVMDKFILE pVmdkFile, uint64_t cbSize) 784 { 785 PVMDKIMAGE pImage = pVmdkFile->pImage; 786 787 #ifndef VBOX_WITH_NEW_IO_CODE 788 if (pVmdkFile->fAsyncIO) 789 { 790 return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser, 791 pVmdkFile->pStorage, 792 cbSize); 793 } 794 else 795 return RTFileSetSize(pVmdkFile->File, cbSize); 796 #else 797 return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser, 798 pVmdkFile->pStorage, 799 cbSize); 800 #endif 801 } 802 803 /** 804 * Internal: flush a file distinguishing between async and normal operation 805 */ 806 DECLINLINE(int) vmdkFileFlush(PVMDKFILE pVmdkFile) 807 { 808 PVMDKIMAGE pImage = pVmdkFile->pImage; 809 810 #ifndef VBOX_WITH_NEW_IO_CODE 811 if (pVmdkFile->fAsyncIO) 812 return pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser, 813 pVmdkFile->pStorage); 814 else 815 return RTFileFlush(pVmdkFile->File); 816 #else 746 DECLINLINE(int) vmdkFileFlush(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile) 747 { 817 748 return pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser, 818 749 pVmdkFile->pStorage); 819 #endif 820 } 821 822 823 DECLINLINE(int) vmdkFileFlushAsync(PVMDKFILE pVmdkFile, PVDIOCTX pIoCtx) 824 { 825 PVMDKIMAGE pImage = pVmdkFile->pImage; 826 750 } 751 752 /** 753 * Internal: read user data (async) 754 */ 755 DECLINLINE(int) vmdkFileReadUserAsync(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile, 756 uint64_t uOffset, PVDIOCTX pIoCtx, 757 size_t cbRead) 758 { 759 return pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser, 760 pVmdkFile->pStorage, 761 uOffset, pIoCtx, 762 cbRead); 763 } 764 765 /** 766 * Internal: write user data (async) 767 */ 768 DECLINLINE(int) vmdkFileWriteUserAsync(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile, 769 uint64_t uOffset, PVDIOCTX pIoCtx, 770 size_t cbWrite, 771 PFNVDXFERCOMPLETED pfnComplete, 772 void *pvCompleteUser) 773 { 774 return pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser, 775 pVmdkFile->pStorage, 776 uOffset, pIoCtx, 777 cbWrite, 778 pfnComplete, 779 pvCompleteUser); 780 } 781 782 /** 783 * Internal: read metadata (async) 784 */ 785 DECLINLINE(int) vmdkFileReadMetaAsync(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile, 786 uint64_t uOffset, void *pvBuffer, 787 size_t cbBuffer, PVDIOCTX pIoCtx, 788 PPVDMETAXFER ppMetaXfer, 789 PFNVDXFERCOMPLETED pfnComplete, 790 void *pvCompleteUser) 791 { 792 return pImage->pInterfaceIOCallbacks->pfnReadMetaAsync(pImage->pInterfaceIO->pvUser, 793 pVmdkFile->pStorage, 794 uOffset, pvBuffer, 795 cbBuffer, pIoCtx, 796 ppMetaXfer, 797 pfnComplete, 798 pvCompleteUser); 799 } 800 801 /** 802 * Internal: write metadata (async) 803 */ 804 DECLINLINE(int) vmdkFileWriteMetaAsync(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile, 805 uint64_t uOffset, void *pvBuffer, 806 size_t cbBuffer, PVDIOCTX pIoCtx, 807 PFNVDXFERCOMPLETED pfnComplete, 808 void *pvCompleteUser) 809 { 810 return pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pImage->pInterfaceIO->pvUser, 811 pVmdkFile->pStorage, 812 uOffset, pvBuffer, 813 cbBuffer, pIoCtx, 814 pfnComplete, 815 pvCompleteUser); 816 } 817 818 /** 819 * Internal: releases a metadata transfer handle (async) 820 */ 821 DECLINLINE(void) vmdkFileMetaXferRelease(PVMDKIMAGE pImage, PVDMETAXFER pMetaXfer) 822 { 823 pImage->pInterfaceIOCallbacks->pfnMetaXferRelease(pImage->pInterfaceIO->pvUser, 824 pMetaXfer); 825 } 826 827 /** 828 * Internal: flush a file (async) 829 */ 830 DECLINLINE(int) vmdkFileFlushAsync(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile, 831 PVDIOCTX pIoCtx) 832 { 827 833 return pImage->pInterfaceIOCallbacks->pfnFlushAsync(pImage->pInterfaceIO->pvUser, 828 834 pVmdkFile->pStorage, pIoCtx, 829 835 NULL, NULL); 836 } 837 838 /** 839 * Internal: sets the buffer to a specific byte (async) 840 */ 841 DECLINLINE(int) vmdkFileIoCtxSet(PVMDKIMAGE pImage, PVDIOCTX pIoCtx, 842 int ch, size_t cbSet) 843 { 844 return pImage->pInterfaceIOCallbacks->pfnIoCtxSet(pImage->pInterfaceIO->pvUser, 845 pIoCtx, ch, cbSet); 830 846 } 831 847 … … 845 861 } 846 862 cbBuf = RT_MIN(cbBuf, pInflateState->cbSize); 847 int rc = vmdkFileReadAt(pInflateState->File, pInflateState->uFileOffset, pvBuf, cbBuf, NULL); 863 int rc = vmdkFileReadSync(pInflateState->pImage, pInflateState->pFile, 864 pInflateState->uFileOffset, pvBuf, cbBuf, NULL); 848 865 if (RT_FAILURE(rc)) 849 866 return rc; … … 860 877 * distinguishing between async and normal operation 861 878 */ 862 DECLINLINE(int) vmdkFileInflate At(PVMDKFILE pVmdkFile,863 uint64_t uOffset, void *pvBuf,864 size_t cbToRead, unsigned uMarker,865 uint64_t *puLBA, uint32_t *pcbMarkerData)879 DECLINLINE(int) vmdkFileInflateSync(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile, 880 uint64_t uOffset, void *pvBuf, 881 size_t cbToRead, unsigned uMarker, 882 uint64_t *puLBA, uint32_t *pcbMarkerData) 866 883 { 867 884 if (pVmdkFile->fAsyncIO) … … 882 899 if (uMarker == VMDK_MARKER_IGNORE) 883 900 cbMarker -= sizeof(Marker.uType); 884 rc = vmdkFileRead At(pVmdkFile, uOffset, &Marker, cbMarker, NULL);901 rc = vmdkFileReadSync(pImage, pVmdkFile, uOffset, &Marker, cbMarker, NULL); 885 902 if (RT_FAILURE(rc)) 886 903 return rc; … … 924 941 } 925 942 } 926 InflateState.File = pVmdkFile; 943 InflateState.pImage = pImage; 944 InflateState.pFile = pVmdkFile; 927 945 InflateState.cbSize = cbComp; 928 946 InflateState.uFileOffset = uCompOffset; … … 959 977 if (!cbBuf) 960 978 return VINF_SUCCESS; 961 int rc = vmdkFileWriteAt(pDeflateState->File, pDeflateState->uFileOffset, pvBuf, cbBuf, NULL); 979 int rc = vmdkFileWriteSync(pDeflateState->pImage, pDeflateState->pFile, 980 pDeflateState->uFileOffset, pvBuf, cbBuf, NULL); 962 981 if (RT_FAILURE(rc)) 963 982 return rc; … … 971 990 * distinguishing between async and normal operation 972 991 */ 973 DECLINLINE(int) vmdkFileDeflate At(PVMDKFILE pVmdkFile,974 uint64_t uOffset, const void *pvBuf,975 size_t cbToWrite, unsigned uMarker,976 uint64_t uLBA, uint32_t *pcbMarkerData)992 DECLINLINE(int) vmdkFileDeflateSync(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile, 993 uint64_t uOffset, const void *pvBuf, 994 size_t cbToWrite, unsigned uMarker, 995 uint64_t uLBA, uint32_t *pcbMarkerData) 977 996 { 978 997 if (pVmdkFile->fAsyncIO) … … 1002 1021 return VERR_NOT_IMPLEMENTED; 1003 1022 } 1004 DeflateState.File = pVmdkFile; 1023 DeflateState.pImage = pImage; 1024 DeflateState.pFile = pVmdkFile; 1005 1025 DeflateState.uFileOffset = uCompOffset; 1006 1026 DeflateState.iOffset = -1; … … 1028 1048 */ 1029 1049 uint64_t cbOld; 1030 rc = vmdkFileGetSize(p VmdkFile, &cbOld);1050 rc = vmdkFileGetSize(pImage, pVmdkFile, &cbOld); 1031 1051 if (RT_FAILURE(rc)) 1032 1052 return rc; 1033 1053 1034 1054 if (cbOld != DeflateState.uFileOffset) 1035 rc = vmdkFileSetSize(p VmdkFile, DeflateState.uFileOffset);1055 rc = vmdkFileSetSize(pImage, pVmdkFile, DeflateState.uFileOffset); 1036 1056 1037 1057 if (uMarker == VMDK_MARKER_IGNORE) … … 1039 1059 /* Compressed grain marker. */ 1040 1060 Marker.cbSize = RT_H2LE_U32(DeflateState.iOffset); 1041 rc = vmdkFileWrite At(pVmdkFile, uOffset, &Marker, 12, NULL);1061 rc = vmdkFileWriteSync(pImage, pVmdkFile, uOffset, &Marker, 12, NULL); 1042 1062 if (RT_FAILURE(rc)) 1043 1063 return rc; … … 1070 1090 pImage->pFiles = pVmdkFile->pNext; 1071 1091 1072 if (pImage->uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO) 1073 rc2 = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser, 1074 pVmdkFile->pStorage); 1075 else 1076 rc2 = vmdkFileClose(pImage, &pVmdkFile, pVmdkFile->fDelete); 1092 rc2 = vmdkFileClose(pImage, &pVmdkFile, pVmdkFile->fDelete); 1077 1093 1078 1094 if (RT_SUCCESS(rc)) … … 1173 1189 } 1174 1190 1175 static int vmdkReadGrainDirectory(PVMDK EXTENT pExtent)1191 static int vmdkReadGrainDirectory(PVMDKIMAGE pImage, PVMDKEXTENT pExtent) 1176 1192 { 1177 1193 int rc = VINF_SUCCESS; … … 1192 1208 /* The VMDK 1.1 spec talks about compressed grain directories, but real 1193 1209 * life files don't have them. The spec is wrong in creative ways. */ 1194 rc = vmdkFileReadAt(pExtent->pFile, VMDK_SECTOR2BYTE(pExtent->uSectorGD), 1195 pGD, cbGD, NULL); 1210 rc = vmdkFileReadSync(pImage, pExtent->pFile, 1211 VMDK_SECTOR2BYTE(pExtent->uSectorGD), 1212 pGD, cbGD, NULL); 1196 1213 AssertRC(rc); 1197 1214 if (RT_FAILURE(rc)) 1198 1215 { 1199 rc = vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: could not read grain directory in '%s': %Rrc"), pExtent->pszFullname);1216 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not read grain directory in '%s': %Rrc"), pExtent->pszFullname); 1200 1217 goto out; 1201 1218 } … … 1214 1231 /* The VMDK 1.1 spec talks about compressed grain directories, but real 1215 1232 * life files don't have them. The spec is wrong in creative ways. */ 1216 rc = vmdkFileReadAt(pExtent->pFile, VMDK_SECTOR2BYTE(pExtent->uSectorRGD), 1217 pRGD, cbGD, NULL); 1233 rc = vmdkFileReadSync(pImage, pExtent->pFile, 1234 VMDK_SECTOR2BYTE(pExtent->uSectorRGD), 1235 pRGD, cbGD, NULL); 1218 1236 AssertRC(rc); 1219 1237 if (RT_FAILURE(rc)) 1220 1238 { 1221 rc = vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: could not read redundant grain directory in '%s'"), pExtent->pszFullname);1239 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not read redundant grain directory in '%s'"), pExtent->pszFullname); 1222 1240 goto out; 1223 1241 } … … 1256 1274 RTMemTmpFree(pTmpGT1); 1257 1275 RTMemTmpFree(pTmpGT2); 1258 rc = vmdkError(p Extent->pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: inconsistent references to grain directory in '%s'"), pExtent->pszFullname);1276 rc = vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: inconsistent references to grain directory in '%s'"), pExtent->pszFullname); 1259 1277 goto out; 1260 1278 } 1261 1279 /* The VMDK 1.1 spec talks about compressed grain tables, but real 1262 1280 * life files don't have them. The spec is wrong in creative ways. */ 1263 rc = vmdkFileReadAt(pExtent->pFile, VMDK_SECTOR2BYTE(*pGDTmp), 1264 pTmpGT1, cbGT, NULL); 1281 rc = vmdkFileReadSync(pImage, pExtent->pFile, 1282 VMDK_SECTOR2BYTE(*pGDTmp), 1283 pTmpGT1, cbGT, NULL); 1265 1284 if (RT_FAILURE(rc)) 1266 1285 { 1267 rc = vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: error reading grain table in '%s'"), pExtent->pszFullname);1286 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error reading grain table in '%s'"), pExtent->pszFullname); 1268 1287 RTMemTmpFree(pTmpGT1); 1269 1288 RTMemTmpFree(pTmpGT2); … … 1272 1291 /* The VMDK 1.1 spec talks about compressed grain tables, but real 1273 1292 * life files don't have them. The spec is wrong in creative ways. */ 1274 rc = vmdkFileReadAt(pExtent->pFile, VMDK_SECTOR2BYTE(*pRGDTmp), 1275 pTmpGT2, cbGT, NULL); 1293 rc = vmdkFileReadSync(pImage, pExtent->pFile, 1294 VMDK_SECTOR2BYTE(*pRGDTmp), 1295 pTmpGT2, cbGT, NULL); 1276 1296 if (RT_FAILURE(rc)) 1277 1297 { 1278 rc = vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: error reading backup grain table in '%s'"), pExtent->pszFullname);1298 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error reading backup grain table in '%s'"), pExtent->pszFullname); 1279 1299 RTMemTmpFree(pTmpGT1); 1280 1300 RTMemTmpFree(pTmpGT2); … … 1285 1305 RTMemTmpFree(pTmpGT1); 1286 1306 RTMemTmpFree(pTmpGT2); 1287 rc = vmdkError(p Extent->pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: inconsistency between grain table and backup grain table in '%s'"), pExtent->pszFullname);1307 rc = vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: inconsistency between grain table and backup grain table in '%s'"), pExtent->pszFullname); 1288 1308 goto out; 1289 1309 } … … 1295 1315 } 1296 1316 1297 if (p Extent->pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)1317 if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED) 1298 1318 { 1299 1319 uint32_t uLastGrainWritten = 0; … … 1314 1334 /* The VMDK 1.1 spec talks about compressed grain tables, but real 1315 1335 * life files don't have them. The spec is wrong in creative ways. */ 1316 rc = vmdkFileReadAt(pExtent->pFile, VMDK_SECTOR2BYTE(*pGDTmp), 1317 pTmpGT, cbGT, NULL); 1336 rc = vmdkFileReadSync(pImage, pExtent->pFile, 1337 VMDK_SECTOR2BYTE(*pGDTmp), 1338 pTmpGT, cbGT, NULL); 1318 1339 if (RT_FAILURE(rc)) 1319 1340 { 1320 rc = vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: error reading grain table in '%s'"), pExtent->pszFullname);1341 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error reading grain table in '%s'"), pExtent->pszFullname); 1321 1342 RTMemTmpFree(pTmpGT); 1322 1343 goto out; … … 1334 1355 if (uLastGrainSector && uLastGrainSector >= uGTTmp) 1335 1356 { 1336 rc = vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: grain table in '%s' contains a violation of the ordering assumptions"), pExtent->pszFullname);1357 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: grain table in '%s' contains a violation of the ordering assumptions"), pExtent->pszFullname); 1337 1358 RTMemTmpFree(pTmpGT); 1338 1359 goto out; … … 1356 1377 uint64_t uLBA = 0; 1357 1378 uint32_t cbMarker = 0; 1358 rc = vmdkFileInflate At(pExtent->pFile, VMDK_SECTOR2BYTE(uLastGrainSector),1359 pExtent->pvGrain, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain), VMDK_MARKER_IGNORE, &uLBA, &cbMarker);1379 rc = vmdkFileInflateSync(pImage, pExtent->pFile, VMDK_SECTOR2BYTE(uLastGrainSector), 1380 pExtent->pvGrain, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain), VMDK_MARKER_IGNORE, &uLBA, &cbMarker); 1360 1381 if (RT_FAILURE(rc)) 1361 1382 goto out; … … 1375 1396 } 1376 1397 1377 static int vmdkCreateGrainDirectory(PVMDK EXTENT pExtent, uint64_t uStartSector,1378 bool fPreAlloc)1398 static int vmdkCreateGrainDirectory(PVMDKIMAGE pImage, PVMDKEXTENT pExtent, 1399 uint64_t uStartSector, bool fPreAlloc) 1379 1400 { 1380 1401 int rc = VINF_SUCCESS; … … 1406 1427 pExtent->pRGD = pRGD; 1407 1428 1408 cbOverhead = RT_ALIGN_64(VMDK_SECTOR2BYTE(uStartSector) + 2 * (cbGDRounded + cbGTRounded), VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain)); 1409 /* For streamOptimized extents put the end-of-stream marker at the end. */ 1410 if (pExtent->pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED) 1411 rc = vmdkFileSetSize(pExtent->pFile, cbOverhead + 512); 1429 if (uStartSector != VMDK_GD_AT_END) 1430 { 1431 cbOverhead = RT_ALIGN_64(VMDK_SECTOR2BYTE(uStartSector) + 2 * (cbGDRounded + cbGTRounded), VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain)); 1432 /* For streamOptimized extents put the end-of-stream marker at the end. */ 1433 if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED) 1434 rc = vmdkFileSetSize(pImage, pExtent->pFile, cbOverhead + 512); 1435 else 1436 rc = vmdkFileSetSize(pImage, pExtent->pFile, cbOverhead); 1437 if (RT_FAILURE(rc)) 1438 goto out; 1439 pExtent->uSectorRGD = uStartSector; 1440 pExtent->uSectorGD = uStartSector + VMDK_BYTE2SECTOR(cbGDRounded + cbGTRounded); 1441 } 1412 1442 else 1413 rc = vmdkFileSetSize(pExtent->pFile, cbOverhead);1414 if (RT_FAILURE(rc))1415 goto out;1416 pExtent->uSectorRGD = uStartSector;1417 pExtent->uSectorGD = uStartSector + VMDK_BYTE2SECTOR(cbGDRounded + cbGTRounded);1443 { 1444 cbOverhead = VMDK_SECTOR2BYTE(uStartSector); 1445 pExtent->uSectorRGD = uStartSector; 1446 pExtent->uSectorGD = uStartSector; 1447 } 1418 1448 1419 1449 if (fPreAlloc) … … 1428 1458 uGTSectorLE = RT_H2LE_U64(uOffsetSectors); 1429 1459 /* Write the redundant grain directory entry to disk. */ 1430 rc = vmdkFileWrite At(pExtent->pFile,1431 VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + i * sizeof(uGTSectorLE),1432 &uGTSectorLE, sizeof(uGTSectorLE), NULL);1460 rc = vmdkFileWriteSync(pImage, pExtent->pFile, 1461 VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + i * sizeof(uGTSectorLE), 1462 &uGTSectorLE, sizeof(uGTSectorLE), NULL); 1433 1463 if (RT_FAILURE(rc)) 1434 1464 { 1435 rc = vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write new redundant grain directory entry in '%s'"), pExtent->pszFullname);1465 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write new redundant grain directory entry in '%s'"), pExtent->pszFullname); 1436 1466 goto out; 1437 1467 } … … 1445 1475 uGTSectorLE = RT_H2LE_U64(uOffsetSectors); 1446 1476 /* Write the grain directory entry to disk. */ 1447 rc = vmdkFileWrite At(pExtent->pFile,1448 VMDK_SECTOR2BYTE(pExtent->uSectorGD) + i * sizeof(uGTSectorLE),1449 &uGTSectorLE, sizeof(uGTSectorLE), NULL);1477 rc = vmdkFileWriteSync(pImage, pExtent->pFile, 1478 VMDK_SECTOR2BYTE(pExtent->uSectorGD) + i * sizeof(uGTSectorLE), 1479 &uGTSectorLE, sizeof(uGTSectorLE), NULL); 1450 1480 if (RT_FAILURE(rc)) 1451 1481 { 1452 rc = vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write new grain directory entry in '%s'"), pExtent->pszFullname);1482 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write new grain directory entry in '%s'"), pExtent->pszFullname); 1453 1483 goto out; 1454 1484 } … … 1459 1489 1460 1490 /* streamOptimized extents need a grain decompress buffer. */ 1461 if (p Extent->pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)1491 if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED) 1462 1492 { 1463 1493 pExtent->pvGrain = RTMemAlloc(VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain)); … … 2043 2073 2044 2074 static int vmdkDescSetPCHSGeometry(PVMDKIMAGE pImage, 2045 PC PDMMEDIAGEOMETRY pPCHSGeometry)2075 PCVDGEOMETRY pPCHSGeometry) 2046 2076 { 2047 2077 int rc = vmdkDescDDBSetU32(pImage, &pImage->Descriptor, … … 2062 2092 2063 2093 static int vmdkDescSetLCHSGeometry(PVMDKIMAGE pImage, 2064 PC PDMMEDIAGEOMETRY pLCHSGeometry)2094 PCVDGEOMETRY pLCHSGeometry) 2065 2095 { 2066 2096 int rc = vmdkDescDDBSetU32(pImage, &pImage->Descriptor, … … 2565 2595 if (RT_SUCCESS(rc)) 2566 2596 { 2567 rc = vmdkFileWrite At(pDescFile, uOffset, pszDescriptor, cbLimit ? cbLimit : offDescriptor, NULL);2597 rc = vmdkFileWriteSync(pImage, pDescFile, uOffset, pszDescriptor, cbLimit ? cbLimit : offDescriptor, NULL); 2568 2598 if (RT_FAILURE(rc)) 2569 2599 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename); … … 2572 2602 if (RT_SUCCESS(rc) && !cbLimit) 2573 2603 { 2574 rc = vmdkFileSetSize(p DescFile, offDescriptor);2604 rc = vmdkFileSetSize(pImage, pDescFile, offDescriptor); 2575 2605 if (RT_FAILURE(rc)) 2576 2606 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error truncating descriptor in '%s'"), pImage->pszFilename); … … 2668 2698 if (RT_SUCCESS(rc)) 2669 2699 { 2670 rc = vmdkFileWrite At(pDescFile, uOffset, pszDescriptor, cbLimit ? cbLimit : offDescriptor, NULL);2700 rc = vmdkFileWriteSync(pImage, pDescFile, uOffset, pszDescriptor, cbLimit ? cbLimit : offDescriptor, NULL); 2671 2701 if (RT_FAILURE(rc)) 2672 2702 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename); … … 2675 2705 if (RT_SUCCESS(rc) && !cbLimit) 2676 2706 { 2677 rc = vmdkFileSetSize(p DescFile, offDescriptor);2707 rc = vmdkFileSetSize(pImage, pDescFile, offDescriptor); 2678 2708 if (RT_FAILURE(rc)) 2679 2709 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error truncating descriptor in '%s'"), pImage->pszFilename); … … 2725 2755 uint64_t cSectorsPerGDE; 2726 2756 2727 int rc = vmdkFileRead At(pExtent->pFile, 0, &Header, sizeof(Header), NULL);2757 int rc = vmdkFileReadSync(pImage, pExtent->pFile, 0, &Header, sizeof(Header), NULL); 2728 2758 AssertRC(rc); 2729 2759 if (RT_FAILURE(rc)) … … 2742 2772 * VMware reality. Theory and practice have very little in common. */ 2743 2773 uint64_t cbSize; 2744 rc = vmdkFileGetSize(p Extent->pFile, &cbSize);2774 rc = vmdkFileGetSize(pImage, pExtent->pFile, &cbSize); 2745 2775 AssertRC(rc); 2746 2776 if (RT_FAILURE(rc)) … … 2750 2780 } 2751 2781 cbSize = RT_ALIGN_64(cbSize, 512); 2752 rc = vmdkFileRead At(pExtent->pFile, cbSize - 2*512, &Header, sizeof(Header), NULL);2782 rc = vmdkFileReadSync(pImage, pExtent->pFile, cbSize - 2*512, &Header, sizeof(Header), NULL); 2753 2783 AssertRC(rc); 2754 2784 if (RT_FAILURE(rc)) … … 2832 2862 * area (flat images only). If not, it means the image is at least 2833 2863 * truncated, or even seriously garbled. */ 2834 rc = vmdkFileGetSize(p Extent->pFile, &cbExtentSize);2864 rc = vmdkFileGetSize(pImage, pExtent->pFile, &cbExtentSize); 2835 2865 if (RT_FAILURE(rc)) 2836 2866 { … … 2868 2898 } 2869 2899 2870 rc = vmdkReadGrainDirectory(p Extent);2900 rc = vmdkReadGrainDirectory(pImage, pExtent); 2871 2901 2872 2902 out: … … 2880 2910 * Internal: write/update the metadata for a sparse extent. 2881 2911 */ 2882 static int vmdkWriteMetaSparseExtent(PVMDKEXTENT pExtent, uint64_t uOffset) 2912 static int vmdkWriteMetaSparseExtent(PVMDKIMAGE pImage, PVMDKEXTENT pExtent, 2913 uint64_t uOffset) 2883 2914 { 2884 2915 SparseExtentHeader Header; … … 2890 2921 if (pExtent->pRGD) 2891 2922 Header.flags |= RT_H2LE_U32(RT_BIT(1)); 2892 if (p Extent->pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)2923 if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED) 2893 2924 Header.flags |= RT_H2LE_U32(RT_BIT(16) | RT_BIT(17)); 2894 2925 Header.capacity = RT_H2LE_U64(pExtent->cSectors); … … 2931 2962 Header.compressAlgorithm = RT_H2LE_U16(pExtent->uCompression); 2932 2963 2933 int rc = vmdkFileWrite At(pExtent->pFile, uOffset, &Header, sizeof(Header), NULL);2964 int rc = vmdkFileWriteSync(pImage, pExtent->pFile, uOffset, &Header, sizeof(Header), NULL); 2934 2965 AssertRC(rc); 2935 2966 if (RT_FAILURE(rc)) 2936 rc = vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: error writing extent header in '%s'"), pExtent->pszFullname);2967 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing extent header in '%s'"), pExtent->pszFullname); 2937 2968 return rc; 2938 2969 } … … 2952 2983 if (pExtent->pRGD) 2953 2984 Header.flags |= RT_H2LE_U32(RT_BIT(1)); 2954 if (p Extent->pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)2985 if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED) 2955 2986 Header.flags |= RT_H2LE_U32(RT_BIT(16) | RT_BIT(17)); 2956 2987 Header.capacity = RT_H2LE_U64(pExtent->cSectors); … … 2993 3024 Header.compressAlgorithm = RT_H2LE_U16(pExtent->uCompression); 2994 3025 2995 int rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pImage->pInterfaceIO->pvUser, 2996 pExtent->pFile->pStorage, 2997 uOffset, &Header, sizeof(Header), 2998 pIoCtx, NULL, NULL); 3026 int rc = vmdkFileWriteMetaAsync(pImage, pExtent->pFile, 3027 uOffset, &Header, sizeof(Header), 3028 pIoCtx, NULL, NULL); 2999 3029 if (RT_FAILURE(rc) && (rc != VERR_VD_ASYNC_IO_IN_PROGRESS)) 3000 rc = vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: error writing extent header in '%s'"), pExtent->pszFullname);3030 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing extent header in '%s'"), pExtent->pszFullname); 3001 3031 return rc; 3002 3032 } … … 3013 3043 uint64_t cSectorsPerGDE; 3014 3044 3015 int rc = vmdkFileRead At(pExtent->pFile, 0, &Header, sizeof(Header), NULL);3045 int rc = vmdkFileReadSync(pImage, pExtent->pFile, 0, &Header, sizeof(Header), NULL); 3016 3046 AssertRC(rc); 3017 3047 if (RT_FAILURE(rc)) … … 3060 3090 pExtent->fUncleanShutdown = !!Header.uncleanShutdown; 3061 3091 3062 rc = vmdkReadGrainDirectory(p Extent);3092 rc = vmdkReadGrainDirectory(pImage, pExtent); 3063 3093 3064 3094 out: … … 3174 3204 3175 3205 /** 3176 * Internal: Translate the VBoxHDD open flags to RTFile open flags.3177 */3178 static uint32_t vmdkFileOpenFlags(unsigned uOpenFlags)3179 {3180 uint32_t fDeny = uOpenFlags & (VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_SHAREABLE)3181 ? RTFILE_O_DENY_NONE3182 : RTFILE_O_DENY_WRITE;3183 uint32_t fOpen = uOpenFlags & VD_OPEN_FLAGS_READONLY3184 ? RTFILE_O_READ3185 : RTFILE_O_READWRITE;3186 fOpen |= RTFILE_O_OPEN | fDeny;3187 return fOpen;3188 }3189 3190 /**3191 3206 * Internal: Open an image, constructing all necessary data structures. 3192 3207 */ … … 3205 3220 pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError); 3206 3221 3207 /* Try to get asyncI/O interface. */3222 /* Get I/O interface. */ 3208 3223 pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IO); 3209 if (pImage->pInterfaceIO) 3210 pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO); 3224 AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER); 3225 pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO); 3226 AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER); 3211 3227 3212 3228 /* … … 3218 3234 3219 3235 rc = vmdkFileOpen(pImage, &pFile, pImage->pszFilename, 3220 vmdkFileOpenFlags(uOpenFlags), false); 3236 VDOpenFlagsToFileOpenFlags(uOpenFlags, false /* fCreate */), 3237 false /* fAsyncIO */); 3221 3238 if (RT_FAILURE(rc)) 3222 3239 { … … 3228 3245 3229 3246 /* Read magic (if present). */ 3230 rc = vmdkFileRead At(pFile, 0, &u32Magic, sizeof(u32Magic), NULL);3247 rc = vmdkFileReadSync(pImage, pFile, 0, &u32Magic, sizeof(u32Magic), NULL); 3231 3248 if (RT_FAILURE(rc)) 3232 3249 { … … 3282 3299 goto out; 3283 3300 } 3284 rc = vmdkFileRead At(pExtent->pFile,3285 VMDK_SECTOR2BYTE(pExtent->uDescriptorSector),3286 pExtent->pDescData,3287 VMDK_SECTOR2BYTE(pExtent->cDescriptorSectors), NULL);3301 rc = vmdkFileReadSync(pImage, pExtent->pFile, 3302 VMDK_SECTOR2BYTE(pExtent->uDescriptorSector), 3303 pExtent->pDescData, 3304 VMDK_SECTOR2BYTE(pExtent->cDescriptorSectors), NULL); 3288 3305 AssertRC(rc); 3289 3306 if (RT_FAILURE(rc)) … … 3316 3333 * and will result in the correct "truncated read" error handling. */ 3317 3334 uint64_t cbFileSize; 3318 rc = vmdkFileGetSize(p File, &cbFileSize);3335 rc = vmdkFileGetSize(pImage, pFile, &cbFileSize); 3319 3336 if (RT_FAILURE(rc)) 3320 3337 goto out; … … 3335 3352 3336 3353 size_t cbRead; 3337 rc = vmdkFileRead At(pImage->pFile, 0, pImage->pDescData,3338 RT_MIN(pImage->cbDescAlloc, cbFileSize),3339 &cbRead);3354 rc = vmdkFileReadSync(pImage, pImage->pFile, 0, pImage->pDescData, 3355 RT_MIN(pImage->cbDescAlloc, cbFileSize), 3356 &cbRead); 3340 3357 if (RT_FAILURE(rc)) 3341 3358 { … … 3433 3450 case VMDKETYPE_HOSTED_SPARSE: 3434 3451 rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname, 3435 vmdkFileOpenFlags(uOpenFlags), false); 3452 VDOpenFlagsToFileOpenFlags(uOpenFlags, 3453 false /* fCreate */), 3454 false /* fAsyncIO */); 3436 3455 if (RT_FAILURE(rc)) 3437 3456 { … … 3458 3477 case VMDKETYPE_FLAT: 3459 3478 rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname, 3460 vmdkFileOpenFlags(uOpenFlags), true); 3479 VDOpenFlagsToFileOpenFlags(uOpenFlags, 3480 false /* fCreate */), 3481 true /* fAsyncIO */); 3461 3482 if (RT_FAILURE(rc)) 3462 3483 { … … 3539 3560 3540 3561 /** 3541 * Internal: Translate the VBoxHDD open flags to RTFile open/create flags.3542 */3543 static uint32_t vmdkFileCreateFlags(unsigned uOpenFlags)3544 {3545 uint32_t fDeny = uOpenFlags & VD_OPEN_FLAGS_SHAREABLE3546 ? RTFILE_O_DENY_NONE3547 : RTFILE_O_DENY_WRITE;3548 uint32_t fOpen = RTFILE_O_READWRITE | RTFILE_O_NOT_CONTENT_INDEXED;3549 fOpen |= RTFILE_O_CREATE | fDeny;3550 return fOpen;3551 }3552 3553 /**3554 3562 * Internal: create VMDK images for raw disk/partition access. 3555 3563 */ … … 3570 3578 /* Create raw disk descriptor file. */ 3571 3579 rc = vmdkFileOpen(pImage, &pImage->pFile, pImage->pszFilename, 3572 vmdkFileCreateFlags(pImage->uOpenFlags), false); 3580 VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags, 3581 true /* fCreate */), 3582 false /* fAsyncIO */); 3573 3583 if (RT_FAILURE(rc)) 3574 3584 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pImage->pszFilename); … … 3593 3603 /* Open flat image, the raw disk. */ 3594 3604 rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname, 3595 vmdkFileOpenFlags(pImage->uOpenFlags & ~VD_OPEN_FLAGS_READONLY), 3596 false); 3605 VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags & ~VD_OPEN_FLAGS_READONLY, 3606 false /* fCreate */), 3607 false /* fAsyncIO */); 3597 3608 if (RT_FAILURE(rc)) 3598 3609 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not open raw disk file '%s'"), pExtent->pszFullname); … … 3630 3641 /* Create raw partition descriptor file. */ 3631 3642 rc = vmdkFileOpen(pImage, &pImage->pFile, pImage->pszFilename, 3632 vmdkFileCreateFlags(pImage->uOpenFlags), false); 3643 VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags, 3644 true /* fCreate */), 3645 false /* fAsyncIO */); 3633 3646 if (RT_FAILURE(rc)) 3634 3647 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pImage->pszFilename); … … 3704 3717 /* Create partition table flat image. */ 3705 3718 rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname, 3706 vmdkFileCreateFlags(pImage->uOpenFlags), 3707 false); 3719 VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags, 3720 true /* fCreate */), 3721 false /* fAsyncIO */); 3708 3722 if (RT_FAILURE(rc)) 3709 3723 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new partition data file '%s'"), pExtent->pszFullname); 3710 rc = vmdkFileWrite At(pExtent->pFile,3711 VMDK_SECTOR2BYTE(uPartOffset),3712 pPart->pvPartitionData,3713 pPart->cbData, NULL);3724 rc = vmdkFileWriteSync(pImage, pExtent->pFile, 3725 VMDK_SECTOR2BYTE(uPartOffset), 3726 pPart->pvPartitionData, 3727 pPart->cbData, NULL); 3714 3728 if (RT_FAILURE(rc)) 3715 3729 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not write partition data to '%s'"), pExtent->pszFullname); … … 3739 3753 /* Open flat image, the raw partition. */ 3740 3754 rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname, 3741 vmdkFileOpenFlags(pImage->uOpenFlags & ~VD_OPEN_FLAGS_READONLY), 3742 false); 3755 VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags & ~VD_OPEN_FLAGS_READONLY, 3756 false /* fCreate */), 3757 false /* fAsyncIO */); 3743 3758 if (RT_FAILURE(rc)) 3744 3759 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not open raw partition file '%s'"), pExtent->pszFullname); … … 3812 3827 { 3813 3828 rc = vmdkFileOpen(pImage, &pImage->pFile, pImage->pszFilename, 3814 vmdkFileCreateFlags(pImage->uOpenFlags), false); 3829 VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags, 3830 true /* fCreate */), 3831 false /* fAsyncIO */); 3815 3832 if (RT_FAILURE(rc)) 3816 3833 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new sparse descriptor file '%s'"), pImage->pszFilename); … … 3881 3898 /* Create file for extent. */ 3882 3899 rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname, 3883 vmdkFileCreateFlags(pImage->uOpenFlags), false); 3900 VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags, 3901 true /* fCreate */), 3902 false /* fAsyncIO */); 3884 3903 if (RT_FAILURE(rc)) 3885 3904 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pExtent->pszFullname); 3886 3905 if (uImageFlags & VD_IMAGE_FLAGS_FIXED) 3887 3906 { 3888 rc = vmdkFileSetSize(p Extent->pFile, cbExtent);3907 rc = vmdkFileSetSize(pImage, pExtent->pFile, cbExtent); 3889 3908 if (RT_FAILURE(rc)) 3890 3909 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not set size of new file '%s'"), pExtent->pszFullname); … … 3909 3928 unsigned cbChunk = (unsigned)RT_MIN(cbExtent, cbBuf); 3910 3929 3911 rc = vmdkFileWrite At(pExtent->pFile, uOff, pvBuf, cbChunk, NULL);3930 rc = vmdkFileWriteSync(pImage, pExtent->pFile, uOff, pvBuf, cbChunk, NULL); 3912 3931 if (RT_FAILURE(rc)) 3913 3932 { … … 3946 3965 uint64_t cSectorsPerGDE, cSectorsPerGD; 3947 3966 pExtent->enmType = VMDKETYPE_HOSTED_SPARSE; 3948 pExtent->cSectors = VMDK_BYTE2SECTOR(RT_ALIGN_64(cbExtent, 65536));3949 pExtent->cSectorsPerGrain = VMDK_BYTE2SECTOR( 65536);3967 pExtent->cSectors = VMDK_BYTE2SECTOR(RT_ALIGN_64(cbExtent, _64K)); 3968 pExtent->cSectorsPerGrain = VMDK_BYTE2SECTOR(_64K); 3950 3969 pExtent->cGTEntries = 512; 3951 3970 cSectorsPerGDE = pExtent->cGTEntries * pExtent->cSectorsPerGrain; … … 3979 3998 { 3980 3999 /* fPreAlloc should never be false because VMware can't use such images. */ 3981 rc = vmdkCreateGrainDirectory(p Extent,4000 rc = vmdkCreateGrainDirectory(pImage, pExtent, 3982 4001 RT_MAX( pExtent->uDescriptorSector 3983 4002 + pExtent->cDescriptorSectors, … … 4036 4055 static int vmdkCreateImage(PVMDKIMAGE pImage, uint64_t cbSize, 4037 4056 unsigned uImageFlags, const char *pszComment, 4038 PC PDMMEDIAGEOMETRY pPCHSGeometry,4039 PC PDMMEDIAGEOMETRY pLCHSGeometry, PCRTUUID pUuid,4057 PCVDGEOMETRY pPCHSGeometry, 4058 PCVDGEOMETRY pLCHSGeometry, PCRTUUID pUuid, 4040 4059 PFNVDPROGRESS pfnProgress, void *pvUser, 4041 4060 unsigned uPercentStart, unsigned uPercentSpan) … … 4050 4069 pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError); 4051 4070 4052 /* Try to get asyncI/O interface. */4071 /* Get I/O interface. */ 4053 4072 pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IO); 4054 if (pImage->pInterfaceIO) 4055 pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO); 4073 AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER); 4074 pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO); 4075 AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER); 4056 4076 4057 4077 rc = vmdkCreateDescriptor(pImage, pImage->pDescData, pImage->cbDescAlloc, … … 4082 4102 4083 4103 if (RT_FAILURE(rc)) 4084 4085 4104 goto out; 4086 4105 … … 4212 4231 * delete the image from disk. 4213 4232 */ 4214 static void vmdkFreeImage(PVMDKIMAGE pImage, bool fDelete) 4215 { 4216 AssertPtr(pImage); 4217 4218 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 4219 { 4220 /* Mark all extents as clean. */ 4221 for (unsigned i = 0; i < pImage->cExtents; i++) 4222 { 4223 if (( pImage->pExtents[i].enmType == VMDKETYPE_HOSTED_SPARSE 4233 static int vmdkFreeImage(PVMDKIMAGE pImage, bool fDelete) 4234 { 4235 int rc = VINF_SUCCESS; 4236 4237 /* Freeing a never allocated image (e.g. because the open failed) is 4238 * not signalled as an error. After all nothing bad happens. */ 4239 if (pImage) 4240 { 4241 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 4242 { 4243 /* Mark all extents as clean. */ 4244 for (unsigned i = 0; i < pImage->cExtents; i++) 4245 { 4246 if ( ( pImage->pExtents[i].enmType == VMDKETYPE_HOSTED_SPARSE 4224 4247 #ifdef VBOX_WITH_VMDK_ESX 4225 || pImage->pExtents[i].enmType == VMDKETYPE_ESX_SPARSE4248 || pImage->pExtents[i].enmType == VMDKETYPE_ESX_SPARSE 4226 4249 #endif /* VBOX_WITH_VMDK_ESX */ 4227 ) 4228 && pImage->pExtents[i].fUncleanShutdown) 4229 { 4230 pImage->pExtents[i].fUncleanShutdown = false; 4231 pImage->pExtents[i].fMetaDirty = true; 4250 ) 4251 && pImage->pExtents[i].fUncleanShutdown) 4252 { 4253 pImage->pExtents[i].fUncleanShutdown = false; 4254 pImage->pExtents[i].fMetaDirty = true; 4255 } 4232 4256 } 4233 4257 } 4234 } 4235 (void)vmdkFlushImage(pImage); 4236 4237 if (pImage->pExtents != NULL) 4238 { 4239 for (unsigned i = 0 ; i < pImage->cExtents; i++) 4240 vmdkFreeExtentData(pImage, &pImage->pExtents[i], fDelete); 4241 RTMemFree(pImage->pExtents); 4242 pImage->pExtents = NULL; 4243 } 4244 pImage->cExtents = 0; 4245 if (pImage->pFile != NULL) 4246 vmdkFileClose(pImage, &pImage->pFile, fDelete); 4247 vmdkFileCheckAllClose(pImage); 4248 if (pImage->pGTCache) 4249 { 4250 RTMemFree(pImage->pGTCache); 4251 pImage->pGTCache = NULL; 4252 } 4253 if (pImage->pDescData) 4254 { 4255 RTMemFree(pImage->pDescData); 4256 pImage->pDescData = NULL; 4257 } 4258 vmdkFlushImage(pImage); 4259 4260 if (pImage->pExtents != NULL) 4261 { 4262 for (unsigned i = 0 ; i < pImage->cExtents; i++) 4263 vmdkFreeExtentData(pImage, &pImage->pExtents[i], fDelete); 4264 RTMemFree(pImage->pExtents); 4265 pImage->pExtents = NULL; 4266 } 4267 pImage->cExtents = 0; 4268 if (pImage->pFile != NULL) 4269 vmdkFileClose(pImage, &pImage->pFile, fDelete); 4270 vmdkFileCheckAllClose(pImage); 4271 4272 if (pImage->pGTCache) 4273 { 4274 RTMemFree(pImage->pGTCache); 4275 pImage->pGTCache = NULL; 4276 } 4277 if (pImage->pDescData) 4278 { 4279 RTMemFree(pImage->pDescData); 4280 pImage->pDescData = NULL; 4281 } 4282 } 4283 4284 LogFlowFunc(("returns %Rrc\n", rc)); 4285 return rc; 4258 4286 } 4259 4287 … … 4282 4310 { 4283 4311 case VMDKETYPE_HOSTED_SPARSE: 4284 rc = vmdkWriteMetaSparseExtent(p Extent, 0);4312 rc = vmdkWriteMetaSparseExtent(pImage, pExtent, 0); 4285 4313 if (RT_FAILURE(rc)) 4286 4314 goto out; … … 4288 4316 { 4289 4317 uint64_t cbSize; 4290 rc = vmdkFileGetSize(p Extent->pFile, &cbSize);4318 rc = vmdkFileGetSize(pImage, pExtent->pFile, &cbSize); 4291 4319 if (RT_FAILURE(rc)) 4292 4320 goto out; 4293 4321 cbSize = RT_ALIGN_64(cbSize, 512); 4294 rc = vmdkWriteMetaSparseExtent(p Extent, cbSize - 2*512);4322 rc = vmdkWriteMetaSparseExtent(pImage, pExtent, cbSize - 2*512); 4295 4323 if (RT_FAILURE(rc)) 4296 4324 goto out; … … 4325 4353 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 4326 4354 && !(pExtent->pszBasename[0] == RTPATH_SLASH)) 4327 rc = vmdkFileFlush(p Extent->pFile);4355 rc = vmdkFileFlush(pImage, pExtent->pFile); 4328 4356 break; 4329 4357 case VMDKETYPE_ZERO: … … 4394 4422 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 4395 4423 && !(pExtent->pszBasename[0] == RTPATH_SLASH)) 4396 rc = vmdkFileFlushAsync(p Extent->pFile, pIoCtx);4424 rc = vmdkFileFlushAsync(pImage, pExtent->pFile, pIoCtx); 4397 4425 break; 4398 4426 case VMDKETYPE_ZERO: … … 4452 4480 * number in the extent. 4453 4481 */ 4454 static int vmdkGetSector(PVMDK GTCACHE pCache, PVMDKEXTENT pExtent,4482 static int vmdkGetSector(PVMDKIMAGE pImage, PVMDKEXTENT pExtent, 4455 4483 uint64_t uSector, uint64_t *puExtentSector) 4456 4484 { 4485 PVMDKGTCACHE pCache = pImage->pGTCache; 4457 4486 uint64_t uGDIndex, uGTSector, uGTBlock; 4458 4487 uint32_t uGTHash, uGTBlockIndex; … … 4480 4509 { 4481 4510 /* Cache miss, fetch data from disk. */ 4482 rc = vmdkFileRead At(pExtent->pFile,4483 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),4484 aGTDataTmp, sizeof(aGTDataTmp), NULL);4511 rc = vmdkFileReadSync(pImage, pExtent->pFile, 4512 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp), 4513 aGTDataTmp, sizeof(aGTDataTmp), NULL); 4485 4514 if (RT_FAILURE(rc)) 4486 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot read grain table entry in '%s'"), pExtent->pszFullname);4515 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot read grain table entry in '%s'"), pExtent->pszFullname); 4487 4516 pGTCacheEntry->uExtent = pExtent->uExtent; 4488 4517 pGTCacheEntry->uGTBlock = uGTBlock; … … 4504 4533 */ 4505 4534 static int vmdkGetSectorAsync(PVMDKIMAGE pImage, PVDIOCTX pIoCtx, 4506 PVMDKGTCACHE pCache, PVMDKEXTENT pExtent, 4507 uint64_t uSector, uint64_t *puExtentSector) 4508 { 4535 PVMDKEXTENT pExtent, uint64_t uSector, 4536 uint64_t *puExtentSector) 4537 { 4538 PVMDKGTCACHE pCache = pImage->pGTCache; 4509 4539 uint64_t uGDIndex, uGTSector, uGTBlock; 4510 4540 uint32_t uGTHash, uGTBlockIndex; … … 4535 4565 /* Cache miss, fetch data from disk. */ 4536 4566 PVDMETAXFER pMetaXfer; 4537 rc = pImage->pInterfaceIOCallbacks->pfnReadMetaAsync(pImage->pInterfaceIO->pvUser, 4538 pExtent->pFile->pStorage, 4539 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp), 4540 aGTDataTmp, sizeof(aGTDataTmp), pIoCtx, &pMetaXfer, NULL, NULL); 4567 rc = vmdkFileReadMetaAsync(pImage, pExtent->pFile, 4568 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp), 4569 aGTDataTmp, sizeof(aGTDataTmp), pIoCtx, &pMetaXfer, NULL, NULL); 4541 4570 if (RT_FAILURE(rc)) 4542 4571 return rc; 4543 4572 /* We can release the metadata transfer immediately. */ 4544 pImage->pInterfaceIOCallbacks->pfnMetaXferRelease(pImage->pInterfaceIO->pvUser, pMetaXfer);4573 vmdkFileMetaXferRelease(pImage, pMetaXfer); 4545 4574 pGTCacheEntry->uExtent = pExtent->uExtent; 4546 4575 pGTCacheEntry->uGTBlock = uGTBlock; … … 4563 4592 * possible. Most code from vmdkGetSector also appears here. 4564 4593 */ 4565 static int vmdkAllocGrain(PVMDK GTCACHE pCache, PVMDKEXTENT pExtent,4594 static int vmdkAllocGrain(PVMDKIMAGE pImage, PVMDKEXTENT pExtent, 4566 4595 uint64_t uSector, const void *pvBuf, 4567 4596 uint64_t cbWrite) 4568 4597 { 4598 PVMDKGTCACHE pCache = pImage->pGTCache; 4569 4599 uint64_t uGDIndex, uGTSector, uRGTSector, uGTBlock; 4570 4600 uint64_t cbExtentSize; … … 4587 4617 * entry. So there is absolutely no data in this area. Allocate 4588 4618 * a new grain table and put the reference to it in the GDs. */ 4589 rc = vmdkFileGetSize(p Extent->pFile, &cbExtentSize);4619 rc = vmdkFileGetSize(pImage, pExtent->pFile, &cbExtentSize); 4590 4620 if (RT_FAILURE(rc)) 4591 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname);4621 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname); 4592 4622 Assert(!(cbExtentSize % 512)); 4593 4623 cbExtentSize = RT_ALIGN_64(cbExtentSize, 512); … … 4596 4626 * end-of-stream marker. Will be re-added after the grain table. 4597 4627 * If the file has a footer it also will be re-added before EOS. */ 4598 if (p Extent->pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)4628 if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED) 4599 4629 { 4600 4630 uint64_t uEOSOff = 0; … … 4604 4634 uGTSector--; 4605 4635 uEOSOff = 512; 4606 rc = vmdkWriteMetaSparseExtent(p Extent, VMDK_SECTOR2BYTE(uGTSector) + pExtent->cGTEntries * sizeof(uint32_t));4636 rc = vmdkWriteMetaSparseExtent(pImage, pExtent, VMDK_SECTOR2BYTE(uGTSector) + pExtent->cGTEntries * sizeof(uint32_t)); 4607 4637 if (RT_FAILURE(rc)) 4608 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write footer after grain table in '%s'"), pExtent->pszFullname);4638 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write footer after grain table in '%s'"), pExtent->pszFullname); 4609 4639 } 4610 4640 pExtent->uLastGrainSector = 0; 4611 4641 uint8_t aEOS[512]; 4612 4642 memset(aEOS, '\0', sizeof(aEOS)); 4613 rc = vmdkFileWrite At(pExtent->pFile,4614 VMDK_SECTOR2BYTE(uGTSector) + pExtent->cGTEntries * sizeof(uint32_t) + uEOSOff,4615 aEOS, sizeof(aEOS), NULL);4643 rc = vmdkFileWriteSync(pImage, pExtent->pFile, 4644 VMDK_SECTOR2BYTE(uGTSector) + pExtent->cGTEntries * sizeof(uint32_t) + uEOSOff, 4645 aEOS, sizeof(aEOS), NULL); 4616 4646 if (RT_FAILURE(rc)) 4617 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write end-of stream marker after grain table in '%s'"), pExtent->pszFullname);4647 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write end-of stream marker after grain table in '%s'"), pExtent->pszFullname); 4618 4648 } 4619 4649 /* Normally the grain table is preallocated for hosted sparse extents … … 4631 4661 i++) 4632 4662 { 4633 rc = vmdkFileWrite At(pExtent->pFile,4634 VMDK_SECTOR2BYTE(uGTSector) + i * sizeof(aGTDataTmp),4635 aGTDataTmp, sizeof(aGTDataTmp), NULL);4663 rc = vmdkFileWriteSync(pImage, pExtent->pFile, 4664 VMDK_SECTOR2BYTE(uGTSector) + i * sizeof(aGTDataTmp), 4665 aGTDataTmp, sizeof(aGTDataTmp), NULL); 4636 4666 if (RT_FAILURE(rc)) 4637 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain table allocation in '%s'"), pExtent->pszFullname);4667 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain table allocation in '%s'"), pExtent->pszFullname); 4638 4668 } 4639 4669 if (pExtent->pRGD) 4640 4670 { 4641 4671 AssertReturn(!uRGTSector, VERR_VD_VMDK_INVALID_HEADER); 4642 rc = vmdkFileGetSize(p Extent->pFile, &cbExtentSize);4672 rc = vmdkFileGetSize(pImage, pExtent->pFile, &cbExtentSize); 4643 4673 if (RT_FAILURE(rc)) 4644 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname);4674 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname); 4645 4675 Assert(!(cbExtentSize % 512)); 4646 4676 uRGTSector = VMDK_BYTE2SECTOR(cbExtentSize); … … 4648 4678 * end-of-stream marker. Will be re-added after the grain table. 4649 4679 * If the file has a footer it also will be re-added before EOS. */ 4650 if (p Extent->pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)4680 if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED) 4651 4681 { 4652 4682 uint64_t uEOSOff = 0; … … 4656 4686 uRGTSector--; 4657 4687 uEOSOff = 512; 4658 rc = vmdkWriteMetaSparseExtent(p Extent, VMDK_SECTOR2BYTE(uRGTSector) + pExtent->cGTEntries * sizeof(uint32_t));4688 rc = vmdkWriteMetaSparseExtent(pImage, pExtent, VMDK_SECTOR2BYTE(uRGTSector) + pExtent->cGTEntries * sizeof(uint32_t)); 4659 4689 if (RT_FAILURE(rc)) 4660 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write footer after redundant grain table in '%s'"), pExtent->pszFullname);4690 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write footer after redundant grain table in '%s'"), pExtent->pszFullname); 4661 4691 } 4662 4692 pExtent->uLastGrainSector = 0; 4663 4693 uint8_t aEOS[512]; 4664 4694 memset(aEOS, '\0', sizeof(aEOS)); 4665 rc = vmdkFileWrite At(pExtent->pFile,4666 VMDK_SECTOR2BYTE(uRGTSector) + pExtent->cGTEntries * sizeof(uint32_t) + uEOSOff,4667 aEOS, sizeof(aEOS), NULL);4695 rc = vmdkFileWriteSync(pImage, pExtent->pFile, 4696 VMDK_SECTOR2BYTE(uRGTSector) + pExtent->cGTEntries * sizeof(uint32_t) + uEOSOff, 4697 aEOS, sizeof(aEOS), NULL); 4668 4698 if (RT_FAILURE(rc)) 4669 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write end-of stream marker after redundant grain table in '%s'"), pExtent->pszFullname);4699 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write end-of stream marker after redundant grain table in '%s'"), pExtent->pszFullname); 4670 4700 } 4671 4701 /* Normally the redundant grain table is preallocated for hosted … … 4682 4712 i++) 4683 4713 { 4684 rc = vmdkFileWrite At(pExtent->pFile,4685 VMDK_SECTOR2BYTE(uRGTSector) + i * sizeof(aGTDataTmp),4686 aGTDataTmp, sizeof(aGTDataTmp), NULL);4714 rc = vmdkFileWriteSync(pImage, pExtent->pFile, 4715 VMDK_SECTOR2BYTE(uRGTSector) + i * sizeof(aGTDataTmp), 4716 aGTDataTmp, sizeof(aGTDataTmp), NULL); 4687 4717 if (RT_FAILURE(rc)) 4688 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain table allocation in '%s'"), pExtent->pszFullname);4718 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain table allocation in '%s'"), pExtent->pszFullname); 4689 4719 } 4690 4720 } … … 4695 4725 * some unused sectors in the extent. */ 4696 4726 uint32_t uGTSectorLE = RT_H2LE_U64(uGTSector); 4697 rc = vmdkFileWrite At(pExtent->pFile,4698 VMDK_SECTOR2BYTE(pExtent->uSectorGD) + uGDIndex * sizeof(uGTSectorLE),4699 &uGTSectorLE, sizeof(uGTSectorLE), NULL);4727 rc = vmdkFileWriteSync(pImage, pExtent->pFile, 4728 VMDK_SECTOR2BYTE(pExtent->uSectorGD) + uGDIndex * sizeof(uGTSectorLE), 4729 &uGTSectorLE, sizeof(uGTSectorLE), NULL); 4700 4730 if (RT_FAILURE(rc)) 4701 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain directory entry in '%s'"), pExtent->pszFullname);4731 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain directory entry in '%s'"), pExtent->pszFullname); 4702 4732 if (pExtent->pRGD) 4703 4733 { 4704 4734 uint32_t uRGTSectorLE = RT_H2LE_U64(uRGTSector); 4705 rc = vmdkFileWrite At(pExtent->pFile,4706 VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + uGDIndex * sizeof(uRGTSectorLE),4707 &uRGTSectorLE, sizeof(uRGTSectorLE), NULL);4735 rc = vmdkFileWriteSync(pImage, pExtent->pFile, 4736 VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + uGDIndex * sizeof(uRGTSectorLE), 4737 &uRGTSectorLE, sizeof(uRGTSectorLE), NULL); 4708 4738 if (RT_FAILURE(rc)) 4709 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain directory entry in '%s'"), pExtent->pszFullname);4739 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain directory entry in '%s'"), pExtent->pszFullname); 4710 4740 } 4711 4741 … … 4716 4746 } 4717 4747 4718 rc = vmdkFileGetSize(p Extent->pFile, &cbExtentSize);4748 rc = vmdkFileGetSize(pImage, pExtent->pFile, &cbExtentSize); 4719 4749 if (RT_FAILURE(rc)) 4720 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname);4750 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname); 4721 4751 Assert(!(cbExtentSize % 512)); 4722 4752 4723 4753 /* Write the data. Always a full grain, or we're in big trouble. */ 4724 if (p Extent->pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)4754 if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED) 4725 4755 { 4726 4756 /* For streamOptimized extents this is a little more difficult, as the … … 4738 4768 Assert(cbWrite == VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain)); 4739 4769 uint32_t cbGrain = 0; 4740 rc = vmdkFileDeflate At(pExtent->pFile, cbExtentSize,4741 pvBuf, cbWrite, VMDK_MARKER_IGNORE, uSector, &cbGrain);4770 rc = vmdkFileDeflateSync(pImage, pExtent->pFile, cbExtentSize, 4771 pvBuf, cbWrite, VMDK_MARKER_IGNORE, uSector, &cbGrain); 4742 4772 if (RT_FAILURE(rc)) 4743 4773 { … … 4745 4775 pExtent->uLastGrainSector = 0; 4746 4776 AssertRC(rc); 4747 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write allocated compressed data block in '%s'"), pExtent->pszFullname);4777 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write allocated compressed data block in '%s'"), pExtent->pszFullname); 4748 4778 } 4749 4779 cbGrain = RT_ALIGN(cbGrain, 512); … … 4758 4788 { 4759 4789 uEOSOff = 512; 4760 rc = vmdkWriteMetaSparseExtent(p Extent, cbExtentSize + RT_ALIGN(cbGrain, 512));4790 rc = vmdkWriteMetaSparseExtent(pImage, pExtent, cbExtentSize + RT_ALIGN(cbGrain, 512)); 4761 4791 if (RT_FAILURE(rc)) 4762 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write footer after allocated data block in '%s'"), pExtent->pszFullname);4792 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write footer after allocated data block in '%s'"), pExtent->pszFullname); 4763 4793 } 4764 4794 uint8_t aEOS[512]; 4765 4795 memset(aEOS, '\0', sizeof(aEOS)); 4766 rc = vmdkFileWriteAt(pExtent->pFile, cbExtentSize + RT_ALIGN(cbGrain, 512) + uEOSOff, 4767 aEOS, sizeof(aEOS), NULL); 4796 rc = vmdkFileWriteSync(pImage, pExtent->pFile, 4797 cbExtentSize + RT_ALIGN(cbGrain, 512) + uEOSOff, 4798 aEOS, sizeof(aEOS), NULL); 4768 4799 if (RT_FAILURE(rc)) 4769 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write end-of stream marker after allocated data block in '%s'"), pExtent->pszFullname);4800 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write end-of stream marker after allocated data block in '%s'"), pExtent->pszFullname); 4770 4801 } 4771 4802 else 4772 4803 { 4773 rc = vmdkFileWrite At(pExtent->pFile, cbExtentSize, pvBuf, cbWrite, NULL);4804 rc = vmdkFileWriteSync(pImage, pExtent->pFile, cbExtentSize, pvBuf, cbWrite, NULL); 4774 4805 if (RT_FAILURE(rc)) 4775 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write allocated data block in '%s'"), pExtent->pszFullname);4806 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write allocated data block in '%s'"), pExtent->pszFullname); 4776 4807 } 4777 4808 … … 4784 4815 { 4785 4816 /* Cache miss, fetch data from disk. */ 4786 rc = vmdkFileRead At(pExtent->pFile,4787 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),4788 aGTDataTmp, sizeof(aGTDataTmp), NULL);4817 rc = vmdkFileReadSync(pImage, pExtent->pFile, 4818 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp), 4819 aGTDataTmp, sizeof(aGTDataTmp), NULL); 4789 4820 if (RT_FAILURE(rc)) 4790 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot read allocated grain table entry in '%s'"), pExtent->pszFullname);4821 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot read allocated grain table entry in '%s'"), pExtent->pszFullname); 4791 4822 pGTCacheEntry->uExtent = pExtent->uExtent; 4792 4823 pGTCacheEntry->uGTBlock = uGTBlock; … … 4805 4836 pGTCacheEntry->aGTData[uGTBlockIndex] = VMDK_BYTE2SECTOR(cbExtentSize); 4806 4837 /* Update grain table on disk. */ 4807 rc = vmdkFileWrite At(pExtent->pFile,4808 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),4809 aGTDataTmp, sizeof(aGTDataTmp), NULL);4838 rc = vmdkFileWriteSync(pImage, pExtent->pFile, 4839 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp), 4840 aGTDataTmp, sizeof(aGTDataTmp), NULL); 4810 4841 if (RT_FAILURE(rc)) 4811 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated grain table in '%s'"), pExtent->pszFullname);4842 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated grain table in '%s'"), pExtent->pszFullname); 4812 4843 if (pExtent->pRGD) 4813 4844 { 4814 4845 /* Update backup grain table on disk. */ 4815 rc = vmdkFileWrite At(pExtent->pFile,4816 VMDK_SECTOR2BYTE(uRGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),4817 aGTDataTmp, sizeof(aGTDataTmp), NULL);4846 rc = vmdkFileWriteSync(pImage, pExtent->pFile, 4847 VMDK_SECTOR2BYTE(uRGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp), 4848 aGTDataTmp, sizeof(aGTDataTmp), NULL); 4818 4849 if (RT_FAILURE(rc)) 4819 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated backup grain table in '%s'"), pExtent->pszFullname);4850 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated backup grain table in '%s'"), pExtent->pszFullname); 4820 4851 } 4821 4852 #ifdef VBOX_WITH_VMDK_ESX … … 4833 4864 */ 4834 4865 static int vmdkAllocGrainAsyncGTUpdate(PVMDKIMAGE pImage, PVMDKEXTENT pExtent, 4835 PV MDKGTCACHE pCache, PVDIOCTX pIoCtx,4866 PVDIOCTX pIoCtx, 4836 4867 PVMDKGRAINALLOCASYNC pGrainAlloc) 4837 4868 { 4838 4869 int rc = VINF_SUCCESS; 4870 PVMDKGTCACHE pCache = pImage->pGTCache; 4839 4871 uint32_t aGTDataTmp[VMDK_GT_CACHELINE_SIZE]; 4840 4872 uint32_t uGTHash, uGTBlockIndex; … … 4860 4892 LogFlow(("Cache miss, fetch data from disk\n")); 4861 4893 PVDMETAXFER pMetaXfer = NULL; 4862 rc = pImage->pInterfaceIOCallbacks->pfnReadMetaAsync(pExtent->pImage->pInterfaceIO->pvUser, 4863 pExtent->pFile->pStorage, 4864 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp), 4865 aGTDataTmp, sizeof(aGTDataTmp), pIoCtx, 4866 &pMetaXfer, 4867 vmdkAllocGrainAsyncComplete, pGrainAlloc); 4894 rc = vmdkFileReadMetaAsync(pImage, pExtent->pFile, 4895 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp), 4896 aGTDataTmp, sizeof(aGTDataTmp), pIoCtx, 4897 &pMetaXfer, vmdkAllocGrainAsyncComplete, pGrainAlloc); 4868 4898 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 4869 4899 { … … 4875 4905 } 4876 4906 else if (RT_FAILURE(rc)) 4877 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot read allocated grain table entry in '%s'"), pExtent->pszFullname);4878 pImage->pInterfaceIOCallbacks->pfnMetaXferRelease(pExtent->pImage->pInterfaceIO->pvUser, pMetaXfer);4907 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot read allocated grain table entry in '%s'"), pExtent->pszFullname); 4908 vmdkFileMetaXferRelease(pImage, pMetaXfer); 4879 4909 pGTCacheEntry->uExtent = pExtent->uExtent; 4880 4910 pGTCacheEntry->uGTBlock = uGTBlock; … … 4894 4924 pGTCacheEntry->aGTData[uGTBlockIndex] = VMDK_BYTE2SECTOR(pGrainAlloc->cbExtentSize); 4895 4925 /* Update grain table on disk. */ 4896 rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pExtent->pImage->pInterfaceIO->pvUser, 4897 pExtent->pFile->pStorage, 4898 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp), 4899 aGTDataTmp, sizeof(aGTDataTmp), pIoCtx, 4900 vmdkAllocGrainAsyncComplete, pGrainAlloc); 4926 rc = vmdkFileWriteMetaAsync(pImage, pExtent->pFile, 4927 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp), 4928 aGTDataTmp, sizeof(aGTDataTmp), pIoCtx, 4929 vmdkAllocGrainAsyncComplete, pGrainAlloc); 4901 4930 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 4902 4931 pGrainAlloc->cIoXfersPending++; 4903 4932 else if (RT_FAILURE(rc)) 4904 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated grain table in '%s'"), pExtent->pszFullname);4933 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated grain table in '%s'"), pExtent->pszFullname); 4905 4934 if (pExtent->pRGD) 4906 4935 { 4907 4936 /* Update backup grain table on disk. */ 4908 rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pExtent->pImage->pInterfaceIO->pvUser, 4909 pExtent->pFile->pStorage, 4910 VMDK_SECTOR2BYTE(uRGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp), 4911 aGTDataTmp, sizeof(aGTDataTmp), pIoCtx, 4912 vmdkAllocGrainAsyncComplete, pGrainAlloc); 4937 rc = vmdkFileWriteMetaAsync(pImage, pExtent->pFile, 4938 VMDK_SECTOR2BYTE(uRGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp), 4939 aGTDataTmp, sizeof(aGTDataTmp), pIoCtx, 4940 vmdkAllocGrainAsyncComplete, pGrainAlloc); 4913 4941 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 4914 4942 pGrainAlloc->cIoXfersPending++; 4915 4943 else if (RT_FAILURE(rc)) 4916 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated backup grain table in '%s'"), pExtent->pszFullname);4944 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated backup grain table in '%s'"), pExtent->pszFullname); 4917 4945 } 4918 4946 #ifdef VBOX_WITH_VMDK_ESX … … 4932 4960 * Internal - complete the grain allocation by updating disk grain table if required. 4933 4961 */ 4934 static int vmdkAllocGrainAsyncComplete(void *p vBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq)4962 static int vmdkAllocGrainAsyncComplete(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq) 4935 4963 { 4936 4964 int rc = VINF_SUCCESS; 4937 PVMDKIMAGE pImage = (PVMDKIMAGE)p vBackendData;4965 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData; 4938 4966 PVMDKGRAINALLOCASYNC pGrainAlloc = (PVMDKGRAINALLOCASYNC)pvUser; 4939 4967 PVMDKEXTENT pExtent = pGrainAlloc->pExtent; 4940 4968 4941 LogFlowFunc(("p vBackendData=%#p pIoCtx=%#p pvUser=%#p rcReq=%Rrc\n",4942 p vBackendData, pIoCtx, pvUser, rcReq));4969 LogFlowFunc(("pBackendData=%#p pIoCtx=%#p pvUser=%#p rcReq=%Rrc\n", 4970 pBackendData, pIoCtx, pvUser, rcReq)); 4943 4971 4944 4972 pGrainAlloc->cIoXfersPending--; 4945 4973 if (!pGrainAlloc->cIoXfersPending && pGrainAlloc->fGTUpdateNeeded) 4946 rc = vmdkAllocGrainAsyncGTUpdate(pImage, pGrainAlloc->pExtent, pImage->pGTCache,4974 rc = vmdkAllocGrainAsyncGTUpdate(pImage, pGrainAlloc->pExtent, 4947 4975 pIoCtx, pGrainAlloc); 4948 4976 … … 4960 4988 * Internal. Allocates a new grain table (if necessary) - async version. 4961 4989 */ 4962 static int vmdkAllocGrainAsync(PVMDK GTCACHE pCache, PVMDKEXTENT pExtent,4990 static int vmdkAllocGrainAsync(PVMDKIMAGE pImage, PVMDKEXTENT pExtent, 4963 4991 PVDIOCTX pIoCtx, uint64_t uSector, 4964 4992 uint64_t cbWrite) 4965 4993 { 4994 PVMDKGTCACHE pCache = pImage->pGTCache; 4966 4995 uint64_t uGDIndex, uGTSector, uRGTSector; 4967 4996 uint64_t cbExtentSize; 4968 4997 PVMDKGRAINALLOCASYNC pGrainAlloc = NULL; 4969 PVMDKIMAGE pImage = pExtent->pImage;4970 4998 int rc; 4971 4999 … … 4973 5001 pCache, pExtent, pIoCtx, uSector, cbWrite)); 4974 5002 4975 AssertReturn(!(p Extent->pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED), VERR_NOT_SUPPORTED);5003 AssertReturn(!(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED), VERR_NOT_SUPPORTED); 4976 5004 4977 5005 pGrainAlloc = (PVMDKGRAINALLOCASYNC)RTMemAllocZ(sizeof(VMDKGRAINALLOCASYNC)); … … 4997 5025 * entry. So there is absolutely no data in this area. Allocate 4998 5026 * a new grain table and put the reference to it in the GDs. */ 4999 rc = vmdkFileGetSize(p Extent->pFile, &cbExtentSize);5027 rc = vmdkFileGetSize(pImage, pExtent->pFile, &cbExtentSize); 5000 5028 if (RT_FAILURE(rc)) 5001 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname);5029 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname); 5002 5030 Assert(!(cbExtentSize % 512)); 5003 5031 … … 5024 5052 5025 5053 memset(paGTDataTmp, '\0', cbGTDataTmp); 5026 rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pExtent->pImage->pInterfaceIO->pvUser, 5027 pExtent->pFile->pStorage, 5028 VMDK_SECTOR2BYTE(uGTSector), 5029 paGTDataTmp, cbGTDataTmp, pIoCtx, 5030 vmdkAllocGrainAsyncComplete, pGrainAlloc); 5054 rc = vmdkFileWriteMetaAsync(pImage, pExtent->pFile, 5055 VMDK_SECTOR2BYTE(uGTSector), 5056 paGTDataTmp, cbGTDataTmp, pIoCtx, 5057 vmdkAllocGrainAsyncComplete, pGrainAlloc); 5031 5058 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 5032 5059 pGrainAlloc->cIoXfersPending++; … … 5034 5061 { 5035 5062 RTMemTmpFree(paGTDataTmp); 5036 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain table allocation in '%s'"), pExtent->pszFullname);5063 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain table allocation in '%s'"), pExtent->pszFullname); 5037 5064 } 5038 5065 … … 5040 5067 { 5041 5068 AssertReturn(!uRGTSector, VERR_VD_VMDK_INVALID_HEADER); 5042 rc = vmdkFileGetSize(p Extent->pFile, &cbExtentSize);5069 rc = vmdkFileGetSize(pImage, pExtent->pFile, &cbExtentSize); 5043 5070 if (RT_FAILURE(rc)) 5044 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname);5071 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname); 5045 5072 Assert(!(cbExtentSize % 512)); 5046 5073 uRGTSector = VMDK_BYTE2SECTOR(cbExtentSize); … … 5056 5083 /* Write backup grain table by writing the required number of grain 5057 5084 * table cache chunks. */ 5058 rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pExtent->pImage->pInterfaceIO->pvUser, 5059 pExtent->pFile->pStorage, 5060 VMDK_SECTOR2BYTE(uRGTSector), 5061 paGTDataTmp, cbGTDataTmp, pIoCtx, 5062 vmdkAllocGrainAsyncComplete, pGrainAlloc); 5085 rc = vmdkFileWriteMetaAsync(pImage, pExtent->pFile, 5086 VMDK_SECTOR2BYTE(uRGTSector), 5087 paGTDataTmp, cbGTDataTmp, pIoCtx, 5088 vmdkAllocGrainAsyncComplete, pGrainAlloc); 5063 5089 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 5064 5090 pGrainAlloc->cIoXfersPending++; … … 5066 5092 { 5067 5093 RTMemTmpFree(paGTDataTmp); 5068 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain table allocation in '%s'"), pExtent->pszFullname);5094 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain table allocation in '%s'"), pExtent->pszFullname); 5069 5095 } 5070 5096 } … … 5077 5103 * some unused sectors in the extent. */ 5078 5104 uint32_t uGTSectorLE = RT_H2LE_U64(uGTSector); 5079 rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pExtent->pImage->pInterfaceIO->pvUser, 5080 pExtent->pFile->pStorage, 5081 VMDK_SECTOR2BYTE(pExtent->uSectorGD) + uGDIndex * sizeof(uGTSectorLE), 5082 &uGTSectorLE, sizeof(uGTSectorLE), pIoCtx, 5083 vmdkAllocGrainAsyncComplete, pGrainAlloc); 5105 rc = vmdkFileWriteMetaAsync(pImage, pExtent->pFile, 5106 VMDK_SECTOR2BYTE(pExtent->uSectorGD) + uGDIndex * sizeof(uGTSectorLE), 5107 &uGTSectorLE, sizeof(uGTSectorLE), pIoCtx, 5108 vmdkAllocGrainAsyncComplete, pGrainAlloc); 5084 5109 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 5085 5110 pGrainAlloc->cIoXfersPending++; 5086 5111 else if (RT_FAILURE(rc)) 5087 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain directory entry in '%s'"), pExtent->pszFullname);5112 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain directory entry in '%s'"), pExtent->pszFullname); 5088 5113 if (pExtent->pRGD) 5089 5114 { 5090 5115 uint32_t uRGTSectorLE = RT_H2LE_U64(uRGTSector); 5091 rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pExtent->pImage->pInterfaceIO->pvUser, 5092 pExtent->pFile->pStorage, 5093 VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + uGDIndex * sizeof(uGTSectorLE), 5094 &uRGTSectorLE, sizeof(uRGTSectorLE), pIoCtx, 5095 vmdkAllocGrainAsyncComplete, pGrainAlloc); 5116 rc = vmdkFileWriteMetaAsync(pImage, pExtent->pFile, 5117 VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + uGDIndex * sizeof(uGTSectorLE), 5118 &uRGTSectorLE, sizeof(uRGTSectorLE), pIoCtx, 5119 vmdkAllocGrainAsyncComplete, pGrainAlloc); 5096 5120 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 5097 5121 pGrainAlloc->cIoXfersPending++; 5098 5122 else if (RT_FAILURE(rc)) 5099 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain directory entry in '%s'"), pExtent->pszFullname);5123 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain directory entry in '%s'"), pExtent->pszFullname); 5100 5124 } 5101 5125 … … 5110 5134 pGrainAlloc->uRGTSector = uRGTSector; 5111 5135 5112 rc = vmdkFileGetSize(p Extent->pFile, &cbExtentSize);5136 rc = vmdkFileGetSize(pImage, pExtent->pFile, &cbExtentSize); 5113 5137 if (RT_FAILURE(rc)) 5114 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname);5138 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname); 5115 5139 Assert(!(cbExtentSize % 512)); 5116 5140 … … 5121 5145 5122 5146 /* Write the data. Always a full grain, or we're in big trouble. */ 5123 rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser, 5124 pExtent->pFile->pStorage, 5125 cbExtentSize, 5126 pIoCtx, cbWrite, 5127 vmdkAllocGrainAsyncComplete, pGrainAlloc); 5147 rc = vmdkFileWriteUserAsync(pImage, pExtent->pFile, 5148 cbExtentSize, pIoCtx, cbWrite, 5149 vmdkAllocGrainAsyncComplete, pGrainAlloc); 5128 5150 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 5129 5151 pGrainAlloc->cIoXfersPending++; 5130 5152 else if (RT_FAILURE(rc)) 5131 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write allocated data block in '%s'"), pExtent->pszFullname);5132 5133 rc = vmdkAllocGrainAsyncGTUpdate(pImage, pExtent, p Cache, pIoCtx, pGrainAlloc);5153 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write allocated data block in '%s'"), pExtent->pszFullname); 5154 5155 rc = vmdkAllocGrainAsyncGTUpdate(pImage, pExtent, pIoCtx, pGrainAlloc); 5134 5156 5135 5157 if (!pGrainAlloc->cIoXfersPending) … … 5144 5166 } 5145 5167 5168 /** 5169 * Replaces a fragment of a string with the specified string. 5170 * 5171 * @returns Pointer to the allocated UTF-8 string. 5172 * @param pszWhere UTF-8 string to search in. 5173 * @param pszWhat UTF-8 string to search for. 5174 * @param pszByWhat UTF-8 string to replace the found string with. 5175 */ 5176 static char *vmdkStrReplace(const char *pszWhere, const char *pszWhat, 5177 const char *pszByWhat) 5178 { 5179 AssertPtr(pszWhere); 5180 AssertPtr(pszWhat); 5181 AssertPtr(pszByWhat); 5182 const char *pszFoundStr = strstr(pszWhere, pszWhat); 5183 if (!pszFoundStr) 5184 return NULL; 5185 size_t cFinal = strlen(pszWhere) + 1 + strlen(pszByWhat) - strlen(pszWhat); 5186 char *pszNewStr = (char *)RTMemAlloc(cFinal); 5187 if (pszNewStr) 5188 { 5189 char *pszTmp = pszNewStr; 5190 memcpy(pszTmp, pszWhere, pszFoundStr - pszWhere); 5191 pszTmp += pszFoundStr - pszWhere; 5192 memcpy(pszTmp, pszByWhat, strlen(pszByWhat)); 5193 pszTmp += strlen(pszByWhat); 5194 strcpy(pszTmp, pszFoundStr + strlen(pszWhat)); 5195 } 5196 return pszNewStr; 5197 } 5198 5146 5199 5147 5200 /** @copydoc VBOXHDDBACKEND::pfnCheckIfValid */ 5148 static int vmdkCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk) 5201 static int vmdkCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk, 5202 PVDINTERFACE pVDIfsImage) 5149 5203 { 5150 5204 LogFlowFunc(("pszFilename=\"%s\"\n", pszFilename)); … … 5159 5213 goto out; 5160 5214 } 5161 5162 pImage = (PVMDKIMAGE)RTMemAllocZ(sizeof(VMDKIMAGE));5163 if (!pImage)5164 {5165 rc = VERR_NO_MEMORY;5166 goto out;5167 }5168 pImage->pszFilename = pszFilename;5169 pImage->pFile = NULL;5170 pImage->pExtents = NULL;5171 pImage->pFiles = NULL;5172 pImage->pGTCache = NULL;5173 pImage->pDescData = NULL;5174 pImage->pVDIfsDisk = pVDIfsDisk;5175 pImage->pVDIfsImage = pVDIfsDisk;5176 /** @todo speed up this test open (VD_OPEN_FLAGS_INFO) by skipping as5177 * much as possible in vmdkOpenImage. */5178 rc = vmdkOpenImage(pImage, VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_READONLY);5179 vmdkFreeImage(pImage, false);5180 RTMemFree(pImage);5181 5182 out:5183 LogFlowFunc(("returns %Rrc\n", rc));5184 return rc;5185 }5186 5187 /** @copydoc VBOXHDDBACKEND::pfnOpen */5188 static int vmdkOpen(const char *pszFilename, unsigned uOpenFlags,5189 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,5190 void **ppBackendData)5191 {5192 LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p ppBackendData=%#p\n", pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, ppBackendData));5193 int rc;5194 PVMDKIMAGE pImage;5195 5196 /* Check open flags. All valid flags are supported. */5197 if (uOpenFlags & ~VD_OPEN_FLAGS_MASK)5198 {5199 rc = VERR_INVALID_PARAMETER;5200 goto out;5201 }5202 5203 /* Check remaining arguments. */5204 if ( !VALID_PTR(pszFilename)5205 || !*pszFilename5206 || strchr(pszFilename, '"'))5207 {5208 rc = VERR_INVALID_PARAMETER;5209 goto out;5210 }5211 5212 5215 5213 5216 pImage = (PVMDKIMAGE)RTMemAllocZ(sizeof(VMDKIMAGE)); … … 5225 5228 pImage->pVDIfsDisk = pVDIfsDisk; 5226 5229 pImage->pVDIfsImage = pVDIfsImage; 5230 /** @todo speed up this test open (VD_OPEN_FLAGS_INFO) by skipping as 5231 * much as possible in vmdkOpenImage. */ 5232 rc = vmdkOpenImage(pImage, VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_READONLY); 5233 vmdkFreeImage(pImage, false); 5234 RTMemFree(pImage); 5235 5236 out: 5237 LogFlowFunc(("returns %Rrc\n", rc)); 5238 return rc; 5239 } 5240 5241 /** @copydoc VBOXHDDBACKEND::pfnOpen */ 5242 static int vmdkOpen(const char *pszFilename, unsigned uOpenFlags, 5243 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage, 5244 void **ppBackendData) 5245 { 5246 LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p ppBackendData=%#p\n", pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, ppBackendData)); 5247 int rc; 5248 PVMDKIMAGE pImage; 5249 5250 /* Check open flags. All valid flags are supported. */ 5251 if (uOpenFlags & ~VD_OPEN_FLAGS_MASK) 5252 { 5253 rc = VERR_INVALID_PARAMETER; 5254 goto out; 5255 } 5256 5257 /* Check remaining arguments. */ 5258 if ( !VALID_PTR(pszFilename) 5259 || !*pszFilename 5260 || strchr(pszFilename, '"')) 5261 { 5262 rc = VERR_INVALID_PARAMETER; 5263 goto out; 5264 } 5265 5266 5267 pImage = (PVMDKIMAGE)RTMemAllocZ(sizeof(VMDKIMAGE)); 5268 if (!pImage) 5269 { 5270 rc = VERR_NO_MEMORY; 5271 goto out; 5272 } 5273 pImage->pszFilename = pszFilename; 5274 pImage->pFile = NULL; 5275 pImage->pExtents = NULL; 5276 pImage->pFiles = NULL; 5277 pImage->pGTCache = NULL; 5278 pImage->pDescData = NULL; 5279 pImage->pVDIfsDisk = pVDIfsDisk; 5280 pImage->pVDIfsImage = pVDIfsImage; 5227 5281 5228 5282 rc = vmdkOpenImage(pImage, uOpenFlags); … … 5238 5292 static int vmdkCreate(const char *pszFilename, uint64_t cbSize, 5239 5293 unsigned uImageFlags, const char *pszComment, 5240 PCPDMMEDIAGEOMETRY pPCHSGeometry, 5241 PCPDMMEDIAGEOMETRY pLCHSGeometry, PCRTUUID pUuid, 5242 unsigned uOpenFlags, unsigned uPercentStart, 5243 unsigned uPercentSpan, PVDINTERFACE pVDIfsDisk, 5244 PVDINTERFACE pVDIfsImage, PVDINTERFACE pVDIfsOperation, 5245 void **ppBackendData) 5294 PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry, 5295 PCRTUUID pUuid, unsigned uOpenFlags, 5296 unsigned uPercentStart, unsigned uPercentSpan, 5297 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage, 5298 PVDINTERFACE pVDIfsOperation, void **ppBackendData) 5246 5299 { 5247 5300 LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p ppBackendData=%#p", pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppBackendData)); … … 5348 5401 } 5349 5402 5350 /**5351 * Replaces a fragment of a string with the specified string.5352 *5353 * @returns Pointer to the allocated UTF-8 string.5354 * @param pszWhere UTF-8 string to search in.5355 * @param pszWhat UTF-8 string to search for.5356 * @param pszByWhat UTF-8 string to replace the found string with.5357 */5358 static char * vmdkStrReplace(const char *pszWhere, const char *pszWhat, const char *pszByWhat)5359 {5360 AssertPtr(pszWhere);5361 AssertPtr(pszWhat);5362 AssertPtr(pszByWhat);5363 const char *pszFoundStr = strstr(pszWhere, pszWhat);5364 if (!pszFoundStr)5365 return NULL;5366 size_t cFinal = strlen(pszWhere) + 1 + strlen(pszByWhat) - strlen(pszWhat);5367 char *pszNewStr = (char *)RTMemAlloc(cFinal);5368 if (pszNewStr)5369 {5370 char *pszTmp = pszNewStr;5371 memcpy(pszTmp, pszWhere, pszFoundStr - pszWhere);5372 pszTmp += pszFoundStr - pszWhere;5373 memcpy(pszTmp, pszByWhat, strlen(pszByWhat));5374 pszTmp += strlen(pszByWhat);5375 strcpy(pszTmp, pszFoundStr + strlen(pszWhat));5376 }5377 return pszNewStr;5378 }5379 5380 5403 /** @copydoc VBOXHDDBACKEND::pfnRename */ 5381 5404 static int vmdkRename(void *pBackendData, const char *pszFilename) … … 5486 5509 pImage->Descriptor.fDirty = true; 5487 5510 /* Flush the descriptor now, in case it is embedded. */ 5488 (void)vmdkFlushImage(pImage);5511 vmdkFlushImage(pImage); 5489 5512 5490 5513 /* Close and rename/move extents. */ … … 5500 5523 vmdkFileClose(pImage, &pExtent->pFile, false); 5501 5524 /* Rename the extent file. */ 5502 rc = RTFileMove(pExtent->pszFullname, apszNewName[i], 0);5525 rc = vmdkFileMove(pImage, pExtent->pszFullname, apszNewName[i], 0); 5503 5526 if (RT_FAILURE(rc)) 5504 5527 goto rollback; … … 5518 5541 if (!fEmbeddedDesc) 5519 5542 { 5520 rc = RTFileMove(pImage->pszFilename, apszNewName[cExtents], 0);5543 rc = vmdkFileMove(pImage, pImage->pszFilename, apszNewName[cExtents], 0); 5521 5544 if (RT_FAILURE(rc)) 5522 5545 goto rollback; … … 5551 5574 if (apszOldName[i]) 5552 5575 { 5553 rrc = RTFileMove(apszNewName[i], apszOldName[i], 0);5576 rrc = vmdkFileMove(pImage, apszNewName[i], apszOldName[i], 0); 5554 5577 AssertRC(rrc); 5555 5578 } … … 5558 5581 PVMDKFILE pFile; 5559 5582 rrc = vmdkFileOpen(pImage, &pFile, pszOldDescName, 5560 vmdkFileOpenFlags(VD_OPEN_FLAGS_NORMAL), 5561 false); 5583 VDOpenFlagsToFileOpenFlags(VD_OPEN_FLAGS_NORMAL, 5584 false /* fCreate */), 5585 false /* fAsyncIO */); 5562 5586 AssertRC(rrc); 5563 5587 if (fEmbeddedDesc) … … 5631 5655 LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete)); 5632 5656 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData; 5633 int rc = VINF_SUCCESS; 5634 5635 /* Freeing a never allocated image (e.g. because the open failed) is 5636 * not signalled as an error. After all nothing bad happens. */ 5637 if (pImage) 5638 { 5639 vmdkFreeImage(pImage, fDelete); 5640 RTMemFree(pImage); 5641 } 5657 int rc; 5658 5659 rc = vmdkFreeImage(pImage, fDelete); 5660 RTMemFree(pImage); 5642 5661 5643 5662 LogFlowFunc(("returns %Rrc\n", rc)); … … 5690 5709 case VMDKETYPE_ESX_SPARSE: 5691 5710 #endif /* VBOX_WITH_VMDK_ESX */ 5692 rc = vmdkGetSector(pImage ->pGTCache, pExtent, uSectorExtentRel,5711 rc = vmdkGetSector(pImage, pExtent, uSectorExtentRel, 5693 5712 &uSectorExtentAbs); 5694 5713 if (RT_FAILURE(rc)) … … 5708 5727 if (pExtent->uGrainSector != uSectorExtentAbs) 5709 5728 { 5710 rc = vmdkFileInflate At(pExtent->pFile, VMDK_SECTOR2BYTE(uSectorExtentAbs),5711 pExtent->pvGrain, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain), VMDK_MARKER_IGNORE, &uLBA, NULL);5729 rc = vmdkFileInflateSync(pImage, pExtent->pFile, VMDK_SECTOR2BYTE(uSectorExtentAbs), 5730 pExtent->pvGrain, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain), VMDK_MARKER_IGNORE, &uLBA, NULL); 5712 5731 if (RT_FAILURE(rc)) 5713 5732 { … … 5723 5742 else 5724 5743 { 5725 rc = vmdkFileRead At(pExtent->pFile,5726 VMDK_SECTOR2BYTE(uSectorExtentAbs),5727 pvBuf, cbToRead, NULL);5744 rc = vmdkFileReadSync(pImage, pExtent->pFile, 5745 VMDK_SECTOR2BYTE(uSectorExtentAbs), 5746 pvBuf, cbToRead, NULL); 5728 5747 } 5729 5748 } … … 5731 5750 case VMDKETYPE_VMFS: 5732 5751 case VMDKETYPE_FLAT: 5733 rc = vmdkFileRead At(pExtent->pFile,5734 VMDK_SECTOR2BYTE(uSectorExtentRel),5735 pvBuf, cbToRead, NULL);5752 rc = vmdkFileReadSync(pImage, pExtent->pFile, 5753 VMDK_SECTOR2BYTE(uSectorExtentRel), 5754 pvBuf, cbToRead, NULL); 5736 5755 break; 5737 5756 case VMDKETYPE_ZERO: … … 5801 5820 case VMDKETYPE_ESX_SPARSE: 5802 5821 #endif /* VBOX_WITH_VMDK_ESX */ 5803 rc = vmdkGetSector(pImage ->pGTCache, pExtent, uSectorExtentRel,5822 rc = vmdkGetSector(pImage, pExtent, uSectorExtentRel, 5804 5823 &uSectorExtentAbs); 5805 5824 if (RT_FAILURE(rc)) … … 5822 5841 { 5823 5842 /* Allocate GT and find out where to store the grain. */ 5824 rc = vmdkAllocGrain(pImage ->pGTCache, pExtent,5825 uSectorExtentRel,pvBuf, cbToWrite);5843 rc = vmdkAllocGrain(pImage, pExtent, uSectorExtentRel, 5844 pvBuf, cbToWrite); 5826 5845 } 5827 5846 else … … 5849 5868 || pExtent->uGrainSector != pExtent->uLastGrainSector) 5850 5869 { 5851 rc = vmdkFileInflate At(pExtent->pFile, VMDK_SECTOR2BYTE(uSectorExtentAbs),5852 pExtent->pvGrain, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain), VMDK_MARKER_IGNORE, &uLBA, NULL);5870 rc = vmdkFileInflateSync(pImage, pExtent->pFile, VMDK_SECTOR2BYTE(uSectorExtentAbs), 5871 pExtent->pvGrain, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain), VMDK_MARKER_IGNORE, &uLBA, NULL); 5853 5872 if (RT_FAILURE(rc)) 5854 5873 { … … 5864 5883 memcpy((uint8_t *)pExtent->pvGrain + VMDK_SECTOR2BYTE(uSectorInGrain), pvBuf, cbToWrite); 5865 5884 uint32_t cbGrain = 0; 5866 rc = vmdkFileDeflate At(pExtent->pFile,5867 VMDK_SECTOR2BYTE(uSectorExtentAbs),5868 pExtent->pvGrain, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain),5869 VMDK_MARKER_IGNORE, uLBA, &cbGrain);5885 rc = vmdkFileDeflateSync(pImage, pExtent->pFile, 5886 VMDK_SECTOR2BYTE(uSectorExtentAbs), 5887 pExtent->pvGrain, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain), 5888 VMDK_MARKER_IGNORE, uLBA, &cbGrain); 5870 5889 if (RT_FAILURE(rc)) 5871 5890 { … … 5873 5892 pExtent->uLastGrainSector = 0; 5874 5893 AssertRC(rc); 5875 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write compressed data block in '%s'"), pExtent->pszFullname);5894 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write compressed data block in '%s'"), pExtent->pszFullname); 5876 5895 } 5877 5896 cbGrain = RT_ALIGN(cbGrain, 512); … … 5884 5903 { 5885 5904 uEOSOff = 512; 5886 rc = vmdkWriteMetaSparseExtent(p Extent, VMDK_SECTOR2BYTE(uSectorExtentAbs) + RT_ALIGN(cbGrain, 512));5905 rc = vmdkWriteMetaSparseExtent(pImage, pExtent, VMDK_SECTOR2BYTE(uSectorExtentAbs) + RT_ALIGN(cbGrain, 512)); 5887 5906 if (RT_FAILURE(rc)) 5888 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write footer after data block in '%s'"), pExtent->pszFullname);5907 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write footer after data block in '%s'"), pExtent->pszFullname); 5889 5908 } 5890 5909 uint8_t aEOS[512]; 5891 5910 memset(aEOS, '\0', sizeof(aEOS)); 5892 rc = vmdkFileWrite At(pExtent->pFile,5893 VMDK_SECTOR2BYTE(uSectorExtentAbs) + RT_ALIGN(cbGrain, 512) + uEOSOff,5894 aEOS, sizeof(aEOS), NULL);5911 rc = vmdkFileWriteSync(pImage, pExtent->pFile, 5912 VMDK_SECTOR2BYTE(uSectorExtentAbs) + RT_ALIGN(cbGrain, 512) + uEOSOff, 5913 aEOS, sizeof(aEOS), NULL); 5895 5914 if (RT_FAILURE(rc)) 5896 return vmdkError(p Extent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write end-of stream marker after data block in '%s'"), pExtent->pszFullname);5915 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write end-of stream marker after data block in '%s'"), pExtent->pszFullname); 5897 5916 } 5898 5917 else 5899 5918 { 5900 rc = vmdkFileWrite At(pExtent->pFile,5901 VMDK_SECTOR2BYTE(uSectorExtentAbs),5902 pvBuf, cbToWrite, NULL);5919 rc = vmdkFileWriteSync(pImage, pExtent->pFile, 5920 VMDK_SECTOR2BYTE(uSectorExtentAbs), 5921 pvBuf, cbToWrite, NULL); 5903 5922 } 5904 5923 } … … 5908 5927 /* Clip write range to remain in this extent. */ 5909 5928 cbToWrite = RT_MIN(cbToWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel)); 5910 rc = vmdkFileWrite At(pExtent->pFile,5911 VMDK_SECTOR2BYTE(uSectorExtentRel),5912 pvBuf, cbToWrite, NULL);5929 rc = vmdkFileWriteSync(pImage, pExtent->pFile, 5930 VMDK_SECTOR2BYTE(uSectorExtentRel), 5931 pvBuf, cbToWrite, NULL); 5913 5932 break; 5914 5933 case VMDKETYPE_ZERO: … … 5917 5936 break; 5918 5937 } 5938 5919 5939 if (pcbWriteProcess) 5920 5940 *pcbWriteProcess = cbToWrite; … … 5981 6001 if (pImage->pFile != NULL) 5982 6002 { 5983 int rc = vmdkFileGetSize(pImage ->pFile, &cbFile);6003 int rc = vmdkFileGetSize(pImage, pImage->pFile, &cbFile); 5984 6004 if (RT_SUCCESS(rc)) 5985 6005 cb += cbFile; … … 5989 6009 if (pImage->pExtents[i].pFile != NULL) 5990 6010 { 5991 int rc = vmdkFileGetSize(pImage ->pExtents[i].pFile, &cbFile);6011 int rc = vmdkFileGetSize(pImage, pImage->pExtents[i].pFile, &cbFile); 5992 6012 if (RT_SUCCESS(rc)) 5993 6013 cb += cbFile; … … 6001 6021 6002 6022 /** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */ 6003 static int vmdkGetPCHSGeometry(void *pBackendData, 6004 PPDMMEDIAGEOMETRY pPCHSGeometry) 6023 static int vmdkGetPCHSGeometry(void *pBackendData, PVDGEOMETRY pPCHSGeometry) 6005 6024 { 6006 6025 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry)); … … 6028 6047 6029 6048 /** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */ 6030 static int vmdkSetPCHSGeometry(void *pBackendData, 6031 PCPDMMEDIAGEOMETRY pPCHSGeometry) 6049 static int vmdkSetPCHSGeometry(void *pBackendData, PCVDGEOMETRY pPCHSGeometry) 6032 6050 { 6033 6051 LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); … … 6060 6078 6061 6079 /** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */ 6062 static int vmdkGetLCHSGeometry(void *pBackendData, 6063 PPDMMEDIAGEOMETRY pLCHSGeometry) 6080 static int vmdkGetLCHSGeometry(void *pBackendData, PVDGEOMETRY pLCHSGeometry) 6064 6081 { 6065 6082 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry)); … … 6087 6104 6088 6105 /** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */ 6089 static int vmdkSetLCHSGeometry(void *pBackendData, 6090 PCPDMMEDIAGEOMETRY pLCHSGeometry) 6106 static int vmdkSetLCHSGeometry(void *pBackendData, PCVDGEOMETRY pLCHSGeometry) 6091 6107 { 6092 6108 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); … … 6463 6479 if (pImage) 6464 6480 { 6465 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",6481 vmdkMessage(pImage, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n", 6466 6482 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors, 6467 6483 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors, 6468 6484 VMDK_BYTE2SECTOR(pImage->cbSize)); 6469 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: uuidCreation={%RTuuid}\n", &pImage->ImageUuid); 6470 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: uuidModification={%RTuuid}\n", &pImage->ModificationUuid); 6471 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: uuidParent={%RTuuid}\n", &pImage->ParentUuid); 6472 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: uuidParentModification={%RTuuid}\n", &pImage->ParentModificationUuid); 6473 } 6474 } 6475 6476 6477 static int vmdkGetTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp) 6478 { 6479 int rc = VERR_NOT_IMPLEMENTED; 6480 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc)); 6481 return rc; 6482 } 6483 6484 static int vmdkGetParentTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp) 6485 { 6486 int rc = VERR_NOT_IMPLEMENTED; 6487 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc)); 6488 return rc; 6489 } 6490 6491 static int vmdkSetParentTimeStamp(void *pvBackendData, PCRTTIMESPEC pTimeStamp) 6492 { 6493 int rc = VERR_NOT_IMPLEMENTED; 6494 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc)); 6495 return rc; 6496 } 6497 6498 static int vmdkGetParentFilename(void *pvBackendData, char **ppszParentFilename) 6499 { 6500 int rc = VERR_NOT_IMPLEMENTED; 6501 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc)); 6502 return rc; 6503 } 6504 6505 static int vmdkSetParentFilename(void *pvBackendData, const char *pszParentFilename) 6506 { 6507 int rc = VERR_NOT_IMPLEMENTED; 6508 LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc)); 6509 return rc; 6510 } 6511 6512 static bool vmdkIsAsyncIOSupported(void *pvBackendData) 6513 { 6514 PVMDKIMAGE pImage = (PVMDKIMAGE)pvBackendData; 6485 vmdkMessage(pImage, "Header: uuidCreation={%RTuuid}\n", &pImage->ImageUuid); 6486 vmdkMessage(pImage, "Header: uuidModification={%RTuuid}\n", &pImage->ModificationUuid); 6487 vmdkMessage(pImage, "Header: uuidParent={%RTuuid}\n", &pImage->ParentUuid); 6488 vmdkMessage(pImage, "Header: uuidParentModification={%RTuuid}\n", &pImage->ParentModificationUuid); 6489 } 6490 } 6491 6492 /** @copydoc VBOXHDDBACKEND::pfnIsAsyncIOSupported */ 6493 static bool vmdkIsAsyncIOSupported(void *pBackendData) 6494 { 6495 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData; 6515 6496 6516 6497 /* We do not support async I/O for stream optimized VMDK images. */ … … 6518 6499 } 6519 6500 6520 static int vmdkAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbRead, 6501 /** @copydoc VBOXHDDBACKEND::pfnAsyncRead */ 6502 static int vmdkAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbRead, 6521 6503 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 6522 6504 { 6523 LogFlowFunc(("p vBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n",6524 p vBackendData, uOffset, pIoCtx, cbRead, pcbActuallyRead));6525 PVMDKIMAGE pImage = (PVMDKIMAGE)p vBackendData;6505 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n", 6506 pBackendData, uOffset, pIoCtx, cbRead, pcbActuallyRead)); 6507 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData; 6526 6508 PVMDKEXTENT pExtent; 6527 6509 uint64_t uSectorExtentRel; … … 6562 6544 case VMDKETYPE_ESX_SPARSE: 6563 6545 #endif /* VBOX_WITH_VMDK_ESX */ 6564 rc = vmdkGetSectorAsync(pImage, pIoCtx, p Image->pGTCache, pExtent,6546 rc = vmdkGetSectorAsync(pImage, pIoCtx, pExtent, 6565 6547 uSectorExtentRel, &uSectorExtentAbs); 6566 6548 if (RT_FAILURE(rc)) … … 6574 6556 { 6575 6557 AssertMsg(!(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED), ("Async I/O is not supported for stream optimized VMDK's\n")); 6576 rc = pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser, 6577 pExtent->pFile->pStorage, 6578 VMDK_SECTOR2BYTE(uSectorExtentAbs), 6579 pIoCtx, cbRead); 6558 rc = vmdkFileReadUserAsync(pImage, pExtent->pFile, 6559 VMDK_SECTOR2BYTE(uSectorExtentAbs), 6560 pIoCtx, cbRead); 6580 6561 } 6581 6562 break; 6582 6563 case VMDKETYPE_VMFS: 6583 6564 case VMDKETYPE_FLAT: 6584 rc = pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser, 6585 pExtent->pFile->pStorage, 6586 VMDK_SECTOR2BYTE(uSectorExtentRel), 6587 pIoCtx, cbRead); 6565 rc = vmdkFileReadUserAsync(pImage, pExtent->pFile, 6566 VMDK_SECTOR2BYTE(uSectorExtentRel), 6567 pIoCtx, cbRead); 6588 6568 break; 6589 6569 case VMDKETYPE_ZERO: 6590 6570 size_t cbSet; 6591 6571 6592 cbSet = pImage->pInterfaceIOCallbacks->pfnIoCtxSet(pImage->pInterfaceIO->pvUser, 6593 pIoCtx, 0, cbRead); 6572 cbSet = vmdkFileIoCtxSet(pImage, pIoCtx, 0, cbRead); 6594 6573 Assert(cbSet == cbRead); 6595 6574 … … 6605 6584 } 6606 6585 6607 static int vmdkAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbWrite, 6586 /** @copydoc VBOXHDDBACKEND::pfnAsyncWrite */ 6587 static int vmdkAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbWrite, 6608 6588 PVDIOCTX pIoCtx, 6609 6589 size_t *pcbWriteProcess, size_t *pcbPreRead, 6610 6590 size_t *pcbPostRead, unsigned fWrite) 6611 6591 { 6612 LogFlowFunc(("p vBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",6613 p vBackendData, uOffset, pIoCtx, cbWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));6614 PVMDKIMAGE pImage = (PVMDKIMAGE)p vBackendData;6592 LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", 6593 pBackendData, uOffset, pIoCtx, cbWrite, pcbWriteProcess, pcbPreRead, pcbPostRead)); 6594 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData; 6615 6595 PVMDKEXTENT pExtent; 6616 6596 uint64_t uSectorExtentRel; … … 6660 6640 case VMDKETYPE_ESX_SPARSE: 6661 6641 #endif /* VBOX_WITH_VMDK_ESX */ 6662 rc = vmdkGetSectorAsync(pImage, pIoCtx, p Image->pGTCache, pExtent, uSectorExtentRel,6642 rc = vmdkGetSectorAsync(pImage, pIoCtx, pExtent, uSectorExtentRel, 6663 6643 &uSectorExtentAbs); 6664 6644 if (RT_FAILURE(rc)) … … 6681 6661 { 6682 6662 /* Allocate GT and find out where to store the grain. */ 6683 rc = vmdkAllocGrainAsync(pImage ->pGTCache, pExtent, pIoCtx,6663 rc = vmdkAllocGrainAsync(pImage, pExtent, pIoCtx, 6684 6664 uSectorExtentRel, cbWrite); 6685 6665 } … … 6701 6681 { 6702 6682 Assert(!(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)); 6703 rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser, 6704 pExtent->pFile->pStorage, 6705 VMDK_SECTOR2BYTE(uSectorExtentAbs), 6706 pIoCtx, cbWrite, 6707 NULL, NULL); 6683 rc = vmdkFileWriteUserAsync(pImage, pExtent->pFile, 6684 VMDK_SECTOR2BYTE(uSectorExtentAbs), 6685 pIoCtx, cbWrite, NULL, NULL); 6708 6686 } 6709 6687 break; … … 6712 6690 /* Clip write range to remain in this extent. */ 6713 6691 cbWrite = RT_MIN(cbWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel)); 6714 rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser, 6715 pExtent->pFile->pStorage, 6716 VMDK_SECTOR2BYTE(uSectorExtentRel), 6717 pIoCtx, cbWrite, NULL, NULL); 6692 rc = vmdkFileWriteUserAsync(pImage, pExtent->pFile, 6693 VMDK_SECTOR2BYTE(uSectorExtentRel), 6694 pIoCtx, cbWrite, NULL, NULL); 6718 6695 break; 6719 6696 case VMDKETYPE_ZERO: … … 6722 6699 break; 6723 6700 } 6701 6724 6702 if (pcbWriteProcess) 6725 6703 *pcbWriteProcess = cbWrite; … … 6730 6708 } 6731 6709 6732 static int vmdkAsyncFlush(void *pvBackendData, PVDIOCTX pIoCtx) 6733 { 6734 PVMDKIMAGE pImage = (PVMDKIMAGE)pvBackendData; 6710 /** @copydoc VBOXHDDBACKEND::pfnAsyncFlush */ 6711 static int vmdkAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx) 6712 { 6713 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData; 6735 6714 PVMDKEXTENT pExtent; 6736 6715 int rc = VINF_SUCCESS; … … 6753 6732 { 6754 6733 uint64_t cbSize; 6755 rc = vmdkFileGetSize(p Extent->pFile, &cbSize);6734 rc = vmdkFileGetSize(pImage, pExtent->pFile, &cbSize); 6756 6735 if (RT_FAILURE(rc)) 6757 6736 goto out; 6758 6737 cbSize = RT_ALIGN_64(cbSize, 512); 6759 rc = vmdkWriteMetaSparseExtent(p Extent, cbSize - 2*512);6738 rc = vmdkWriteMetaSparseExtent(pImage, pExtent, cbSize - 2*512); 6760 6739 if (RT_FAILURE(rc) && (rc != VERR_VD_ASYNC_IO_IN_PROGRESS)) 6761 6740 goto out; … … 6785 6764 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 6786 6765 && !(pExtent->pszBasename[0] == RTPATH_SLASH)) 6787 rc = vmdkFileFlushAsync(p Extent->pFile, pIoCtx);6766 rc = vmdkFileFlushAsync(pImage, pExtent->pFile, pIoCtx); 6788 6767 break; 6789 6768 case VMDKETYPE_ZERO: … … 6809 6788 /* uBackendCaps */ 6810 6789 VD_CAP_UUID | VD_CAP_CREATE_FIXED | VD_CAP_CREATE_DYNAMIC 6811 | VD_CAP_CREATE_SPLIT_2G | VD_CAP_DIFF | VD_CAP_FILE |VD_CAP_ASYNC, 6790 | VD_CAP_CREATE_SPLIT_2G | VD_CAP_DIFF | VD_CAP_FILE | VD_CAP_ASYNC 6791 | VD_CAP_VFS, 6812 6792 /* papszFileExtensions */ 6813 6793 s_apszVmdkFileExtensions, … … 6875 6855 vmdkDump, 6876 6856 /* pfnGetTimeStamp */ 6877 vmdkGetTimeStamp,6857 NULL, 6878 6858 /* pfnGetParentTimeStamp */ 6879 vmdkGetParentTimeStamp,6859 NULL, 6880 6860 /* pfnSetParentTimeStamp */ 6881 vmdkSetParentTimeStamp,6861 NULL, 6882 6862 /* pfnGetParentFilename */ 6883 vmdkGetParentFilename,6863 NULL, 6884 6864 /* pfnSetParentFilename */ 6885 vmdkSetParentFilename,6865 NULL, 6886 6866 /* pfnIsAsyncIOSupported */ 6887 6867 vmdkIsAsyncIOSupported, -
trunk/src/VBox/Devices/Storage/testcase/Makefile.kmk
r32432 r32536 96 96 $(VBOX_PATH_DEVICES_SRC)/Storage/ParallelsHDDCore.cpp \ 97 97 $(VBOX_PATH_DEVICES_SRC)/Storage/DMGHDDCore.cpp 98 ifdef VBOX_WITH_NEW_IO_CODE99 vbox-img_DEFS += VBOX_WITH_NEW_IO_CODE100 endif101 98 vbox-img_DEFS += VBOX_HDD_NO_DYNAMIC_BACKENDS IN_VBOXDDU IN_VBOXDDU_STATIC IN_RT_R3 102 99 endif -
trunk/src/VBox/Devices/Storage/testcase/tstVD.cpp
r29250 r32536 5 5 6 6 /* 7 * Copyright (C) 2006-20 07Oracle Corporation7 * Copyright (C) 2006-2010 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 53 53 } 54 54 55 static int tstVDMessage(void *pvUser, const char *pszFormat, ...) 56 { 57 va_list va; 58 55 static int tstVDMessage(void *pvUser, const char *pszFormat, va_list va) 56 { 59 57 RTPrintf("tstVD: "); 60 va_start(va, pszFormat);61 58 RTPrintfV(pszFormat, va); 62 va_end(va);63 59 return VINF_SUCCESS; 64 60 } … … 69 65 int rc; 70 66 PVBOXHDD pVD = NULL; 71 PDMMEDIAGEOMETRYPCHS = { 0, 0, 0 };72 PDMMEDIAGEOMETRYLCHS = { 0, 0, 0 };67 VDGEOMETRY PCHS = { 0, 0, 0 }; 68 VDGEOMETRY LCHS = { 0, 0, 0 }; 73 69 PVDINTERFACE pVDIfs = NULL; 74 70 VDINTERFACE VDIError; … … 127 123 int rc; 128 124 PVBOXHDD pVD = NULL; 129 PDMMEDIAGEOMETRYPCHS = { 0, 0, 0 };130 PDMMEDIAGEOMETRYLCHS = { 0, 0, 0 };125 VDGEOMETRY PCHS = { 0, 0, 0 }; 126 VDGEOMETRY LCHS = { 0, 0, 0 }; 131 127 PVDINTERFACE pVDIfs = NULL; 132 128 VDINTERFACE VDIError; … … 509 505 PVBOXHDD pVD = NULL; 510 506 char *pszFormat; 511 PDMMEDIAGEOMETRY PCHS = { 0, 0, 0 };512 PDMMEDIAGEOMETRY LCHS = { 0, 0, 0 };513 uint64_t u64DiskSize 507 VDGEOMETRY PCHS = { 0, 0, 0 }; 508 VDGEOMETRY LCHS = { 0, 0, 0 }; 509 uint64_t u64DiskSize = 1000 * _1M; 514 510 uint32_t u32SectorSize = 512; 515 511 PVDINTERFACE pVDIfs = NULL; … … 551 547 { 552 548 RTFileClose(File); 553 rc = VDGetFormat(NULL, pszBaseFilename, &pszFormat); 549 rc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */, 550 pszBaseFilename, &pszFormat); 554 551 RTPrintf("VDGetFormat() pszFormat=%s rc=%Rrc\n", pszFormat, rc); 555 552 if (RT_SUCCESS(rc) && strcmp(pszFormat, pszBackend)) … … 633 630 int rc; 634 631 PVBOXHDD pVD = NULL; 635 PDMMEDIAGEOMETRY PCHS = { 0, 0, 0 };636 PDMMEDIAGEOMETRY LCHS = { 0, 0, 0 };637 uint64_t u64DiskSize 632 VDGEOMETRY PCHS = { 0, 0, 0 }; 633 VDGEOMETRY LCHS = { 0, 0, 0 }; 634 uint64_t u64DiskSize = 1000 * _1M; 638 635 uint32_t u32SectorSize = 512; 639 636 PVDINTERFACE pVDIfs = NULL; -
trunk/src/VBox/Devices/Storage/testcase/tstVDCopy.cpp
r31493 r32536 97 97 AssertRC(rc); 98 98 99 rc = VDGetFormat(NULL, argv[1], &pszVD1); 99 rc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */, 100 argv[1], &pszVD1); 100 101 CHECK("VDGetFormat() hdd1"); 101 102 102 rc = VDGetFormat(NULL, argv[2], &pszVD2); 103 rc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */, 104 argv[2], &pszVD2); 103 105 CHECK("VDGetFormat() hdd2"); 104 106 -
trunk/src/VBox/Devices/Storage/testcase/tstVDShareable.cpp
r31193 r32536 53 53 } 54 54 55 static int tstVDMessage(void *pvUser, const char *pszFormat, ...)55 static int tstVDMessage(void *pvUser, const char *pszFormat, va_list va) 56 56 { 57 va_list va;58 59 57 RTPrintf("tstVD: "); 60 va_start(va, pszFormat);61 58 RTPrintfV(pszFormat, va); 62 va_end(va);63 59 return VINF_SUCCESS; 64 60 } … … 69 65 int rc; 70 66 PVBOXHDD pVD = NULL, pVD2 = NULL; 71 PDMMEDIAGEOMETRYPCHS = { 0, 0, 0 };72 PDMMEDIAGEOMETRYLCHS = { 0, 0, 0 };67 VDGEOMETRY PCHS = { 0, 0, 0 }; 68 VDGEOMETRY LCHS = { 0, 0, 0 }; 73 69 PVDINTERFACE pVDIfs = NULL; 74 70 VDINTERFACE VDIError; -
trunk/src/VBox/Devices/Storage/testcase/tstVDSnap.cpp
r28800 r32536 92 92 } 93 93 94 static int tstVDMessage(void *pvUser, const char *pszFormat, ...) 95 { 96 va_list va; 97 94 static int tstVDMessage(void *pvUser, const char *pszFormat, va_list va) 95 { 98 96 RTPrintf("tstVD: "); 99 va_start(va, pszFormat);100 97 RTPrintfV(pszFormat, va); 101 va_end(va);102 98 return VINF_SUCCESS; 103 99 } … … 220 216 int rc; 221 217 PVBOXHDD pVD = NULL; 222 PDMMEDIAGEOMETRYPCHS = { 0, 0, 0 };223 PDMMEDIAGEOMETRYLCHS = { 0, 0, 0 };218 VDGEOMETRY PCHS = { 0, 0, 0 }; 219 VDGEOMETRY LCHS = { 0, 0, 0 }; 224 220 PVDINTERFACE pVDIfs = NULL; 225 221 VDINTERFACE VDIError; -
trunk/src/VBox/Devices/Storage/testcase/vbox-img.cpp
r32431 r32536 72 72 } 73 73 74 static int handleVDMessage(void *pvUser, const char *pszFormat, ...)74 static int handleVDMessage(void *pvUser, const char *pszFormat, va_list va) 75 75 { 76 76 NOREF(pvUser); 77 va_list args; 78 va_start(args, pszFormat); 79 RTPrintfV(pszFormat, args); 80 va_end(args); 77 RTPrintfV(pszFormat, va); 81 78 return VINF_SUCCESS; 82 79 } … … 177 174 /* Don't pass error interface, as that would triggers error messages 178 175 * because some backends fail to open the image. */ 179 rc = VDGetFormat(NULL, pszFilename, &pszFormat);176 rc = VDGetFormat(NULL, NULL, pszFilename, &pszFormat); 180 177 if (RT_FAILURE(rc)) 181 178 return errorRuntime("Format autodetect failed: %Rrc\n", rc); … … 246 243 const char *pszDstFilename = NULL; 247 244 char *pszSrcFormat = NULL; 248 c har *pszDstFormat = NULL;245 const char *pszDstFormat = NULL; 249 246 const char *pszVariant = NULL; 250 247 PVBOXHDD pSrcDisk = NULL; … … 338 335 if (!pszSrcFormat) 339 336 { 340 rc = VDGetFormat(NULL, pszSrcFilename, &pszSrcFormat);337 rc = VDGetFormat(NULL, NULL, pszSrcFilename, &pszSrcFormat); 341 338 if (RT_FAILURE(rc)) 342 339 { … … 431 428 /* just try it */ 432 429 char *pszFormat = NULL; 433 rc = VDGetFormat(NULL, pszFilename, &pszFormat);430 rc = VDGetFormat(NULL, NULL, pszFilename, &pszFormat); 434 431 if (RT_FAILURE(rc)) 435 432 return errorSyntax("Format autodetect failed: %Rrc\n", rc); … … 487 484 /* just try it */ 488 485 char *pszFormat = NULL; 489 rc = VDGetFormat(NULL, pszFilename, &pszFormat);486 rc = VDGetFormat(NULL, NULL, pszFilename, &pszFormat); 490 487 if (RT_FAILURE(rc)) 491 488 return errorSyntax("Format autodetect failed: %Rrc\n", rc); -
trunk/src/VBox/Devices/Storage/testcase/vditool.cpp
r28855 r32536 5 5 6 6 /* 7 * Copyright (C) 2006-20 07Oracle Corporation7 * Copyright (C) 2006-2010 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 108 108 return PrintDone(rc); 109 109 110 PDMMEDIAGEOMETRY geo = { 0, 0, 0 }; /* auto-detect */110 VDGEOMETRY geo = { 0, 0, 0 }; /* auto-detect */ 111 111 rc = VDCreateBase(hdd, "vdi", pszUtf8Filename, 112 112 (uint64_t)cMBs * _1M, … … 274 274 if (RT_SUCCESS(rc)) 275 275 { 276 PDMMEDIAGEOMETRY LCHSGeometry = {0, 0, 0};276 VDGEOMETRY LCHSGeometry = {0, 0, 0}; 277 277 rc = VDIDiskSetLCHSGeometry(pVdi, &LCHSGeometry); 278 278 } -
trunk/src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp
r32531 r32536 508 508 } 509 509 510 static int handleVDMessage(void *pvUser, const char *pszFormat, ...)510 static int handleVDMessage(void *pvUser, const char *pszFormat, va_list va) 511 511 { 512 512 NOREF(pvUser); 513 va_list args; 514 va_start(args, pszFormat); 515 int rc = RTPrintfV(pszFormat, args); 516 va_end(args); 517 return rc; 513 return RTPrintfV(pszFormat, va); 518 514 } 519 515 … … 555 551 /* just try it */ 556 552 char *pszFormat = NULL; 557 int rc = VDGetFormat(NULL /* pVDIfsDisk */, argv[1], &pszFormat); 553 int rc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */, 554 argv[1], &pszFormat); 558 555 if (RT_FAILURE(rc)) 559 556 { … … 616 613 /* just try it */ 617 614 char *pszFormat = NULL; 618 int rc = VDGetFormat(NULL /* pVDIfsDisk */, argv[0], &pszFormat); 615 int rc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */, 616 argv[0], &pszFormat); 619 617 if (RT_FAILURE(rc)) 620 618 { … … 1437 1435 Assert(RT_MIN(cbSize / 512 / 16 / 63, 16383) - 1438 1436 (unsigned int)RT_MIN(cbSize / 512 / 16 / 63, 16383) == 0); 1439 PDMMEDIAGEOMETRY PCHS, LCHS;1437 VDGEOMETRY PCHS, LCHS; 1440 1438 PCHS.cCylinders = (unsigned int)RT_MIN(cbSize / 512 / 16 / 63, 16383); 1441 1439 PCHS.cHeads = 16; … … 1641 1639 { 1642 1640 char *pszFormat = NULL; 1643 vrc = VDGetFormat(NULL /* pVDIfsDisk */, src.c_str(), &pszFormat); 1641 vrc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */, 1642 src.c_str(), &pszFormat); 1644 1643 if (RT_FAILURE(vrc)) 1645 1644 { … … 1788 1787 { 1789 1788 char *pszFormat = NULL; 1790 vrc = VDGetFormat(NULL /* pVDIfsDisk */, src.c_str(), &pszFormat); 1789 vrc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */, 1790 src.c_str(), &pszFormat); 1791 1791 if (RT_FAILURE(vrc)) 1792 1792 { -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp
r32531 r32536 890 890 Assert(RT_MIN(cbFile / 512 / 16 / 63, 16383) - 891 891 (unsigned int)RT_MIN(cbFile / 512 / 16 / 63, 16383) == 0); 892 PDMMEDIAGEOMETRY PCHS, LCHS;892 VDGEOMETRY PCHS, LCHS; 893 893 PCHS.cCylinders = (unsigned int)RT_MIN(cbFile / 512 / 16 / 63, 16383); 894 894 PCHS.cHeads = 16; -
trunk/src/VBox/Main/MediumImpl.cpp
r32531 r32536 3522 3522 if (RT_SUCCESS(vrc)) 3523 3523 { 3524 vrc = VDGetFormat(NULL, locationFull.c_str(), &backendName); 3524 vrc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */, 3525 locationFull.c_str(), &backendName); 3525 3526 } 3526 3527 else if (vrc != VERR_FILE_NOT_FOUND && vrc != VERR_PATH_NOT_FOUND) … … 3528 3529 /* assume it's not a file, restore the original location */ 3529 3530 location = locationFull = aLocation; 3530 vrc = VDGetFormat(NULL, locationFull.c_str(), &backendName); 3531 vrc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */, 3532 locationFull.c_str(), &backendName); 3531 3533 } 3532 3534 … … 5609 5611 throw rc; 5610 5612 5611 PDMMEDIAGEOMETRY geo = { 0, 0, 0 }; /* auto-detect */5613 VDGEOMETRY geo = { 0, 0, 0 }; /* auto-detect */ 5612 5614 5613 5615 vrc = VDCreateBase(hdd, … … 6809 6811 thisLock.release(); 6810 6812 6811 PDMMEDIAGEOMETRY geo = {0, 0, 0}; /* auto */6813 VDGEOMETRY geo = {0, 0, 0}; /* auto */ 6812 6814 vrc = VDResize(hdd, task.mSize, &geo, &geo, task.mVDOperationIfaces); 6813 6815 if (RT_FAILURE(vrc)) -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r32531 r32536 9982 9982 <enum 9983 9983 name="MediumFormatCapabilities" 9984 uuid=" be44ec10-9540-4d3f-aee5-4a4d4c4ad42c"9984 uuid="7342ba79-7ce0-4d94-8f86-5ed5a185d9bd" 9985 9985 > 9986 9986 <desc> … … 10049 10049 </const> 10050 10050 10051 <const name="CapabilityMask" value="0x1FF"/> 10051 <const name="VFS" value="0x200"> 10052 <desc> 10053 The format backend supports virtual filesystem functionality. 10054 </desc> 10055 </const> 10056 10057 <const name="CapabilityMask" value="0x3FF"/> 10052 10058 </enum> 10053 10059 -
trunk/src/VBox/Runtime/VBox/log-vbox.cpp
r30732 r32536 239 239 ASSERT_LOG_GROUP(DRV_HOST_DVD); 240 240 ASSERT_LOG_GROUP(DRV_HOST_FLOPPY); 241 ASSERT_LOG_GROUP(DRV_ISCSI);242 ASSERT_LOG_GROUP(DRV_ISCSI_TRANSPORT_TCP);243 241 ASSERT_LOG_GROUP(DRV_ISO); 244 242 ASSERT_LOG_GROUP(DRV_KBD_QUEUE);
Note:
See TracChangeset
for help on using the changeset viewer.